Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4944066fa7 | ||
|
|
cfed3c1c5a | ||
|
|
4a517a384c | ||
|
|
675d7bb4f9 | ||
|
|
1b167061a1 | ||
|
|
d4b2ce50a5 | ||
|
|
9b3597e981 | ||
|
|
43d622ee08 | ||
|
|
607f6aa1e8 | ||
|
|
f6a92669da | ||
|
|
d9a6de9c43 | ||
|
|
b45d2ba97a | ||
|
|
b354e6f3d7 | ||
|
|
b0906baa6d | ||
|
|
63a36ea295 | ||
|
|
26b35642b4 | ||
|
|
8b45b16431 | ||
|
|
583ec35475 | ||
|
|
c3fa3f6074 | ||
|
|
eed51b8d17 | ||
|
|
7f28b377dd | ||
|
|
51aac88868 | ||
|
|
79bfcf8306 | ||
|
|
65c4fe13cd | ||
|
|
636229c097 | ||
|
|
c9df4372d7 | ||
|
|
954c612f69 | ||
|
|
a65fc1d975 | ||
|
|
14a3084c7f | ||
|
|
8d011bf094 | ||
|
|
403590585d | ||
|
|
b78e167105 | ||
|
|
d002f5556d | ||
|
|
a256b589ac | ||
|
|
07291a0eac | ||
|
|
1d297d5228 | ||
|
|
326594f3e6 | ||
|
|
d5e06e943f | ||
|
|
26ce12cd6f | ||
|
|
c8ec329f14 | ||
|
|
2fd740e529 | ||
|
|
572bfe5df7 | ||
|
|
2c72709003 | ||
|
|
face88a940 | ||
|
|
76512daba2 | ||
|
|
319e903f24 | ||
|
|
42ae359abc | ||
|
|
df866b3f7f | ||
|
|
7b72b2e3d4 | ||
|
|
3c9c3455af | ||
|
|
e733bc78d6 | ||
|
|
ffc3ddd854 | ||
|
|
ea4e1873de | ||
|
|
9333498538 | ||
|
|
344ef39d66 | ||
|
|
62734f3727 | ||
|
|
ca71140a88 | ||
|
|
e674fc3214 | ||
|
|
5c4cd57ff8 | ||
|
|
2934c82b75 | ||
|
|
c8289bffda | ||
|
|
476dd1cd1c |
58
.clangd
58
.clangd
@@ -1,8 +1,34 @@
|
||||
# YAZE ROM Editor - clangd configuration
|
||||
# Optimized for C++23, Google style, Abseil/gRPC, and ROM hacking workflows
|
||||
|
||||
CompileFlags:
|
||||
CompilationDatabase: build
|
||||
Add:
|
||||
# Additional include paths for better IntelliSense
|
||||
- -I/Users/scawful/Code/yaze/src
|
||||
- -I/Users/scawful/Code/yaze/src/lib
|
||||
- -I/Users/scawful/Code/yaze/src/lib/imgui
|
||||
- -I/Users/scawful/Code/yaze/src/lib/imgui/backends
|
||||
- -I/Users/scawful/Code/yaze/src/lib/SDL/include
|
||||
- -I/Users/scawful/Code/yaze/incl
|
||||
- -I/Users/scawful/Code/yaze/third_party
|
||||
- -I/Users/scawful/Code/yaze/third_party/json/include
|
||||
- -I/Users/scawful/Code/yaze/third_party/httplib
|
||||
- -I/Users/scawful/Code/yaze/build
|
||||
- -I/Users/scawful/Code/yaze/build/src/lib/SDL/include
|
||||
- -I/Users/scawful/Code/yaze/build/src/lib/SDL/include-config-Debug
|
||||
# Feature flags
|
||||
- -DYAZE_WITH_GRPC
|
||||
- -DYAZE_WITH_JSON
|
||||
- -DZ3ED_AI
|
||||
# Standard library
|
||||
- -std=c++23
|
||||
# Platform detection
|
||||
- -DMACOS
|
||||
Remove:
|
||||
- -mllvm
|
||||
- -xclang
|
||||
- -w # Remove warning suppression for better diagnostics
|
||||
|
||||
Index:
|
||||
Background: Build
|
||||
@@ -18,20 +44,44 @@ Hover:
|
||||
|
||||
Diagnostics:
|
||||
MissingIncludes: Strict
|
||||
UnusedIncludes: Strict
|
||||
ClangTidy:
|
||||
Add:
|
||||
# Core checks for ROM hacking software
|
||||
- performance-*
|
||||
- bugprone-*
|
||||
- readability-*
|
||||
- modernize-*
|
||||
- misc-*
|
||||
- clang-analyzer-*
|
||||
# Abseil-specific checks
|
||||
- abseil-*
|
||||
# Google C++ style enforcement
|
||||
- google-*
|
||||
Remove:
|
||||
# - readability-*
|
||||
# - modernize-*
|
||||
# Disable overly strict checks for ROM hacking workflow
|
||||
- modernize-use-trailing-return-type
|
||||
- readability-braces-around-statements
|
||||
- readability-magic-numbers
|
||||
- readability-magic-numbers # ROM hacking uses many magic numbers
|
||||
- readability-implicit-bool-conversion
|
||||
- readability-identifier-naming
|
||||
- readability-identifier-naming # Allow ROM-specific naming
|
||||
- readability-function-cognitive-complexity
|
||||
- readability-function-size
|
||||
- readability-uppercase-literal-suffix
|
||||
# Disable checks that conflict with ROM data structures
|
||||
- modernize-use-auto # ROM hacking needs explicit types
|
||||
- modernize-avoid-c-arrays # ROM data often uses C arrays
|
||||
- bugprone-easily-swappable-parameters
|
||||
- bugprone-exception-escape
|
||||
- bugprone-narrowing-conversions # ROM data often requires narrowing
|
||||
- bugprone-implicit-widening-of-multiplication-result
|
||||
- misc-no-recursion
|
||||
- misc-non-private-member-variables-in-classes
|
||||
- misc-const-correctness
|
||||
|
||||
Completion:
|
||||
AllScopes: Yes
|
||||
|
||||
SemanticTokens:
|
||||
DisabledKinds: []
|
||||
DisabledModifiers: []
|
||||
|
||||
126
.githooks/pre-commit
Executable file
126
.githooks/pre-commit
Executable file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
# Pre-commit Hook - Quick symbol conflict detection
|
||||
#
|
||||
# This hook runs on staged changes and warns if duplicate symbol definitions
|
||||
# are detected in affected object files.
|
||||
#
|
||||
# Bypass with: git commit --no-verify
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${BLUE}[Pre-Commit]${NC} Checking for symbol conflicts..."
|
||||
|
||||
# Get the repository root
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||
SCRIPTS_DIR="${REPO_ROOT}/scripts"
|
||||
BUILD_DIR="${REPO_ROOT}/build"
|
||||
|
||||
# Check if build directory exists
|
||||
if [[ ! -d "${BUILD_DIR}" ]]; then
|
||||
echo -e "${YELLOW}[Pre-Commit]${NC} Build directory not found - skipping symbol check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get list of changed .cc and .h files
|
||||
CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(cc|h)$' || echo "")
|
||||
|
||||
if [[ -z "${CHANGED_FILES}" ]]; then
|
||||
echo -e "${YELLOW}[Pre-Commit]${NC} No C++ source changes detected"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${CYAN}Changed files:${NC}"
|
||||
echo "${CHANGED_FILES}" | sed 's/^/ /'
|
||||
echo ""
|
||||
|
||||
# Quick symbol database check (only on changed files)
|
||||
# Find object files that might be affected by the changes
|
||||
AFFECTED_OBJ_FILES=""
|
||||
for file in ${CHANGED_FILES}; do
|
||||
# Convert source file path to likely object file names
|
||||
# e.g., src/cli/flags.cc -> *flags.cc.o
|
||||
filename=$(basename "${file}" | sed 's/\.[ch]$//')
|
||||
|
||||
# Find matching object files in build directory
|
||||
matching=$(find "${BUILD_DIR}" -name "*${filename}*.o" -o -name "*${filename}*.obj" 2>/dev/null | head -5)
|
||||
if [[ -n "${matching}" ]]; then
|
||||
AFFECTED_OBJ_FILES+=$'\n'"${matching}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "${AFFECTED_OBJ_FILES}" ]]; then
|
||||
echo -e "${YELLOW}[Pre-Commit]${NC} No compiled objects found for changed files (might not be built yet)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${CYAN}Affected object files:${NC}"
|
||||
echo "${AFFECTED_OBJ_FILES}" | grep -v '^$' | sed 's/^/ /' || echo " (none found)"
|
||||
echo ""
|
||||
|
||||
# Extract symbols from affected files
|
||||
echo -e "${CYAN}Analyzing symbols...${NC}"
|
||||
|
||||
TEMP_SYMBOLS="/tmp/yaze_precommit_symbols_$$.txt"
|
||||
trap "rm -f ${TEMP_SYMBOLS}" EXIT
|
||||
|
||||
: > "${TEMP_SYMBOLS}"
|
||||
|
||||
# Platform detection
|
||||
UNAME_S=$(uname -s)
|
||||
SYMBOL_CONFLICTS=0
|
||||
|
||||
while IFS= read -r obj_file; do
|
||||
[[ -z "${obj_file}" ]] && continue
|
||||
[[ ! -f "${obj_file}" ]] && continue
|
||||
|
||||
# Extract symbols using nm (Unix/macOS)
|
||||
if [[ "${UNAME_S}" == "Darwin"* ]] || [[ "${UNAME_S}" == "Linux"* ]]; then
|
||||
nm -P "${obj_file}" 2>/dev/null | while read -r sym rest; do
|
||||
[[ -z "${sym}" ]] && continue
|
||||
# Skip undefined symbols (contain 'U')
|
||||
[[ "${rest}" == *"U"* ]] && continue
|
||||
echo "${sym}|${obj_file##*/}"
|
||||
done >> "${TEMP_SYMBOLS}" || true
|
||||
fi
|
||||
done < <(echo "${AFFECTED_OBJ_FILES}" | grep -v '^$')
|
||||
|
||||
# Check for duplicates
|
||||
if [[ -f "${TEMP_SYMBOLS}" ]]; then
|
||||
SYMBOL_CONFLICTS=$(cut -d'|' -f1 "${TEMP_SYMBOLS}" | sort | uniq -d | wc -l)
|
||||
fi
|
||||
|
||||
# Report results
|
||||
if [[ ${SYMBOL_CONFLICTS} -gt 0 ]]; then
|
||||
echo -e "${RED}WARNING: Symbol conflicts detected!${NC}\n"
|
||||
echo "Duplicate symbols in affected files:"
|
||||
|
||||
cut -d'|' -f1 "${TEMP_SYMBOLS}" | sort | uniq -d | while read -r symbol; do
|
||||
echo -e " ${CYAN}${symbol}${NC}"
|
||||
grep "^${symbol}|" "${TEMP_SYMBOLS}" | cut -d'|' -f2 | sort | uniq | sed 's/^/ - /'
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}You can:${NC}"
|
||||
echo " 1. Fix the conflicts before committing"
|
||||
echo " 2. Skip this check: git commit --no-verify"
|
||||
echo " 3. Run full analysis: ./scripts/extract-symbols.sh && ./scripts/check-duplicate-symbols.sh"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Common fixes:${NC}"
|
||||
echo " - Add 'static' keyword to make it internal linkage"
|
||||
echo " - Use anonymous namespace in .cc files"
|
||||
echo " - Use 'inline' keyword for function/variable definitions"
|
||||
echo ""
|
||||
|
||||
exit 1
|
||||
else
|
||||
echo -e "${GREEN}No symbol conflicts in changed files${NC}"
|
||||
exit 0
|
||||
fi
|
||||
84
.github/actions/README.md
vendored
Normal file
84
.github/actions/README.md
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
# GitHub Actions - Composite Actions
|
||||
|
||||
This directory contains reusable composite actions for the YAZE CI/CD pipeline.
|
||||
|
||||
## Available Actions
|
||||
|
||||
### 1. `setup-build`
|
||||
Sets up the build environment with dependencies and caching.
|
||||
|
||||
**Inputs:**
|
||||
- `platform` (required): Target platform (linux, macos, windows)
|
||||
- `preset` (required): CMake preset to use
|
||||
- `cache-key` (optional): Cache key for dependencies
|
||||
|
||||
**What it does:**
|
||||
- Configures CPM cache
|
||||
- Installs platform-specific build dependencies
|
||||
- Sets up sccache/ccache for faster builds
|
||||
|
||||
### 2. `build-project`
|
||||
Builds the project with CMake and caching.
|
||||
|
||||
**Inputs:**
|
||||
- `platform` (required): Target platform (linux, macos, windows)
|
||||
- `preset` (required): CMake preset to use
|
||||
- `build-type` (optional): Build type (Debug, Release, RelWithDebInfo)
|
||||
|
||||
**What it does:**
|
||||
- Caches build artifacts
|
||||
- Configures the project with CMake
|
||||
- Builds the project with optimal parallel settings
|
||||
- Shows build artifacts for verification
|
||||
|
||||
### 3. `run-tests`
|
||||
Runs the test suite with appropriate filtering.
|
||||
|
||||
**Inputs:**
|
||||
- `test-type` (required): Type of tests to run (stable, unit, integration, all)
|
||||
- `preset` (optional): CMake preset to use (default: ci)
|
||||
|
||||
**What it does:**
|
||||
- Runs the specified test suite(s)
|
||||
- Generates JUnit XML test results
|
||||
- Uploads test results as artifacts
|
||||
|
||||
## Usage
|
||||
|
||||
These composite actions are used in the main CI workflow (`.github/workflows/ci.yml`). They must be called after checking out the repository:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: linux
|
||||
preset: ci
|
||||
cache-key: ${{ hashFiles('cmake/dependencies.lock') }}
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **Repository checkout required**: The repository must be checked out before calling any of these composite actions. They do not include a checkout step themselves.
|
||||
|
||||
2. **Platform-specific behavior**: Each action adapts to the target platform (Linux, macOS, Windows) and runs appropriate commands for that environment.
|
||||
|
||||
3. **Caching**: The actions use GitHub Actions caching to speed up builds by caching:
|
||||
- CPM dependencies (~/.cpm-cache)
|
||||
- Build artifacts (build/)
|
||||
- Compiler cache (sccache/ccache)
|
||||
|
||||
4. **Dependencies**: The Linux CI packages are listed in `.github/workflows/scripts/linux-ci-packages.txt`.
|
||||
|
||||
## Maintenance
|
||||
|
||||
When updating these actions:
|
||||
- Test on all three platforms (Linux, macOS, Windows)
|
||||
- Ensure shell compatibility (bash for Linux/macOS, pwsh for Windows)
|
||||
- Update this README if inputs or behavior changes
|
||||
|
||||
58
.github/actions/build-project/action.yml
vendored
Normal file
58
.github/actions/build-project/action.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: 'Build Project'
|
||||
description: 'Build the project with CMake and caching'
|
||||
inputs:
|
||||
platform:
|
||||
description: 'Target platform (linux, macos, windows)'
|
||||
required: true
|
||||
preset:
|
||||
description: 'CMake preset to use'
|
||||
required: true
|
||||
build-type:
|
||||
description: 'Build type (Debug, Release, RelWithDebInfo)'
|
||||
required: false
|
||||
default: 'RelWithDebInfo'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Cache build artifacts
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: build
|
||||
key: build-${{ inputs.platform }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
build-${{ inputs.platform }}-
|
||||
|
||||
- name: Configure project
|
||||
shell: bash
|
||||
run: |
|
||||
cmake --preset "${{ inputs.preset }}"
|
||||
|
||||
- name: Build project (Linux/macOS)
|
||||
if: inputs.platform != 'windows'
|
||||
shell: bash
|
||||
run: |
|
||||
if command -v nproc >/dev/null 2>&1; then
|
||||
CORES=$(nproc)
|
||||
elif command -v sysctl >/dev/null 2>&1; then
|
||||
CORES=$(sysctl -n hw.ncpu)
|
||||
else
|
||||
CORES=2
|
||||
fi
|
||||
echo "Using $CORES parallel jobs"
|
||||
cmake --build build --config "${{ inputs.build-type }}" --parallel "$CORES"
|
||||
|
||||
- name: Build project (Windows)
|
||||
if: inputs.platform == 'windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$JOBS = ${env:CMAKE_BUILD_PARALLEL_LEVEL:-4}
|
||||
echo "Using $JOBS parallel jobs"
|
||||
cmake --build build --config "${{ inputs.build-type }}" --parallel "$JOBS"
|
||||
|
||||
- name: Show build artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Build artifacts:"
|
||||
find build -name "*.exe" -o -name "yaze" -o -name "*.app" | head -10
|
||||
|
||||
61
.github/actions/run-tests/action.yml
vendored
Normal file
61
.github/actions/run-tests/action.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: 'Run Tests'
|
||||
description: 'Run test suite with appropriate filtering'
|
||||
inputs:
|
||||
test-type:
|
||||
description: 'Type of tests to run (stable, unit, integration, all)'
|
||||
required: true
|
||||
preset:
|
||||
description: 'CMake preset to use (for reference, tests use minimal preset)'
|
||||
required: false
|
||||
default: 'minimal'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Select test preset suffix
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ inputs.preset }}" = "ci-windows-ai" ]; then
|
||||
echo "CTEST_SUFFIX=-ai" >> $GITHUB_ENV
|
||||
else
|
||||
echo "CTEST_SUFFIX=" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Run stable tests
|
||||
if: inputs.test-type == 'stable' || inputs.test-type == 'all'
|
||||
shell: bash
|
||||
run: |
|
||||
cd build
|
||||
ctest --preset stable${CTEST_SUFFIX} \
|
||||
--output-on-failure \
|
||||
--timeout 300 \
|
||||
--output-junit stable_test_results.xml || true
|
||||
|
||||
- name: Run unit tests
|
||||
if: inputs.test-type == 'unit' || inputs.test-type == 'all'
|
||||
shell: bash
|
||||
run: |
|
||||
cd build
|
||||
ctest --preset unit${CTEST_SUFFIX} \
|
||||
--output-on-failure \
|
||||
--timeout 300 \
|
||||
--output-junit unit_test_results.xml || true
|
||||
|
||||
- name: Run integration tests
|
||||
if: inputs.test-type == 'integration' || inputs.test-type == 'all'
|
||||
shell: bash
|
||||
run: |
|
||||
cd build
|
||||
ctest --preset integration${CTEST_SUFFIX} \
|
||||
--output-on-failure \
|
||||
--timeout 300 \
|
||||
--output-junit integration_test_results.xml || true
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-results-${{ inputs.test-type }}
|
||||
path: build/*test_results.xml
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
||||
83
.github/actions/setup-build/action.yml
vendored
Normal file
83
.github/actions/setup-build/action.yml
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
name: 'Setup Build Environment'
|
||||
description: 'Setup build environment with dependencies and caching'
|
||||
inputs:
|
||||
platform:
|
||||
description: 'Target platform (linux, macos, windows)'
|
||||
required: true
|
||||
preset:
|
||||
description: 'CMake preset to use'
|
||||
required: true
|
||||
cache-key:
|
||||
description: 'Cache key for dependencies'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup CPM cache
|
||||
if: inputs.cache-key != ''
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cpm-cache
|
||||
key: cpm-${{ inputs.platform }}-${{ inputs.cache-key }}
|
||||
restore-keys: |
|
||||
cpm-${{ inputs.platform }}-
|
||||
|
||||
- name: Setup build environment (Linux)
|
||||
if: inputs.platform == 'linux'
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y $(tr '\n' ' ' < .github/workflows/scripts/linux-ci-packages.txt) gcc-12 g++-12
|
||||
sudo apt-get clean
|
||||
|
||||
- name: Setup build environment (macOS)
|
||||
if: inputs.platform == 'macos'
|
||||
shell: bash
|
||||
run: |
|
||||
brew install ninja pkg-config ccache
|
||||
if ! command -v cmake &> /dev/null; then
|
||||
brew install cmake
|
||||
fi
|
||||
|
||||
- name: Setup build environment (Windows)
|
||||
if: inputs.platform == 'windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
choco install --no-progress -y nasm ccache
|
||||
if ($env:ChocolateyInstall) {
|
||||
$profilePath = Join-Path $env:ChocolateyInstall "helpers\chocolateyProfile.psm1"
|
||||
if (Test-Path $profilePath) {
|
||||
Import-Module $profilePath
|
||||
refreshenv
|
||||
}
|
||||
}
|
||||
# Ensure Git can handle long paths and cached directories when cloning gRPC dependencies
|
||||
git config --global core.longpaths true
|
||||
git config --global --add safe.directory '*'
|
||||
|
||||
- name: Setup sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ inputs.platform }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ inputs.platform }}-
|
||||
max-size: 500M
|
||||
variant: sccache
|
||||
|
||||
- name: Setup MSVC Dev Cmd (Windows)
|
||||
if: inputs.platform == 'windows'
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: Configure compiler for Windows
|
||||
if: inputs.platform == 'windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
echo "CC=clang-cl" >> $env:GITHUB_ENV
|
||||
echo "CXX=clang-cl" >> $env:GITHUB_ENV
|
||||
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $env:GITHUB_ENV
|
||||
echo "CMAKE_C_COMPILER_LAUNCHER=sccache" >> $env:GITHUB_ENV
|
||||
|
||||
84
.github/scripts/validate-actions.sh
vendored
Executable file
84
.github/scripts/validate-actions.sh
vendored
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# Validate GitHub Actions composite action structure
|
||||
|
||||
set -e
|
||||
|
||||
echo "Validating GitHub Actions composite actions..."
|
||||
|
||||
ACTIONS_DIR=".github/actions"
|
||||
REQUIRED_FIELDS=("name" "description" "runs")
|
||||
|
||||
validate_action() {
|
||||
local action_file="$1"
|
||||
local action_name=$(basename $(dirname "$action_file"))
|
||||
|
||||
echo "Checking $action_name..."
|
||||
|
||||
# Check if file exists
|
||||
if [ ! -f "$action_file" ]; then
|
||||
echo " ✗ action.yml not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check required fields
|
||||
for field in "${REQUIRED_FIELDS[@]}"; do
|
||||
if ! grep -q "^${field}:" "$action_file"; then
|
||||
echo " ✗ Missing required field: $field"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for 'using: composite'
|
||||
if ! grep -q "using: 'composite'" "$action_file"; then
|
||||
echo " ✗ Not marked as composite action"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo " ✓ Valid composite action"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Validate all actions
|
||||
all_valid=true
|
||||
for action_yml in "$ACTIONS_DIR"/*/action.yml; do
|
||||
if ! validate_action "$action_yml"; then
|
||||
all_valid=false
|
||||
fi
|
||||
done
|
||||
|
||||
# Check that CI workflow references actions correctly
|
||||
echo ""
|
||||
echo "Checking CI workflow..."
|
||||
CI_FILE=".github/workflows/ci.yml"
|
||||
|
||||
if [ ! -f "$CI_FILE" ]; then
|
||||
echo " ✗ CI workflow not found"
|
||||
all_valid=false
|
||||
else
|
||||
# Check for checkout before action usage
|
||||
if grep -q "uses: actions/checkout@v4" "$CI_FILE"; then
|
||||
echo " ✓ Repository checkout step present"
|
||||
else
|
||||
echo " ✗ Missing checkout step"
|
||||
all_valid=false
|
||||
fi
|
||||
|
||||
# Check for composite action references
|
||||
action_refs=$(grep -c "uses: ./.github/actions/" "$CI_FILE" || echo "0")
|
||||
if [ "$action_refs" -gt 0 ]; then
|
||||
echo " ✓ Found $action_refs composite action references"
|
||||
else
|
||||
echo " ✗ No composite action references found"
|
||||
all_valid=false
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ "$all_valid" = true ]; then
|
||||
echo "✓ All validations passed!"
|
||||
exit 0
|
||||
else
|
||||
echo "✗ Some validations failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
783
.github/workflows/ci.yml
vendored
783
.github/workflows/ci.yml
vendored
@@ -1,5 +1,19 @@
|
||||
name: CI/CD Pipeline
|
||||
|
||||
# Test Strategy:
|
||||
# - PR/Push: Run lean test set (stable tests + smoke tests) for fast feedback
|
||||
# - Nightly: Run comprehensive suite including ROM-dependent, experimental, benchmarks
|
||||
# - See .github/workflows/nightly.yml for extended test coverage
|
||||
#
|
||||
# Test Labels:
|
||||
# - stable: Core functionality tests that should always pass
|
||||
# - unit: Fast isolated component tests (subset of stable)
|
||||
# - integration: Multi-component tests (subset of stable)
|
||||
# - rom_dependent: Tests requiring Zelda3 ROM file (nightly only)
|
||||
# - experimental: AI and experimental feature tests (nightly only)
|
||||
# - gui: GUI/E2E tests with ImGuiTestEngine (nightly only)
|
||||
# - benchmark: Performance benchmarks (nightly only)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", "develop" ]
|
||||
@@ -38,13 +52,18 @@ on:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
enable_http_api_tests:
|
||||
description: 'Enable HTTP API tests'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
BUILD_TYPE: ${{ github.event.inputs.build_type || 'RelWithDebInfo' }}
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: "${{ matrix.name }}"
|
||||
build:
|
||||
name: "Build - ${{ matrix.name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -52,513 +71,39 @@ jobs:
|
||||
include:
|
||||
- name: "Ubuntu 22.04 (GCC-12)"
|
||||
os: ubuntu-22.04
|
||||
cc: gcc-12
|
||||
cxx: g++-12
|
||||
platform: linux
|
||||
preset: ci-linux
|
||||
- name: "macOS 14 (Clang)"
|
||||
os: macos-14
|
||||
cc: clang
|
||||
cxx: clang++
|
||||
- name: "Windows 2022 (Clang-CL)"
|
||||
platform: macos
|
||||
preset: ci-macos
|
||||
- name: "Windows 2022 (Core)"
|
||||
os: windows-2022
|
||||
cc: clang-cl
|
||||
cxx: clang-cl
|
||||
- name: "Windows 2022 (MSVC)"
|
||||
os: windows-2022
|
||||
cc: cl
|
||||
cxx: cl
|
||||
platform: windows
|
||||
preset: ci-windows
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up vcpkg (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: vcpkg
|
||||
continue-on-error: true
|
||||
env:
|
||||
VCPKG_DEFAULT_TRIPLET: x64-windows-static
|
||||
VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite'
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
vcpkgDirectory: '${{ github.workspace }}/vcpkg'
|
||||
vcpkgGitCommitId: 'b2c74683ecfd6a8e7d27ffb0df077f66a9339509' # 2025.01.20 release
|
||||
runVcpkgInstall: true # Pre-install SDL2, yaml-cpp (fast packages only)
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
cache-key: ${{ github.sha }}
|
||||
|
||||
- name: Retry vcpkg setup (Windows)
|
||||
if: runner.os == 'Windows' && steps.vcpkg.outcome == 'failure'
|
||||
uses: lukka/run-vcpkg@v11
|
||||
id: vcpkg_retry
|
||||
env:
|
||||
VCPKG_DEFAULT_TRIPLET: x64-windows-static
|
||||
VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite'
|
||||
- name: Build project
|
||||
uses: ./.github/actions/build-project
|
||||
with:
|
||||
vcpkgDirectory: '${{ github.workspace }}/vcpkg'
|
||||
vcpkgGitCommitId: 'b2c74683ecfd6a8e7d27ffb0df077f66a9339509'
|
||||
runVcpkgInstall: true
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
build-type: ${{ env.BUILD_TYPE }}
|
||||
|
||||
- name: Resolve vcpkg toolchain (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
# Try to get vcpkg root from either initial setup or retry
|
||||
$vcpkgRoot = "${{ steps.vcpkg.outputs.vcpkgRoot }}"
|
||||
if (-not $vcpkgRoot) {
|
||||
$vcpkgRoot = "${{ steps.vcpkg_retry.outputs.vcpkgRoot }}"
|
||||
}
|
||||
if (-not $vcpkgRoot) {
|
||||
$vcpkgRoot = Join-Path "${{ github.workspace }}" "vcpkg"
|
||||
}
|
||||
|
||||
Write-Host "Checking vcpkg root: $vcpkgRoot"
|
||||
if (-not (Test-Path $vcpkgRoot)) {
|
||||
Write-Host "::error::vcpkg root not found at $vcpkgRoot"
|
||||
Write-Host "vcpkg setup status: ${{ steps.vcpkg.outcome }}"
|
||||
Write-Host "vcpkg retry status: ${{ steps.vcpkg_retry.outcome }}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$toolchain = Join-Path $vcpkgRoot "scripts/buildsystems/vcpkg.cmake"
|
||||
if (-not (Test-Path $toolchain)) {
|
||||
Write-Host "::error::vcpkg toolchain file missing at $toolchain"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$normalizedRoot = $vcpkgRoot -replace '\\', '/'
|
||||
$normalizedToolchain = $toolchain -replace '\\', '/'
|
||||
|
||||
Write-Host "✓ vcpkg root: $normalizedRoot"
|
||||
Write-Host "✓ Toolchain: $normalizedToolchain"
|
||||
|
||||
"VCPKG_ROOT=$normalizedRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
"CMAKE_TOOLCHAIN_FILE=$normalizedToolchain" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
|
||||
- name: Install Windows build tools
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
choco install --no-progress -y nasm ccache
|
||||
if ($env:ChocolateyInstall) {
|
||||
$profilePath = Join-Path $env:ChocolateyInstall "helpers\chocolateyProfile.psm1"
|
||||
if (Test-Path $profilePath) {
|
||||
Import-Module $profilePath
|
||||
refreshenv
|
||||
}
|
||||
}
|
||||
if (Test-Path "C:\Program Files\NASM") {
|
||||
"C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
}
|
||||
|
||||
- name: Ensure MSVC Dev Cmd (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: Diagnose vcpkg (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "=== vcpkg Diagnostics ===" -ForegroundColor Cyan
|
||||
Write-Host "Initial setup: ${{ steps.vcpkg.outcome }}"
|
||||
Write-Host "Retry setup: ${{ steps.vcpkg_retry.outcome }}"
|
||||
Write-Host "vcpkg directory: ${{ github.workspace }}/vcpkg"
|
||||
|
||||
if (Test-Path "${{ github.workspace }}/vcpkg/vcpkg.exe") {
|
||||
Write-Host "✅ vcpkg.exe found" -ForegroundColor Green
|
||||
& "${{ github.workspace }}/vcpkg/vcpkg.exe" version
|
||||
Write-Host "`nvcpkg installed packages:" -ForegroundColor Cyan
|
||||
& "${{ github.workspace }}/vcpkg/vcpkg.exe" list | Select-Object -First 20
|
||||
} else {
|
||||
Write-Host "❌ vcpkg.exe not found" -ForegroundColor Red
|
||||
}
|
||||
|
||||
Write-Host "`nEnvironment:" -ForegroundColor Cyan
|
||||
Write-Host "CMAKE_TOOLCHAIN_FILE: $env:CMAKE_TOOLCHAIN_FILE"
|
||||
Write-Host "VCPKG_DEFAULT_TRIPLET: $env:VCPKG_DEFAULT_TRIPLET"
|
||||
Write-Host "VCPKG_ROOT: $env:VCPKG_ROOT"
|
||||
Write-Host "Workspace: ${{ github.workspace }}"
|
||||
|
||||
Write-Host "`nManifest files:" -ForegroundColor Cyan
|
||||
if (Test-Path "vcpkg.json") {
|
||||
Write-Host "✅ vcpkg.json found"
|
||||
Get-Content "vcpkg.json" | Write-Host
|
||||
}
|
||||
if (Test-Path "vcpkg-configuration.json") {
|
||||
Write-Host "✅ vcpkg-configuration.json found"
|
||||
}
|
||||
|
||||
- name: Setup sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.cc }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ matrix.cc }}-
|
||||
max-size: 500M
|
||||
variant: sccache
|
||||
|
||||
- name: Configure sccache for clang-cl
|
||||
if: runner.os == 'Windows' && matrix.cc == 'clang-cl'
|
||||
shell: pwsh
|
||||
run: |
|
||||
echo "CC=sccache clang-cl" >> $env:GITHUB_ENV
|
||||
echo "CXX=sccache clang-cl" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Restore vcpkg packages cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
build/vcpkg_installed
|
||||
${{ github.workspace }}/vcpkg/packages
|
||||
${{ github.workspace }}/vcpkg/buildtrees
|
||||
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
|
||||
restore-keys: |
|
||||
vcpkg-${{ runner.os }}-
|
||||
|
||||
- name: Restore FetchContent dependencies (gRPC)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
build/_deps
|
||||
key: fetchcontent-${{ runner.os }}-${{ matrix.cc }}-${{ hashFiles('cmake/grpc*.cmake') }}-v2
|
||||
restore-keys: |
|
||||
fetchcontent-${{ runner.os }}-${{ matrix.cc }}-
|
||||
|
||||
- name: Monitor build progress (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "=== Pre-Build Status ===" -ForegroundColor Cyan
|
||||
|
||||
# Check if gRPC is cached
|
||||
if (Test-Path "build/_deps/grpc-subbuild") {
|
||||
Write-Host "✅ gRPC FetchContent cache found" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "⚠️ gRPC will be built from source (~10-15 min first time)" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Check vcpkg packages
|
||||
if (Test-Path "build/vcpkg_installed") {
|
||||
Write-Host "✅ vcpkg packages cache found" -ForegroundColor Green
|
||||
if (Test-Path "${{ github.workspace }}/vcpkg/vcpkg.exe") {
|
||||
& "${{ github.workspace }}/vcpkg/vcpkg.exe" list
|
||||
}
|
||||
} else {
|
||||
Write-Host "⚠️ vcpkg packages will be installed (~2-3 min)" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
- name: Install Dependencies (Unix)
|
||||
id: deps
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if [[ "${{ runner.os }}" == "Linux" ]]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential ninja-build pkg-config ccache \
|
||||
libglew-dev libxext-dev libwavpack-dev libboost-all-dev \
|
||||
libpng-dev python3-dev libpython3-dev \
|
||||
libasound2-dev libpulse-dev libaudio-dev \
|
||||
libx11-dev libxrandr-dev libxcursor-dev libxinerama-dev libxi-dev \
|
||||
libxss-dev libxxf86vm-dev libxkbcommon-dev libwayland-dev libdecor-0-dev \
|
||||
libgtk-3-dev libdbus-1-dev \
|
||||
${{ matrix.cc }} ${{ matrix.cxx }}
|
||||
# Note: libabsl-dev removed - gRPC uses bundled Abseil via FetchContent when enabled
|
||||
elif [[ "${{ runner.os }}" == "macOS" ]]; then
|
||||
brew install ninja pkg-config ccache
|
||||
fi
|
||||
|
||||
- name: Retry Dependencies (Unix)
|
||||
if: steps.deps.outcome == 'failure'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::warning::First dependency install failed, retrying..."
|
||||
if [[ "${{ runner.os }}" == "Linux" ]]; then
|
||||
sudo apt-get clean
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get install -y \
|
||||
build-essential ninja-build pkg-config ccache \
|
||||
libglew-dev libxext-dev libwavpack-dev libboost-all-dev \
|
||||
libpng-dev python3-dev libpython3-dev \
|
||||
libasound2-dev libpulse-dev libaudio-dev \
|
||||
libx11-dev libxrandr-dev libxcursor-dev libxinerama-dev libxi-dev \
|
||||
libxss-dev libxxf86vm-dev libxkbcommon-dev libwayland-dev libdecor-0-dev \
|
||||
libgtk-3-dev libdbus-1-dev \
|
||||
${{ matrix.cc }} ${{ matrix.cxx }}
|
||||
elif [[ "${{ runner.os }}" == "macOS" ]]; then
|
||||
brew update
|
||||
brew install ninja pkg-config ccache
|
||||
fi
|
||||
|
||||
- name: Free Disk Space (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "=== Freeing Disk Space ==="
|
||||
df -h
|
||||
echo ""
|
||||
echo "Removing unnecessary software..."
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo apt-get clean
|
||||
echo ""
|
||||
echo "Disk space after cleanup:"
|
||||
df -h
|
||||
|
||||
- name: Pre-configure Diagnostics (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "=== Pre-configure Diagnostics ===" -ForegroundColor Cyan
|
||||
Write-Host "Build Type: ${{ env.BUILD_TYPE }}"
|
||||
Write-Host "Workspace: ${{ github.workspace }}"
|
||||
|
||||
# Check Visual Studio installation
|
||||
$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
if (Test-Path $vsWhere) {
|
||||
Write-Host "`nVisual Studio Installation:" -ForegroundColor Cyan
|
||||
& $vsWhere -latest -property displayName
|
||||
& $vsWhere -latest -property installationVersion
|
||||
}
|
||||
|
||||
# Check CMake
|
||||
Write-Host "`nCMake Version:" -ForegroundColor Cyan
|
||||
cmake --version
|
||||
|
||||
# Verify vcpkg toolchain
|
||||
$toolchain = "${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake"
|
||||
if (Test-Path $toolchain) {
|
||||
Write-Host "✅ vcpkg toolchain found at: $toolchain" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "⚠️ vcpkg toolchain not found at: $toolchain" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Show vcpkg manifest
|
||||
if (Test-Path "vcpkg.json") {
|
||||
Write-Host "`nvcpkg.json contents:" -ForegroundColor Cyan
|
||||
Get-Content "vcpkg.json" | Write-Host
|
||||
}
|
||||
|
||||
# Show available disk space
|
||||
Write-Host "`nDisk Space:" -ForegroundColor Cyan
|
||||
Get-PSDrive C | Select-Object Used,Free | Format-Table -AutoSize
|
||||
|
||||
- name: Configure (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
id: configure_windows
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "::group::CMake Configuration (Windows)" -ForegroundColor Cyan
|
||||
if (Get-Command ccache -ErrorAction SilentlyContinue) {
|
||||
$env:CCACHE_BASEDIR = "${{ github.workspace }}"
|
||||
$env:CCACHE_DIR = Join-Path $env:USERPROFILE ".ccache"
|
||||
ccache --zero-stats
|
||||
}
|
||||
|
||||
$toolchain = "${env:CMAKE_TOOLCHAIN_FILE}"
|
||||
if (-not $toolchain -or -not (Test-Path $toolchain)) {
|
||||
Write-Host "::error::CMAKE_TOOLCHAIN_FILE is missing or invalid: '$toolchain'"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$cmakeArgs = @(
|
||||
"-S", ".",
|
||||
"-B", "build",
|
||||
"-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}",
|
||||
"-DCMAKE_TOOLCHAIN_FILE=$toolchain",
|
||||
"-DVCPKG_TARGET_TRIPLET=x64-windows-static",
|
||||
"-DVCPKG_MANIFEST_MODE=ON",
|
||||
"-DYAZE_BUILD_TESTS=ON",
|
||||
"-DYAZE_BUILD_EMU=ON",
|
||||
"-DYAZE_BUILD_Z3ED=ON",
|
||||
"-DYAZE_BUILD_TOOLS=ON",
|
||||
"-DYAZE_ENABLE_ROM_TESTS=OFF"
|
||||
)
|
||||
|
||||
cmake @cmakeArgs 2>&1 | Tee-Object -FilePath cmake_config.log
|
||||
$exit = $LASTEXITCODE
|
||||
Write-Host "::endgroup::"
|
||||
|
||||
if ($exit -ne 0) {
|
||||
exit $exit
|
||||
}
|
||||
|
||||
if (Get-Command ccache -ErrorAction SilentlyContinue) {
|
||||
ccache --show-stats
|
||||
}
|
||||
|
||||
- name: Configure (Unix)
|
||||
if: runner.os != 'Windows'
|
||||
id: configure_unix
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
echo "::group::CMake Configuration"
|
||||
if command -v ccache >/dev/null 2>&1; then
|
||||
export CCACHE_BASEDIR=${GITHUB_WORKSPACE}
|
||||
export CCACHE_DIR=${HOME}/.ccache
|
||||
ccache --zero-stats
|
||||
fi
|
||||
if [[ "${{ runner.os }}" == "Linux" ]]; then
|
||||
# Linux: Use portal backend for file dialogs (more reliable in CI)
|
||||
cmake -B build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_C_COMPILER=${{ matrix.cc }} \
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \
|
||||
-DYAZE_BUILD_TESTS=ON \
|
||||
-DYAZE_BUILD_EMU=ON \
|
||||
-DYAZE_ENABLE_ROM_TESTS=OFF \
|
||||
-DYAZE_BUILD_Z3ED=ON \
|
||||
-DYAZE_BUILD_TOOLS=ON \
|
||||
-DNFD_PORTAL=ON 2>&1 | tee cmake_config.log
|
||||
else
|
||||
# macOS: Use default GTK backend
|
||||
cmake -B build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_C_COMPILER=${{ matrix.cc }} \
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \
|
||||
-DYAZE_BUILD_TESTS=ON \
|
||||
-DYAZE_BUILD_EMU=ON \
|
||||
-DYAZE_ENABLE_ROM_TESTS=OFF \
|
||||
-DYAZE_BUILD_Z3ED=ON \
|
||||
-DYAZE_BUILD_TOOLS=ON 2>&1 | tee cmake_config.log
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
if command -v ccache >/dev/null 2>&1; then
|
||||
ccache --show-stats
|
||||
fi
|
||||
# Note: Full-featured build to match release configuration
|
||||
# Note: YAZE_BUILD_EMU=OFF disables standalone emulator executable
|
||||
# but yaze_emulator library is still built for main app/tests
|
||||
# Note: NFD_PORTAL=ON uses D-Bus portal instead of GTK on Linux (more reliable in CI)
|
||||
|
||||
- name: Report Configure Failure
|
||||
if: always() && (steps.configure_windows.outcome == 'failure' || steps.configure_unix.outcome == 'failure')
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::error::CMake configuration failed. Check cmake_config.log for details."
|
||||
if [ -f cmake_config.log ]; then
|
||||
echo "::group::CMake Configuration Log (last 50 lines)"
|
||||
tail -50 cmake_config.log
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
if [ -f build/CMakeFiles/CMakeError.log ]; then
|
||||
echo "::group::CMake Error Log"
|
||||
cat build/CMakeFiles/CMakeError.log
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
shell: bash
|
||||
run: |
|
||||
BUILD_TYPE=${BUILD_TYPE:-${{ env.BUILD_TYPE }}}
|
||||
echo "Building with ${BUILD_TYPE} configuration..."
|
||||
if [[ "${{ runner.os }}" == "Windows" ]]; then
|
||||
JOBS=${CMAKE_BUILD_PARALLEL_LEVEL:-4}
|
||||
echo "Using $JOBS parallel jobs"
|
||||
cmake --build build --config "${BUILD_TYPE}" --parallel "${JOBS}" 2>&1 | tee build.log
|
||||
else
|
||||
# Determine number of parallel jobs based on platform
|
||||
if command -v nproc >/dev/null 2>&1; then
|
||||
CORES=$(nproc)
|
||||
elif command -v sysctl >/dev/null 2>&1; then
|
||||
CORES=$(sysctl -n hw.ncpu)
|
||||
else
|
||||
CORES=2
|
||||
fi
|
||||
echo "Using $CORES parallel jobs"
|
||||
cmake --build build --parallel $CORES 2>&1 | tee build.log
|
||||
fi
|
||||
if command -v ccache >/dev/null 2>&1; then
|
||||
ccache --show-stats
|
||||
fi
|
||||
|
||||
- name: Report Build Failure
|
||||
if: always() && steps.build.outcome == 'failure'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::error::Build failed. Check build.log for details."
|
||||
if [ -f build.log ]; then
|
||||
echo "::group::Build Log (last 100 lines)"
|
||||
tail -100 build.log
|
||||
echo "::endgroup::"
|
||||
|
||||
# Extract and highlight actual errors
|
||||
echo "::group::Build Errors"
|
||||
grep -i "error" build.log | head -20 || true
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
- name: Windows Build Diagnostics
|
||||
if: always() && runner.os == 'Windows' && steps.build.outcome == 'failure'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "=== Windows Build Diagnostics ===" -ForegroundColor Red
|
||||
|
||||
# Check for vcpkg-related errors
|
||||
if (Select-String -Path "build.log" -Pattern "vcpkg" -Quiet) {
|
||||
Write-Host "`nvcpkg-related errors found:" -ForegroundColor Yellow
|
||||
Select-String -Path "build.log" -Pattern "vcpkg.*error" -CaseSensitive:$false | Select-Object -First 10
|
||||
}
|
||||
|
||||
# Check for linker errors
|
||||
if (Select-String -Path "build.log" -Pattern "LNK[0-9]{4}" -Quiet) {
|
||||
Write-Host "`nLinker errors found:" -ForegroundColor Yellow
|
||||
Select-String -Path "build.log" -Pattern "LNK[0-9]{4}" | Select-Object -First 10
|
||||
}
|
||||
|
||||
# Check for missing dependencies
|
||||
if (Select-String -Path "build.log" -Pattern "fatal error.*No such file" -Quiet) {
|
||||
Write-Host "`nMissing file errors found:" -ForegroundColor Yellow
|
||||
Select-String -Path "build.log" -Pattern "fatal error.*No such file" | Select-Object -First 10
|
||||
}
|
||||
|
||||
# List vcpkg installed packages if available
|
||||
$vcpkgExe = "${{ github.workspace }}/vcpkg/vcpkg.exe"
|
||||
if (Test-Path $vcpkgExe) {
|
||||
Write-Host "`nInstalled vcpkg packages:" -ForegroundColor Cyan
|
||||
& $vcpkgExe list
|
||||
}
|
||||
|
||||
- name: Post-Build Diagnostics (Windows)
|
||||
if: always() && runner.os == 'Windows' && steps.build.outcome == 'success'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "=== Post-Build Diagnostics ===" -ForegroundColor Green
|
||||
|
||||
$binCandidates = @("build/bin", "build/bin/${{ env.BUILD_TYPE }}")
|
||||
$found = $false
|
||||
foreach ($candidate in $binCandidates) {
|
||||
if (-not (Test-Path $candidate)) { continue }
|
||||
$found = $true
|
||||
Write-Host "`nArtifacts under $candidate:" -ForegroundColor Cyan
|
||||
Get-ChildItem -Path $candidate -Include *.exe,*.dll -Recurse | ForEach-Object {
|
||||
$size = [math]::Round($_.Length / 1MB, 2)
|
||||
Write-Host " $($_.FullName.Replace($PWD.Path + '\', '')) - ${size} MB"
|
||||
}
|
||||
}
|
||||
if (-not $found) {
|
||||
Write-Host "⚠️ Build output directories not found." -ForegroundColor Yellow
|
||||
} else {
|
||||
$yazeExe = Get-ChildItem -Path build -Filter yaze.exe -Recurse | Select-Object -First 1
|
||||
if ($yazeExe) {
|
||||
Write-Host "`n✅ yaze.exe located at $($yazeExe.FullName)" -ForegroundColor Green
|
||||
$yazeSize = [math]::Round($yazeExe.Length / 1MB, 2)
|
||||
Write-Host " Size: ${yazeSize} MB"
|
||||
} else {
|
||||
Write-Host "`n⚠️ yaze.exe not found in build output" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
- name: Upload Build Artifacts (Windows)
|
||||
if: |
|
||||
runner.os == 'Windows' &&
|
||||
steps.build.outcome == 'success' &&
|
||||
(github.event.inputs.upload_artifacts == 'true' || github.event_name == 'push')
|
||||
- name: Upload build artifacts (Windows)
|
||||
if: matrix.platform == 'windows' && (github.event.inputs.upload_artifacts == 'true' || github.event_name == 'push')
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: yaze-windows-ci-${{ github.run_number }}
|
||||
@@ -570,135 +115,126 @@ jobs:
|
||||
if-no-files-found: warn
|
||||
retention-days: 3
|
||||
|
||||
- name: Test (Stable)
|
||||
id: test_stable
|
||||
working-directory: build
|
||||
shell: bash
|
||||
run: |
|
||||
BUILD_TYPE=${BUILD_TYPE:-${{ env.BUILD_TYPE }}}
|
||||
echo "Running stable test suite..."
|
||||
ctest --output-on-failure -C "$BUILD_TYPE" -j1 \
|
||||
-L "stable" \
|
||||
--output-junit stable_test_results.xml 2>&1 | tee ../stable_test.log || true
|
||||
test:
|
||||
name: "Test - ${{ matrix.name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "Ubuntu 22.04"
|
||||
os: ubuntu-22.04
|
||||
platform: linux
|
||||
preset: ci-linux
|
||||
- name: "macOS 14"
|
||||
os: macos-14
|
||||
platform: macos
|
||||
preset: ci-macos
|
||||
- name: "Windows 2022 (Core)"
|
||||
os: windows-2022
|
||||
platform: windows
|
||||
preset: ci-windows
|
||||
|
||||
- name: Test (Experimental - Informational)
|
||||
id: test_experimental
|
||||
working-directory: build
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
cache-key: ${{ github.sha }}
|
||||
|
||||
- name: Build project
|
||||
uses: ./.github/actions/build-project
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
build-type: ${{ env.BUILD_TYPE }}
|
||||
|
||||
- name: Run stable tests only
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
test-type: stable
|
||||
preset: ${{ matrix.preset }}
|
||||
|
||||
- name: Run smoke tests (GUI framework validation)
|
||||
if: matrix.platform == 'linux'
|
||||
run: |
|
||||
cd build
|
||||
# Run just the smoke tests to validate GUI framework is working
|
||||
./bin/yaze_test_gui -nogui --gtest_filter="*Smoke*" || true
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
BUILD_TYPE=${BUILD_TYPE:-${{ env.BUILD_TYPE }}}
|
||||
echo "Running experimental test suite (informational only)..."
|
||||
ctest --output-on-failure -C "$BUILD_TYPE" --parallel \
|
||||
-L "experimental" \
|
||||
--output-junit experimental_test_results.xml 2>&1 | tee ../experimental_test.log
|
||||
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: Run HTTP API tests
|
||||
if: github.event.inputs.enable_http_api_tests == 'true'
|
||||
run: scripts/agents/test-http-api.sh
|
||||
|
||||
windows-agent:
|
||||
name: "Windows Agent (Full Stack)"
|
||||
runs-on: windows-2022
|
||||
needs: [build, test]
|
||||
if: github.event_name != 'pull_request'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
name: test-results-${{ matrix.name }}
|
||||
path: |
|
||||
build/*test_results.xml
|
||||
stable_test.log
|
||||
experimental_test.log
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
submodules: recursive
|
||||
|
||||
- name: Upload Build Logs on Failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
name: build-logs-${{ matrix.name }}
|
||||
path: |
|
||||
cmake_config.log
|
||||
build.log
|
||||
build/CMakeFiles/CMakeError.log
|
||||
build/CMakeFiles/CMakeOutput.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
platform: windows
|
||||
preset: ci-windows-ai
|
||||
cache-key: ${{ github.sha }}
|
||||
|
||||
- name: Generate Job Summary
|
||||
if: always()
|
||||
shell: bash
|
||||
- name: Build project
|
||||
uses: ./.github/actions/build-project
|
||||
with:
|
||||
platform: windows
|
||||
preset: ci-windows-ai
|
||||
build-type: ${{ env.BUILD_TYPE }}
|
||||
|
||||
- name: Run stable tests only (agent stack)
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
test-type: stable
|
||||
preset: ci-windows-ai
|
||||
|
||||
wasm-smoke-test:
|
||||
name: "WASM Build Smoke Test"
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Emscripten
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: 3.1.51
|
||||
actions-cache-folder: 'emsdk-cache'
|
||||
|
||||
- name: Setup Ninja
|
||||
uses: seanmiddleditch/gha-setup-ninja@v4
|
||||
|
||||
- name: Quick WASM build test
|
||||
run: |
|
||||
echo "## Build Summary - ${{ matrix.name }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Workflow trigger info
|
||||
echo "### Workflow Information" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Trigger**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
echo "- **Manual Build Type**: ${{ github.event.inputs.build_type }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Upload Artifacts**: ${{ github.event.inputs.upload_artifacts }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Run Sanitizers**: ${{ github.event.inputs.run_sanitizers }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Configuration info
|
||||
echo "### Configuration" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Platform**: ${{ matrix.os }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Compiler**: ${{ matrix.cc }}/${{ matrix.cxx }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Build Type**: ${{ env.BUILD_TYPE }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Build Mode**: Full (matches release)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Features**: gRPC, JSON, AI, ImGui Test Engine" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ runner.os }}" == "Windows" ]]; then
|
||||
echo "- **vcpkg Triplet**: x64-windows-static" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ steps.vcpkg.outcome }}" != "" ]]; then
|
||||
echo "- **vcpkg Setup**: ${{ steps.vcpkg.outcome }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
fi
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Build status
|
||||
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
|
||||
CONFIGURE_OUTCOME="${{ steps.configure_windows.outcome || steps.configure_unix.outcome }}"
|
||||
if [[ "$CONFIGURE_OUTCOME" == "success" ]]; then
|
||||
echo "- ✅ Configure: Success" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "- ❌ Configure: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [[ "${{ steps.build.outcome }}" == "success" ]]; then
|
||||
echo "- ✅ Build: Success" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "- ❌ Build: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [[ "${{ steps.test_stable.outcome }}" == "success" ]]; then
|
||||
echo "- ✅ Stable Tests: Passed" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "- ❌ Stable Tests: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [[ "${{ steps.test_experimental.outcome }}" == "success" ]]; then
|
||||
echo "- ✅ Experimental Tests: Passed" >> $GITHUB_STEP_SUMMARY
|
||||
elif [[ "${{ steps.test_experimental.outcome }}" == "failure" ]]; then
|
||||
echo "- ⚠️ Experimental Tests: Failed (informational)" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "- ⏭️ Experimental Tests: Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Artifacts info
|
||||
if [[ "${{ runner.os }}" == "Windows" && "${{ steps.build.outcome }}" == "success" ]]; then
|
||||
if [[ "${{ github.event.inputs.upload_artifacts }}" == "true" || "${{ github.event_name }}" == "push" ]]; then
|
||||
echo "### Artifacts" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- 📦 Windows build artifacts uploaded: yaze-windows-ci-${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
fi
|
||||
|
||||
# Test results
|
||||
if [ -f build/stable_test_results.xml ]; then
|
||||
echo "### Test Results" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
grep -E "tests=|failures=|errors=" build/stable_test_results.xml | head -1 || echo "Test summary not available"
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
emcmake cmake --preset wasm-debug
|
||||
cmake --build build-wasm-debug --target yaze --parallel
|
||||
# Verify output exists
|
||||
test -f build-wasm-debug/bin/yaze.wasm
|
||||
echo "WASM build successful!"
|
||||
|
||||
code-quality:
|
||||
name: "✨ Code Quality"
|
||||
name: "Code Quality"
|
||||
runs-on: ubuntu-22.04
|
||||
continue-on-error: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') }}
|
||||
|
||||
@@ -724,7 +260,7 @@ jobs:
|
||||
xargs clang-tidy-14 --header-filter='src/.*\.(h|hpp)$'
|
||||
|
||||
memory-sanitizer:
|
||||
name: "🔬 Memory Sanitizer"
|
||||
name: "Memory Sanitizer"
|
||||
runs-on: ubuntu-22.04
|
||||
if: |
|
||||
github.event_name == 'pull_request' ||
|
||||
@@ -761,8 +297,10 @@ jobs:
|
||||
run: ctest --output-on-failure
|
||||
|
||||
z3ed-agent-test:
|
||||
name: "🤖 z3ed Agent"
|
||||
name: "z3ed Agent"
|
||||
runs-on: macos-14
|
||||
# Only run on master/develop push, not on PRs (moved to nightly for PRs)
|
||||
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -777,16 +315,23 @@ jobs:
|
||||
cmake -B build_test -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DZ3ED_AI=ON \
|
||||
-DYAZE_BUILD_Z3ED=ON
|
||||
-DYAZE_BUILD_Z3ED=ON \
|
||||
-DYAZE_ENABLE_AI_RUNTIME=ON \
|
||||
-DYAZE_ENABLE_REMOTE_AUTOMATION=ON \
|
||||
-DYAZE_BUILD_AGENT_UI=ON
|
||||
cmake --build build_test --target z3ed
|
||||
|
||||
- name: Start Ollama
|
||||
env:
|
||||
OLLAMA_MODEL: qwen2.5-coder:0.5b
|
||||
run: |
|
||||
ollama serve &
|
||||
sleep 10
|
||||
ollama pull qwen2.5-coder:7b
|
||||
ollama pull "$OLLAMA_MODEL"
|
||||
|
||||
- name: Run Test Suite
|
||||
env:
|
||||
OLLAMA_MODEL: qwen2.5-coder:0.5b
|
||||
run: |
|
||||
chmod +x ./scripts/agent_test_suite.sh
|
||||
./scripts/agent_test_suite.sh ollama
|
||||
|
||||
68
.github/workflows/doxy.yml
vendored
68
.github/workflows/doxy.yml
vendored
@@ -1,16 +1,7 @@
|
||||
name: Doxygen Documentation
|
||||
name: Doxygen Documentation Check
|
||||
|
||||
# Only run when documentation-related files are modified
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- 'src/**/*.h'
|
||||
- 'src/**/*.cc'
|
||||
- 'src/**/*.cpp'
|
||||
- 'docs/**'
|
||||
- 'Doxyfile'
|
||||
- '.github/workflows/doxy.yml'
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
@@ -21,12 +12,10 @@ on:
|
||||
- 'Doxyfile'
|
||||
- '.github/workflows/doxy.yml'
|
||||
|
||||
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
generate-docs:
|
||||
name: Generate Documentation
|
||||
check-docs:
|
||||
name: Check Documentation Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -35,47 +24,26 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install dependencies
|
||||
- name: Install Graphviz
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y doxygen graphviz
|
||||
sudo apt-get install -y graphviz
|
||||
|
||||
- name: Check if documentation build is needed
|
||||
id: changes
|
||||
run: |
|
||||
# Check if this is the first commit or if docs-related files changed
|
||||
if git show --name-only HEAD | grep -E '\.(h|cc|cpp|md)$|Doxyfile'; then
|
||||
echo "docs_changed=true" >> $GITHUB_OUTPUT
|
||||
echo "📝 Documentation-related files have changed"
|
||||
else
|
||||
echo "docs_changed=false" >> $GITHUB_OUTPUT
|
||||
echo "ℹ️ No documentation changes detected"
|
||||
fi
|
||||
|
||||
- name: Clean previous build
|
||||
if: steps.changes.outputs.docs_changed == 'true'
|
||||
run: rm -rf html
|
||||
- name: Install Doxygen 1.10.0
|
||||
uses: ssciwr/doxygen-install@v1
|
||||
with:
|
||||
version: "1.10.0"
|
||||
|
||||
- name: Generate Doxygen documentation
|
||||
if: steps.changes.outputs.docs_changed == 'true'
|
||||
uses: mattnotmitt/doxygen-action@v1.9.8
|
||||
with:
|
||||
doxyfile-path: "./Doxyfile"
|
||||
working-directory: "."
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
if: steps.changes.outputs.docs_changed == 'true'
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./html
|
||||
commit_message: 'docs: update API documentation'
|
||||
|
||||
- name: Summary
|
||||
run: |
|
||||
if [[ "${{ steps.changes.outputs.docs_changed }}" == "true" ]]; then
|
||||
echo "✅ Documentation generated and deployed successfully"
|
||||
echo "📖 View at: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}"
|
||||
mkdir -p build/docs
|
||||
doxygen Doxyfile
|
||||
|
||||
- name: Verify Generation
|
||||
run: |
|
||||
if [ -d "build/docs/html" ]; then
|
||||
echo "✅ Documentation generated successfully"
|
||||
else
|
||||
echo "⏭️ Documentation build skipped - no relevant changes detected"
|
||||
echo "❌ Documentation generation failed"
|
||||
exit 1
|
||||
fi
|
||||
352
.github/workflows/nightly.yml
vendored
Normal file
352
.github/workflows/nightly.yml
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
name: Nightly Test Suite
|
||||
|
||||
on:
|
||||
# Disabled scheduled runs until test infrastructure matures
|
||||
# schedule:
|
||||
# - cron: '0 3 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
test_suites:
|
||||
description: 'Test suites to run'
|
||||
required: false
|
||||
default: 'all'
|
||||
type: choice
|
||||
options:
|
||||
- all
|
||||
- experimental
|
||||
- benchmarks
|
||||
- gui_e2e
|
||||
- extended_integration
|
||||
|
||||
env:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
|
||||
jobs:
|
||||
experimental-ai-tests:
|
||||
name: "Experimental AI Tests - ${{ matrix.os }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: |
|
||||
github.event_name == 'schedule' ||
|
||||
github.event.inputs.test_suites == 'all' ||
|
||||
github.event.inputs.test_suites == 'experimental'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-14, windows-2022]
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
platform: linux
|
||||
preset: ci-linux
|
||||
- os: macos-14
|
||||
platform: macos
|
||||
preset: ci-macos
|
||||
- os: windows-2022
|
||||
platform: windows
|
||||
preset: ci-windows-ai
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
cache-key: ${{ hashFiles('cmake/dependencies.lock') }}
|
||||
|
||||
- name: Configure with AI runtime enabled
|
||||
run: |
|
||||
cmake --preset ${{ matrix.preset }} \
|
||||
-B build_nightly \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DYAZE_ENABLE_AI_RUNTIME=ON \
|
||||
-DYAZE_ENABLE_GRPC=ON \
|
||||
-DYAZE_BUILD_AGENT_UI=ON
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
cmake --build build_nightly \
|
||||
--config ${{ env.BUILD_TYPE }} \
|
||||
--target yaze_test_experimental \
|
||||
--parallel
|
||||
|
||||
- name: Setup Ollama (Linux/macOS)
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
if [ "${{ runner.os }}" = "macOS" ]; then
|
||||
brew install ollama || true
|
||||
else
|
||||
curl -fsSL https://ollama.com/install.sh | sh || true
|
||||
fi
|
||||
ollama serve &
|
||||
sleep 10
|
||||
ollama pull qwen2.5-coder:0.5b || true
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run experimental AI tests
|
||||
run: |
|
||||
cd build_nightly
|
||||
ctest -L experimental \
|
||||
--output-on-failure \
|
||||
--timeout 600 \
|
||||
--output-junit experimental_results.xml
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: experimental-test-results-${{ matrix.platform }}
|
||||
path: build_nightly/experimental_results.xml
|
||||
retention-days: 30
|
||||
|
||||
gui-e2e-tests:
|
||||
name: "GUI E2E Tests - ${{ matrix.os }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: |
|
||||
github.event_name == 'schedule' ||
|
||||
github.event.inputs.test_suites == 'all' ||
|
||||
github.event.inputs.test_suites == 'gui_e2e'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-14] # Windows GUI tests are flaky in CI
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
platform: linux
|
||||
preset: ci-linux
|
||||
- os: macos-14
|
||||
platform: macos
|
||||
preset: ci-macos
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
cache-key: ${{ hashFiles('cmake/dependencies.lock') }}
|
||||
|
||||
- name: Install GUI dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y xvfb libgl1-mesa-dev libglu1-mesa-dev
|
||||
|
||||
- name: Build project
|
||||
uses: ./.github/actions/build-project
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
build-type: ${{ env.BUILD_TYPE }}
|
||||
|
||||
- name: Run GUI E2E tests (Linux with Xvfb)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
xvfb-run -a ./build/bin/yaze_test_gui \
|
||||
--e2e \
|
||||
--nogui \
|
||||
--output-junit gui_e2e_results.xml
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run GUI E2E tests (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
./build/bin/yaze_test_gui \
|
||||
--e2e \
|
||||
--nogui \
|
||||
--output-junit gui_e2e_results.xml
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gui-e2e-results-${{ matrix.platform }}
|
||||
path: gui_e2e_results.xml
|
||||
retention-days: 30
|
||||
|
||||
benchmark-tests:
|
||||
name: "Performance Benchmarks"
|
||||
runs-on: ubuntu-22.04
|
||||
if: |
|
||||
github.event_name == 'schedule' ||
|
||||
github.event.inputs.test_suites == 'all' ||
|
||||
github.event.inputs.test_suites == 'benchmarks'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: linux
|
||||
preset: ci-linux
|
||||
cache-key: ${{ hashFiles('cmake/dependencies.lock') }}
|
||||
|
||||
- name: Build benchmarks
|
||||
run: |
|
||||
cmake --preset ci-linux \
|
||||
-B build_bench \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DYAZE_BUILD_TESTS=ON
|
||||
cmake --build build_bench \
|
||||
--config Release \
|
||||
--target yaze_test_benchmark \
|
||||
--parallel
|
||||
|
||||
- name: Run benchmarks
|
||||
run: |
|
||||
./build_bench/bin/yaze_test_benchmark \
|
||||
--benchmark_format=json \
|
||||
--benchmark_out=benchmark_results.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload benchmark results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: benchmark-results
|
||||
path: benchmark_results.json
|
||||
retention-days: 90
|
||||
|
||||
- name: Compare with baseline (if exists)
|
||||
if: ${{ hashFiles('benchmark_baseline.json') != '' }}
|
||||
run: |
|
||||
# Compare current results with baseline
|
||||
# This would use a tool like google/benchmark's compare.py
|
||||
echo "Benchmark comparison would happen here"
|
||||
continue-on-error: true
|
||||
|
||||
extended-integration-tests:
|
||||
name: "Extended Integration Tests"
|
||||
runs-on: ubuntu-22.04
|
||||
if: |
|
||||
github.event_name == 'schedule' ||
|
||||
github.event.inputs.test_suites == 'all' ||
|
||||
github.event.inputs.test_suites == 'extended_integration'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: linux
|
||||
preset: ci-linux
|
||||
cache-key: ${{ hashFiles('cmake/dependencies.lock') }}
|
||||
|
||||
- name: Build with full features
|
||||
run: |
|
||||
cmake --preset ci-linux \
|
||||
-B build_extended \
|
||||
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
|
||||
-DYAZE_ENABLE_GRPC=ON \
|
||||
-DYAZE_ENABLE_JSON=ON \
|
||||
-DYAZE_ENABLE_HTTP_API=ON \
|
||||
-DYAZE_BUILD_AGENT_UI=ON
|
||||
cmake --build build_extended \
|
||||
--config ${{ env.BUILD_TYPE }} \
|
||||
--parallel
|
||||
|
||||
- name: Run extended integration tests
|
||||
run: |
|
||||
cd build_extended
|
||||
# Run all integration tests with extended timeout
|
||||
ctest -L integration \
|
||||
--output-on-failure \
|
||||
--timeout 1200 \
|
||||
--output-junit extended_integration_results.xml
|
||||
|
||||
- name: Run HTTP API tests
|
||||
if: ${{ hashFiles('scripts/agents/test-http-api.sh') != '' }}
|
||||
run: |
|
||||
chmod +x scripts/agents/test-http-api.sh
|
||||
scripts/agents/test-http-api.sh
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: extended-integration-results
|
||||
path: build_extended/extended_integration_results.xml
|
||||
retention-days: 30
|
||||
|
||||
nightly-summary:
|
||||
name: "Nightly Test Summary"
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
needs: [
|
||||
experimental-ai-tests,
|
||||
gui-e2e-tests,
|
||||
benchmark-tests,
|
||||
extended-integration-tests
|
||||
]
|
||||
|
||||
steps:
|
||||
- name: Generate summary
|
||||
run: |
|
||||
echo "# Nightly Test Results - $(date +'%Y-%m-%d')" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Experimental AI Tests
|
||||
if [ "${{ needs.experimental-ai-tests.result }}" == "success" ]; then
|
||||
echo "✅ **Experimental AI Tests:** Passed" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ needs.experimental-ai-tests.result }}" == "skipped" ]; then
|
||||
echo "⏭️ **Experimental AI Tests:** Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Experimental AI Tests:** Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# GUI E2E Tests
|
||||
if [ "${{ needs.gui-e2e-tests.result }}" == "success" ]; then
|
||||
echo "✅ **GUI E2E Tests:** Passed" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ needs.gui-e2e-tests.result }}" == "skipped" ]; then
|
||||
echo "⏭️ **GUI E2E Tests:** Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **GUI E2E Tests:** Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# Benchmark Tests
|
||||
if [ "${{ needs.benchmark-tests.result }}" == "success" ]; then
|
||||
echo "✅ **Performance Benchmarks:** Completed" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ needs.benchmark-tests.result }}" == "skipped" ]; then
|
||||
echo "⏭️ **Performance Benchmarks:** Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Performance Benchmarks:** Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# Extended Integration Tests
|
||||
if [ "${{ needs.extended-integration-tests.result }}" == "success" ]; then
|
||||
echo "✅ **Extended Integration Tests:** Passed" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ needs.extended-integration-tests.result }}" == "skipped" ]; then
|
||||
echo "⏭️ **Extended Integration Tests:** Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Extended Integration Tests:** Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "---" >> $GITHUB_STEP_SUMMARY
|
||||
echo "*Nightly tests include comprehensive suites not run during PR/push CI.*" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Send notification (if configured)
|
||||
if: ${{ failure() && vars.SLACK_WEBHOOK_URL != '' }}
|
||||
run: |
|
||||
# Send notification about nightly test failures
|
||||
echo "Notification would be sent here"
|
||||
continue-on-error: true
|
||||
668
.github/workflows/release.yml
vendored
668
.github/workflows/release.yml
vendored
@@ -6,399 +6,335 @@ on:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag (e.g., v0.3.2)'
|
||||
version:
|
||||
description: 'Version to release (e.g., v1.0.0)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
VERSION: ${{ github.event.inputs.version || github.ref_name }}
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
name: Windows x64
|
||||
runs-on: windows-2022
|
||||
build:
|
||||
name: "Build Release - ${{ matrix.name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "Ubuntu 22.04"
|
||||
os: ubuntu-22.04
|
||||
platform: linux
|
||||
preset: release
|
||||
- name: "macOS 14"
|
||||
os: macos-14
|
||||
platform: macos
|
||||
preset: release
|
||||
- name: "Windows 2022"
|
||||
os: windows-2022
|
||||
platform: windows
|
||||
preset: release
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
with:
|
||||
vcpkgDirectory: '${{ github.workspace }}/vcpkg'
|
||||
vcpkgGitCommitId: 'b2c74683ecfd6a8e7d27ffb0df077f66a9339509'
|
||||
runVcpkgInstall: true
|
||||
env:
|
||||
VCPKG_DEFAULT_TRIPLET: x64-windows-static
|
||||
VCPKG_BINARY_SOURCES: 'clear;x-gha,readwrite'
|
||||
|
||||
- name: Install build tools
|
||||
shell: pwsh
|
||||
run: |
|
||||
choco install --no-progress -y nasm
|
||||
"C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Append
|
||||
|
||||
- name: Setup MSVC environment for clang-cl
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: Configure clang-cl
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "Setting up clang-cl compiler"
|
||||
echo "CC=clang-cl" >> $env:GITHUB_ENV
|
||||
echo "CXX=clang-cl" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Setup sccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: windows-x64-release-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
windows-x64-release-
|
||||
max-size: 500M
|
||||
variant: sccache
|
||||
|
||||
- name: Restore vcpkg packages cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
build/vcpkg_installed
|
||||
${{ github.workspace }}/vcpkg/packages
|
||||
key: vcpkg-release-${{ hashFiles('vcpkg.json') }}
|
||||
restore-keys: |
|
||||
vcpkg-release-
|
||||
|
||||
- name: Restore FetchContent dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
build/_deps
|
||||
key: fetchcontent-release-${{ hashFiles('cmake/grpc*.cmake') }}-v2
|
||||
restore-keys: |
|
||||
fetchcontent-release-
|
||||
|
||||
- name: Configure sccache
|
||||
shell: pwsh
|
||||
run: |
|
||||
echo "CC=sccache clang-cl" >> $env:GITHUB_ENV
|
||||
echo "CXX=sccache clang-cl" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Configure
|
||||
id: configure
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "=== Build Configuration ===" -ForegroundColor Cyan
|
||||
Write-Host "Compiler: clang-cl"
|
||||
Write-Host "Build Type: Release"
|
||||
cmake --version
|
||||
clang-cl --version
|
||||
|
||||
$toolchain = "${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake"
|
||||
cmake -S . -B build `
|
||||
-DCMAKE_BUILD_TYPE=Release `
|
||||
-DCMAKE_C_COMPILER=clang-cl `
|
||||
-DCMAKE_CXX_COMPILER=clang-cl `
|
||||
-DCMAKE_TOOLCHAIN_FILE=$toolchain `
|
||||
-DVCPKG_TARGET_TRIPLET=x64-windows-static `
|
||||
-DVCPKG_MANIFEST_MODE=ON `
|
||||
-DYAZE_BUILD_TESTS=OFF `
|
||||
-DYAZE_BUILD_EMU=ON `
|
||||
-DYAZE_BUILD_Z3ED=ON `
|
||||
-DYAZE_BUILD_TOOLS=ON 2>&1 | Tee-Object -FilePath cmake_config.log
|
||||
|
||||
- name: Report Configure Failure
|
||||
if: always() && steps.configure.outcome == 'failure'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "::error::CMake configuration failed. Check cmake_config.log for details." -ForegroundColor Red
|
||||
if (Test-Path cmake_config.log) {
|
||||
Write-Host "::group::CMake Configuration Log (last 50 lines)"
|
||||
Get-Content cmake_config.log -Tail 50
|
||||
Write-Host "::endgroup::"
|
||||
}
|
||||
exit 1
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
shell: pwsh
|
||||
run: cmake --build build --config Release --parallel 4 -- /p:CL_MPcount=4 2>&1 | Tee-Object -FilePath build.log
|
||||
|
||||
- name: Report Build Failure
|
||||
if: always() && steps.build.outcome == 'failure'
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Host "::error::Build failed. Check build.log for details." -ForegroundColor Red
|
||||
if (Test-Path build.log) {
|
||||
Write-Host "::group::Build Log (last 100 lines)"
|
||||
Get-Content build.log -Tail 100
|
||||
Write-Host "::endgroup::"
|
||||
|
||||
# Check for specific error patterns
|
||||
if (Select-String -Path "build.log" -Pattern "vcpkg" -Quiet) {
|
||||
Write-Host "`n::group::vcpkg-related errors" -ForegroundColor Yellow
|
||||
Select-String -Path "build.log" -Pattern "vcpkg.*error" -CaseSensitive:$false | Select-Object -First 10
|
||||
Write-Host "::endgroup::"
|
||||
}
|
||||
|
||||
if (Select-String -Path "build.log" -Pattern "LNK[0-9]{4}" -Quiet) {
|
||||
Write-Host "`n::group::Linker errors" -ForegroundColor Yellow
|
||||
Select-String -Path "build.log" -Pattern "LNK[0-9]{4}" | Select-Object -First 10
|
||||
Write-Host "::endgroup::"
|
||||
}
|
||||
|
||||
if (Select-String -Path "build.log" -Pattern "fatal error" -Quiet) {
|
||||
Write-Host "`n::group::Fatal errors" -ForegroundColor Yellow
|
||||
Select-String -Path "build.log" -Pattern "fatal error" | Select-Object -First 10
|
||||
Write-Host "::endgroup::"
|
||||
}
|
||||
}
|
||||
|
||||
# List vcpkg installed packages
|
||||
$vcpkgExe = "${{ github.workspace }}/vcpkg/vcpkg.exe"
|
||||
if (Test-Path $vcpkgExe) {
|
||||
Write-Host "`n::group::Installed vcpkg packages"
|
||||
& $vcpkgExe list
|
||||
Write-Host "::endgroup::"
|
||||
}
|
||||
exit 1
|
||||
|
||||
- name: Package
|
||||
shell: pwsh
|
||||
run: |
|
||||
New-Item -ItemType Directory -Path release
|
||||
Copy-Item -Path build/bin/Release/* -Destination release/ -Recurse
|
||||
Copy-Item -Path assets -Destination release/ -Recurse
|
||||
Copy-Item LICENSE, README.md -Destination release/
|
||||
Compress-Archive -Path release/* -DestinationPath yaze-windows-x64.zip
|
||||
|
||||
- name: Upload Build Logs on Failure (Windows)
|
||||
if: always() && (steps.configure.outcome == 'failure' || steps.build.outcome == 'failure')
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-logs-windows
|
||||
path: |
|
||||
cmake_config.log
|
||||
build.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: steps.build.outcome == 'success'
|
||||
with:
|
||||
name: yaze-windows-x64
|
||||
path: yaze-windows-x64.zip
|
||||
|
||||
build-macos:
|
||||
name: macOS Universal
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: brew install ninja cmake
|
||||
|
||||
- name: Configure arm64
|
||||
id: configure_arm64
|
||||
run: |
|
||||
cmake -S . -B build-arm64 -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_OSX_ARCHITECTURES=arm64 \
|
||||
-DYAZE_BUILD_TESTS=OFF \
|
||||
-DYAZE_BUILD_EMU=ON \
|
||||
-DYAZE_BUILD_Z3ED=ON \
|
||||
-DYAZE_BUILD_TOOLS=ON 2>&1 | tee cmake_config_arm64.log
|
||||
|
||||
- name: Build arm64
|
||||
id: build_arm64
|
||||
run: cmake --build build-arm64 --config Release 2>&1 | tee build_arm64.log
|
||||
|
||||
- name: Configure x86_64
|
||||
id: configure_x86_64
|
||||
run: |
|
||||
cmake -S . -B build-x86_64 -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
|
||||
-DYAZE_BUILD_TESTS=OFF \
|
||||
-DYAZE_BUILD_EMU=ON \
|
||||
-DYAZE_BUILD_Z3ED=ON \
|
||||
-DYAZE_BUILD_TOOLS=ON 2>&1 | tee cmake_config_x86_64.log
|
||||
|
||||
- name: Build x86_64
|
||||
id: build_x86_64
|
||||
run: cmake --build build-x86_64 --config Release 2>&1 | tee build_x86_64.log
|
||||
|
||||
- name: Create Universal Binary
|
||||
run: |
|
||||
cp -R build-arm64/bin/yaze.app yaze.app
|
||||
lipo -create \
|
||||
build-arm64/bin/yaze.app/Contents/MacOS/yaze \
|
||||
build-x86_64/bin/yaze.app/Contents/MacOS/yaze \
|
||||
-output yaze.app/Contents/MacOS/yaze
|
||||
lipo -info yaze.app/Contents/MacOS/yaze
|
||||
|
||||
- name: Create DMG
|
||||
run: |
|
||||
hdiutil create -fs HFS+ -srcfolder yaze.app \
|
||||
-volname "yaze" yaze-macos-universal.dmg
|
||||
|
||||
- name: Upload Build Logs on Failure (macOS)
|
||||
if: always() && (steps.configure_arm64.outcome == 'failure' || steps.build_arm64.outcome == 'failure' || steps.configure_x86_64.outcome == 'failure' || steps.build_x86_64.outcome == 'failure')
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-logs-macos
|
||||
path: |
|
||||
cmake_config_arm64.log
|
||||
build_arm64.log
|
||||
cmake_config_x86_64.log
|
||||
build_x86_64.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: steps.build_arm64.outcome == 'success' && steps.build_x86_64.outcome == 'success'
|
||||
with:
|
||||
name: yaze-macos-universal
|
||||
path: yaze-macos-universal.dmg
|
||||
|
||||
build-linux:
|
||||
name: Linux x64
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Free disk space
|
||||
- name: Free up disk space (Linux)
|
||||
if: matrix.platform == 'linux'
|
||||
run: |
|
||||
echo "=== Disk space before cleanup ==="
|
||||
df -h
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo apt-get clean
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force
|
||||
echo "=== Disk space after cleanup ==="
|
||||
df -h
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
build-essential ninja-build pkg-config \
|
||||
libglew-dev libxext-dev libwavpack-dev libboost-all-dev \
|
||||
libpng-dev python3-dev \
|
||||
libasound2-dev libpulse-dev \
|
||||
libx11-dev libxrandr-dev libxcursor-dev libxinerama-dev libxi-dev \
|
||||
libxss-dev libxxf86vm-dev libxkbcommon-dev libwayland-dev libdecor-0-dev \
|
||||
libgtk-3-dev libdbus-1-dev
|
||||
|
||||
- name: Configure
|
||||
id: configure
|
||||
run: |
|
||||
cmake -S . -B build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DYAZE_BUILD_TESTS=OFF \
|
||||
-DYAZE_BUILD_EMU=ON \
|
||||
-DYAZE_BUILD_Z3ED=ON \
|
||||
-DYAZE_BUILD_TOOLS=ON \
|
||||
-DNFD_PORTAL=ON 2>&1 | tee cmake_config.log
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
run: cmake --build build --config Release 2>&1 | tee build.log
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
mkdir -p release
|
||||
cp build/bin/yaze release/
|
||||
cp -r assets release/
|
||||
cp LICENSE README.md release/
|
||||
tar -czf yaze-linux-x64.tar.gz -C release .
|
||||
|
||||
- name: Upload Build Logs on Failure (Linux)
|
||||
if: always() && (steps.configure.outcome == 'failure' || steps.build.outcome == 'failure')
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
name: build-logs-linux
|
||||
path: |
|
||||
cmake_config.log
|
||||
build.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: steps.build.outcome == 'success'
|
||||
with:
|
||||
name: yaze-linux-x64
|
||||
path: yaze-linux-x64.tar.gz
|
||||
|
||||
create-release:
|
||||
name: Create Release
|
||||
needs: [build-windows, build-macos, build-linux]
|
||||
runs-on: ubuntu-latest
|
||||
if: always() && (needs.build-windows.result == 'success' || needs.build-macos.result == 'success' || needs.build-linux.result == 'success')
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Determine tag
|
||||
id: tag
|
||||
- name: Compute dependency lock hash
|
||||
id: deps-hash
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
|
||||
python_cmd="$(command -v python3 || command -v python || true)"
|
||||
if [ -z "$python_cmd" ]; then
|
||||
echo "hash=none" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
hash=$("$python_cmd" - <<'PY'
|
||||
import hashlib
|
||||
import pathlib
|
||||
path = pathlib.Path("cmake/dependencies.lock")
|
||||
if path.is_file():
|
||||
print(hashlib.sha256(path.read_bytes()).hexdigest())
|
||||
else:
|
||||
print("none")
|
||||
PY
|
||||
)
|
||||
echo "hash=$hash" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
path: artifacts
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
cache-key: ${{ steps.deps-hash.outputs.hash }}
|
||||
|
||||
- name: Display structure
|
||||
run: ls -R artifacts
|
||||
- name: Build project
|
||||
uses: ./.github/actions/build-project
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
build-type: Release
|
||||
|
||||
- name: Create release notes
|
||||
id: notes
|
||||
- name: Patch cmake_install.cmake (Unix)
|
||||
if: matrix.platform == 'linux' || matrix.platform == 'macos'
|
||||
shell: bash
|
||||
run: |
|
||||
TAG="${{ steps.tag.outputs.tag }}"
|
||||
VERSION="${TAG#v}"
|
||||
|
||||
cat > release_notes.md << 'EOF'
|
||||
## yaze ${{ steps.tag.outputs.tag }}
|
||||
|
||||
### Downloads
|
||||
- **Windows**: `yaze-windows-x64.zip`
|
||||
- **macOS**: `yaze-macos-universal.dmg` (Universal Binary)
|
||||
- **Linux**: `yaze-linux-x64.tar.gz`
|
||||
|
||||
### Installation
|
||||
|
||||
**Windows**: Extract the ZIP file and run `yaze.exe`
|
||||
|
||||
**macOS**: Open the DMG and drag yaze.app to Applications
|
||||
|
||||
**Linux**: Extract the tarball and run `./yaze`
|
||||
|
||||
### Changes
|
||||
See the [changelog](https://github.com/${{ github.repository }}/blob/develop/docs/H1-changelog.md) for details.
|
||||
cd build
|
||||
# Create a Python script to patch cmake_install.cmake
|
||||
python3 << 'EOF'
|
||||
import re
|
||||
with open('cmake_install.cmake', 'r') as f:
|
||||
content = f.read()
|
||||
# Wrap include() statements with if(EXISTS)
|
||||
pattern = r'(\s*)include\("(.*)/_deps/([^"]+)/cmake_install\.cmake"\)'
|
||||
replacement = r'\1if(EXISTS "\2/_deps/\3/cmake_install.cmake")\n\1 include("\2/_deps/\3/cmake_install.cmake")\n\1endif()'
|
||||
content = re.sub(pattern, replacement, content)
|
||||
with open('cmake_install.cmake', 'w') as f:
|
||||
f.write(content)
|
||||
print("Patched cmake_install.cmake to handle missing dependency install scripts")
|
||||
EOF
|
||||
|
||||
cat release_notes.md
|
||||
- name: Clean old packages before CPack
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Cleaning old package files to ensure fresh generation"
|
||||
rm -rf build/packages build/_CPack_Packages
|
||||
rm -f build/*.deb build/*.tar.gz build/*.dmg build/*.zip build/*.exe
|
||||
mkdir -p build/packages
|
||||
|
||||
- name: Package artifacts (Linux)
|
||||
if: matrix.platform == 'linux'
|
||||
run: |
|
||||
cd build
|
||||
cpack -G DEB -G TGZ
|
||||
echo "=== Contents of packages directory ==="
|
||||
ls -la packages/ 2>/dev/null || echo "No packages directory"
|
||||
echo "=== Package files created ==="
|
||||
ls -la packages/*.deb packages/*.tar.gz 2>/dev/null || echo "No packages found"
|
||||
|
||||
- name: Package artifacts (macOS)
|
||||
if: matrix.platform == 'macos'
|
||||
run: |
|
||||
cd build
|
||||
cpack -G DragNDrop
|
||||
echo "=== Contents of packages directory ==="
|
||||
ls -la packages/ 2>/dev/null || echo "No packages directory"
|
||||
echo "=== Package files created ==="
|
||||
ls -la packages/*.dmg 2>/dev/null || echo "No packages found"
|
||||
|
||||
- name: Create notarized bundle (macOS)
|
||||
if: matrix.platform == 'macos'
|
||||
shell: bash
|
||||
run: |
|
||||
chmod +x ./scripts/create-macos-bundle.sh
|
||||
./scripts/create-macos-bundle.sh ${{ env.VERSION }} yaze-${{ env.VERSION }}-bundle || true
|
||||
if [ -f "yaze-${{ env.VERSION }}-bundle.dmg" ]; then
|
||||
mkdir -p build/packages
|
||||
mv yaze-${{ env.VERSION }}-bundle.dmg build/packages/
|
||||
fi
|
||||
|
||||
- name: Patch cmake_install.cmake (Windows)
|
||||
if: matrix.platform == 'windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd build
|
||||
# Wrap include() statements with if(EXISTS) to handle missing dependency install scripts
|
||||
$nl = [Environment]::NewLine
|
||||
$content = Get-Content cmake_install.cmake -Raw
|
||||
$content = $content -replace '(\s+)include\("(.*)/_deps/([^"]+)/cmake_install\.cmake"\)', "`$1if(EXISTS `"`$2/_deps/`$3/cmake_install.cmake`")$nl`$1 include(`"`$2/_deps/`$3/cmake_install.cmake`")$nl`$1endif()"
|
||||
Set-Content cmake_install.cmake $content
|
||||
Write-Host "Patched cmake_install.cmake to handle missing dependency install scripts"
|
||||
|
||||
- name: Package artifacts (Windows)
|
||||
if: matrix.platform == 'windows'
|
||||
shell: pwsh
|
||||
run: |
|
||||
cd build
|
||||
cpack -G NSIS -G ZIP
|
||||
Write-Host "=== Contents of packages directory ==="
|
||||
Get-ChildItem packages -ErrorAction SilentlyContinue
|
||||
Write-Host "=== Package files created ==="
|
||||
Get-ChildItem packages/*.exe, packages/*.zip -ErrorAction SilentlyContinue
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: yaze-${{ matrix.platform }}-${{ env.VERSION }}
|
||||
path: |
|
||||
build/packages/*.deb
|
||||
build/packages/*.tar.gz
|
||||
build/packages/*.dmg
|
||||
build/packages/*.exe
|
||||
build/packages/*.zip
|
||||
if-no-files-found: warn
|
||||
retention-days: 30
|
||||
|
||||
test:
|
||||
name: "Test Release - ${{ matrix.name }}"
|
||||
needs: build
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "Ubuntu 22.04"
|
||||
os: ubuntu-22.04
|
||||
platform: linux
|
||||
preset: release
|
||||
- name: "macOS 14"
|
||||
os: macos-14
|
||||
platform: macos
|
||||
preset: release
|
||||
- name: "Windows 2022"
|
||||
os: windows-2022
|
||||
platform: windows
|
||||
preset: release
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Compute dependency lock hash
|
||||
id: deps-hash
|
||||
shell: bash
|
||||
run: |
|
||||
python_cmd="$(command -v python3 || command -v python || true)"
|
||||
if [ -z "$python_cmd" ]; then
|
||||
echo "hash=none" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
hash=$("$python_cmd" - <<'PY'
|
||||
import hashlib
|
||||
import pathlib
|
||||
path = pathlib.Path("cmake/dependencies.lock")
|
||||
if path.is_file():
|
||||
print(hashlib.sha256(path.read_bytes()).hexdigest())
|
||||
else:
|
||||
print("none")
|
||||
PY
|
||||
)
|
||||
echo "hash=$hash" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
cache-key: ${{ steps.deps-hash.outputs.hash }}
|
||||
|
||||
- name: Build project
|
||||
uses: ./.github/actions/build-project
|
||||
with:
|
||||
platform: ${{ matrix.platform }}
|
||||
preset: ${{ matrix.preset }}
|
||||
build-type: Release
|
||||
|
||||
- name: Run tests
|
||||
uses: ./.github/actions/run-tests
|
||||
with:
|
||||
test-type: stable
|
||||
preset: ${{ matrix.preset }}
|
||||
|
||||
create-release:
|
||||
name: "Create Release"
|
||||
needs: [build] # Tests are informational only in pre-1.0
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./artifacts
|
||||
|
||||
- name: Display downloaded artifacts
|
||||
run: |
|
||||
echo "=== Downloaded artifacts structure ==="
|
||||
ls -laR artifacts/
|
||||
echo "=== Package files found ==="
|
||||
find artifacts -type f \( -name "*.zip" -o -name "*.exe" -o -name "*.deb" -o -name "*.tar.gz" -o -name "*.dmg" \)
|
||||
|
||||
- name: Reorganize artifacts
|
||||
run: |
|
||||
# Flatten the artifact directory structure
|
||||
mkdir -p release-files
|
||||
find artifacts -type f \( -name "*.zip" -o -name "*.exe" -o -name "*.deb" -o -name "*.tar.gz" -o -name "*.dmg" \) -exec cp {} release-files/ \;
|
||||
echo "=== Files in release-files ==="
|
||||
ls -la release-files/
|
||||
|
||||
- name: Generate release checksums
|
||||
run: |
|
||||
cd release-files
|
||||
sha256sum * > checksums.txt
|
||||
cat checksums.txt
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ steps.tag.outputs.tag }}
|
||||
name: yaze ${{ steps.tag.outputs.tag }}
|
||||
body_path: release_notes.md
|
||||
draft: false
|
||||
prerelease: ${{ contains(steps.tag.outputs.tag, '-') }}
|
||||
tag_name: ${{ env.VERSION }}
|
||||
name: "YAZE ${{ env.VERSION }}"
|
||||
body: |
|
||||
## What's Changed
|
||||
|
||||
This release includes:
|
||||
- Cross-platform builds for Linux, macOS, and Windows
|
||||
- Improved dependency management with CPM.cmake
|
||||
- Enhanced CI/CD pipeline with parallel execution
|
||||
- Automated packaging and release creation
|
||||
|
||||
## Downloads
|
||||
|
||||
### Linux
|
||||
- **DEB Package**: `yaze-*.deb` (Ubuntu/Debian)
|
||||
- **Tarball**: `yaze-*.tar.gz` (Generic Linux)
|
||||
|
||||
### macOS
|
||||
- **DMG**: `yaze-*.dmg` (macOS 11.0+)
|
||||
|
||||
### Windows
|
||||
- **Installer**: `yaze-*.exe` (Windows 10/11)
|
||||
- **ZIP**: `yaze-*.zip` (Portable)
|
||||
|
||||
## Installation
|
||||
|
||||
### Linux (DEB)
|
||||
```bash
|
||||
sudo dpkg -i yaze-*.deb
|
||||
```
|
||||
|
||||
### macOS
|
||||
```bash
|
||||
# Mount the DMG and drag to Applications
|
||||
open yaze-*.dmg
|
||||
```
|
||||
|
||||
### Windows
|
||||
```bash
|
||||
# Run the installer
|
||||
yaze-*.exe
|
||||
```
|
||||
files: |
|
||||
artifacts/yaze-windows-x64/*
|
||||
artifacts/yaze-macos-universal/*
|
||||
artifacts/yaze-linux-x64/*
|
||||
fail_on_unmatched_files: false
|
||||
release-files/*
|
||||
draft: false
|
||||
prerelease: ${{ contains(env.VERSION, 'alpha') || contains(env.VERSION, 'beta') || contains(env.VERSION, 'rc') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
26
.github/workflows/scripts/linux-ci-packages.txt
vendored
Normal file
26
.github/workflows/scripts/linux-ci-packages.txt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
build-essential
|
||||
ninja-build
|
||||
pkg-config
|
||||
ccache
|
||||
libglew-dev
|
||||
libxext-dev
|
||||
libwavpack-dev
|
||||
libboost-all-dev
|
||||
libpng-dev
|
||||
python3-dev
|
||||
libasound2-dev
|
||||
libpulse-dev
|
||||
libaudio-dev
|
||||
libx11-dev
|
||||
libxrandr-dev
|
||||
libxcursor-dev
|
||||
libxinerama-dev
|
||||
libxi-dev
|
||||
libxss-dev
|
||||
libxxf86vm-dev
|
||||
libxkbcommon-dev
|
||||
libwayland-dev
|
||||
libdecor-0-dev
|
||||
libgtk-3-dev
|
||||
libdbus-1-dev
|
||||
libgtk-3-0
|
||||
88
.github/workflows/security.yml
vendored
Normal file
88
.github/workflows/security.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Security Scanning
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", "develop" ]
|
||||
pull_request:
|
||||
branches: [ "master", "develop" ]
|
||||
schedule:
|
||||
- cron: '0 2 * * 1' # Weekly on Monday at 2 AM
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
codeql:
|
||||
name: "CodeQL Analysis"
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp' ]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: security-and-quality
|
||||
|
||||
- name: Setup build environment
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
platform: linux
|
||||
preset: ci
|
||||
cache-key: ${{ hashFiles('cmake/dependencies.lock') }}
|
||||
|
||||
- name: Build project
|
||||
uses: ./.github/actions/build-project
|
||||
with:
|
||||
platform: linux
|
||||
preset: ci
|
||||
build-type: RelWithDebInfo
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
dependency-scan:
|
||||
name: "Dependency Scan"
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
scan-ref: '.'
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
if: always()
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
|
||||
dependabot:
|
||||
name: "Dependabot"
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event_name == 'schedule'
|
||||
|
||||
steps:
|
||||
- name: Dependabot metadata
|
||||
run: |
|
||||
echo "Dependabot is configured via .github/dependabot.yml"
|
||||
echo "This job runs weekly to ensure dependencies are up to date"
|
||||
|
||||
175
.github/workflows/wasm-dev.yml
vendored
Normal file
175
.github/workflows/wasm-dev.yml
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
name: WASM Development Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'CMakeLists.txt'
|
||||
- 'CMakePresets.json'
|
||||
- 'scripts/build-wasm.sh'
|
||||
- '.github/workflows/wasm-dev.yml'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
debug_build:
|
||||
description: 'Build debug version'
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
run_tests:
|
||||
description: 'Run WASM tests (experimental)'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
wasm-build:
|
||||
name: "WASM Build (Debug)"
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Emscripten
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: 3.1.51
|
||||
actions-cache-folder: 'emsdk-cache'
|
||||
|
||||
- name: Setup Ninja
|
||||
uses: seanmiddleditch/gha-setup-ninja@v4
|
||||
|
||||
- name: Setup CMake
|
||||
uses: jwlawson/actions-setup-cmake@v1.14
|
||||
with:
|
||||
cmake-version: '3.27.x'
|
||||
|
||||
- name: Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: wasm-dev-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: Cache CPM packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/CPM
|
||||
key: cpm-wasm-debug-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
restore-keys: |
|
||||
cpm-wasm-debug-
|
||||
cpm-wasm-
|
||||
|
||||
- name: Verify Emscripten setup
|
||||
run: |
|
||||
echo "=== Emscripten Configuration ==="
|
||||
emcc --version
|
||||
emcmake --version
|
||||
echo "=== Node.js Version ==="
|
||||
node --version
|
||||
echo "=== Environment ==="
|
||||
env | grep -i em || true
|
||||
|
||||
- name: Build WASM (Debug)
|
||||
if: github.event.inputs.debug_build != 'false'
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:$PATH"
|
||||
echo "Building WASM debug version..."
|
||||
chmod +x scripts/build-wasm.sh
|
||||
./scripts/build-wasm.sh debug
|
||||
|
||||
- name: Build WASM (Release)
|
||||
if: github.event.inputs.debug_build == 'false'
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:$PATH"
|
||||
echo "Building WASM release version..."
|
||||
chmod +x scripts/build-wasm.sh
|
||||
./scripts/build-wasm.sh release
|
||||
|
||||
- name: Verify build output
|
||||
run: |
|
||||
BUILD_DIR="build-wasm-debug"
|
||||
if [ "${{ github.event.inputs.debug_build }}" == "false" ]; then
|
||||
BUILD_DIR="build-wasm"
|
||||
fi
|
||||
|
||||
echo "=== Build Output Verification ==="
|
||||
ls -lh "$BUILD_DIR/bin/" || true
|
||||
|
||||
# Check for critical files
|
||||
if [ ! -f "$BUILD_DIR/bin/yaze.wasm" ]; then
|
||||
echo "ERROR: yaze.wasm not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$BUILD_DIR/bin/yaze.js" ]; then
|
||||
echo "ERROR: yaze.js not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$BUILD_DIR/bin/yaze.html" ]; then
|
||||
echo "ERROR: yaze.html not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Report file sizes
|
||||
echo ""
|
||||
echo "=== File Sizes ==="
|
||||
du -h "$BUILD_DIR/bin/yaze.wasm"
|
||||
du -h "$BUILD_DIR/bin/yaze.js"
|
||||
du -h "$BUILD_DIR/bin/yaze.data" 2>/dev/null || echo "No .data file (lazy loading enabled?)"
|
||||
|
||||
# Check for SharedArrayBuffer support
|
||||
if grep -q "SharedArrayBuffer" "$BUILD_DIR/bin/yaze.js"; then
|
||||
echo "✓ SharedArrayBuffer support detected"
|
||||
else
|
||||
echo "⚠ SharedArrayBuffer not detected - threading may not work"
|
||||
fi
|
||||
|
||||
- name: Run WASM tests (experimental)
|
||||
if: github.event.inputs.run_tests == 'true'
|
||||
run: |
|
||||
echo "WASM tests are experimental and not yet implemented"
|
||||
# TODO: Add Node.js-based WASM tests here
|
||||
|
||||
- name: Upload WASM artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: wasm-debug-${{ github.sha }}
|
||||
path: |
|
||||
build-wasm-debug/bin/*.wasm
|
||||
build-wasm-debug/bin/*.js
|
||||
build-wasm-debug/bin/*.html
|
||||
build-wasm-debug/bin/*.data
|
||||
build-wasm/bin/*.wasm
|
||||
build-wasm/bin/*.js
|
||||
build-wasm/bin/*.html
|
||||
build-wasm/bin/*.data
|
||||
if-no-files-found: warn
|
||||
retention-days: 7
|
||||
|
||||
- name: Build summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## WASM Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
BUILD_DIR="build-wasm-debug"
|
||||
BUILD_TYPE="Debug"
|
||||
if [ "${{ github.event.inputs.debug_build }}" == "false" ]; then
|
||||
BUILD_DIR="build-wasm"
|
||||
BUILD_TYPE="Release"
|
||||
fi
|
||||
|
||||
echo "**Build Type:** $BUILD_TYPE" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Emscripten Version:** 3.1.51" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ -f "$BUILD_DIR/bin/yaze.wasm" ]; then
|
||||
WASM_SIZE=$(du -h "$BUILD_DIR/bin/yaze.wasm" | cut -f1)
|
||||
echo "**WASM Size:** $WASM_SIZE" >> $GITHUB_STEP_SUMMARY
|
||||
echo "✓ Build successful" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ Build failed - WASM file not generated" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
209
.github/workflows/web-build.yml
vendored
Normal file
209
.github/workflows/web-build.yml
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
name: Web Build & Deploy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ master, main ]
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'docs/**'
|
||||
- 'CMakeLists.txt'
|
||||
- 'CMakePresets.json'
|
||||
- 'Doxyfile'
|
||||
- 'scripts/build-wasm.sh'
|
||||
|
||||
jobs:
|
||||
build-deploy:
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 2
|
||||
|
||||
# --- Detect what changed ---
|
||||
- name: Check for web-only changes
|
||||
id: changes
|
||||
run: |
|
||||
set -e
|
||||
echo "Event: ${GITHUB_EVENT_NAME}"
|
||||
|
||||
NEEDS_BUILD=false
|
||||
CHANGED=""
|
||||
|
||||
if git rev-parse HEAD~1 >/dev/null 2>&1; then
|
||||
CHANGED=$(git diff --name-only HEAD~1 HEAD || echo "")
|
||||
else
|
||||
echo "No previous commit to diff against; forcing WASM build."
|
||||
NEEDS_BUILD=true
|
||||
fi
|
||||
|
||||
echo "Changed files:"
|
||||
echo "${CHANGED}"
|
||||
|
||||
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
|
||||
echo "Manual dispatch - force WASM build."
|
||||
NEEDS_BUILD=true
|
||||
fi
|
||||
|
||||
if echo "${CHANGED}" | grep -qE '\.(cc|cpp|h|hpp|c)$|CMakeLists\.txt|CMakePresets\.json|build-wasm\.sh'; then
|
||||
echo "C++ or build files changed - full WASM build required"
|
||||
NEEDS_BUILD=true
|
||||
fi
|
||||
|
||||
echo "needs_wasm_build=${NEEDS_BUILD}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
# --- Cache CPM dependencies ---
|
||||
- name: Cache CPM packages
|
||||
if: steps.changes.outputs.needs_wasm_build == 'true' || steps.wasm_cache.outputs.has_cached_wasm == 'false'
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/CPM
|
||||
key: cpm-wasm-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
restore-keys: |
|
||||
cpm-wasm-
|
||||
|
||||
# --- Cache WASM build artifacts ---
|
||||
- name: Cache WASM build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
build_wasm_ai/bin
|
||||
build_wasm_ai/CMakeCache.txt
|
||||
build_wasm_ai/CMakeFiles
|
||||
key: wasm-build-${{ hashFiles('src/**/*.cc', 'src/**/*.h', 'CMakeLists.txt', 'CMakePresets.json') }}
|
||||
restore-keys: |
|
||||
wasm-build-
|
||||
|
||||
- name: Check cached WASM artifacts
|
||||
if: steps.changes.outputs.needs_wasm_build == 'false'
|
||||
id: wasm_cache
|
||||
run: |
|
||||
if [ -f build_wasm_ai/bin/yaze.js ] && [ -f build_wasm_ai/bin/yaze.wasm ]; then
|
||||
echo "Cached WASM found."
|
||||
echo "has_cached_wasm=true" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
echo "No cached WASM artifacts; will trigger a build."
|
||||
echo "has_cached_wasm=false" >> "${GITHUB_OUTPUT}"
|
||||
fi
|
||||
|
||||
# --- Setup Tools (only if WASM build needed or cache missing) ---
|
||||
- name: Setup Emscripten
|
||||
if: steps.changes.outputs.needs_wasm_build == 'true' || steps.wasm_cache.outputs.has_cached_wasm == 'false'
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: 3.1.51
|
||||
actions-cache-folder: 'emsdk-cache'
|
||||
|
||||
- name: Setup Ninja
|
||||
if: steps.changes.outputs.needs_wasm_build == 'true' || steps.wasm_cache.outputs.has_cached_wasm == 'false'
|
||||
uses: seanmiddleditch/gha-setup-ninja@v4
|
||||
|
||||
- name: Setup CMake
|
||||
if: steps.changes.outputs.needs_wasm_build == 'true' || steps.wasm_cache.outputs.has_cached_wasm == 'false'
|
||||
uses: jwlawson/actions-setup-cmake@v1.14
|
||||
with:
|
||||
cmake-version: '3.27.x'
|
||||
|
||||
- name: Setup ccache
|
||||
if: steps.changes.outputs.needs_wasm_build == 'true' || steps.wasm_cache.outputs.has_cached_wasm == 'false'
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: wasm-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: Install Graphviz
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y graphviz
|
||||
|
||||
- name: Install Doxygen 1.10.0
|
||||
uses: ssciwr/doxygen-install@v1
|
||||
with:
|
||||
version: "1.10.0"
|
||||
|
||||
# --- Build Web App (full build or use cache) ---
|
||||
- name: Build WASM App
|
||||
if: steps.changes.outputs.needs_wasm_build == 'true' || steps.wasm_cache.outputs.has_cached_wasm == 'false'
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:$PATH"
|
||||
chmod +x scripts/build-wasm.sh
|
||||
./scripts/build-wasm.sh ai
|
||||
|
||||
- name: Use cached WASM + update web assets
|
||||
if: steps.changes.outputs.needs_wasm_build == 'false' && steps.wasm_cache.outputs.has_cached_wasm == 'true'
|
||||
run: |
|
||||
echo "Using cached WASM build, updating web assets only..."
|
||||
mkdir -p build_wasm_ai/dist
|
||||
|
||||
# Check if we have cached WASM files
|
||||
if [ -f build_wasm_ai/bin/yaze.wasm ]; then
|
||||
cp build_wasm_ai/bin/yaze.html build_wasm_ai/dist/index.html
|
||||
cp build_wasm_ai/bin/yaze.js build_wasm_ai/dist/
|
||||
cp build_wasm_ai/bin/yaze.wasm build_wasm_ai/dist/
|
||||
cp build_wasm_ai/bin/yaze.data build_wasm_ai/dist/ 2>/dev/null || true
|
||||
# CRITICAL: Copy pthread worker script for multi-threading
|
||||
cp build_wasm_ai/bin/yaze.worker.js build_wasm_ai/dist/ 2>/dev/null || true
|
||||
else
|
||||
echo "ERROR: No cached WASM build found. Triggering full build..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy updated web assets (new directory structure)
|
||||
# Root level files
|
||||
cp src/web/app.js build_wasm_ai/dist/
|
||||
|
||||
# Copy subdirectories
|
||||
cp -r src/web/styles build_wasm_ai/dist/ 2>/dev/null || true
|
||||
cp -r src/web/components build_wasm_ai/dist/ 2>/dev/null || true
|
||||
cp -r src/web/core build_wasm_ai/dist/ 2>/dev/null || true
|
||||
cp -r src/web/pwa build_wasm_ai/dist/ 2>/dev/null || true
|
||||
cp -r src/web/icons build_wasm_ai/dist/ 2>/dev/null || true
|
||||
cp -r src/web/debug build_wasm_ai/dist/ 2>/dev/null || true
|
||||
|
||||
# CRITICAL: coi-serviceworker.js must be at root for proper service worker scope
|
||||
if [ -f src/web/pwa/coi-serviceworker.js ]; then
|
||||
cp src/web/pwa/coi-serviceworker.js build_wasm_ai/dist/
|
||||
echo "coi-serviceworker.js copied to root (required for SharedArrayBuffer)"
|
||||
else
|
||||
echo "WARNING: coi-serviceworker.js not found!"
|
||||
fi
|
||||
|
||||
# Copy yaze icon
|
||||
if [ -f assets/yaze.png ]; then
|
||||
mkdir -p build_wasm_ai/dist/assets
|
||||
cp assets/yaze.png build_wasm_ai/dist/assets/
|
||||
fi
|
||||
|
||||
echo "Web assets updated!"
|
||||
|
||||
# --- Build Documentation ---
|
||||
- name: Build Documentation
|
||||
run: |
|
||||
mkdir -p build/docs
|
||||
doxygen Doxyfile
|
||||
# Move docs into dist/docs
|
||||
mkdir -p build_wasm_ai/dist/docs
|
||||
mv build/docs/html/* build_wasm_ai/dist/docs/
|
||||
|
||||
# --- Deploy ---
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Upload Pages artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: build_wasm_ai/dist/
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
54
.gitignore
vendored
54
.gitignore
vendored
@@ -1,8 +1,8 @@
|
||||
# Build directories - organized by platform
|
||||
build/
|
||||
build-*/
|
||||
out/
|
||||
build*/
|
||||
# Build directories - organized by platform (root level only)
|
||||
/build/
|
||||
/build-*/
|
||||
/build_*/
|
||||
/out/
|
||||
docs/html/
|
||||
docs/latex/
|
||||
|
||||
@@ -14,7 +14,7 @@ compile_commands.json
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
CTestTestfile.cmake
|
||||
Testing/
|
||||
CMakeUserPresets.json
|
||||
|
||||
# Build artifacts
|
||||
*.o
|
||||
@@ -33,16 +33,15 @@ Testing/
|
||||
*.swo
|
||||
*~
|
||||
.DS_Store
|
||||
src/ios/yaze_ios.xcodeproj/
|
||||
src/ios/yaze.xcodeproj/xcuserdata/
|
||||
src/ios/yaze.xcodeproj/project.xcworkspace/xcuserdata/
|
||||
|
||||
# Test outputs
|
||||
test_screenshots/
|
||||
test_temp_rom.sfc
|
||||
zelda3_v3_test.sfc
|
||||
|
||||
# Logs
|
||||
yaze_log.txt
|
||||
*.log
|
||||
|
||||
# vcpkg
|
||||
vcpkg_installed/
|
||||
|
||||
@@ -79,6 +78,7 @@ src/lib/cmake/
|
||||
src/lib/GL/
|
||||
src/lib/libpng/
|
||||
src/lib/zlib/
|
||||
assets/asm/usdasm/
|
||||
src/app/gui/modules/component.h
|
||||
src/ios/macOS/Info-macOS.plist
|
||||
src/ios/macOS/MainMenu.storyboard
|
||||
@@ -93,3 +93,37 @@ recent_files.txt
|
||||
.gitignore
|
||||
.genkit
|
||||
.claude
|
||||
scripts/__pycache__/
|
||||
build_gemini
|
||||
scripts/ai/results/*.json
|
||||
scripts/ai/results/*.md
|
||||
scripts/ai/results/*.txt
|
||||
logs/breakthrough_test.log
|
||||
logs/cmake_config 2.log
|
||||
logs/cmake_config 3.log
|
||||
logs/cmake_config.log
|
||||
logs/dungeon_debug.log
|
||||
logs/final_rendering.log
|
||||
logs/flag_fix_enhanced_test.log
|
||||
logs/flag_fix_test.log
|
||||
logs/layout_rendering.log
|
||||
logs/layout_tiles_test.log
|
||||
logs/scale_test.log
|
||||
logs/test_fixed.log
|
||||
logs/test_output.log
|
||||
logs/tile_data_test.log
|
||||
logs/timing_analysis.log
|
||||
logs/visual_test.log
|
||||
logs/windows_ci_linker_error.log
|
||||
logs/yaze_emu_trace.log
|
||||
logs/yaze_release.wasm
|
||||
logs/yaze_release.wat
|
||||
logs/build-logs-Windows 2022 (Clang)/build.log
|
||||
logs/build-logs-Windows 2022 (Clang)/cmake_config.log
|
||||
logs/build-logs-Windows 2022 (Clang-CL)/build.log
|
||||
logs/build-logs-Windows 2022 (Clang-CL)/cmake_config.log
|
||||
vanilla.sfc
|
||||
zelda3.sfc
|
||||
yaze_manual.log
|
||||
yaze_startup.log
|
||||
roms/
|
||||
|
||||
32
.gitmodules
vendored
32
.gitmodules
vendored
@@ -1,27 +1,15 @@
|
||||
[submodule "src/lib/imgui"]
|
||||
path = src/lib/imgui
|
||||
[submodule "ext/imgui"]
|
||||
path = ext/imgui
|
||||
url = https://github.com/ocornut/imgui.git
|
||||
[submodule "assets/asm/alttp-hacker-workspace"]
|
||||
path = assets/asm/alttp-hacker-workspace
|
||||
url = https://github.com/scawful/alttp-hacker-workspace.git
|
||||
[submodule "src/lib/SDL"]
|
||||
path = src/lib/SDL
|
||||
[submodule "ext/SDL"]
|
||||
path = ext/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
[submodule "src/lib/asar"]
|
||||
path = src/lib/asar
|
||||
[submodule "ext/asar"]
|
||||
path = ext/asar
|
||||
url = https://github.com/RPGHacker/asar.git
|
||||
[submodule "src/lib/imgui_test_engine"]
|
||||
path = src/lib/imgui_test_engine
|
||||
[submodule "ext/imgui_test_engine"]
|
||||
path = ext/imgui_test_engine
|
||||
url = https://github.com/ocornut/imgui_test_engine.git
|
||||
[submodule "src/lib/nativefiledialog-extended"]
|
||||
path = src/lib/nativefiledialog-extended
|
||||
[submodule "ext/nativefiledialog-extended"]
|
||||
path = ext/nativefiledialog-extended
|
||||
url = https://github.com/btzy/nativefiledialog-extended.git
|
||||
[submodule "assets/asm/usdasm"]
|
||||
path = assets/asm/usdasm
|
||||
url = https://github.com/spannerisms/usdasm.git
|
||||
[submodule "third_party/json"]
|
||||
path = third_party/json
|
||||
url = https://github.com/nlohmann/json.git
|
||||
[submodule "third_party/httplib"]
|
||||
path = third_party/httplib
|
||||
url = https://github.com/yhirose/cpp-httplib.git
|
||||
|
||||
81
.pre-commit-config.yaml
Normal file
81
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,81 @@
|
||||
# Pre-commit hooks for YAZE
|
||||
# Install with: pip install pre-commit && pre-commit install
|
||||
|
||||
repos:
|
||||
# Clang format
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v18.1.0
|
||||
hooks:
|
||||
- id: clang-format
|
||||
args: [--style=Google, -i]
|
||||
files: \.(cc|cpp|h|hpp)$
|
||||
exclude: ^(src/lib/|third_party/)
|
||||
|
||||
# Clang tidy
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: clang-tidy
|
||||
name: clang-tidy
|
||||
entry: clang-tidy
|
||||
language: system
|
||||
args: [--header-filter=src/.*\.(h|hpp)$]
|
||||
files: \.(cc|cpp)$
|
||||
exclude: ^(src/lib/|third_party/)
|
||||
|
||||
# Cppcheck
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cppcheck
|
||||
name: cppcheck
|
||||
entry: cppcheck
|
||||
language: system
|
||||
args: [--enable=warning,style,performance, --inconclusive, --error-exitcode=0]
|
||||
files: \.(cc|cpp|h|hpp)$
|
||||
exclude: ^(src/lib/|third_party/)
|
||||
|
||||
# General hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-json
|
||||
- id: check-merge-conflict
|
||||
- id: check-added-large-files
|
||||
args: [--maxkb=1000]
|
||||
- id: check-case-conflict
|
||||
- id: check-merge-conflict
|
||||
- id: mixed-line-ending
|
||||
args: [--fix=lf]
|
||||
|
||||
# CMake formatting
|
||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||
rev: v0.6.13
|
||||
hooks:
|
||||
- id: cmake-format
|
||||
args: [--config-files=cmake-format.yaml]
|
||||
files: CMakeLists\.txt$|\.cmake$
|
||||
|
||||
# Shell script linting
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.9.0.6
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
files: \.(sh|bash)$
|
||||
|
||||
# Python linting (for scripts)
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.12.1
|
||||
hooks:
|
||||
- id: black
|
||||
files: \.py$
|
||||
exclude: ^(third_party/|build/)
|
||||
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
files: \.py$
|
||||
exclude: ^(third_party/|build/)
|
||||
|
||||
60
AGENTS.md
Normal file
60
AGENTS.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Agent Protocol
|
||||
|
||||
_Extends: ~/AGENTS.md_
|
||||
|
||||
Project-specific operating procedures for AI agents contributing to `yaze`.
|
||||
|
||||
## 1. Persona Adoption
|
||||
**Rule:** You must adopt a specific persona for every session.
|
||||
* **Source of Truth:** [docs/internal/agents/personas.md](docs/internal/agents/personas.md)
|
||||
* **Requirement:** Use the exact `Agent ID` from that list in all logs, commits, and board updates.
|
||||
* **Legacy IDs:** Do not use `CLAUDE_CORE`, `CLAUDE_AIINF`, etc. Use the role-based IDs (e.g., `ai-infra-architect`).
|
||||
* **System Prompts:** Load the matching persona prompt from `.claude/agents/<agent-id>.md` (accessible to all agents) before starting work.
|
||||
|
||||
## 2. Workflows & Coordination
|
||||
|
||||
### Quick Tasks (< 30 min)
|
||||
* **Board:** No update required.
|
||||
* **Tools:** Use `z3ed agent todo` to track your own sub-steps if helpful.
|
||||
* **Commit:** Commit directly with a clear message.
|
||||
|
||||
### Substantial Work (> 30 min / Multi-file)
|
||||
1. **Check Context:**
|
||||
* Read [docs/internal/agents/coordination-board.md](docs/internal/agents/coordination-board.md) for `REQUEST` or `BLOCKER` tags.
|
||||
* Run `git status` and `git diff` to understand the current state.
|
||||
2. **Declare Intent:**
|
||||
* If your work overlaps with an active task on the board, post a note or Request for Comments (RFC) there first.
|
||||
* Otherwise, log a new entry on the **Coordination Board**.
|
||||
3. **Execute:**
|
||||
* Use `z3ed agent todo` to break down the complex task.
|
||||
* Use `z3ed agent handoff` if you cannot finish in one session.
|
||||
|
||||
### Multi-Day Initiatives
|
||||
* Create a dedicated document using [docs/internal/agents/initiative-template.md](docs/internal/agents/initiative-template.md).
|
||||
* Link to this document from the Coordination Board.
|
||||
|
||||
### Specs & Docs
|
||||
* Keep one canonical spec per initiative (link it from the board entry and back).
|
||||
* Add a header with Status/Owner/Created/Last Reviewed/Next Review (≤14 days) and validation/exit criteria.
|
||||
* Use existing templates (`initiative-template.md`, `release-checklist-template.md`) instead of creating ad-hoc files.
|
||||
* Archive idle or completed specs to `docs/internal/agents/archive/` with the date; do not open duplicate status pages.
|
||||
|
||||
## 3. The Coordination Board
|
||||
**Location:** `docs/internal/agents/coordination-board.md`
|
||||
|
||||
* **Hygiene:** Keep entries concise (≤ 5 lines).
|
||||
* **Status:** Update your entry status to `COMPLETE` or `ARCHIVED` when done.
|
||||
* **Maintenance:** Archive completed work weekly to `docs/internal/agents/archive/`.
|
||||
|
||||
## 4. Helper Scripts
|
||||
Located in `scripts/agents/`:
|
||||
* `run-gh-workflow.sh`: Trigger CI manually.
|
||||
* `smoke-build.sh`: Fast verification build.
|
||||
* `test-http-api.sh`: Validate the agent API.
|
||||
|
||||
**Log results:** When running these scripts for significant validation, paste the run ID or result summary to the Board.
|
||||
|
||||
## 5. Documentation Hygiene
|
||||
- Follow [docs/internal/agents/doc-hygiene.md](docs/internal/agents/doc-hygiene.md) to avoid doc sprawl.
|
||||
- Keep specs short, template-driven, and linked to the coordination board; prefer edits over new files.
|
||||
- Archive completed/idle docs (>=14 days) under `docs/internal/agents/archive/` with dates to keep the root clean.
|
||||
64
CLAUDE.md
Normal file
64
CLAUDE.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# CLAUDE.md
|
||||
|
||||
_Extends: ~/AGENTS.md, ~/CLAUDE.md_
|
||||
|
||||
C++23 ROM editor for Zelda: A Link to the Past. GUI editor + SNES emulator + AI CLI (`z3ed`).
|
||||
|
||||
## Build & Test
|
||||
|
||||
```bash
|
||||
cmake --preset mac-dbg && cmake --build build -j8 # Build
|
||||
ctest --test-dir build -L stable -j4 # Test
|
||||
./yaze --rom_file=zelda3.sfc --editor=Dungeon # Run
|
||||
```
|
||||
|
||||
Presets: `mac-dbg`/`lin-dbg`/`win-dbg`, `mac-ai`/`win-ai`, `*-rel`. See `docs/public/build/quick-reference.md`.
|
||||
|
||||
## Architecture
|
||||
|
||||
| Component | Location | Purpose |
|
||||
|-----------|----------|---------|
|
||||
| Rom | `src/app/rom.h` | ROM data access, transactions |
|
||||
| Editors | `src/app/editor/` | Overworld, Dungeon, Graphics, Palette |
|
||||
| Graphics | `src/app/gfx/` | Bitmap, Arena (async loading), Tiles |
|
||||
| Zelda3 | `src/zelda3/` | Overworld (160 maps), Dungeon (296 rooms) |
|
||||
| Canvas | `src/app/gui/canvas.h` | ImGui canvas with pan/zoom |
|
||||
| CLI | `src/cli/z3ed.cc` | AI-powered ROM hacking tool |
|
||||
|
||||
## Key Patterns
|
||||
|
||||
**Graphics refresh**: Update model → `Load*()` → `Renderer::Get().RenderBitmap()`
|
||||
|
||||
**Async loading**: `Arena::Get().QueueDeferredTexture(bitmap, priority)` + process in `Update()`
|
||||
|
||||
**Bitmap sync**: Use `set_data()` for bulk updates (syncs `data_` and `surface_->pixels`)
|
||||
|
||||
**Theming**: Always use `AgentUI::GetTheme()`, never hardcoded colors
|
||||
|
||||
**Multi-area maps**: Always use `Overworld::ConfigureMultiAreaMap()`, never set `area_size` directly
|
||||
|
||||
## Naming
|
||||
|
||||
- **Load**: ROM → memory
|
||||
- **Render**: Data → bitmap (CPU)
|
||||
- **Draw**: Bitmap → screen (GPU)
|
||||
|
||||
## Pitfalls
|
||||
|
||||
1. Use `set_data()` not `mutable_data()` assignment for bitmap bulk updates
|
||||
2. Call `ProcessTextureQueue()` every frame
|
||||
3. Pass `0x800` to `DecompressV2`, never `0`
|
||||
4. SMC header: `size % 1MB == 512`, not `size % 32KB`
|
||||
5. Check `rom_->is_loaded()` before ROM operations
|
||||
|
||||
## Code Style
|
||||
|
||||
Google C++ Style. Use `absl::Status`/`StatusOr<T>` with `RETURN_IF_ERROR()`/`ASSIGN_OR_RETURN()`.
|
||||
|
||||
Format: `cmake --build build --target format`
|
||||
|
||||
## Docs
|
||||
|
||||
- Architecture: `docs/internal/architecture/`
|
||||
- Build issues: `docs/BUILD-TROUBLESHOOTING.md`
|
||||
- Tests: `test/README.md`
|
||||
161
CMakeLists.txt
161
CMakeLists.txt
@@ -8,35 +8,62 @@ set(CMAKE_POLICY_VERSION_MINIMUM 3.5 CACHE STRING "Minimum policy version for su
|
||||
|
||||
# Set policies for compatibility
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
|
||||
# Ensure we consistently use the static MSVC runtime (/MT, /MTd) to match vcpkg static triplets
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE STRING "" FORCE)
|
||||
# CMP0091 allows CMAKE_MSVC_RUNTIME_LIBRARY to be set by presets
|
||||
# Windows presets specify dynamic CRT (/MD) to avoid linking issues
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
cmake_policy(SET CMP0077 NEW)
|
||||
|
||||
# Enable Objective-C only on macOS where it's actually used
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
project(yaze VERSION 0.3.2
|
||||
if(DEFINED ENV{YAZE_VERSION_OVERRIDE})
|
||||
set(YAZE_VERSION $ENV{YAZE_VERSION_OVERRIDE})
|
||||
elseif(DEFINED YAZE_VERSION_OVERRIDE)
|
||||
set(YAZE_VERSION ${YAZE_VERSION_OVERRIDE})
|
||||
else()
|
||||
set(YAZE_VERSION "0.5.0")
|
||||
set(YAZE_VERSION_SUFFIX "")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
project(yaze VERSION ${YAZE_VERSION}
|
||||
DESCRIPTION "Yet Another Zelda3 Editor"
|
||||
LANGUAGES CXX C OBJC OBJCXX)
|
||||
else()
|
||||
project(yaze VERSION 0.3.2
|
||||
project(yaze VERSION ${YAZE_VERSION}
|
||||
DESCRIPTION "Yet Another Zelda3 Editor"
|
||||
LANGUAGES CXX C)
|
||||
endif()
|
||||
|
||||
# Enable ccache for faster rebuilds if available
|
||||
# Set language standards early so dependencies (e.g., Abseil) build with them.
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
# Include build options first
|
||||
include(cmake/options.cmake)
|
||||
|
||||
# Enable sccache/ccache for faster rebuilds if available
|
||||
find_program(SCCACHE_FOUND sccache)
|
||||
if(SCCACHE_FOUND)
|
||||
message(STATUS "✓ sccache found, enabling for faster builds")
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER sccache)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER sccache)
|
||||
else()
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
message(STATUS "✓ ccache found, enabling for faster builds")
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ccache)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ccache)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set project metadata
|
||||
set(YAZE_VERSION_MAJOR 0)
|
||||
set(YAZE_VERSION_MINOR 3)
|
||||
set(YAZE_VERSION_PATCH 2)
|
||||
# Version is defined in project() above - use those variables
|
||||
# CMake automatically sets: yaze_VERSION, yaze_VERSION_MAJOR, yaze_VERSION_MINOR, yaze_VERSION_PATCH
|
||||
# These YAZE_VERSION_* aliases are for compatibility with existing code
|
||||
set(YAZE_VERSION_MAJOR ${yaze_VERSION_MAJOR})
|
||||
set(YAZE_VERSION_MINOR ${yaze_VERSION_MINOR})
|
||||
set(YAZE_VERSION_PATCH ${yaze_VERSION_PATCH})
|
||||
|
||||
# Suppress deprecation warnings from submodules
|
||||
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Suppress deprecation warnings")
|
||||
@@ -44,64 +71,37 @@ set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Suppress deprecation warnings")
|
||||
# Add cmake directory to module path
|
||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
|
||||
# Include utility functions
|
||||
include(cmake/utils.cmake)
|
||||
|
||||
# Build Flags
|
||||
set(YAZE_BUILD_APP ON)
|
||||
set(YAZE_BUILD_LIB ON)
|
||||
set(YAZE_BUILD_EMU ON)
|
||||
set(YAZE_BUILD_Z3ED ON)
|
||||
set(YAZE_BUILD_TESTS ON CACHE BOOL "Build test suite")
|
||||
set(YAZE_INSTALL_LIB OFF)
|
||||
|
||||
# Testing and CI Configuration
|
||||
option(YAZE_ENABLE_ROM_TESTS "Enable tests that require ROM files" OFF)
|
||||
option(YAZE_MINIMAL_BUILD "Minimal build for CI (disable optional features)" OFF)
|
||||
option(YAZE_UNITY_BUILD "Enable Unity (Jumbo) builds" OFF)
|
||||
|
||||
# Feature Flags - Simplified: Always enabled by default (use wrapper classes to hide complexity)
|
||||
# JSON is header-only with minimal overhead
|
||||
# gRPC is only used in agent/cli tools, not in core editor runtime
|
||||
set(YAZE_WITH_JSON ON)
|
||||
set(YAZE_WITH_GRPC ON)
|
||||
set(Z3ED_AI ON)
|
||||
|
||||
# Minimal build override - disable only the most expensive features
|
||||
if(YAZE_MINIMAL_BUILD)
|
||||
set(YAZE_WITH_GRPC OFF)
|
||||
set(Z3ED_AI OFF)
|
||||
message(STATUS "✓ Minimal build: gRPC and AI disabled")
|
||||
else()
|
||||
message(STATUS "✓ Full build: All features enabled (JSON, gRPC, AI)")
|
||||
endif()
|
||||
|
||||
# Define preprocessor macros for feature flags (so #ifdef works in source code)
|
||||
if(YAZE_WITH_GRPC)
|
||||
add_compile_definitions(YAZE_WITH_GRPC)
|
||||
endif()
|
||||
if(YAZE_WITH_JSON)
|
||||
add_compile_definitions(YAZE_WITH_JSON)
|
||||
endif()
|
||||
if(Z3ED_AI)
|
||||
add_compile_definitions(Z3ED_AI)
|
||||
endif()
|
||||
|
||||
option(YAZE_SUPPRESS_WARNINGS "Suppress compiler warnings (use -v preset suffix for verbose)" ON)
|
||||
set(YAZE_TEST_ROM_PATH "${CMAKE_BINARY_DIR}/bin/zelda3.sfc" CACHE STRING "Path to test ROM file")
|
||||
|
||||
# Export compile commands for clangd/LSP
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Platform detection
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
if(APPLE)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
set(YAZE_PLATFORM_IOS ON)
|
||||
else()
|
||||
set(YAZE_PLATFORM_MACOS ON)
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(YAZE_PLATFORM_LINUX ON)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
set(YAZE_PLATFORM_WINDOWS ON)
|
||||
endif()
|
||||
|
||||
# Include utility functions
|
||||
include(cmake/utils.cmake)
|
||||
|
||||
# Set up dependencies using CPM.cmake
|
||||
include(cmake/dependencies.cmake)
|
||||
|
||||
# Additional configuration options
|
||||
option(YAZE_SUPPRESS_WARNINGS "Suppress compiler warnings (use -v preset suffix for verbose)" ON)
|
||||
set(YAZE_TEST_ROM_VANILLA_PATH "" CACHE STRING "Path to vanilla test ROM file")
|
||||
set(YAZE_TEST_ROM_US_PATH "" CACHE STRING "Path to US test ROM file")
|
||||
set(YAZE_TEST_ROM_JP_PATH "" CACHE STRING "Path to JP test ROM file")
|
||||
set(YAZE_TEST_ROM_EU_PATH "" CACHE STRING "Path to EU test ROM file")
|
||||
set(YAZE_TEST_ROM_EXPANDED_PATH "" CACHE STRING "Path to expanded test ROM file")
|
||||
set(YAZE_TEST_ROM_PATH "" CACHE STRING "Legacy path to test ROM file (vanilla)")
|
||||
|
||||
# Export compile commands for clangd/LSP
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Setup compiler flags and common interface target
|
||||
yaze_add_compiler_flags()
|
||||
|
||||
@@ -121,13 +121,11 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
# Handle dependencies
|
||||
include(cmake/dependencies.cmake)
|
||||
|
||||
# Project Files
|
||||
add_subdirectory(src)
|
||||
|
||||
# Tools
|
||||
option(YAZE_BUILD_TOOLS "Build development utility tools" OFF)
|
||||
if(YAZE_BUILD_TOOLS)
|
||||
message(STATUS "Building development tools")
|
||||
add_subdirectory(tools)
|
||||
@@ -139,7 +137,27 @@ if(YAZE_BUILD_TESTS)
|
||||
endif()
|
||||
|
||||
# Code quality targets
|
||||
find_program(CLANG_FORMAT NAMES clang-format clang-format-14 clang-format-15 clang-format-16 clang-format-17 clang-format-18)
|
||||
if(YAZE_ENABLE_CLANG_TIDY)
|
||||
if(NOT YAZE_CLANG_TIDY_EXE)
|
||||
find_program(YAZE_CLANG_TIDY_EXE NAMES clang-tidy clang-tidy-18 clang-tidy-17 clang-tidy-16)
|
||||
endif()
|
||||
|
||||
if(YAZE_CLANG_TIDY_EXE)
|
||||
message(STATUS "✓ clang-tidy enabled: ${YAZE_CLANG_TIDY_EXE}")
|
||||
set(CMAKE_CXX_CLANG_TIDY "${YAZE_CLANG_TIDY_EXE}")
|
||||
else()
|
||||
message(WARNING "clang-tidy requested but not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_program(CLANG_FORMAT
|
||||
NAMES clang-format-18 clang-format
|
||||
HINTS "${HOMEBREW_LLVM_PREFIX}/bin" # Prefer clang-format from Homebrew LLVM
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(NOT CLANG_FORMAT) # Fallback to generic search if not found in Homebrew prefix
|
||||
find_program(CLANG_FORMAT NAMES clang-format clang-format-17 clang-format-16 clang-format-15 clang-format-14)
|
||||
endif()
|
||||
if(CLANG_FORMAT)
|
||||
file(GLOB_RECURSE ALL_SOURCE_FILES
|
||||
"${CMAKE_SOURCE_DIR}/src/*.cc"
|
||||
@@ -147,19 +165,24 @@ if(CLANG_FORMAT)
|
||||
"${CMAKE_SOURCE_DIR}/test/*.cc"
|
||||
"${CMAKE_SOURCE_DIR}/test/*.h")
|
||||
|
||||
add_custom_target(format
|
||||
COMMAND ${CLANG_FORMAT} -i --style=Google ${ALL_SOURCE_FILES}
|
||||
# Exclude third-party library directories from formatting
|
||||
list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX "src/lib/.*")
|
||||
|
||||
add_custom_target(yaze-format
|
||||
COMMAND ${CLANG_FORMAT} -i --style=file ${ALL_SOURCE_FILES}
|
||||
COMMENT "Running clang-format on source files"
|
||||
)
|
||||
|
||||
add_custom_target(format-check
|
||||
COMMAND ${CLANG_FORMAT} --dry-run --Werror --style=Google ${ALL_SOURCE_FILES}
|
||||
add_custom_target(yaze-format-check
|
||||
COMMAND ${CLANG_FORMAT} --dry-run --Werror --style=file ${ALL_SOURCE_FILES}
|
||||
COMMENT "Checking code format"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Packaging configuration
|
||||
include(cmake/packaging.cmake)
|
||||
if(NOT YAZE_PLATFORM_IOS)
|
||||
include(cmake/packaging/cpack.cmake)
|
||||
endif()
|
||||
|
||||
add_custom_target(build_cleaner
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running scripts/build_cleaner.py --dry-run"
|
||||
|
||||
1922
CMakePresets.json
1922
CMakePresets.json
File diff suppressed because it is too large
Load Diff
49
CMakeUserPresets.json.example
Normal file
49
CMakeUserPresets.json.example
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"version": 6,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "dev-local",
|
||||
"inherits": "dev",
|
||||
"binaryDir": "$env{YAZE_BUILD_ROOT}/build",
|
||||
"environment": {
|
||||
"CPM_SOURCE_CACHE": "$env{HOME}/.cpm-cache",
|
||||
"VCPKG_DOWNLOADS": "$env{HOME}/.cache/vcpkg/downloads",
|
||||
"VCPKG_BINARY_SOURCES": "clear;files,$env{HOME}/.cache/vcpkg/bincache,readwrite"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wasm-debug-local",
|
||||
"inherits": "wasm-debug",
|
||||
"binaryDir": "$env{YAZE_BUILD_ROOT}/build-wasm",
|
||||
"environment": {
|
||||
"CPM_SOURCE_CACHE": "$env{HOME}/.cpm-cache",
|
||||
"VCPKG_DOWNLOADS": "$env{HOME}/.cache/vcpkg/downloads",
|
||||
"VCPKG_BINARY_SOURCES": "clear;files,$env{HOME}/.cache/vcpkg/bincache,readwrite"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wasm-release-local",
|
||||
"inherits": "wasm-release",
|
||||
"binaryDir": "$env{YAZE_BUILD_ROOT}/build-wasm",
|
||||
"environment": {
|
||||
"CPM_SOURCE_CACHE": "$env{HOME}/.cpm-cache",
|
||||
"VCPKG_DOWNLOADS": "$env{HOME}/.cache/vcpkg/downloads",
|
||||
"VCPKG_BINARY_SOURCES": "clear;files,$env{HOME}/.cache/vcpkg/bincache,readwrite"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "dev-local",
|
||||
"configurePreset": "dev-local"
|
||||
},
|
||||
{
|
||||
"name": "wasm-debug-local",
|
||||
"configurePreset": "wasm-debug-local"
|
||||
},
|
||||
{
|
||||
"name": "wasm-release-local",
|
||||
"configurePreset": "wasm-release-local"
|
||||
}
|
||||
]
|
||||
}
|
||||
14
Doxyfile
14
Doxyfile
@@ -74,7 +74,7 @@ PROJECT_ICON = "assets/yaze.ico"
|
||||
# entered, it will be relative to the location where doxygen was started. If
|
||||
# left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY =
|
||||
OUTPUT_DIRECTORY = build/docs
|
||||
|
||||
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
|
||||
# sub-directories (in 2 levels) under the output directory of each output format
|
||||
@@ -949,7 +949,9 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT =
|
||||
INPUT = docs/public \
|
||||
src \
|
||||
incl
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
@@ -1057,8 +1059,10 @@ RECURSIVE = YES
|
||||
EXCLUDE = assets/ \
|
||||
build/ \
|
||||
cmake/ \
|
||||
docs/archive/ \
|
||||
src/lib/ \
|
||||
docs/html/ \
|
||||
docs/latex/ \
|
||||
docs/internal/ \
|
||||
src/lib/
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
@@ -1169,7 +1173,7 @@ FILTER_SOURCE_PATTERNS =
|
||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||
# and want to reuse the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE = getting-started.md
|
||||
USE_MDFILE_AS_MAINPAGE = docs/public/index.md
|
||||
|
||||
# The Fortran standard specifies that for fixed formatted Fortran code all
|
||||
# characters from position 72 are to be considered as comment. A common
|
||||
|
||||
354
GEMINI.md
Normal file
354
GEMINI.md
Normal file
@@ -0,0 +1,354 @@
|
||||
# GEMINI.md - YAZE Build Instructions
|
||||
|
||||
_Extends: ~/AGENTS.md, ~/GEMINI.md_
|
||||
|
||||
Build and test instructions for YAZE project. Follow commands exactly.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
1. **Use `build_ai/` directory** - Never use `build/` (reserved for user)
|
||||
2. **Use `*-ai` presets** - Never use `*-dbg` presets
|
||||
3. **Load persona** - Check `.claude/agents/<agent-id>.md` for system prompt
|
||||
4. **Use helper script:**
|
||||
```bash
|
||||
./scripts/agent_build.sh [target]
|
||||
```
|
||||
*Example:* `./scripts/agent_build.sh yaze` or `./scripts/agent_build.sh yaze_test`
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: Build Times
|
||||
|
||||
**First Build (Cold Start)**:
|
||||
- **Fast Mode (Recommended)**: 2-4 minutes (uses system gRPC/sccache)
|
||||
- Standard Mode: 10-20 minutes (compiles gRPC from source)
|
||||
|
||||
**Incremental Builds (After Changes)**:
|
||||
- Typically 10-60 seconds depending on what changed
|
||||
- **sccache/ccache**: Automatically detected and used if installed (highly recommended)
|
||||
|
||||
## Platform-Specific Build Commands
|
||||
|
||||
### macOS
|
||||
|
||||
```bash
|
||||
# Step 1: Configure (First time only, or when CMakeLists.txt changes)
|
||||
cmake --preset mac-ai
|
||||
|
||||
# Step 2: Build the entire project
|
||||
cmake --build build_ai --preset mac-ai
|
||||
|
||||
# Step 3: Build specific targets (faster for incremental work)
|
||||
cmake --build build_ai --target yaze # GUI application only
|
||||
cmake --build build_ai --target yaze_test # Test suite only
|
||||
cmake --build build_ai --target ylib # Core library only
|
||||
```
|
||||
|
||||
**Available macOS Presets**:
|
||||
- `mac-ai` - **Preferred for Agents**. Configured to use system gRPC/protobuf if available (brew installed) and defaults to `build_ai`.
|
||||
- `mac-dbg` - User's debug build (DO NOT USE).
|
||||
|
||||
### Linux
|
||||
|
||||
```bash
|
||||
# Step 1: Configure
|
||||
cmake --preset lin-ai
|
||||
|
||||
# Step 2: Build
|
||||
cmake --build build_ai --preset lin-ai
|
||||
```
|
||||
|
||||
**Available Linux Presets**:
|
||||
- `lin-ai` - **Preferred for Agents**. Uses `build_ai` and system libraries.
|
||||
|
||||
### Windows
|
||||
|
||||
```bash
|
||||
# Step 1: Configure (PowerShell or CMD)
|
||||
cmake --preset win-ai
|
||||
|
||||
# Step 2: Build
|
||||
cmake --build build_ai --preset win-ai
|
||||
```
|
||||
|
||||
**Available Windows Presets**:
|
||||
- `win-ai` - **Preferred for Agents**. Uses `build_ai`.
|
||||
|
||||
## Testing
|
||||
|
||||
### Running All Tests
|
||||
|
||||
```bash
|
||||
# Build tests first
|
||||
cmake --build build_ai --target yaze_test
|
||||
|
||||
# Run all tests
|
||||
./build_ai/bin/yaze_test
|
||||
```
|
||||
|
||||
### Running Specific Test Categories
|
||||
|
||||
```bash
|
||||
# Unit tests only (fast, ~5-10 seconds)
|
||||
./build/bin/yaze_test --unit
|
||||
|
||||
# Integration tests (requires ROM file)
|
||||
./build/bin/yaze_test --integration --rom-path /path/to/zelda3.sfc
|
||||
|
||||
# End-to-end GUI tests
|
||||
./build/bin/yaze_test --e2e --show-gui
|
||||
|
||||
# Run specific test by name pattern
|
||||
./build/bin/yaze_test "*Asar*" # All tests with "Asar" in name
|
||||
./build/bin/yaze_test "*Dungeon*" # All dungeon-related tests
|
||||
```
|
||||
|
||||
### Test Output Modes
|
||||
|
||||
```bash
|
||||
# Minimal output (default)
|
||||
./build/bin/yaze_test
|
||||
|
||||
# Verbose output (shows all test names)
|
||||
./build/bin/yaze_test -v
|
||||
|
||||
# Very verbose (shows detailed test execution)
|
||||
./build/bin/yaze_test -vv
|
||||
|
||||
# List all available tests without running
|
||||
./build/bin/yaze_test --list-tests
|
||||
```
|
||||
|
||||
## Common Build Issues and Solutions
|
||||
|
||||
### Issue 1: "No preset found"
|
||||
|
||||
**Error**: `CMake Error: No such preset in CMakePresets.json`
|
||||
|
||||
**Solution**: Check the exact preset name. Use tab-completion or check `CMakePresets.json`.
|
||||
|
||||
```bash
|
||||
# List available presets
|
||||
cmake --list-presets
|
||||
|
||||
# Common mistake: Using wrong platform prefix
|
||||
cmake --preset dbg # ❌ WRONG
|
||||
cmake --preset mac-dbg # ✅ CORRECT (macOS)
|
||||
cmake --preset lin-dbg # ✅ CORRECT (Linux)
|
||||
cmake --preset win-dbg # ✅ CORRECT (Windows)
|
||||
```
|
||||
|
||||
### Issue 2: "Build directory exists but is outdated"
|
||||
|
||||
**Error**: CMake complains about existing build directory
|
||||
|
||||
**Solution**: Clean and reconfigure
|
||||
|
||||
```bash
|
||||
# Remove old build directory
|
||||
rm -rf build
|
||||
|
||||
# Reconfigure from scratch
|
||||
cmake --preset mac-dbg # or lin-dbg / win-dbg
|
||||
```
|
||||
|
||||
### Issue 3: "Tests fail with 'ROM not found'"
|
||||
|
||||
**Error**: Integration tests fail with ROM-related errors
|
||||
|
||||
**Solution**: Some tests require a Zelda3 ROM file
|
||||
|
||||
```bash
|
||||
# Skip ROM-dependent tests
|
||||
./build/bin/yaze_test --unit
|
||||
|
||||
# Or provide ROM path
|
||||
./build/bin/yaze_test --integration --rom-path zelda3.sfc
|
||||
```
|
||||
|
||||
### Issue 4: Long build times on first run
|
||||
|
||||
**Not an Error**: This is normal!
|
||||
|
||||
**Explanation**:
|
||||
- CPM.cmake downloads all dependencies (~3-5 minutes)
|
||||
- gRPC compilation (Windows only, ~15-20 minutes)
|
||||
- ImGui compilation (~2-3 minutes)
|
||||
- SDL2, Abseil, PNG libraries (~3-5 minutes)
|
||||
|
||||
**Solution**: Be patient on first build. Subsequent builds use ccache/sccache and are MUCH faster (10-60 seconds).
|
||||
|
||||
```bash
|
||||
# Monitor build progress with verbose output
|
||||
cmake --build build --preset mac-dbg -v | tee build.log
|
||||
|
||||
# Check build log for specific step taking long
|
||||
grep "Linking" build.log
|
||||
```
|
||||
|
||||
### Issue 5: Incremental builds seem slow
|
||||
|
||||
**Solution**: Only rebuild what changed
|
||||
|
||||
```bash
|
||||
# Instead of rebuilding everything:
|
||||
cmake --build build --preset mac-dbg # ❌ Rebuilds all targets
|
||||
|
||||
# Build only what you need:
|
||||
cmake --build build --target yaze # ✅ Just the GUI app
|
||||
cmake --build build --target ylib # ✅ Just the core library
|
||||
cmake --build build --target object_editor_card # ✅ Just one component
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Typical Development Session
|
||||
|
||||
```bash
|
||||
# 1. Configure once (first time only)
|
||||
cmake --preset mac-dbg
|
||||
|
||||
# 2. Make code changes to src/app/editor/dungeon/object_editor_card.cc
|
||||
|
||||
# 3. Rebuild only the affected target (fast!)
|
||||
cmake --build build --target yaze
|
||||
|
||||
# 4. Run the application to test manually
|
||||
./build/bin/yaze --rom_file zelda3.sfc --editor Dungeon
|
||||
|
||||
# 5. Run automated tests to verify
|
||||
./build/bin/yaze_test --unit
|
||||
|
||||
# 6. If tests pass, commit
|
||||
git add src/app/editor/dungeon/object_editor_card.cc
|
||||
git commit -m "feat(dungeon): add feature X"
|
||||
```
|
||||
|
||||
### Testing Dungeon Editor Changes
|
||||
|
||||
```bash
|
||||
# 1. Build just the GUI app (includes dungeon editor)
|
||||
cmake --build build --target yaze
|
||||
|
||||
# 2. Launch directly to dungeon editor with ROM
|
||||
./build/bin/yaze --rom_file zelda3.sfc --editor Dungeon
|
||||
|
||||
# 3. To test keyboard shortcuts specifically:
|
||||
# - Open Object Editor card
|
||||
# - Try Ctrl+A (select all)
|
||||
# - Try Delete key (delete selected)
|
||||
# - Try Ctrl+D (duplicate)
|
||||
# - Try Arrow keys (nudge objects)
|
||||
# - Try Tab (cycle selection)
|
||||
```
|
||||
|
||||
### Before Committing Changes
|
||||
|
||||
```bash
|
||||
# 1. Run unit tests (fast check)
|
||||
./build/bin/yaze_test --unit
|
||||
|
||||
# 2. Run format check (ensure code style)
|
||||
cmake --build build --target format-check
|
||||
|
||||
# 3. If format check fails, auto-format
|
||||
cmake --build build --target format
|
||||
|
||||
# 4. Build in release mode to catch optimization warnings
|
||||
cmake --preset mac-rel
|
||||
cmake --build build --preset mac-rel
|
||||
|
||||
# 5. If all passes, you're ready to commit!
|
||||
```
|
||||
|
||||
## Preset Comparison Matrix
|
||||
|
||||
| Preset | Platform | Build Type | AI Features | gRPC | Agent UI | Use Case |
|
||||
|------------|----------|------------|-------------|------|----------|----------|
|
||||
| mac-dbg | macOS | Debug | No | No | No | Daily development |
|
||||
| mac-rel | macOS | Release | No | No | No | Performance testing |
|
||||
| mac-ai | macOS | Debug | Yes | Yes | Yes | z3ed development |
|
||||
| lin-dbg | Linux | Debug | No | No | No | Daily development |
|
||||
| lin-rel | Linux | Release | No | No | No | Performance testing |
|
||||
| lin-ai | Linux | Debug | Yes | Yes | Yes | z3ed development |
|
||||
| win-dbg | Windows | Debug | No | No | No | Daily development |
|
||||
| win-rel | Windows | Release | No | No | No | Performance testing |
|
||||
| win-ai | Windows | Debug | Yes | Yes | Yes | z3ed development |
|
||||
|
||||
## CI/CD Build Times (For Reference)
|
||||
|
||||
GitHub Actions runners typically see these build times:
|
||||
|
||||
- **Ubuntu 22.04**: 6-8 minutes (with caching)
|
||||
- **macOS 14**: 8-10 minutes (with caching)
|
||||
- **Windows 2022**: 12-18 minutes (gRPC adds time)
|
||||
|
||||
Your local builds may be faster or slower depending on:
|
||||
- CPU cores (more = faster parallel builds)
|
||||
- SSD speed (affects linking time)
|
||||
- Available RAM (swap = slower builds)
|
||||
- ccache/sccache hit rate (warm cache = much faster)
|
||||
|
||||
## Target Dependencies Reference
|
||||
|
||||
Understanding what rebuilds when you change files:
|
||||
|
||||
```
|
||||
yaze (GUI app)
|
||||
├── ylib (core library)
|
||||
│ ├── zelda3_dungeon (dungeon module)
|
||||
│ │ └── object_editor_card.cc ← Your changes here
|
||||
│ ├── zelda3_overworld
|
||||
│ ├── gfx (graphics system)
|
||||
│ └── core (compression, ROM I/O)
|
||||
├── imgui (UI framework)
|
||||
└── SDL2 (windowing/graphics)
|
||||
|
||||
yaze_test (test suite)
|
||||
├── ylib (same as above)
|
||||
├── gtest (Google Test framework)
|
||||
└── test/*.cc files
|
||||
```
|
||||
|
||||
**When you change**:
|
||||
- `object_editor_card.cc` → Rebuilds: ylib, yaze (30-60 seconds)
|
||||
- `object_editor_card.h` → Rebuilds: ylib, yaze, any test including header (1-2 minutes)
|
||||
- `rom.cc` → Rebuilds: Most of ylib, yaze, yaze_test (3-5 minutes)
|
||||
- `CMakeLists.txt` → Reconfigure + full rebuild (5-10 minutes)
|
||||
|
||||
## Quick Command Cheat Sheet
|
||||
|
||||
```bash
|
||||
# === Configuration ===
|
||||
cmake --list-presets # Show available presets
|
||||
cmake --preset mac-dbg # Configure for macOS debug
|
||||
|
||||
# === Building ===
|
||||
cmake --build build --target yaze # Build GUI app
|
||||
cmake --build build --target yaze_test # Build test suite
|
||||
cmake --build build --target format # Format all code
|
||||
cmake --build build -v # Verbose build output
|
||||
|
||||
# === Testing ===
|
||||
./build/bin/yaze_test # Run all tests
|
||||
./build/bin/yaze_test --unit # Unit tests only
|
||||
./build/bin/yaze_test "*Asar*" # Specific test pattern
|
||||
./build/bin/yaze_test --list-tests # List available tests
|
||||
|
||||
# === Running ===
|
||||
./build/bin/yaze # Launch GUI
|
||||
./build/bin/yaze --rom_file zelda3.sfc # Load ROM
|
||||
./build/bin/yaze --editor Dungeon # Open editor
|
||||
./build/bin/yaze --rom_file zelda3.sfc --editor Dungeon # Combined
|
||||
|
||||
# === Cleaning ===
|
||||
cmake --build build --target clean # Clean build artifacts
|
||||
rm -rf build # Full clean (reconfigure needed)
|
||||
```
|
||||
|
||||
## Key Reminders
|
||||
|
||||
- Use full preset names: `mac-ai` not just `ai`
|
||||
- First builds: 10-20 min (normal), incremental: 10-60 sec
|
||||
- Build specific targets: `--target yaze` faster than full build
|
||||
- Some tests require ROM file to pass
|
||||
185
README.md
185
README.md
@@ -1,139 +1,100 @@
|
||||
# yaze - Yet Another Zelda3 Editor
|
||||
# YAZE - Yet Another Zelda3 Editor
|
||||
|
||||
A modern, cross-platform editor for The Legend of Zelda: A Link to the Past ROM hacking, built with C++23 and featuring complete Asar 65816 assembler integration.
|
||||
[](https://github.com/scawful/yaze/actions)
|
||||
[](https://github.com/scawful/yaze/actions)
|
||||
[](https://github.com/scawful/yaze/actions)
|
||||
[](https://github.com/scawful/yaze/actions)
|
||||
[](LICENSE)
|
||||
|
||||
[](https://github.com/scawful/yaze/actions)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
A cross-platform Zelda 3 ROM editor with a modern C++ GUI, Asar 65816 assembler integration, and an automation-friendly CLI (`z3ed`). YAZE bundles its toolchain, offers AI-assisted editing flows, and targets reproducible builds on Windows, macOS, and Linux. A preview web version is also available for browser-based editing.
|
||||
|
||||
## Version 0.3.2 - Release
|
||||
## Highlights
|
||||
- **All-in-one editing**: Overworld, dungeon, sprite, palette, and messaging tools with live previews.
|
||||
- **Assembler-first workflow**: Built-in Asar integration, symbol extraction, and patch validation.
|
||||
- **Automation & AI**: `z3ed` exposes CLI/TUI automation, proposal workflows, and optional AI agents.
|
||||
- **Web preview**: Experimental browser-based editor (WASM) - see [Web App Guide](docs/public/usage/web-app.md).
|
||||
- **Testing & CI hooks**: CMake presets, ROM-less test fixtures, and gRPC-based GUI automation support.
|
||||
- **Cross-platform toolchains**: Single source tree targeting MSVC, Clang, and GCC with identical presets.
|
||||
- **Modular AI stack**: Toggle agent UI (`YAZE_BUILD_AGENT_UI`), remote automation/gRPC (`YAZE_ENABLE_REMOTE_AUTOMATION`), and AI runtimes (`YAZE_ENABLE_AI_RUNTIME`) per preset.
|
||||
|
||||
#### z3ed agent - AI-powered CLI assistant
|
||||
- **AI-assisted ROM hacking** with ollama and Gemini support
|
||||
- **Natural language commands** for editing and querying ROM data
|
||||
- **Tool calling** for structured data extraction and modification
|
||||
- **Interactive chat** with conversation history and context
|
||||
|
||||
#### ZSCustomOverworld v3
|
||||
- **Enhanced overworld editing** capabilities
|
||||
- **Advanced map properties** and metadata support
|
||||
- **Custom graphics support** and tile management
|
||||
- **Improved compatibility** with existing projects
|
||||
|
||||
#### Asar 65816 Assembler Integration
|
||||
- **Cross-platform ROM patching** with assembly code support
|
||||
- **Symbol extraction** with addresses and opcodes from assembly files
|
||||
- **Assembly validation** with comprehensive error reporting
|
||||
- **Modern C++ API** with safe memory management
|
||||
|
||||
#### Advanced Features
|
||||
- **Theme Management**: Complete theme system with 5+ built-in themes and custom theme editor
|
||||
- **Multi-Session Support**: Work with multiple ROMs simultaneously in docked workspace
|
||||
- **Enhanced Welcome Screen**: Themed interface with quick access to all editors
|
||||
- **Message Editing**: Enhanced text editing interface with real-time preview
|
||||
- **GUI Docking**: Flexible workspace management with customizable layouts
|
||||
- **Modern CLI**: Enhanced z3ed tool with interactive TUI and subcommands
|
||||
- **Cross-Platform**: Full support for Windows, macOS, and Linux
|
||||
## Project Status
|
||||
v0.5.0 is the current release. New to YAZE? Start with a clean, legally obtained ALttP (USA) ROM and the Quick Start steps below. See [`docs/public/release-notes.md`](docs/public/release-notes.md) for details.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Build
|
||||
### Clone & Bootstrap
|
||||
```bash
|
||||
# Clone with submodules
|
||||
git clone --recursive https://github.com/scawful/yaze.git
|
||||
cd yaze
|
||||
|
||||
# Build with CMake
|
||||
cmake --preset debug # macOS
|
||||
cmake -B build && cmake --build build # Linux/Windows
|
||||
|
||||
# Windows-specific
|
||||
scripts\verify-build-environment.ps1 # Verify your setup
|
||||
cmake --preset windows-debug # Basic build
|
||||
cmake --preset windows-ai-debug # With AI features
|
||||
cmake --build build --config Debug # Build
|
||||
```
|
||||
|
||||
### Applications
|
||||
- **yaze**: Complete GUI editor for Zelda 3 ROM hacking
|
||||
- **z3ed**: Command-line tool with interactive interface
|
||||
- **yaze_test**: Comprehensive test suite for development
|
||||
|
||||
## Usage
|
||||
|
||||
### GUI Editor
|
||||
Launch the main application to edit Zelda 3 ROMs:
|
||||
- Load ROM files using native file dialogs
|
||||
- Edit overworld maps, dungeons, sprites, and graphics
|
||||
- Apply assembly patches with integrated Asar support
|
||||
- Export modifications as patches or modified ROMs
|
||||
|
||||
### Command Line Tool
|
||||
Run the environment verifier once per machine:
|
||||
```bash
|
||||
# Apply assembly patch
|
||||
z3ed asar patch.asm --rom=zelda3.sfc
|
||||
# macOS / Linux
|
||||
./scripts/verify-build-environment.sh --fix
|
||||
|
||||
# Extract symbols from assembly
|
||||
z3ed extract patch.asm
|
||||
|
||||
# Interactive mode
|
||||
z3ed --tui
|
||||
# Windows (PowerShell)
|
||||
.\scripts\verify-build-environment.ps1 -FixIssues
|
||||
```
|
||||
|
||||
### C++ API
|
||||
```cpp
|
||||
#include "yaze.h"
|
||||
### Configure & Build
|
||||
- Use the CMake preset that matches your platform (`mac-dbg`, `lin-dbg`, `win-dbg`, etc.).
|
||||
- Build with `cmake --build --preset <name> [--target …]`.
|
||||
- See [`docs/public/build/quick-reference.md`](docs/public/build/quick-reference.md) for the canonical
|
||||
list of presets, AI build policy, and testing commands.
|
||||
|
||||
// Load ROM and apply patch
|
||||
yaze_project_t* project = yaze_load_project("zelda3.sfc");
|
||||
yaze_apply_asar_patch(project, "patch.asm");
|
||||
yaze_save_project(project, "modified.sfc");
|
||||
### Agent Feature Flags
|
||||
|
||||
| Option | Default | Effect |
|
||||
| --- | --- | --- |
|
||||
| `YAZE_BUILD_AGENT_UI` | `ON` when GUI builds are enabled | Compiles the chat/dialog widgets so the editor can host agent sessions. Turn this `OFF` when you want a lean GUI-only build. |
|
||||
| `YAZE_ENABLE_REMOTE_AUTOMATION` | `ON` for `*-ai` presets | Builds the gRPC servers/clients and protobufs that power GUI automation. |
|
||||
| `YAZE_ENABLE_AI_RUNTIME` | `ON` for `*-ai` presets | Enables Gemini/Ollama transports, proposal planning, and advanced routing logic. |
|
||||
| `YAZE_ENABLE_AGENT_CLI` | `ON` when CLI builds are enabled | Compiles the conversational agent stack consumed by `z3ed`. Disable to skip the CLI entirely. |
|
||||
|
||||
Windows `win-*` presets keep every switch `OFF` by default (`win-dbg`, `win-rel`, `ci-windows`) so MSVC builds stay fast. Use `win-ai`, `win-vs-ai`, or the new `ci-windows-ai` preset whenever you need remote automation or AI runtime features.
|
||||
|
||||
All bundled third-party code (SDL, ImGui, ImGui Test Engine, Asar, nlohmann/json, cpp-httplib, nativefiledialog-extended) now lives under `ext/` for easier vendoring and cleaner include paths.
|
||||
|
||||
## Applications & Workflows
|
||||
- **`./build/bin/yaze`** – full GUI editor with multi-session dockspace, theming, and ROM patching.
|
||||
- **Web App (Preview)** – browser-based editor at your deployed instance; see [`docs/public/usage/web-app.md`](docs/public/usage/web-app.md) for details and limitations.
|
||||
- **`./build/bin/z3ed --tui`** – CLI/TUI companion for scripting, AI-assisted edits, and Asar workflows.
|
||||
- **`ctest --test-dir build -L unit|integration|e2e`** – structured test runner for quick regression checks.
|
||||
- **`z3ed` + macOS automation** – pair the CLI with sketchybar/yabai/skhd or Emacs/Spacemacs to drive ROM workflows without opening the GUI.
|
||||
|
||||
Typical commands:
|
||||
```bash
|
||||
# Launch GUI with a ROM
|
||||
./build/bin/yaze roms/alttp_vanilla.sfc
|
||||
|
||||
# Apply a patch via CLI
|
||||
./build/bin/z3ed asar patch.asm --rom roms/alttp_vanilla.sfc
|
||||
|
||||
# Run focused tests
|
||||
cmake --build --preset mac-ai --target yaze_test
|
||||
ctest --test-dir build -L unit
|
||||
```
|
||||
|
||||
## Testing
|
||||
- `ctest --test-dir build -L unit` for fast checks; add `-L integration` or `-L e2e --output-on-failure` for broader coverage.
|
||||
- `ctest --preset dev` mirrors CI’s stable set; `ctest --preset all` runs the full matrix.
|
||||
- Set `YAZE_TEST_ROM_VANILLA` or pass `--rom-vanilla` when a test needs a real ROM image (legacy `--rom-path` still works).
|
||||
|
||||
## Documentation
|
||||
- Human-readable docs live under `docs/public/` with an entry point at [`docs/public/index.md`](docs/public/index.md).
|
||||
- Run `doxygen Doxyfile` to generate API + guide pages (`build/docs/html` and `build/docs/latex`).
|
||||
- Agent playbooks, architecture notes, and testing recipes now live in [`docs/internal/`](docs/internal/README.md).
|
||||
|
||||
- [Getting Started](docs/01-getting-started.md) - Setup and basic usage
|
||||
- [Build Instructions](docs/02-build-instructions.md) - Building from source
|
||||
- [API Reference](docs/04-api-reference.md) - Programming interface
|
||||
- [Contributing](docs/B1-contributing.md) - Development guidelines
|
||||
|
||||
**[Complete Documentation](docs/index.md)**
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
- **Windows** (MSVC 2019+, MinGW)
|
||||
- **macOS** (Intel and Apple Silicon)
|
||||
- **Linux** (GCC 13+, Clang 16+)
|
||||
## ROM Compatibility
|
||||
|
||||
- Original Zelda 3 ROMs (US/Japan versions)
|
||||
- ZSCustomOverworld v2/v3 enhanced overworld features
|
||||
- Community ROM hacks and modifications
|
||||
|
||||
## Contributing
|
||||
|
||||
See [Contributing Guide](docs/B1-contributing.md) for development guidelines.
|
||||
|
||||
**Community**: [Oracle of Secrets Discord](https://discord.gg/MBFkMTPEmk)
|
||||
## Contributing & Community
|
||||
- Review [`CONTRIBUTING.md`](CONTRIBUTING.md) and the build/test guides in `docs/public/`.
|
||||
- Conventional commit messages (`feat:`, `fix:`, etc.) keep history clean; use topic branches for larger work.
|
||||
- Chat with the team on [Oracle of Secrets Discord](https://discord.gg/MBFkMTPEmk).
|
||||
|
||||
## License
|
||||
YAZE is licensed under the GNU GPL v3. See [`LICENSE`](LICENSE) for details and third-party notices.
|
||||
|
||||
GNU GPL v3 - See [LICENSE](LICENSE) for details.
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
Takes inspiration from:
|
||||
- [Hyrule Magic](https://www.romhacking.net/utilities/200/) - Original Zelda 3 editor
|
||||
- [ZScream](https://github.com/Zarby89/ZScreamDungeon) - Dungeon editing capabilities
|
||||
- [Asar](https://github.com/RPGHacker/asar) - 65816 assembler integration
|
||||
|
||||
## 📸 Screenshots
|
||||
|
||||
## Screenshots
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
**Ready to hack Zelda 3? [Get started now!](docs/01-getting-started.md)**
|
||||
Submodule assets/asm/alttp-hacker-workspace deleted from 2520fb70c3
Submodule assets/asm/usdasm deleted from d53311a54a
12
assets/patches/Hex Edits/File Fairy.asm
Normal file
12
assets/patches/Hex Edits/File Fairy.asm
Normal file
@@ -0,0 +1,12 @@
|
||||
;#ENABLED=False
|
||||
;#PATCH_NAME=File fairy skin color fix
|
||||
;#PATCH_AUTHOR=kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Fixes the file select fairy's skin color
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
pushpc
|
||||
org $1BF02A
|
||||
db $10
|
||||
pullpc
|
||||
69
assets/patches/Hex Edits/Misc Small Patches.asm
Normal file
69
assets/patches/Hex Edits/Misc Small Patches.asm
Normal file
@@ -0,0 +1,69 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Misc Small Patches
|
||||
;#PATCH_AUTHOR=Zarby89
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Lots of small patches to do various things
|
||||
;No Zelda Telepathy is removing the timed message that tell you to rescue her every minute
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Titlescreen forever (no intro)
|
||||
;#type=bool
|
||||
!TitleScreenForever = $00
|
||||
|
||||
;#name=Skip Ending (before credits)
|
||||
;#type=bool
|
||||
!SkipEnding = $00
|
||||
|
||||
;#name=Prevent S+Q to Dark World
|
||||
;#type=bool
|
||||
!NoDwSpan = $00
|
||||
|
||||
;#name=Disable Dungeon Map
|
||||
;#type=bool
|
||||
!NoDungeonMap = $00
|
||||
|
||||
;#name=Disable Oveworld Map
|
||||
;#type=bool
|
||||
!NoOWnMap = $00
|
||||
|
||||
;#name=No Zelda Telepathy
|
||||
;#type=bool
|
||||
!NoZeldaFollower = $00
|
||||
|
||||
;#DEFINE_END
|
||||
|
||||
if !TitleScreenForever = 1
|
||||
org $0CC2E3
|
||||
db $80
|
||||
endif
|
||||
|
||||
if !SkipEnding = 1
|
||||
org $0E9889
|
||||
LDA #$20 : STA $11
|
||||
RTS
|
||||
endif
|
||||
|
||||
if !NoDwSpan = 1
|
||||
org $028192
|
||||
LDA #$00 : STA $7EF3CA ; Clear the DW address so game doesn't think we are in DW
|
||||
JML $0281BD ; To the lightworld !
|
||||
endif
|
||||
|
||||
if !NoDungeonMap = 1
|
||||
org $0288FD ; Replace a BEQ by a BRA (dungeon map removed)
|
||||
db $80
|
||||
endif
|
||||
|
||||
if !NoOWnMap = 1
|
||||
org $02A55E ; Replace a BEQ by a BRA (overworld map removed)
|
||||
db $80
|
||||
endif
|
||||
|
||||
if !NoZeldaFollower = 1
|
||||
org $05DEF8
|
||||
LDA.b #$00
|
||||
endif
|
||||
|
||||
|
||||
12
assets/patches/Hex Edits/No Beams.asm
Normal file
12
assets/patches/Hex Edits/No Beams.asm
Normal file
@@ -0,0 +1,12 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=No sword beams
|
||||
;#PATCH_AUTHOR=kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Disables sword beams
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
pushpc
|
||||
org $079C70
|
||||
JMP.w $079CA0
|
||||
pullpc
|
||||
11
assets/patches/Hex Edits/No Grass Cut.asm
Normal file
11
assets/patches/Hex Edits/No Grass Cut.asm
Normal file
@@ -0,0 +1,11 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=No grass cutting
|
||||
;#PATCH_AUTHOR=kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Grass no longer gets cut by the sword
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
pushpc
|
||||
org $1BBE26
|
||||
BRA + : NOP #3 : +
|
||||
pullpc
|
||||
80
assets/patches/Items/AST Boots.asm
Normal file
80
assets/patches/Items/AST Boots.asm
Normal file
@@ -0,0 +1,80 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=AST Boots
|
||||
;#PATCH_AUTHOR=Conn, Zarby89
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Copies the boots mechanics from Ancient Stone Tablets.
|
||||
;DPad changes boots directions, and transitions can be
|
||||
;optionally prevented from halting the dash
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Keep running after transition
|
||||
;#type=bool
|
||||
!KeepRunningTransition = $00
|
||||
;#DEFINE_END
|
||||
|
||||
|
||||
pushpc
|
||||
org $87911D
|
||||
JML AstBoots
|
||||
|
||||
if !KeepRunningTransition != 00
|
||||
org $828B13
|
||||
db $80
|
||||
endif
|
||||
pullpc
|
||||
|
||||
AstBoots:
|
||||
BIT.b $F2
|
||||
BPL .continue
|
||||
|
||||
LDA.b $F0
|
||||
AND.b #$0F
|
||||
BNE .pressing_direction
|
||||
|
||||
JML $879138
|
||||
|
||||
.pressing_direction
|
||||
CMP.b #$0A ; up left
|
||||
BEQ +
|
||||
|
||||
CMP.b #$05 ; down right
|
||||
BEQ +
|
||||
|
||||
CMP.b #$09 ; down left
|
||||
BEQ +
|
||||
|
||||
CMP.b #$06 ; up right
|
||||
BNE ++
|
||||
|
||||
+ AND.b #$0C
|
||||
|
||||
++ CMP.b $26
|
||||
BNE +
|
||||
|
||||
JML $879138
|
||||
|
||||
+ STA.b $26
|
||||
STA.b $67
|
||||
STA.w $0340
|
||||
|
||||
JSL $87E6A6
|
||||
|
||||
JML $879138
|
||||
|
||||
.continue
|
||||
LDA.b #$12
|
||||
STA.b $5D
|
||||
|
||||
LDA.b $3A
|
||||
AND.b #$7F
|
||||
STA.b $3A
|
||||
|
||||
STZ.b $3C
|
||||
STZ.b $3D
|
||||
|
||||
LDA.b #$11
|
||||
STA.w $0374
|
||||
|
||||
JML $87915E
|
||||
44
assets/patches/Misc/Big Bomb Requirements.asm
Normal file
44
assets/patches/Misc/Big Bomb Requirements.asm
Normal file
@@ -0,0 +1,44 @@
|
||||
;#ENABLED=True
|
||||
|
||||
;#PATCH_NAME=Big Bomb requirement
|
||||
;#PATCH_AUTHOR=Zarby89,kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Modify the crystal and dwarf requirements for the big bomb
|
||||
;If SmithRequirement is set to 20, you will need to save the Smith first
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Crystals Required
|
||||
;#type=bitfield
|
||||
;#bit0=Crystal 6
|
||||
;#bit1=Crystal 1
|
||||
;#bit2=Crystal 5
|
||||
;#bit3=Crystal 7
|
||||
;#bit4=Crystal 2
|
||||
;#bit5=Crystal 4
|
||||
;#bit6=Crystal 3
|
||||
!CrystalRequirement =$02
|
||||
|
||||
|
||||
;#name=Required smith saved?
|
||||
;#type=bool
|
||||
;#uncheckedvalue=$00
|
||||
;#checkedvalue=$20
|
||||
!SmithRequirement =$00
|
||||
|
||||
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
|
||||
org $1EE16A
|
||||
|
||||
LDA.l $7EF37A : AND.b #!CrystalRequirement : CMP.b #!CrystalRequirement
|
||||
|
||||
skip 2
|
||||
|
||||
LDA.l $7EF3C9 : AND.b #!SmithRequirement
|
||||
|
||||
pullpc
|
||||
41
assets/patches/Misc/HoleOverlayFix.asm
Normal file
41
assets/patches/Misc/HoleOverlayFix.asm
Normal file
@@ -0,0 +1,41 @@
|
||||
;#ENABLED=True
|
||||
|
||||
;#PATCH_NAME=Hole Overlay Fix
|
||||
;#PATCH_AUTHOR=kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Allow the floor collision of the hole overlay to work on every floor types
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
pushpc
|
||||
|
||||
org $01B83E : JSL FigureOutFloor1
|
||||
|
||||
; change comparisons to our dynamic values
|
||||
org $01FE6C : CMP.w $0318
|
||||
org $01FE71 : CMP.w $031A
|
||||
|
||||
pullpc
|
||||
|
||||
;===================================================================================================
|
||||
|
||||
; Find floor 1 index and save its tiles
|
||||
FigureOutFloor1:
|
||||
REP #$30
|
||||
|
||||
LDX.w $046A ; read floor 1 index
|
||||
|
||||
; this reuses some memory related to conveyors
|
||||
; the memory is very temporary so it should be safe
|
||||
|
||||
; databank is 0, so we can use abs,X
|
||||
LDA.w $009B52+0,X ; find top tile
|
||||
AND.w #$03FE ; isolate tile name
|
||||
STA.w $0318 ; save tile
|
||||
|
||||
LDA.w $009B52+8,X ; find bottom tile
|
||||
AND.w #$03FE ; isolate tile name
|
||||
STA.w $031A ; save tile
|
||||
|
||||
LDA.b $BA ; vanilla code and return
|
||||
RTL
|
||||
13
assets/patches/Misc/IntroSkip.asm
Normal file
13
assets/patches/Misc/IntroSkip.asm
Normal file
@@ -0,0 +1,13 @@
|
||||
;#ENABLED=true
|
||||
|
||||
;#PATCH_NAME=Intro skip
|
||||
;#PATCH_AUTHOR=kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Skip the intro sooner
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
pushpc
|
||||
org $0CC123
|
||||
db 4
|
||||
pullpc
|
||||
39
assets/patches/Misc/JP1.0 Glitches.asm
Normal file
39
assets/patches/Misc/JP1.0 Glitches.asm
Normal file
@@ -0,0 +1,39 @@
|
||||
;#ENABLED=True
|
||||
|
||||
;#PATCH_NAME=1.0 Glitches
|
||||
;#PATCH_AUTHOR=kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Restore the JP 1.0 glitches
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Mirror block erase
|
||||
;#type=bool
|
||||
!MirrorEraseBlock = $00
|
||||
|
||||
;#name=Spin speed and Item dash
|
||||
;#type=bool
|
||||
!SpinSpeedItemDash = $00
|
||||
|
||||
;#name=Fake flippers
|
||||
;#type=bool
|
||||
!FakeFlippers = $00
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
if !MirrorEraseBlock == 1
|
||||
org $07A969
|
||||
JMP.w $07A970
|
||||
endif
|
||||
|
||||
if !SpinSpeedItemDash == 1
|
||||
org $0781C0
|
||||
BRA + : NOP #4 : +
|
||||
endif
|
||||
|
||||
if !FakeFlippers == 1
|
||||
org $079665
|
||||
JMP.w $07966C
|
||||
endif
|
||||
pullpc
|
||||
39
assets/patches/Misc/Link Bed Start Position.asm
Normal file
39
assets/patches/Misc/Link Bed Start Position.asm
Normal file
@@ -0,0 +1,39 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Link Bed Starting Position
|
||||
;#PATCH_AUTHOR=Zarby89, Jared_Brian_, kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Changes where Link spawns during the opening bed cutscene
|
||||
;Positions can be found by temporarily moving the Link's house entrance to
|
||||
;the desired location
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Link Y Position
|
||||
;#type=word
|
||||
!LinkYPosition = $2182
|
||||
|
||||
;#name=Link Y Position
|
||||
;#type=word
|
||||
!LinkXPosition = $095B
|
||||
;#DEFINE_END
|
||||
|
||||
; Link sleep position changes
|
||||
org $079A31
|
||||
LDA.w #!LinkYPosition : STA.b $20 ; Y link position in bed
|
||||
LDA.w #!LinkXPosition : STA.b $22 ; X link position in bed
|
||||
|
||||
org $05DE52 ; These values should be the same as the ones above
|
||||
LDA.b #!LinkXPosition : STA.w $0FC2 ; X link position in bed
|
||||
LDA.b #!LinkXPosition>>8 : STA.w $0FC3 ; X link position in bed
|
||||
|
||||
LDA.b #!LinkYPosition : STA.w $0FC4 ; Y link position in bed
|
||||
LDA.b #!LinkYPosition>>8 : STA.w $0FC5 ; Y link position in bed
|
||||
|
||||
org $0980B7
|
||||
LDA.w #(!LinkYPosition+8) : STA.b $00 ; Y link sheet in bed
|
||||
LDA.w #(!LinkXPosition-8) : STA.b $02 ; X link sheet in bed
|
||||
|
||||
org $05DE8C
|
||||
LDA.b #(!LinkYPosition-3) : STA.b $20 ; Y link position in bed when awoken
|
||||
LDA.b #(!LinkYPosition-3)>>8 : STA.b $21 ; Y link position in bed when awoken
|
||||
28
assets/patches/Misc/NoRocks.asm
Normal file
28
assets/patches/Misc/NoRocks.asm
Normal file
@@ -0,0 +1,28 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=No Hardcoded Rocks
|
||||
;#PATCH_AUTHOR=Jared_Brian_
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Removes the 2 hardcoded rocks that get placed in area 33 and 2F.
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Remove rock in area 33.
|
||||
;#type=bool
|
||||
!RemoveRock1 = $01
|
||||
;#name=Remove rock in area 2F.
|
||||
;#type=bool
|
||||
!RemoveRock2 = $01
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
if !RemoveRock1 == 1
|
||||
org $02EF33
|
||||
NOP #4
|
||||
endif
|
||||
|
||||
if !RemoveRock2 == 1
|
||||
org $02EF3C
|
||||
NOP #4
|
||||
endif
|
||||
pullpc
|
||||
51
assets/patches/Misc/Rainstate Skip.asm
Normal file
51
assets/patches/Misc/Rainstate Skip.asm
Normal file
@@ -0,0 +1,51 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Rainstate Skip
|
||||
;#PATCH_AUTHOR=Zarby89
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Skips over gamestates 0 and 1 (rain) straight to 2 (Zelda rescued)
|
||||
;Setting BedIntro to 00 will keep the opening bed sequence
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
lorom
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Remove bed intro
|
||||
;#type=bool
|
||||
!BedIntro = $00
|
||||
;#DEFINE_END
|
||||
|
||||
if !BedIntro == 00
|
||||
|
||||
pushpc
|
||||
org $828356
|
||||
JSL NewIntroRain
|
||||
pullpc
|
||||
|
||||
NewIntroRain:
|
||||
LDA.l $7EF3C5 : BNE +
|
||||
LDA.b #$02 : STA.l $7EF3C5 ; Set Game mode on 2
|
||||
|
||||
PHX
|
||||
|
||||
JSL $80FC62 ; Sprite_LoadGfxProperties.justLightWorld
|
||||
|
||||
PLX
|
||||
|
||||
LDA.b #$00 ; will take care of the bed intro wether we are in game rainstate or not
|
||||
+ RTL
|
||||
|
||||
else
|
||||
pushpc
|
||||
org $0CD8F6
|
||||
JSL NewIntroRain
|
||||
|
||||
pullpc
|
||||
NewIntroRain:
|
||||
PHA
|
||||
LDA.w #$1002
|
||||
STA.l $7003C5, X
|
||||
PLA
|
||||
STA.l $7003D9, X
|
||||
RTL
|
||||
endif
|
||||
30
assets/patches/Misc/TorchTags.asm
Normal file
30
assets/patches/Misc/TorchTags.asm
Normal file
@@ -0,0 +1,30 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Torch Tags
|
||||
;#PATCH_AUTHOR=Jared_Brian_
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Changes the number of torches required to open doors and chests when using the "Light_Torches_to_Open" and "Light_Torches_to_get_Chest" tags.
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=torches required to make a chest appear.
|
||||
;#type=word
|
||||
;#range=$01,$08
|
||||
!ChestTorches =$01
|
||||
|
||||
;#name=torches required to open a door.
|
||||
;#type=word
|
||||
;#range=$01,$08
|
||||
!DoorTorches =$08
|
||||
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
; Changes the amount of torches required to make a chest appear.
|
||||
org $01C8CA
|
||||
dw !ChestTorches
|
||||
|
||||
; Changes the amount of torches required to open a door.
|
||||
org $01C645
|
||||
dw !DoorTorches
|
||||
pullpc
|
||||
153
assets/patches/Misc/Weathervane.asm
Normal file
153
assets/patches/Misc/Weathervane.asm
Normal file
@@ -0,0 +1,153 @@
|
||||
;#ENABLED=True
|
||||
|
||||
;=========================
|
||||
;TODO FINISH ADDING DEFINES
|
||||
;INCOMPLETE PATCH
|
||||
;==========================
|
||||
;#PATCH_NAME=Weathervane Position
|
||||
;#PATCH_AUTHOR=Jared_Brian_
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Modify the position of where you need to use the flute to destroy weathervane and spawn bird
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
!AREAID = $34
|
||||
|
||||
; Weather vane explosion changes:
|
||||
; Let the flute work in special areas.
|
||||
org $07A40A
|
||||
NOP : NOP
|
||||
|
||||
org $07A418
|
||||
JML NewVaneCheck
|
||||
|
||||
org $07A441
|
||||
VanePassed:
|
||||
|
||||
org $07A44F
|
||||
VaneFailed:
|
||||
|
||||
org $07A453
|
||||
SpawnBird:
|
||||
|
||||
; Disable the area check for the weather vane sprite.
|
||||
org $06C2EB
|
||||
LDA $8A : CMP.b #!AREAID : BNE .outside_village
|
||||
; Check if we have the flute activated already:
|
||||
LDA $7EF34C : CMP.b #$03 : BNE .player_lacks_bird_enabled_flute
|
||||
STZ $0DD0, X
|
||||
|
||||
.player_lacks_bird_enabled_flute
|
||||
|
||||
RTS
|
||||
|
||||
.outside_village
|
||||
|
||||
; What to do in an area outside of the village:
|
||||
LDA $7EF34C : AND.b #$02 : BEQ .player_lacks_flute_completely
|
||||
STZ $0DD0, X ; Suicide.
|
||||
.player_lacks_flute_completely
|
||||
RTS
|
||||
|
||||
warnpc $06C309
|
||||
|
||||
; Tile 1
|
||||
org $1BC226
|
||||
dw $06CA
|
||||
|
||||
; Tile 2
|
||||
org $1BC232
|
||||
dw $06CE
|
||||
|
||||
; Tile 3
|
||||
org $1BC243
|
||||
dw #$074C
|
||||
|
||||
; Bird coords
|
||||
org $098DC1
|
||||
LDA.w #$08C8 : STA $00
|
||||
LDA.w #$0460 : STA $02
|
||||
|
||||
; Vane Debris coords
|
||||
org $098CED
|
||||
.y_coords
|
||||
db $F4, $E7, $E4, $E6, $E4, $EC, $E4, $E4, $EC, $E5, $F4, $E4
|
||||
|
||||
.x_coords
|
||||
db $7C, $5E, $6C, $60, $62, $64, $7C, $60, $64, $62, $60, $6C
|
||||
|
||||
; Debris Y high byte
|
||||
org $098D65
|
||||
db $08
|
||||
|
||||
; Debris X high byte
|
||||
org $098D72
|
||||
db $04
|
||||
|
||||
pullpc ; Continue extended space.
|
||||
|
||||
NewVaneCheck:
|
||||
{
|
||||
REP #$20
|
||||
|
||||
; Check if its the master sword area.
|
||||
LDA $8A : CMP.w #!AREAID : BNE .not_weathervane_trigger2
|
||||
LDA $20
|
||||
CMP.w #$0068 : BCC .not_weathervane_trigger1
|
||||
CMP.w #$00A0 : BCS .not_weathervane_trigger1
|
||||
|
||||
LDA $22
|
||||
CMP.w #$0040 : BCC .not_weathervane_trigger1
|
||||
CMP.w #$00A0 : BCS .not_weathervane_trigger1
|
||||
|
||||
SEP #$20
|
||||
|
||||
; Cancel other sounds
|
||||
STZ $012E
|
||||
STZ $012F
|
||||
|
||||
; Stop player input
|
||||
INC InCutScene
|
||||
|
||||
; Trigger Zelda
|
||||
INC $0642
|
||||
|
||||
JML VaneFailed
|
||||
|
||||
.not_weathervane_trigger2
|
||||
|
||||
SEP #$20
|
||||
|
||||
; Check if we already have the bird.
|
||||
LDA $7EF34C : CMP.b #$02 : BNE .travel_bird_not_already_released
|
||||
REP #$20
|
||||
|
||||
; Check the area for #$22.
|
||||
LDA $8A : CMP.w #$0022 : BNE .not_weathervane_trigger1
|
||||
LDA $20
|
||||
CMP.w #$0900 : BCC .not_weathervane_trigger1
|
||||
CMP.w #$0920 : BCS .not_weathervane_trigger1
|
||||
|
||||
LDA $22
|
||||
CMP.w #$0450 : BCC .not_weathervane_trigger1
|
||||
CMP.w #$0470 : BCS .not_weathervane_trigger1
|
||||
SEP #$20
|
||||
LDA $7EF2A2 : ORA.b #$20 : STA $7EF2A2
|
||||
REP #$20
|
||||
|
||||
STZ FluteIndex
|
||||
|
||||
JML VanePassed
|
||||
|
||||
.not_weathervane_trigger1
|
||||
|
||||
JML VaneFailed
|
||||
|
||||
.travel_bird_not_already_released
|
||||
|
||||
JML SpawnBird
|
||||
}
|
||||
|
||||
pushpc ; Pause expanded space.
|
||||
|
||||
; ==============================================================================
|
||||
22
assets/patches/Music/LostWoodsExitMusic.asm
Normal file
22
assets/patches/Music/LostWoodsExitMusic.asm
Normal file
@@ -0,0 +1,22 @@
|
||||
;#ENABLED=True
|
||||
|
||||
;#PATCH_NAME=Lost Woods Exit Music
|
||||
;#PATCH_AUTHOR=Jared_Brian_
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Changes the room that plays the lost woods theme when exiting. Note: This only works for the first byte, so if you want to play music when leaving room 13, this will also cause room 113 to play the music. In vanilla this is used for room E1 Cave (Lost Woods HP).
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=The room number.
|
||||
;#type=byte
|
||||
!MusicRoomNumber = $E1
|
||||
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
|
||||
org $02844F
|
||||
db !MusicRoomNumber
|
||||
|
||||
pullpc
|
||||
29
assets/patches/Npcs/Bottle Vendor.asm
Normal file
29
assets/patches/Npcs/Bottle Vendor.asm
Normal file
@@ -0,0 +1,29 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Bottle Vendor
|
||||
;#PATCH_AUTHOR=Zarby89
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Modify the item and price of sold by the Kakariko bottle vendor
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Item Price
|
||||
;#type=word
|
||||
;#decimal=true
|
||||
!ItemPrice = 100
|
||||
|
||||
;#name=Item ID
|
||||
;#type=item
|
||||
!ItemID = $16
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
org $05EAF9
|
||||
dw !BottlePrice
|
||||
|
||||
org $05EB34
|
||||
dw !BottlePrice
|
||||
|
||||
org $05EB18
|
||||
db !ItemID
|
||||
pullpc
|
||||
153
assets/patches/Overworld/TailMapExpansion.asm
Normal file
153
assets/patches/Overworld/TailMapExpansion.asm
Normal file
@@ -0,0 +1,153 @@
|
||||
;#ENABLED=false
|
||||
|
||||
;#PATCH_NAME=Overworld Tail Map Expansion
|
||||
;#PATCH_AUTHOR=yaze
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Expands the overworld pointer tables from 160 to 192 entries,
|
||||
;enabling support for Special World tail maps (0xA0-0xBF).
|
||||
;
|
||||
;IMPORTANT: This patch MUST be applied AFTER ZSCustomOverworld v3.
|
||||
;If applied manually via Asar:
|
||||
; 1. First apply ZSCustomOverworld v3 patch to your ROM
|
||||
; 2. Then apply this patch: asar TailMapExpansion.asm your_rom.sfc
|
||||
;
|
||||
;If applied via yaze CLI:
|
||||
; z3ed overworld-doctor --rom=your_rom.sfc --apply-tail-expansion
|
||||
;
|
||||
;Technical details:
|
||||
; - Relocates Map32 pointer tables from $02:F94D to $28:A400
|
||||
; - Adds 32 blank entries for maps 0xA0-0xBF pointing to $30:8000
|
||||
; - Patches 8 code locations in bank $02 to use new table addresses
|
||||
; - Writes detection marker 0xEA at $28:A3FF
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
lorom
|
||||
|
||||
;==============================================================================
|
||||
; Constants
|
||||
;==============================================================================
|
||||
!OldHighTable = $02F94D ; Vanilla high pointer table (160 entries)
|
||||
!OldLowTable = $02FB2D ; Vanilla low pointer table (160 entries)
|
||||
!NewHighTable = $28A400 ; New high pointer table (192 entries)
|
||||
!NewLowTable = $28A640 ; New low pointer table (192 entries)
|
||||
!BlankMapHigh = $308000 ; Blank map data for tail maps (high bytes)
|
||||
!BlankMapLow = $309000 ; Blank map data for tail maps (low bytes)
|
||||
!MarkerAddr = $28A3FF ; Detection marker location
|
||||
!MarkerValue = $EA ; Detection marker value (NOP opcode = "expanded")
|
||||
|
||||
;==============================================================================
|
||||
; PC address macros (for read3 function)
|
||||
;==============================================================================
|
||||
; LoROM: PC = (bank * $8000) + (addr - $8000)
|
||||
; $02F94D -> PC = (2 * $8000) + ($F94D - $8000) = $10000 + $794D = $1794D
|
||||
!OldHighTablePC = $01794D
|
||||
!OldLowTablePC = $017B2D
|
||||
|
||||
;==============================================================================
|
||||
; Detection marker - allows yaze to detect expanded tables
|
||||
;==============================================================================
|
||||
org !MarkerAddr
|
||||
db !MarkerValue
|
||||
|
||||
;==============================================================================
|
||||
; Blank map data for tail maps (0xA0-0xBF)
|
||||
; Located in safe free space at bank $30
|
||||
;==============================================================================
|
||||
org !BlankMapHigh ; PC $180000
|
||||
BlankMap32High:
|
||||
fillbyte $00
|
||||
fill 188 ; 0xBC bytes - compressed blank map32 high data
|
||||
|
||||
org !BlankMapLow ; PC $181000
|
||||
BlankMap32Low:
|
||||
fillbyte $00
|
||||
fill 4 ; 0x04 bytes - compressed blank map32 low data
|
||||
|
||||
;==============================================================================
|
||||
; New expanded High pointer table (192 entries x 3 bytes = 576 bytes)
|
||||
; Copies existing 160 entries, adds 32 blank entries for tail maps
|
||||
;==============================================================================
|
||||
org !NewHighTable ; PC $142400
|
||||
ExpandedMap32HPointers:
|
||||
; Copy 160 vanilla entries (preserves any ZSCustomOverworld modifications)
|
||||
; Using Asar's read1() to copy bytes from current ROM state
|
||||
!n = 0
|
||||
while !n < 160
|
||||
db read1(!OldHighTablePC+(!n*3)+0)
|
||||
db read1(!OldHighTablePC+(!n*3)+1)
|
||||
db read1(!OldHighTablePC+(!n*3)+2)
|
||||
!n #= !n+1
|
||||
endwhile
|
||||
|
||||
; Add 32 blank entries for tail maps (0xA0-0xBF)
|
||||
; Each entry is a 24-bit pointer to BlankMap32High ($30:8000)
|
||||
!n = 0
|
||||
while !n < 32
|
||||
dl BlankMap32High
|
||||
!n #= !n+1
|
||||
endwhile
|
||||
|
||||
;==============================================================================
|
||||
; New expanded Low pointer table (192 entries x 3 bytes = 576 bytes)
|
||||
;==============================================================================
|
||||
org !NewLowTable ; PC $142640
|
||||
ExpandedMap32LPointers:
|
||||
; Copy 160 vanilla entries (preserves any ZSCustomOverworld modifications)
|
||||
!n = 0
|
||||
while !n < 160
|
||||
db read1(!OldLowTablePC+(!n*3)+0)
|
||||
db read1(!OldLowTablePC+(!n*3)+1)
|
||||
db read1(!OldLowTablePC+(!n*3)+2)
|
||||
!n #= !n+1
|
||||
endwhile
|
||||
|
||||
; Add 32 blank entries for tail maps (0xA0-0xBF)
|
||||
!n = 0
|
||||
while !n < 32
|
||||
dl BlankMap32Low
|
||||
!n #= !n+1
|
||||
endwhile
|
||||
|
||||
;==============================================================================
|
||||
; Patch game code to use new pointer tables
|
||||
; Each LDA.l instruction is 4 bytes: AF xx xx xx (opcode + 24-bit address)
|
||||
; We patch the 3 address bytes to point to the new tables
|
||||
;==============================================================================
|
||||
|
||||
; Function 1: Overworld_DecompressAndDrawOneQuadrant
|
||||
; Original at PC $1F59D: LDA.l $02F94D,X -> LDA.l $28A400,X
|
||||
org $02F59E ; Address bytes of instruction at $02F59D
|
||||
dl ExpandedMap32HPointers ; New high table address
|
||||
|
||||
org $02F5A4 ; Address bytes for +1 offset access
|
||||
dl ExpandedMap32HPointers+1
|
||||
|
||||
; Original at PC $1F5C8: LDA.l $02FB2D,X -> LDA.l $28A640,X
|
||||
org $02F5C9 ; Address bytes of instruction at $02F5C8
|
||||
dl ExpandedMap32LPointers ; New low table address
|
||||
|
||||
org $02F5CF ; Address bytes for +1 offset access
|
||||
dl ExpandedMap32LPointers+1
|
||||
|
||||
; Function 2: Secondary quadrant loader (parallel decompression path)
|
||||
org $02F7E4
|
||||
dl ExpandedMap32HPointers
|
||||
|
||||
org $02F7EA
|
||||
dl ExpandedMap32HPointers+1
|
||||
|
||||
org $02F80F
|
||||
dl ExpandedMap32LPointers
|
||||
|
||||
org $02F815
|
||||
dl ExpandedMap32LPointers+1
|
||||
|
||||
;==============================================================================
|
||||
; End of patch
|
||||
;==============================================================================
|
||||
print "Tail Map Expansion patch applied successfully."
|
||||
print "- New High Table: $28:A400 (192 entries)"
|
||||
print "- New Low Table: $28:A640 (192 entries)"
|
||||
print "- Blank Map Data: $30:8000, $30:9000"
|
||||
print "- Detection Marker: $28:A3FF = $EA"
|
||||
19
assets/patches/Sprites/Crystalswitch Conveyor.asm
Normal file
19
assets/patches/Sprites/Crystalswitch Conveyor.asm
Normal file
@@ -0,0 +1,19 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Crystal Switch Conveyor
|
||||
;#PATCH_AUTHOR=Zarby89
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Causes crystal switches to be moved by conveyors
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
lorom
|
||||
|
||||
pushpc
|
||||
org $06B8D0
|
||||
JSL ConveyorSwitch
|
||||
NOP
|
||||
pullpc
|
||||
|
||||
ConveyorSwitch:
|
||||
JSL $06E496 ; Sprite_CheckTileCollisionLong
|
||||
LDA.w $0F50, X : AND.b #$F1
|
||||
RTL
|
||||
95
assets/patches/Sprites/Elemental Trinexx.asm
Normal file
95
assets/patches/Sprites/Elemental Trinexx.asm
Normal file
@@ -0,0 +1,95 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Elemental Trinexx
|
||||
;#PATCH_AUTHOR=Jared_Brian_
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Changes Trinexx's side heads to be both ice heads, both fire heads, or swapped.
|
||||
;The heads will shoot the corrisponding beams and will also appear the correct color.
|
||||
;The main head will appear the elemental color if you set that option but otherwise will be the default palette.
|
||||
;You will still need to set the side heads to take damage from the appropriate elemental rod with the advanced damage editor.
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Changes the arrangement of side heads.
|
||||
;#type=choice
|
||||
;#choice0=Inverted Heads
|
||||
;#choice1=Ice Heads Only
|
||||
;#choice2=Fire Heads Only
|
||||
!ElementType = $00
|
||||
|
||||
;#name=Changes the main head palette.
|
||||
;#type=choice
|
||||
;#choice0=Default Palette
|
||||
;#choice1=Ice Palette
|
||||
;#choice2=Fire Palette
|
||||
!MainHeadPalette = $00
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
|
||||
if !ElementType == 0
|
||||
; Change the palettes of the side heads to the inverted palette.
|
||||
org $0DB425
|
||||
db $0D, $0B
|
||||
|
||||
; Swap which head shows the apropriate particales when charging up.
|
||||
org $1DBAD9
|
||||
db $F0 ; Replace a BNE with a BEQ.
|
||||
|
||||
; Swap which head shoots what beam.
|
||||
org $1DBAE8
|
||||
LDA $0E20, X : CMP.b #$CC
|
||||
|
||||
; Another beam related thing.
|
||||
org $1DBAF8
|
||||
LDA.b #$CC
|
||||
|
||||
elseif !ElementType == 1
|
||||
; Change the palettes of the side heads to the ice palette.
|
||||
org $0DB425
|
||||
db $0D, $0D
|
||||
|
||||
; Make the fire head show ice spakles when charging up.
|
||||
org $1DBAD9
|
||||
db $80 ; Replace a BNE with a BRA.
|
||||
|
||||
; Make the fire head shoot ice instead of fire.
|
||||
org $1DBAE8
|
||||
LDA.b #$CD : NOP #5
|
||||
|
||||
elseif !ElementType == 2
|
||||
; Change the palettes of the side heads to the fire palette.
|
||||
org $0DB425
|
||||
db $0B, $0B
|
||||
|
||||
; Make the ice head show flames when charging up.
|
||||
org $1DBAD9
|
||||
NOP : NOP ; Remove the BNE and never branch.
|
||||
|
||||
; Make the ice head shoot fire instead of ice.
|
||||
org $1DBAE8
|
||||
LDA.b #$CC : NOP : NOP : NOP
|
||||
db $80 ; Replace a BNE with a BRA.
|
||||
|
||||
endif
|
||||
|
||||
if !MainHeadPalette == 1
|
||||
; Change the palette of all the main head to the ice.
|
||||
org $0DB424
|
||||
db $4D
|
||||
|
||||
; Change the snake trinexx palette to ice.
|
||||
org $1DB033
|
||||
db $0D
|
||||
|
||||
elseif !MainHeadPalette == 2
|
||||
; Change the palette of all the main head to the fire.
|
||||
org $0DB424
|
||||
db $4B
|
||||
|
||||
; Change the snake trinexx palette to fire.
|
||||
org $1DB033
|
||||
db $0B
|
||||
endif
|
||||
|
||||
pullpc
|
||||
43
assets/patches/Sprites/Eye Lasers Active.asm
Normal file
43
assets/patches/Sprites/Eye Lasers Active.asm
Normal file
@@ -0,0 +1,43 @@
|
||||
;#PATCH_NAME=Eye Lasers Active
|
||||
;#PATCH_AUTHOR=Jared_Brian_
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Changes the wall eye lasers to always be active or always inactive reguardless of what X position they are placed on.
|
||||
;Normally in vanilla every other X position is set to be inactive unless link is looking directly at them.
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Active?
|
||||
;#type=bool
|
||||
!EyeActive = $00
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
|
||||
if !EyeActive == $00
|
||||
; Make it so the eye lazers are always inactive reguardless of what X position they are placed on.
|
||||
org $1EA50B
|
||||
; Replaced code:
|
||||
; LDA $0D10, X : AND.b #$10 : EOR.b #$10 : STA !requires_facing, X
|
||||
NOP #5 : LDA.b #$00 : STA $0EB0, X
|
||||
|
||||
org $1EA52C
|
||||
; Replace code:
|
||||
; LDA $0D00, X : AND.b #$10 : STA !requires_facing, X
|
||||
NOP #3 : LDA.b #$00 : STA $0EB0, X
|
||||
|
||||
elseif !EyeActive == $01
|
||||
; Make it so the eye lazers are always active reguardless of what X position they are placed on.
|
||||
org $1EA50B
|
||||
; Replaced code:
|
||||
; LDA $0D10, X : AND.b #$10 : EOR.b #$10 : STA !requires_facing, X
|
||||
NOP #5 : LDA.b #$01 : STA $0EB0, X
|
||||
|
||||
org $1EA52C
|
||||
; Replace code:
|
||||
; LDA $0D00, X : AND.b #$10 : STA !requires_facing, X
|
||||
NOP #3 : LDA.b #$01 : STA $0EB0, X
|
||||
|
||||
endif
|
||||
|
||||
pullpc
|
||||
56
assets/patches/Sprites/Khodstare Speeds.asm
Normal file
56
assets/patches/Sprites/Khodstare Speeds.asm
Normal file
@@ -0,0 +1,56 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Kholdstare Speeds
|
||||
;#PATCH_AUTHOR=Jared_Brian_
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Changes the speeds at which kholdstare can move.
|
||||
;By default he will move the same speed on the x and y axis in all 4 diagonal directions.
|
||||
;Values above 0x80 are negative.
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=X Value 1
|
||||
;#type=byte
|
||||
!XValue1 = $0010
|
||||
|
||||
;#name=X Value 2
|
||||
;#type=byte
|
||||
!XValue2 = $0010
|
||||
|
||||
;#name=X Value 3
|
||||
;#type=byte
|
||||
!XValue3 = $00F0
|
||||
|
||||
;#name=X Value 4
|
||||
;#type=byte
|
||||
!XValue4 = $00F0
|
||||
|
||||
;#name=Y Value 1
|
||||
;#type=byte
|
||||
!YValue1 = $00F0
|
||||
|
||||
;#name=Y Value 2
|
||||
;#type=byte
|
||||
!YValue2 = $0010
|
||||
|
||||
;#name=Y Value 3
|
||||
;#type=byte
|
||||
!YValue3 = $0010
|
||||
|
||||
;#name=Y Value 4
|
||||
;#type=byte
|
||||
!YValue4 = $00F0
|
||||
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
|
||||
; Speed chagnes.
|
||||
org $1E95DD
|
||||
.x_speed_limits
|
||||
db !XValue1, !XValue2, !XValue3, !XValue4
|
||||
|
||||
.y_speed_limits
|
||||
db !YValue1, !YValue2, !YValue3, !YValue4
|
||||
|
||||
pullpc
|
||||
24
assets/patches/Sprites/Spike Damage.asm
Normal file
24
assets/patches/Sprites/Spike Damage.asm
Normal file
@@ -0,0 +1,24 @@
|
||||
;#ENABLED=True
|
||||
;#PATCH_NAME=Spike damage
|
||||
;#PATCH_AUTHOR=kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Allows mail upgrades to reduce sprite damage
|
||||
;$08 = 1 heart, $04 = half heart, $10 = 2 heart, etc...
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
|
||||
;#DEFINE_START
|
||||
;#name=Green Mail Damage
|
||||
!GreenMailDamage = $08
|
||||
;#name=Blue Mail Damage
|
||||
!BlueMailDamage = $08
|
||||
;#name=Red Mail Damage
|
||||
!RedMailDamage = $08
|
||||
;#DEFINE_END
|
||||
|
||||
pushpc
|
||||
org $07BA07
|
||||
db !GreenMailDamage
|
||||
db !BlueMailDamage
|
||||
db !RedMailDamage
|
||||
pullpc
|
||||
52
assets/patches/Sprites/Spikes_Subtype.asm
Normal file
52
assets/patches/Sprites/Spikes_Subtype.asm
Normal file
@@ -0,0 +1,52 @@
|
||||
;#ENABLED=True
|
||||
|
||||
;#PATCH_NAME=More spike directions
|
||||
;#PATCH_AUTHOR=Zarby89,kan
|
||||
;#PATCH_VERSION=1.0
|
||||
;#PATCH_DESCRIPTION
|
||||
;Allows more spike blocks Subtype (sprite property)
|
||||
;Default Values : (00) = normal, (08) = normal vertical
|
||||
;Values, ascending by speed
|
||||
;00,01,02,03,04,05,06 = Horizontal
|
||||
;08,09,0A,0B,0C,0D,0E = Vertical
|
||||
;#ENDPATCH_DESCRIPTION
|
||||
lorom
|
||||
|
||||
pushpc
|
||||
org $0691D7 ; SpritePrep_SpikeBlock:
|
||||
JSL NewSpikePrep
|
||||
RTS
|
||||
|
||||
org $1EBD0E
|
||||
JSL NewSpikeCollision
|
||||
RTS
|
||||
pullpc
|
||||
|
||||
speedValuesH:
|
||||
db $20, $10, $18, $28, $30, $38, $40, $FF
|
||||
db $00, $00, $00, $00, $00, $00, $00, $FF
|
||||
|
||||
speedValuesV:
|
||||
db $00, $00, $00, $00, $00, $00, $00, $FF
|
||||
db $20, $18, $20, $28, $30, $38, $40, $FF
|
||||
|
||||
NewSpikePrep:
|
||||
TXY
|
||||
|
||||
LDX.w $0E30,Y
|
||||
|
||||
LDA.l speedValuesH,X : STA.w $0D50,Y
|
||||
LDA.l speedValuesV,X : STA.w $0D40,Y
|
||||
|
||||
TYX
|
||||
RTL
|
||||
|
||||
NewSpikeCollision:
|
||||
LDA.b #$04 : STA.w $0DF0, X
|
||||
|
||||
LDA.w $0D50, X : EOR.b #$FF : INC A : STA.w $0D50, X
|
||||
LDA.w $0D40, X : EOR.b #$FF : INC A : STA.w $0D40, X
|
||||
|
||||
LDA.b #$05 : JSL $0DBB7C ; Sound_SetSfx2PanLong
|
||||
|
||||
RTL
|
||||
1
assets/patches/Version.txt
Normal file
1
assets/patches/Version.txt
Normal file
@@ -0,0 +1 @@
|
||||
0000
|
||||
12
cmake-format.yaml
Normal file
12
cmake-format.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
# CMake format configuration
|
||||
line_width: 80
|
||||
tab_size: 2
|
||||
max_subargs_per_line: 3
|
||||
separate_ctrl_name_with_space: true
|
||||
separate_fn_name_with_space: true
|
||||
dangle_parens: true
|
||||
command_case: lower
|
||||
keyword_case: upper
|
||||
enable_sort: true
|
||||
autosort: true
|
||||
|
||||
52
cmake/CPM.cmake
Normal file
52
cmake/CPM.cmake
Normal file
@@ -0,0 +1,52 @@
|
||||
# CPM.cmake - C++ Package Manager
|
||||
# https://github.com/cpm-cmake/CPM.cmake
|
||||
|
||||
set(CPM_DOWNLOAD_VERSION 0.38.7)
|
||||
|
||||
if(CPM_SOURCE_CACHE)
|
||||
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
|
||||
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
else()
|
||||
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||
endif()
|
||||
|
||||
# Expand relative path. This is important if the provided path contains a tilde (~)
|
||||
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
|
||||
|
||||
function(download_cpm)
|
||||
message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}")
|
||||
file(DOWNLOAD
|
||||
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
|
||||
${CPM_DOWNLOAD_LOCATION}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
|
||||
download_cpm()
|
||||
else()
|
||||
# resume download if it previously failed
|
||||
file(READ ${CPM_DOWNLOAD_LOCATION} check)
|
||||
if("${check}" STREQUAL "")
|
||||
download_cpm()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(${CPM_DOWNLOAD_LOCATION})
|
||||
|
||||
# Set CPM options for better caching and performance
|
||||
if(NOT DEFINED CPM_USE_LOCAL_PACKAGES)
|
||||
set(CPM_USE_LOCAL_PACKAGES OFF)
|
||||
endif()
|
||||
if(NOT DEFINED CPM_LOCAL_PACKAGES_ONLY)
|
||||
set(CPM_LOCAL_PACKAGES_ONLY OFF)
|
||||
endif()
|
||||
set(CPM_DONT_CREATE_PACKAGE_LOCK ON)
|
||||
set(CPM_DONT_UPDATE_MODULE_PATH ON)
|
||||
set(CPM_DONT_PREPEND_TO_MODULE_PATH ON)
|
||||
|
||||
# Set cache directory for CI builds
|
||||
if(DEFINED ENV{GITHUB_ACTIONS})
|
||||
set(CPM_SOURCE_CACHE "$ENV{HOME}/.cpm-cache")
|
||||
message(STATUS "CPM cache directory: ${CPM_SOURCE_CACHE}")
|
||||
endif()
|
||||
490
cmake/TestInfrastructure.cmake
Normal file
490
cmake/TestInfrastructure.cmake
Normal file
@@ -0,0 +1,490 @@
|
||||
# TestInfrastructure.cmake
|
||||
# Advanced test infrastructure configuration for yaze project
|
||||
# Provides optimized test builds, parallel execution, and smart test selection
|
||||
|
||||
include(GoogleTest)
|
||||
include(CTest)
|
||||
|
||||
# =============================================================================
|
||||
# Test Configuration Options
|
||||
# =============================================================================
|
||||
|
||||
option(YAZE_TEST_PARALLEL "Enable parallel test execution" ON)
|
||||
option(YAZE_TEST_COVERAGE "Enable code coverage collection" OFF)
|
||||
option(YAZE_TEST_SANITIZERS "Enable address and undefined behavior sanitizers" OFF)
|
||||
option(YAZE_TEST_PROFILE "Enable test profiling" OFF)
|
||||
option(YAZE_TEST_MINIMAL_DEPS "Use minimal dependencies for faster test builds" OFF)
|
||||
option(YAZE_TEST_PCH "Use precompiled headers for tests" ON)
|
||||
|
||||
# Test categories
|
||||
option(YAZE_TEST_SMOKE "Build smoke tests (critical path)" ON)
|
||||
option(YAZE_TEST_UNIT "Build unit tests" ON)
|
||||
option(YAZE_TEST_INTEGRATION "Build integration tests" ON)
|
||||
option(YAZE_TEST_E2E "Build end-to-end GUI tests" OFF)
|
||||
option(YAZE_TEST_BENCHMARK "Build performance benchmarks" OFF)
|
||||
option(YAZE_TEST_FUZZ "Build fuzzing tests" OFF)
|
||||
|
||||
# Test execution settings
|
||||
set(YAZE_TEST_TIMEOUT_SMOKE 30 CACHE STRING "Timeout for smoke tests (seconds)")
|
||||
set(YAZE_TEST_TIMEOUT_UNIT 60 CACHE STRING "Timeout for unit tests (seconds)")
|
||||
set(YAZE_TEST_TIMEOUT_INTEGRATION 300 CACHE STRING "Timeout for integration tests (seconds)")
|
||||
set(YAZE_TEST_TIMEOUT_E2E 600 CACHE STRING "Timeout for E2E tests (seconds)")
|
||||
|
||||
# =============================================================================
|
||||
# Precompiled Headers Configuration
|
||||
# =============================================================================
|
||||
|
||||
if(YAZE_TEST_PCH)
|
||||
set(YAZE_TEST_PCH_HEADERS
|
||||
<gtest/gtest.h>
|
||||
<gmock/gmock.h>
|
||||
<absl/status/status.h>
|
||||
<absl/status/statusor.h>
|
||||
<absl/strings/string_view.h>
|
||||
<memory>
|
||||
<vector>
|
||||
<string>
|
||||
<unordered_map>
|
||||
)
|
||||
|
||||
# Create PCH target
|
||||
add_library(yaze_test_pch INTERFACE)
|
||||
target_precompile_headers(yaze_test_pch INTERFACE ${YAZE_TEST_PCH_HEADERS})
|
||||
|
||||
message(STATUS "Test Infrastructure: Precompiled headers enabled")
|
||||
endif()
|
||||
|
||||
# =============================================================================
|
||||
# Test Interface Library
|
||||
# =============================================================================
|
||||
|
||||
add_library(yaze_test_interface INTERFACE)
|
||||
|
||||
# Common compile options
|
||||
target_compile_options(yaze_test_interface INTERFACE
|
||||
$<$<CONFIG:Debug>:-O0 -g3>
|
||||
$<$<CONFIG:Release>:-O3 -DNDEBUG>
|
||||
$<$<CONFIG:RelWithDebInfo>:-O2 -g>
|
||||
$<$<BOOL:${YAZE_TEST_COVERAGE}>:--coverage -fprofile-arcs -ftest-coverage>
|
||||
$<$<BOOL:${YAZE_TEST_PROFILE}>:-pg>
|
||||
)
|
||||
|
||||
# Common link options
|
||||
target_link_options(yaze_test_interface INTERFACE
|
||||
$<$<BOOL:${YAZE_TEST_COVERAGE}>:--coverage>
|
||||
$<$<BOOL:${YAZE_TEST_PROFILE}>:-pg>
|
||||
)
|
||||
|
||||
# Sanitizers
|
||||
if(YAZE_TEST_SANITIZERS)
|
||||
target_compile_options(yaze_test_interface INTERFACE
|
||||
-fsanitize=address,undefined
|
||||
-fno-omit-frame-pointer
|
||||
-fno-optimize-sibling-calls
|
||||
)
|
||||
target_link_options(yaze_test_interface INTERFACE
|
||||
-fsanitize=address,undefined
|
||||
)
|
||||
|
||||
message(STATUS "Test Infrastructure: Sanitizers enabled (ASan + UBSan)")
|
||||
endif()
|
||||
|
||||
# Coverage
|
||||
if(YAZE_TEST_COVERAGE)
|
||||
find_program(LCOV lcov)
|
||||
find_program(GENHTML genhtml)
|
||||
|
||||
if(LCOV AND GENHTML)
|
||||
add_custom_target(coverage
|
||||
COMMAND ${LCOV} --capture --directory ${CMAKE_BINARY_DIR}
|
||||
--output-file ${CMAKE_BINARY_DIR}/coverage.info
|
||||
--ignore-errors source
|
||||
COMMAND ${LCOV} --remove ${CMAKE_BINARY_DIR}/coverage.info
|
||||
'*/test/*' '*/ext/*' '/usr/*' '*/build/*'
|
||||
--output-file ${CMAKE_BINARY_DIR}/coverage_filtered.info
|
||||
COMMAND ${GENHTML} ${CMAKE_BINARY_DIR}/coverage_filtered.info
|
||||
--output-directory ${CMAKE_BINARY_DIR}/coverage_html
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Generating code coverage report"
|
||||
)
|
||||
|
||||
message(STATUS "Test Infrastructure: Coverage target available")
|
||||
else()
|
||||
message(WARNING "lcov/genhtml not found, coverage target disabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# =============================================================================
|
||||
# Test Creation Function
|
||||
# =============================================================================
|
||||
|
||||
function(yaze_create_test_suite)
|
||||
set(options GUI_TEST REQUIRES_ROM USE_PCH)
|
||||
set(oneValueArgs NAME CATEGORY TIMEOUT PARALLEL_JOBS OUTPUT_DIR)
|
||||
set(multiValueArgs SOURCES DEPENDENCIES LABELS COMPILE_DEFINITIONS)
|
||||
cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
# Validate required arguments
|
||||
if(NOT TEST_NAME)
|
||||
message(FATAL_ERROR "yaze_create_test_suite: NAME is required")
|
||||
endif()
|
||||
if(NOT TEST_SOURCES)
|
||||
message(FATAL_ERROR "yaze_create_test_suite: SOURCES is required")
|
||||
endif()
|
||||
|
||||
# Set defaults
|
||||
if(NOT TEST_CATEGORY)
|
||||
set(TEST_CATEGORY "general")
|
||||
endif()
|
||||
if(NOT TEST_TIMEOUT)
|
||||
set(TEST_TIMEOUT 60)
|
||||
endif()
|
||||
if(NOT TEST_OUTPUT_DIR)
|
||||
set(TEST_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin/test")
|
||||
endif()
|
||||
|
||||
# Create test executable
|
||||
set(target_name yaze_test_${TEST_NAME})
|
||||
add_executable(${target_name} ${TEST_SOURCES})
|
||||
|
||||
# Set output directory
|
||||
set_target_properties(${target_name} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${TEST_OUTPUT_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${TEST_OUTPUT_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${TEST_OUTPUT_DIR}"
|
||||
)
|
||||
|
||||
# Link libraries
|
||||
target_link_libraries(${target_name} PRIVATE
|
||||
yaze_test_interface
|
||||
yaze_test_support
|
||||
GTest::gtest_main
|
||||
GTest::gmock
|
||||
${TEST_DEPENDENCIES}
|
||||
)
|
||||
|
||||
# Apply PCH if requested
|
||||
if(TEST_USE_PCH AND TARGET yaze_test_pch)
|
||||
target_link_libraries(${target_name} PRIVATE yaze_test_pch)
|
||||
target_precompile_headers(${target_name} REUSE_FROM yaze_test_pch)
|
||||
endif()
|
||||
|
||||
# Add compile definitions
|
||||
if(TEST_COMPILE_DEFINITIONS)
|
||||
target_compile_definitions(${target_name} PRIVATE ${TEST_COMPILE_DEFINITIONS})
|
||||
endif()
|
||||
|
||||
# GUI test configuration
|
||||
if(TEST_GUI_TEST)
|
||||
target_compile_definitions(${target_name} PRIVATE
|
||||
IMGUI_ENABLE_TEST_ENGINE=1
|
||||
YAZE_GUI_TEST_TARGET=1
|
||||
)
|
||||
if(TARGET ImGuiTestEngine)
|
||||
target_link_libraries(${target_name} PRIVATE ImGuiTestEngine)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ROM test configuration
|
||||
if(TEST_REQUIRES_ROM)
|
||||
target_compile_definitions(${target_name} PRIVATE
|
||||
YAZE_ROM_TEST=1
|
||||
)
|
||||
endif()
|
||||
|
||||
# Discover tests with CTest
|
||||
set(test_labels "${TEST_CATEGORY}")
|
||||
if(TEST_LABELS)
|
||||
list(APPEND test_labels ${TEST_LABELS})
|
||||
endif()
|
||||
|
||||
gtest_discover_tests(${target_name}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
PROPERTIES
|
||||
LABELS "${test_labels}"
|
||||
TIMEOUT ${TEST_TIMEOUT}
|
||||
DISCOVERY_MODE PRE_TEST
|
||||
DISCOVERY_TIMEOUT 30
|
||||
)
|
||||
|
||||
# Set parallel execution if specified
|
||||
if(TEST_PARALLEL_JOBS)
|
||||
set_property(TEST ${target_name} PROPERTY PROCESSORS ${TEST_PARALLEL_JOBS})
|
||||
endif()
|
||||
|
||||
# Create category-specific test target
|
||||
add_custom_target(test-${TEST_CATEGORY}-${TEST_NAME}
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} -R "^${target_name}" --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running ${TEST_CATEGORY} tests: ${TEST_NAME}"
|
||||
)
|
||||
|
||||
message(STATUS "Test Suite: ${target_name} (${TEST_CATEGORY})")
|
||||
endfunction()
|
||||
|
||||
# =============================================================================
|
||||
# Test Suites Configuration
|
||||
# =============================================================================
|
||||
|
||||
# Smoke Tests (Critical Path)
|
||||
if(YAZE_TEST_SMOKE)
|
||||
file(GLOB SMOKE_TEST_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/test/smoke/*.cc
|
||||
${CMAKE_SOURCE_DIR}/test/smoke/*.h
|
||||
)
|
||||
|
||||
if(SMOKE_TEST_SOURCES)
|
||||
yaze_create_test_suite(
|
||||
NAME smoke
|
||||
CATEGORY smoke
|
||||
SOURCES ${SMOKE_TEST_SOURCES}
|
||||
LABELS critical fast ci-stage1
|
||||
TIMEOUT ${YAZE_TEST_TIMEOUT_SMOKE}
|
||||
USE_PCH
|
||||
)
|
||||
else()
|
||||
message(WARNING "No smoke test sources found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Unit Tests
|
||||
if(YAZE_TEST_UNIT)
|
||||
file(GLOB_RECURSE UNIT_TEST_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/test/unit/*.cc
|
||||
)
|
||||
|
||||
if(UNIT_TEST_SOURCES)
|
||||
# Split unit tests into multiple binaries for parallel execution
|
||||
list(LENGTH UNIT_TEST_SOURCES num_unit_tests)
|
||||
|
||||
if(num_unit_tests GREATER 50)
|
||||
# Create sharded unit test executables
|
||||
set(shard_size 25)
|
||||
math(EXPR num_shards "(${num_unit_tests} + ${shard_size} - 1) / ${shard_size}")
|
||||
|
||||
foreach(shard RANGE 1 ${num_shards})
|
||||
math(EXPR start "(${shard} - 1) * ${shard_size}")
|
||||
math(EXPR end "${shard} * ${shard_size} - 1")
|
||||
|
||||
if(end GREATER ${num_unit_tests})
|
||||
set(end ${num_unit_tests})
|
||||
endif()
|
||||
|
||||
list(SUBLIST UNIT_TEST_SOURCES ${start} ${shard_size} shard_sources)
|
||||
|
||||
yaze_create_test_suite(
|
||||
NAME unit_shard${shard}
|
||||
CATEGORY unit
|
||||
SOURCES ${shard_sources}
|
||||
LABELS unit fast ci-stage2 shard${shard}
|
||||
TIMEOUT ${YAZE_TEST_TIMEOUT_UNIT}
|
||||
USE_PCH
|
||||
)
|
||||
endforeach()
|
||||
else()
|
||||
# Single unit test executable
|
||||
yaze_create_test_suite(
|
||||
NAME unit
|
||||
CATEGORY unit
|
||||
SOURCES ${UNIT_TEST_SOURCES}
|
||||
LABELS unit fast ci-stage2
|
||||
TIMEOUT ${YAZE_TEST_TIMEOUT_UNIT}
|
||||
USE_PCH
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Integration Tests
|
||||
if(YAZE_TEST_INTEGRATION)
|
||||
file(GLOB_RECURSE INTEGRATION_TEST_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/test/integration/*.cc
|
||||
)
|
||||
|
||||
if(INTEGRATION_TEST_SOURCES)
|
||||
yaze_create_test_suite(
|
||||
NAME integration
|
||||
CATEGORY integration
|
||||
SOURCES ${INTEGRATION_TEST_SOURCES}
|
||||
LABELS integration medium ci-stage3
|
||||
TIMEOUT ${YAZE_TEST_TIMEOUT_INTEGRATION}
|
||||
PARALLEL_JOBS 2
|
||||
USE_PCH
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# E2E Tests
|
||||
if(YAZE_TEST_E2E)
|
||||
file(GLOB_RECURSE E2E_TEST_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/test/e2e/*.cc
|
||||
)
|
||||
|
||||
if(E2E_TEST_SOURCES)
|
||||
yaze_create_test_suite(
|
||||
NAME e2e
|
||||
CATEGORY e2e
|
||||
SOURCES ${E2E_TEST_SOURCES}
|
||||
LABELS e2e slow gui ci-stage3
|
||||
TIMEOUT ${YAZE_TEST_TIMEOUT_E2E}
|
||||
GUI_TEST
|
||||
USE_PCH
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Benchmark Tests
|
||||
if(YAZE_TEST_BENCHMARK)
|
||||
file(GLOB_RECURSE BENCHMARK_TEST_SOURCES
|
||||
${CMAKE_SOURCE_DIR}/test/benchmarks/*.cc
|
||||
)
|
||||
|
||||
if(BENCHMARK_TEST_SOURCES)
|
||||
yaze_create_test_suite(
|
||||
NAME benchmark
|
||||
CATEGORY benchmark
|
||||
SOURCES ${BENCHMARK_TEST_SOURCES}
|
||||
LABELS benchmark performance nightly
|
||||
TIMEOUT 1800
|
||||
COMPILE_DEFINITIONS BENCHMARK_BUILD=1
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# =============================================================================
|
||||
# Custom Test Commands
|
||||
# =============================================================================
|
||||
|
||||
# Run all fast tests
|
||||
add_custom_target(test-fast
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} -L "fast" --parallel ${CMAKE_NUMBER_OF_CORES} --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running fast tests"
|
||||
)
|
||||
|
||||
# Run tests by stage
|
||||
add_custom_target(test-stage1
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} -L "ci-stage1" --parallel 4 --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running Stage 1 (Smoke) tests"
|
||||
)
|
||||
|
||||
add_custom_target(test-stage2
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} -L "ci-stage2" --parallel ${CMAKE_NUMBER_OF_CORES} --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running Stage 2 (Unit) tests"
|
||||
)
|
||||
|
||||
add_custom_target(test-stage3
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} -L "ci-stage3" --parallel 2 --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running Stage 3 (Integration/E2E) tests"
|
||||
)
|
||||
|
||||
# Smart test selection based on changed files
|
||||
add_custom_target(test-changed
|
||||
COMMAND ${CMAKE_COMMAND} -E env python3 ${CMAKE_SOURCE_DIR}/scripts/smart_test_selector.py
|
||||
--output filter | xargs ${CMAKE_CTEST_COMMAND} -R --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running tests for changed files"
|
||||
)
|
||||
|
||||
# Parallel test execution with sharding
|
||||
add_custom_target(test-parallel
|
||||
COMMAND python3 ${CMAKE_SOURCE_DIR}/scripts/test_runner.py
|
||||
${CMAKE_BINARY_DIR}/bin/test/yaze_test_unit
|
||||
--shards ${CMAKE_NUMBER_OF_CORES}
|
||||
--output-dir ${CMAKE_BINARY_DIR}/test_results
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running tests with parallel sharding"
|
||||
)
|
||||
|
||||
# Test with retries for flaky tests
|
||||
add_custom_target(test-retry
|
||||
COMMAND python3 ${CMAKE_SOURCE_DIR}/scripts/test_runner.py
|
||||
${CMAKE_BINARY_DIR}/bin/test/yaze_test_unit
|
||||
--retry 2
|
||||
--output-dir ${CMAKE_BINARY_DIR}/test_results
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running tests with retry for failures"
|
||||
)
|
||||
|
||||
# =============================================================================
|
||||
# CTest Configuration
|
||||
# =============================================================================
|
||||
|
||||
set(CTEST_PARALLEL_LEVEL ${CMAKE_NUMBER_OF_CORES} CACHE STRING "Default parallel level for CTest")
|
||||
set(CTEST_OUTPUT_ON_FAILURE ON CACHE BOOL "Show output on test failure")
|
||||
set(CTEST_PROGRESS_OUTPUT ON CACHE BOOL "Show progress during test execution")
|
||||
|
||||
# Configure test output
|
||||
set(CMAKE_CTEST_ARGUMENTS
|
||||
--output-on-failure
|
||||
--progress
|
||||
--parallel ${CTEST_PARALLEL_LEVEL}
|
||||
)
|
||||
|
||||
# Configure test timeout multiplier for slower systems
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(CTEST_TEST_TIMEOUT_MULTIPLIER 1.5)
|
||||
endif()
|
||||
|
||||
# =============================================================================
|
||||
# Test Data Management
|
||||
# =============================================================================
|
||||
|
||||
# Download test data if needed
|
||||
if(YAZE_TEST_INTEGRATION OR YAZE_TEST_E2E)
|
||||
include(FetchContent)
|
||||
|
||||
# Check if test data exists
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/test_data/VERSION")
|
||||
message(STATUS "Downloading test data...")
|
||||
|
||||
FetchContent_Declare(
|
||||
yaze_test_data
|
||||
URL https://github.com/yaze/test-data/archive/refs/tags/v1.0.0.tar.gz
|
||||
URL_HASH SHA256=abcdef1234567890 # Replace with actual hash
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP ON
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(yaze_test_data)
|
||||
|
||||
set(YAZE_TEST_DATA_DIR ${yaze_test_data_SOURCE_DIR} CACHE PATH "Test data directory")
|
||||
else()
|
||||
set(YAZE_TEST_DATA_DIR ${CMAKE_BINARY_DIR}/test_data CACHE PATH "Test data directory")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# =============================================================================
|
||||
# Test Report Generation
|
||||
# =============================================================================
|
||||
|
||||
add_custom_target(test-report
|
||||
COMMAND python3 ${CMAKE_SOURCE_DIR}/scripts/aggregate_test_results.py
|
||||
--input-dir ${CMAKE_BINARY_DIR}/Testing
|
||||
--output ${CMAKE_BINARY_DIR}/test_report.json
|
||||
--generate-html ${CMAKE_BINARY_DIR}/test_report.html
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Generating test report"
|
||||
DEPENDS test-all
|
||||
)
|
||||
|
||||
# =============================================================================
|
||||
# Summary Message
|
||||
# =============================================================================
|
||||
|
||||
message(STATUS "========================================")
|
||||
message(STATUS "Test Infrastructure Configuration:")
|
||||
message(STATUS " Parallel Testing: ${YAZE_TEST_PARALLEL}")
|
||||
message(STATUS " Precompiled Headers: ${YAZE_TEST_PCH}")
|
||||
message(STATUS " Code Coverage: ${YAZE_TEST_COVERAGE}")
|
||||
message(STATUS " Sanitizers: ${YAZE_TEST_SANITIZERS}")
|
||||
message(STATUS " Test Categories:")
|
||||
message(STATUS " Smoke Tests: ${YAZE_TEST_SMOKE}")
|
||||
message(STATUS " Unit Tests: ${YAZE_TEST_UNIT}")
|
||||
message(STATUS " Integration Tests: ${YAZE_TEST_INTEGRATION}")
|
||||
message(STATUS " E2E Tests: ${YAZE_TEST_E2E}")
|
||||
message(STATUS " Benchmarks: ${YAZE_TEST_BENCHMARK}")
|
||||
message(STATUS " Parallel Level: ${CTEST_PARALLEL_LEVEL}")
|
||||
message(STATUS "========================================")
|
||||
@@ -38,6 +38,9 @@ if(_yaze_use_fetched_absl)
|
||||
set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(absl)
|
||||
message(STATUS "Fetched Abseil ${YAZE_ABSL_GIT_TAG}")
|
||||
|
||||
# NEW: Export source directory for Windows builds that need explicit include paths
|
||||
set(YAZE_ABSL_SOURCE_DIR "${absl_SOURCE_DIR}" CACHE INTERNAL "Abseil source directory")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -97,7 +100,17 @@ endif()
|
||||
|
||||
# ABSL_TARGETS is now available to the rest of the project via include()
|
||||
|
||||
if(APPLE AND DEFINED CMAKE_OSX_ARCHITECTURES AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
set(_yaze_absl_arm64 FALSE)
|
||||
if(APPLE)
|
||||
if(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
set(_yaze_absl_arm64 TRUE)
|
||||
elseif(CMAKE_OSX_ARCHITECTURES STREQUAL "" AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
|
||||
# Homebrew LLVM doesn't honor -Xarch_x86_64; strip x86 flags on arm64-only builds.
|
||||
set(_yaze_absl_arm64 TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_yaze_absl_arm64)
|
||||
foreach(_absl_target IN ITEMS absl_random_internal_randen_hwaes absl_random_internal_randen_hwaes_impl)
|
||||
if(TARGET ${_absl_target})
|
||||
get_target_property(_absl_opts ${_absl_target} COMPILE_OPTIONS)
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
# Improved cross-platform support for macOS, Linux, and Windows
|
||||
|
||||
# Configure Asar build options
|
||||
set(ASAR_GEN_EXE OFF CACHE BOOL "Build Asar standalone executable")
|
||||
# Build the standalone executable so we can fall back to a bundled CLI when the
|
||||
# static library misbehaves.
|
||||
set(ASAR_GEN_EXE ON CACHE BOOL "Build Asar standalone executable")
|
||||
set(ASAR_GEN_DLL ON CACHE BOOL "Build Asar shared library")
|
||||
set(ASAR_GEN_LIB ON CACHE BOOL "Build Asar static library")
|
||||
set(ASAR_GEN_EXE_TEST OFF CACHE BOOL "Build Asar executable tests")
|
||||
@@ -14,10 +16,10 @@ if(MSVC)
|
||||
endif()
|
||||
|
||||
# Set Asar source directory
|
||||
set(ASAR_SRC_DIR "${CMAKE_SOURCE_DIR}/src/lib/asar/src")
|
||||
set(ASAR_SRC_DIR "${CMAKE_SOURCE_DIR}/ext/asar/src")
|
||||
|
||||
# Add Asar as subdirectory
|
||||
add_subdirectory(${ASAR_SRC_DIR} EXCLUDE_FROM_ALL)
|
||||
# Add Asar as subdirectory with explicit binary directory
|
||||
add_subdirectory(${ASAR_SRC_DIR} ${CMAKE_BINARY_DIR}/asar EXCLUDE_FROM_ALL)
|
||||
|
||||
# Create modern CMake target for Asar integration
|
||||
if(TARGET asar-static)
|
||||
@@ -42,11 +44,16 @@ if(TARGET asar-static)
|
||||
linux
|
||||
stricmp=strcasecmp
|
||||
)
|
||||
elseif(APPLE)
|
||||
elseif(YAZE_PLATFORM_MACOS)
|
||||
target_compile_definitions(asar-static PRIVATE
|
||||
MACOS
|
||||
stricmp=strcasecmp
|
||||
)
|
||||
elseif(YAZE_PLATFORM_IOS)
|
||||
target_compile_definitions(asar-static PRIVATE
|
||||
YAZE_IOS
|
||||
stricmp=strcasecmp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add include directories
|
||||
|
||||
@@ -1,155 +1,120 @@
|
||||
# This file centralizes the management of all third-party dependencies.
|
||||
# It provides functions to find or fetch dependencies and creates alias targets
|
||||
# for consistent usage throughout the project.
|
||||
# YAZE Dependencies Management
|
||||
# Centralized dependency management using CPM.cmake
|
||||
|
||||
include(FetchContent)
|
||||
# Include CPM and options
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/options.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
# ============================================================================
|
||||
# Helper function to add a dependency
|
||||
# ============================================================================
|
||||
function(yaze_add_dependency name)
|
||||
set(options)
|
||||
set(oneValueArgs GIT_REPOSITORY GIT_TAG URL)
|
||||
set(multiValueArgs)
|
||||
cmake_parse_arguments(DEP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
message(STATUS "=== Setting up YAZE dependencies with CPM.cmake ===")
|
||||
|
||||
if(TARGET yaze::${name})
|
||||
return()
|
||||
endif()
|
||||
# Only prefer local/system packages when explicitly requested.
|
||||
set(CPM_USE_LOCAL_PACKAGES ${YAZE_USE_SYSTEM_DEPS} CACHE BOOL "" FORCE)
|
||||
|
||||
# Try to find the package via find_package first
|
||||
find_package(${name} QUIET)
|
||||
# Clear any previous dependency targets
|
||||
set(YAZE_ALL_DEPENDENCIES "")
|
||||
set(YAZE_SDL2_TARGETS "")
|
||||
set(YAZE_YAML_TARGETS "")
|
||||
set(YAZE_IMGUI_TARGETS "")
|
||||
set(YAZE_IMPLOT_TARGETS "")
|
||||
set(YAZE_JSON_TARGETS "")
|
||||
set(YAZE_HTTPLIB_TARGETS "")
|
||||
set(YAZE_GRPC_TARGETS "")
|
||||
set(YAZE_FTXUI_TARGETS "")
|
||||
set(YAZE_TESTING_TARGETS "")
|
||||
|
||||
if(${name}_FOUND)
|
||||
message(STATUS "Found ${name} via find_package")
|
||||
if(TARGET ${name}::${name})
|
||||
add_library(yaze::${name} ALIAS ${name}::${name})
|
||||
# Core dependencies (always required)
|
||||
# SDL selection: SDL2 (default) or SDL3 (experimental)
|
||||
if(YAZE_USE_SDL3)
|
||||
include(cmake/dependencies/sdl3.cmake)
|
||||
# Debug: message(STATUS "After SDL3 setup, YAZE_SDL3_TARGETS = '${YAZE_SDL3_TARGETS}'")
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_SDL3_TARGETS})
|
||||
else()
|
||||
# Handle cases where find_package doesn't create an imported target
|
||||
# This is a simplified approach; more logic may be needed for specific packages
|
||||
add_library(yaze::${name} INTERFACE IMPORTED)
|
||||
target_include_directories(yaze::${name} INTERFACE ${${name}_INCLUDE_DIRS})
|
||||
target_link_libraries(yaze::${name} INTERFACE ${${name}_LIBRARIES})
|
||||
endif()
|
||||
return()
|
||||
include(cmake/dependencies/sdl2.cmake)
|
||||
# Debug: message(STATUS "After SDL2 setup, YAZE_SDL2_TARGETS = '${YAZE_SDL2_TARGETS}'")
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_SDL2_TARGETS})
|
||||
endif()
|
||||
|
||||
# If not found, use FetchContent
|
||||
message(STATUS "Could not find ${name}, fetching from source.")
|
||||
FetchContent_Declare(
|
||||
${name}
|
||||
GIT_REPOSITORY ${DEP_GIT_REPOSITORY}
|
||||
GIT_TAG ${DEP_GIT_TAG}
|
||||
)
|
||||
include(cmake/dependencies/yaml.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_YAML_TARGETS})
|
||||
|
||||
FetchContent_GetProperties(${name})
|
||||
if(NOT ${name}_POPULATED)
|
||||
FetchContent_Populate(${name})
|
||||
add_subdirectory(${${name}_SOURCE_DIR} ${${name}_BINARY_DIR})
|
||||
endif()
|
||||
include(cmake/dependencies/imgui.cmake)
|
||||
# Debug: message(STATUS "After ImGui setup, YAZE_IMGUI_TARGETS = '${YAZE_IMGUI_TARGETS}'")
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_IMGUI_TARGETS})
|
||||
|
||||
if(TARGET ${name})
|
||||
add_library(yaze::${name} ALIAS ${name})
|
||||
elseif(TARGET ${name}::${name})
|
||||
add_library(yaze::${name} ALIAS ${name}::${name})
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to create target for ${name}")
|
||||
endif()
|
||||
endfunction()
|
||||
include(cmake/dependencies/implot.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_IMPLOT_TARGETS})
|
||||
|
||||
# ============================================================================
|
||||
# Dependency Declarations
|
||||
# ============================================================================
|
||||
|
||||
# gRPC (must come before Abseil - provides its own compatible Abseil)
|
||||
if(YAZE_WITH_GRPC)
|
||||
include(cmake/grpc.cmake)
|
||||
# Verify ABSL_TARGETS was populated by gRPC
|
||||
list(LENGTH ABSL_TARGETS _absl_count)
|
||||
if(_absl_count EQUAL 0)
|
||||
message(FATAL_ERROR "ABSL_TARGETS is empty after including grpc.cmake!")
|
||||
else()
|
||||
message(STATUS "gRPC provides ${_absl_count} Abseil targets for linking")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Abseil (only if gRPC didn't provide it)
|
||||
if(NOT YAZE_WITH_GRPC)
|
||||
# Abseil is required for failure_signal_handler, status, and other utilities
|
||||
# Only include standalone Abseil when gRPC is disabled - when gRPC is enabled,
|
||||
# it provides its own bundled Abseil via CPM
|
||||
if(NOT YAZE_ENABLE_GRPC)
|
||||
include(cmake/absl.cmake)
|
||||
# Verify ABSL_TARGETS was populated
|
||||
list(LENGTH ABSL_TARGETS _absl_count)
|
||||
if(_absl_count EQUAL 0)
|
||||
message(FATAL_ERROR "ABSL_TARGETS is empty after including absl.cmake!")
|
||||
else()
|
||||
message(STATUS "Abseil provides ${_absl_count} targets for linking")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(YAZE_PROTOBUF_TARGETS)
|
||||
|
||||
if(TARGET protobuf::libprotobuf)
|
||||
list(APPEND YAZE_PROTOBUF_TARGETS protobuf::libprotobuf)
|
||||
else()
|
||||
if(TARGET libprotobuf)
|
||||
list(APPEND YAZE_PROTOBUF_TARGETS libprotobuf)
|
||||
endif()
|
||||
# Optional dependencies based on feature flags
|
||||
if(YAZE_ENABLE_JSON)
|
||||
include(cmake/dependencies/json.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_JSON_TARGETS})
|
||||
endif()
|
||||
|
||||
set(YAZE_PROTOBUF_WHOLEARCHIVE_TARGETS ${YAZE_PROTOBUF_TARGETS})
|
||||
|
||||
if(YAZE_PROTOBUF_TARGETS)
|
||||
list(GET YAZE_PROTOBUF_TARGETS 0 YAZE_PROTOBUF_TARGET)
|
||||
else()
|
||||
set(YAZE_PROTOBUF_TARGET "")
|
||||
# Native HTTP/HTTPS (cpp-httplib) for non-WASM builds
|
||||
if(NOT EMSCRIPTEN)
|
||||
include(cmake/dependencies/httplib.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_HTTPLIB_TARGETS})
|
||||
endif()
|
||||
|
||||
# SDL2
|
||||
include(cmake/sdl2.cmake)
|
||||
# CRITICAL: Load testing dependencies BEFORE gRPC when both are enabled
|
||||
# This ensures gmock is available before Abseil (bundled with gRPC) tries to export test_allocator
|
||||
# which depends on gmock. This prevents CMake export errors.
|
||||
if(YAZE_BUILD_TESTS AND YAZE_ENABLE_GRPC)
|
||||
include(cmake/dependencies/testing.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_TESTING_TARGETS})
|
||||
endif()
|
||||
|
||||
# Asar
|
||||
include(cmake/asar.cmake)
|
||||
if(YAZE_ENABLE_GRPC)
|
||||
include(cmake/dependencies/grpc.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_GRPC_TARGETS})
|
||||
endif()
|
||||
|
||||
# Google Test
|
||||
if(YAZE_BUILD_CLI AND NOT EMSCRIPTEN)
|
||||
include(cmake/dependencies/ftxui.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_FTXUI_TARGETS})
|
||||
endif()
|
||||
|
||||
# Load testing dependencies after gRPC if tests are enabled but gRPC is not
|
||||
if(YAZE_BUILD_TESTS AND NOT YAZE_ENABLE_GRPC)
|
||||
include(cmake/dependencies/testing.cmake)
|
||||
list(APPEND YAZE_ALL_DEPENDENCIES ${YAZE_TESTING_TARGETS})
|
||||
endif()
|
||||
|
||||
# ASAR dependency (for ROM assembly) - temporarily disabled
|
||||
# TODO: Add CMakeLists.txt to bundled ASAR or find working repository
|
||||
message(STATUS "ASAR dependency temporarily disabled - will be added later")
|
||||
|
||||
# Print dependency summary
|
||||
message(STATUS "=== YAZE Dependencies Summary ===")
|
||||
message(STATUS "Total dependencies: ${YAZE_ALL_DEPENDENCIES}")
|
||||
message(STATUS "SDL2: ${YAZE_SDL2_TARGETS}")
|
||||
message(STATUS "YAML: ${YAZE_YAML_TARGETS}")
|
||||
message(STATUS "ImGui: ${YAZE_IMGUI_TARGETS}")
|
||||
message(STATUS "ImPlot: ${YAZE_IMPLOT_TARGETS}")
|
||||
if(YAZE_ENABLE_JSON)
|
||||
message(STATUS "JSON: ${YAZE_JSON_TARGETS}")
|
||||
endif()
|
||||
if(YAZE_ENABLE_GRPC)
|
||||
message(STATUS "gRPC: ${YAZE_GRPC_TARGETS}")
|
||||
endif()
|
||||
if(NOT EMSCRIPTEN)
|
||||
message(STATUS "httplib: ${YAZE_HTTPLIB_TARGETS}")
|
||||
endif()
|
||||
if(YAZE_BUILD_CLI AND NOT EMSCRIPTEN)
|
||||
message(STATUS "FTXUI: ${YAZE_FTXUI_TARGETS}")
|
||||
endif()
|
||||
if(YAZE_BUILD_TESTS)
|
||||
include(cmake/gtest.cmake)
|
||||
message(STATUS "Testing: ${YAZE_TESTING_TARGETS}")
|
||||
endif()
|
||||
message(STATUS "=================================")
|
||||
|
||||
# ImGui
|
||||
include(cmake/imgui.cmake)
|
||||
|
||||
# FTXUI (for z3ed)
|
||||
if(YAZE_BUILD_Z3ED)
|
||||
FetchContent_Declare(ftxui
|
||||
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
|
||||
GIT_TAG v5.0.0
|
||||
)
|
||||
FetchContent_MakeAvailable(ftxui)
|
||||
endif()
|
||||
|
||||
# yaml-cpp (always available for configuration files)
|
||||
set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "Disable yaml-cpp tests" FORCE)
|
||||
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "Disable yaml-cpp contrib" FORCE)
|
||||
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "Disable yaml-cpp tools" FORCE)
|
||||
set(YAML_CPP_INSTALL OFF CACHE BOOL "Disable yaml-cpp install" FORCE)
|
||||
set(YAML_CPP_FORMAT_SOURCE OFF CACHE BOOL "Disable yaml-cpp format target" FORCE)
|
||||
|
||||
# yaml-cpp (uses CMAKE_POLICY_VERSION_MINIMUM set in root CMakeLists.txt)
|
||||
FetchContent_Declare(yaml-cpp
|
||||
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
|
||||
GIT_TAG 0.8.0
|
||||
)
|
||||
FetchContent_MakeAvailable(yaml-cpp)
|
||||
|
||||
# Fix MSVC exception handling warning for yaml-cpp
|
||||
if(MSVC AND TARGET yaml-cpp)
|
||||
target_compile_options(yaml-cpp PRIVATE /EHsc)
|
||||
endif()
|
||||
|
||||
# nlohmann_json (header only)
|
||||
if(YAZE_WITH_JSON)
|
||||
set(JSON_BuildTests OFF CACHE INTERNAL "Disable nlohmann_json tests")
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/third_party/json ${CMAKE_BINARY_DIR}/third_party/json EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
# httplib (header only)
|
||||
# No action needed here as it's included directly.
|
||||
# Export all dependency targets for use in other CMake files
|
||||
set(YAZE_ALL_DEPENDENCIES ${YAZE_ALL_DEPENDENCIES})
|
||||
|
||||
30
cmake/dependencies.lock
Normal file
30
cmake/dependencies.lock
Normal file
@@ -0,0 +1,30 @@
|
||||
# CPM Dependencies Lock File
|
||||
# This file pins exact versions to ensure reproducible builds
|
||||
# Update versions here when upgrading dependencies
|
||||
|
||||
# Core dependencies
|
||||
set(SDL2_VERSION "2.30.0" CACHE STRING "SDL2 version")
|
||||
set(YAML_CPP_VERSION "0.8.0" CACHE STRING "yaml-cpp version")
|
||||
set(NLOHMANN_JSON_VERSION "3.11.3" CACHE STRING "nlohmann/json version")
|
||||
set(HTTPLIB_VERSION "0.26.0" CACHE STRING "cpp-httplib version")
|
||||
|
||||
# gRPC and related
|
||||
# Using v1.67.1 for MSVC compatibility (v1.75.1 has UPB compilation errors on Windows)
|
||||
set(GRPC_VERSION "1.67.1" CACHE STRING "gRPC version - MSVC compatible")
|
||||
set(PROTOBUF_VERSION "3.25.1" CACHE STRING "Protobuf version")
|
||||
set(ABSEIL_VERSION "20240116.0" CACHE STRING "Abseil version")
|
||||
# Cache revision: increment to force CPM cache invalidation (current: 2)
|
||||
|
||||
# Testing
|
||||
set(GTEST_VERSION "1.14.0" CACHE STRING "Google Test version")
|
||||
set(BENCHMARK_VERSION "1.8.3" CACHE STRING "Google Benchmark version")
|
||||
|
||||
# CLI tools
|
||||
set(FTXUI_VERSION "5.0.0" CACHE STRING "FTXUI version")
|
||||
|
||||
# ImGui
|
||||
set(IMGUI_VERSION "1.90.4" CACHE STRING "Dear ImGui version")
|
||||
# Cache revision: increment to force rebuild (current: 2)
|
||||
|
||||
# ASAR
|
||||
set(ASAR_VERSION "main" CACHE STRING "ASAR version")
|
||||
55
cmake/dependencies/ftxui.cmake
Normal file
55
cmake/dependencies/ftxui.cmake
Normal file
@@ -0,0 +1,55 @@
|
||||
# FTXUI dependency management for CLI tools
|
||||
# Uses CPM.cmake for consistent cross-platform builds
|
||||
|
||||
if(NOT YAZE_BUILD_CLI)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
message(STATUS "Setting up FTXUI ${FTXUI_VERSION} with CPM.cmake")
|
||||
|
||||
# Use CPM to fetch FTXUI
|
||||
CPMAddPackage(
|
||||
NAME ftxui
|
||||
VERSION ${FTXUI_VERSION}
|
||||
GITHUB_REPOSITORY ArthurSonzogni/ftxui
|
||||
GIT_TAG v${FTXUI_VERSION}
|
||||
OPTIONS
|
||||
"FTXUI_BUILD_EXAMPLES OFF"
|
||||
"FTXUI_BUILD_TESTS OFF"
|
||||
"FTXUI_ENABLE_INSTALL OFF"
|
||||
)
|
||||
|
||||
# FTXUI targets are created during the build phase
|
||||
# We'll create our own interface target and link when available
|
||||
add_library(yaze_ftxui INTERFACE)
|
||||
|
||||
# Link to the actual FTXUI targets
|
||||
if(TARGET ftxui::screen AND TARGET ftxui::dom AND TARGET ftxui::component)
|
||||
target_link_libraries(yaze_ftxui INTERFACE
|
||||
ftxui::screen
|
||||
ftxui::dom
|
||||
ftxui::component
|
||||
)
|
||||
else()
|
||||
# Fallback for when targets aren't namespaced
|
||||
target_link_libraries(yaze_ftxui INTERFACE
|
||||
screen
|
||||
dom
|
||||
component
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add include path with compile options for Ninja Multi-Config compatibility
|
||||
# The -isystem-after flag doesn't work properly with some generator/compiler combinations
|
||||
if(ftxui_SOURCE_DIR)
|
||||
add_compile_options(-I${ftxui_SOURCE_DIR}/include)
|
||||
message(STATUS " Added FTXUI include: ${ftxui_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
# Export FTXUI targets for use in other CMake files
|
||||
set(YAZE_FTXUI_TARGETS yaze_ftxui)
|
||||
|
||||
message(STATUS "FTXUI setup complete")
|
||||
581
cmake/dependencies/grpc.cmake
Normal file
581
cmake/dependencies/grpc.cmake
Normal file
@@ -0,0 +1,581 @@
|
||||
# gRPC and Protobuf dependency management
|
||||
# Uses CPM.cmake for consistent cross-platform builds, with optional system package fallback
|
||||
|
||||
if(NOT YAZE_ENABLE_GRPC)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Include CPM and dependencies lock
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
message(STATUS "Setting up gRPC ${GRPC_VERSION}")
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Option: YAZE_PREFER_SYSTEM_GRPC - Use system-installed gRPC/protobuf/abseil
|
||||
# when available (e.g., from Homebrew, apt, vcpkg).
|
||||
#
|
||||
# Benefits: Much faster configure/build times for local development
|
||||
# Trade-off: May have version mismatches between system packages
|
||||
#
|
||||
# Example: cmake --preset mac-ai-fast (uses system packages)
|
||||
#-----------------------------------------------------------------------
|
||||
option(YAZE_PREFER_SYSTEM_GRPC "Prefer system-installed gRPC/protobuf over CPM" OFF)
|
||||
|
||||
if(YAZE_PREFER_SYSTEM_GRPC OR YAZE_USE_SYSTEM_DEPS)
|
||||
message(STATUS "Attempting to use system gRPC/protobuf packages...")
|
||||
|
||||
# Try CMake's find_package first (works with Homebrew on macOS)
|
||||
find_package(gRPC CONFIG QUIET)
|
||||
find_package(Protobuf CONFIG QUIET)
|
||||
find_package(absl CONFIG QUIET)
|
||||
|
||||
if(gRPC_FOUND AND Protobuf_FOUND AND absl_FOUND)
|
||||
message(STATUS "✓ Found system gRPC: ${gRPC_VERSION}")
|
||||
message(STATUS "✓ Found system Protobuf: ${Protobuf_VERSION}")
|
||||
message(STATUS "✓ Found system Abseil")
|
||||
|
||||
# Find protoc and grpc_cpp_plugin executables
|
||||
find_program(PROTOC_EXECUTABLE protoc)
|
||||
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
|
||||
|
||||
if(PROTOC_EXECUTABLE AND GRPC_CPP_PLUGIN)
|
||||
message(STATUS "✓ Found protoc: ${PROTOC_EXECUTABLE}")
|
||||
message(STATUS "✓ Found grpc_cpp_plugin: ${GRPC_CPP_PLUGIN}")
|
||||
|
||||
# Create imported targets for the executables if they don't exist
|
||||
if(NOT TARGET protoc)
|
||||
add_executable(protoc IMPORTED)
|
||||
set_target_properties(protoc PROPERTIES IMPORTED_LOCATION "${PROTOC_EXECUTABLE}")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET grpc_cpp_plugin)
|
||||
add_executable(grpc_cpp_plugin IMPORTED)
|
||||
set_target_properties(grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION "${GRPC_CPP_PLUGIN}")
|
||||
endif()
|
||||
|
||||
# Create convenience interface for basic gRPC linking
|
||||
add_library(yaze_grpc_deps INTERFACE)
|
||||
target_link_libraries(yaze_grpc_deps INTERFACE
|
||||
gRPC::grpc++
|
||||
gRPC::grpc++_reflection
|
||||
protobuf::libprotobuf
|
||||
)
|
||||
|
||||
# Ensure Abseil include directories are available
|
||||
# Homebrew's abseil may not properly export include dirs
|
||||
get_target_property(_ABSL_BASE_INCLUDE absl::base INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if(_ABSL_BASE_INCLUDE)
|
||||
target_include_directories(yaze_grpc_deps INTERFACE ${_ABSL_BASE_INCLUDE})
|
||||
message(STATUS " Added Abseil include: ${_ABSL_BASE_INCLUDE}")
|
||||
elseif(APPLE)
|
||||
# Fallback for Homebrew on macOS
|
||||
target_include_directories(yaze_grpc_deps INTERFACE /opt/homebrew/include)
|
||||
message(STATUS " Added Homebrew Abseil include: /opt/homebrew/include")
|
||||
endif()
|
||||
|
||||
# Create interface libraries for compatibility with CPM target names
|
||||
# CPM gRPC creates lowercase 'grpc++' targets
|
||||
# System gRPC (Homebrew) creates namespaced 'gRPC::grpc++' targets
|
||||
# We create interface libs (not aliases) so we can add include directories
|
||||
if(NOT TARGET grpc++)
|
||||
add_library(grpc++ INTERFACE)
|
||||
target_link_libraries(grpc++ INTERFACE gRPC::grpc++)
|
||||
# Add abseil includes for targets linking to grpc++
|
||||
if(_ABSL_BASE_INCLUDE)
|
||||
target_include_directories(grpc++ INTERFACE ${_ABSL_BASE_INCLUDE})
|
||||
elseif(APPLE)
|
||||
target_include_directories(grpc++ INTERFACE /opt/homebrew/include)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT TARGET grpc++_reflection)
|
||||
add_library(grpc++_reflection INTERFACE)
|
||||
target_link_libraries(grpc++_reflection INTERFACE gRPC::grpc++_reflection)
|
||||
endif()
|
||||
if(NOT TARGET grpc::grpc++)
|
||||
add_library(grpc::grpc++ ALIAS gRPC::grpc++)
|
||||
endif()
|
||||
if(NOT TARGET grpc::grpc++_reflection)
|
||||
add_library(grpc::grpc++_reflection ALIAS gRPC::grpc++_reflection)
|
||||
endif()
|
||||
|
||||
# Export targets
|
||||
set(YAZE_GRPC_TARGETS
|
||||
gRPC::grpc++
|
||||
gRPC::grpc++_reflection
|
||||
protobuf::libprotobuf
|
||||
)
|
||||
|
||||
# Setup protobuf generation directory
|
||||
set(_gRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens CACHE INTERNAL "Protobuf generated files directory")
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/gens)
|
||||
|
||||
# Get protobuf include directory from package
|
||||
get_target_property(_PROTOBUF_INCLUDE_DIRS protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if(_PROTOBUF_INCLUDE_DIRS)
|
||||
list(GET _PROTOBUF_INCLUDE_DIRS 0 _gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR)
|
||||
set(_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR ${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR} CACHE INTERNAL "Protobuf include directory")
|
||||
endif()
|
||||
|
||||
# Add global include directories for system packages
|
||||
# This ensures all targets can find abseil headers even if target propagation fails
|
||||
# Use add_compile_options for reliable include path propagation with Ninja Multi-Config
|
||||
if(_ABSL_BASE_INCLUDE)
|
||||
add_compile_options(-I${_ABSL_BASE_INCLUDE})
|
||||
message(STATUS " Added Abseil include via compile options: ${_ABSL_BASE_INCLUDE}")
|
||||
elseif(APPLE)
|
||||
add_compile_options(-I/opt/homebrew/include)
|
||||
message(STATUS " Added Homebrew include via compile options: /opt/homebrew/include")
|
||||
endif()
|
||||
|
||||
message(STATUS "✓ Using SYSTEM gRPC stack - fast configure!")
|
||||
message(STATUS " Protobuf gens dir: ${_gRPC_PROTO_GENS_DIR}")
|
||||
message(STATUS " Protobuf include dir: ${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR}")
|
||||
set(_YAZE_USING_SYSTEM_GRPC TRUE)
|
||||
else()
|
||||
message(STATUS "○ System gRPC found but protoc/grpc_cpp_plugin missing, falling back to CPM")
|
||||
set(_YAZE_USING_SYSTEM_GRPC FALSE)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "○ System gRPC/protobuf not found, falling back to CPM")
|
||||
set(_YAZE_USING_SYSTEM_GRPC FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If we're using system gRPC, skip CPM entirely and jump to function definition
|
||||
if(_YAZE_USING_SYSTEM_GRPC)
|
||||
message(STATUS "Skipping CPM gRPC build - using system packages")
|
||||
else()
|
||||
# CPM build path
|
||||
message(STATUS "Building gRPC from source via CPM (this takes 15-20 minutes on first build)")
|
||||
message(STATUS " Tip: Install gRPC via Homebrew and use -DYAZE_PREFER_SYSTEM_GRPC=ON for faster builds")
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Guard CMake's package lookup so CPM always downloads a consistent gRPC
|
||||
# toolchain instead of picking up partially-installed Homebrew/apt copies.
|
||||
#-----------------------------------------------------------------------
|
||||
if(DEFINED CPM_USE_LOCAL_PACKAGES)
|
||||
set(_YAZE_GRPC_SAVED_CPM_USE_LOCAL_PACKAGES "${CPM_USE_LOCAL_PACKAGES}")
|
||||
else()
|
||||
set(_YAZE_GRPC_SAVED_CPM_USE_LOCAL_PACKAGES "__YAZE_UNSET__")
|
||||
endif()
|
||||
set(CPM_USE_LOCAL_PACKAGES OFF)
|
||||
|
||||
foreach(_yaze_pkg IN ITEMS gRPC Protobuf absl)
|
||||
string(TOUPPER "CMAKE_DISABLE_FIND_PACKAGE_${_yaze_pkg}" _yaze_disable_var)
|
||||
if(DEFINED ${_yaze_disable_var})
|
||||
set("_YAZE_GRPC_SAVE_${_yaze_disable_var}" "${${_yaze_disable_var}}")
|
||||
else()
|
||||
set("_YAZE_GRPC_SAVE_${_yaze_disable_var}" "__YAZE_UNSET__")
|
||||
endif()
|
||||
set(${_yaze_disable_var} TRUE)
|
||||
endforeach()
|
||||
|
||||
if(DEFINED PKG_CONFIG_USE_CMAKE_PREFIX_PATH)
|
||||
set(_YAZE_GRPC_SAVED_PKG_CONFIG_USE_CMAKE_PREFIX_PATH "${PKG_CONFIG_USE_CMAKE_PREFIX_PATH}")
|
||||
else()
|
||||
set(_YAZE_GRPC_SAVED_PKG_CONFIG_USE_CMAKE_PREFIX_PATH "__YAZE_UNSET__")
|
||||
endif()
|
||||
set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH FALSE)
|
||||
|
||||
set(_YAZE_GRPC_SAVED_PREFIX_PATH "${CMAKE_PREFIX_PATH}")
|
||||
set(CMAKE_PREFIX_PATH "")
|
||||
|
||||
if(DEFINED CMAKE_CROSSCOMPILING)
|
||||
set(_YAZE_GRPC_SAVED_CROSSCOMPILING "${CMAKE_CROSSCOMPILING}")
|
||||
else()
|
||||
set(_YAZE_GRPC_SAVED_CROSSCOMPILING "__YAZE_UNSET__")
|
||||
endif()
|
||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL CMAKE_SYSTEM_NAME
|
||||
AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR)
|
||||
set(CMAKE_CROSSCOMPILING FALSE)
|
||||
endif()
|
||||
|
||||
if(DEFINED CMAKE_CXX_STANDARD)
|
||||
set(_YAZE_GRPC_SAVED_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
|
||||
else()
|
||||
set(_YAZE_GRPC_SAVED_CXX_STANDARD "__YAZE_UNSET__")
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Set gRPC options before adding package
|
||||
set(gRPC_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_CODEGEN ON CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_CPP_PLUGIN ON CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_CSHARP_EXT OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_CSHARP_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_NODE_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_PHP_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_PYTHON_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_RUBY_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_CPP_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPCPP_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BENCHMARK_PROVIDER "none" CACHE STRING "" FORCE)
|
||||
set(gRPC_ZLIB_PROVIDER "module" CACHE STRING "" FORCE)
|
||||
set(gRPC_PROTOBUF_PROVIDER "module" CACHE STRING "" FORCE)
|
||||
set(gRPC_ABSL_PROVIDER "module" CACHE STRING "" FORCE)
|
||||
set(protobuf_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(protobuf_BUILD_CONFORMANCE OFF CACHE BOOL "" FORCE)
|
||||
set(protobuf_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
set(protobuf_BUILD_PROTOC_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(protobuf_WITH_ZLIB ON CACHE BOOL "" FORCE)
|
||||
set(protobuf_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
set(protobuf_MSVC_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
|
||||
set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "" FORCE)
|
||||
set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
set(ABSL_BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
||||
set(utf8_range_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(utf8_range_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
set(utf8_range_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
|
||||
# Force consistent MSVC runtime library across all gRPC components (Windows only)
|
||||
# This ensures gRPC, protobuf, and Abseil all use the same CRT linking mode
|
||||
if(WIN32 AND MSVC)
|
||||
# Use dynamic CRT (/MD for Release, /MDd for Debug) to avoid undefined math symbols
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL" CACHE STRING "" FORCE)
|
||||
# Also ensure protobuf doesn't try to use static runtime
|
||||
set(protobuf_MSVC_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
|
||||
message(STATUS "Forcing dynamic MSVC runtime for gRPC dependencies: ${CMAKE_MSVC_RUNTIME_LIBRARY}")
|
||||
endif()
|
||||
|
||||
# Temporarily disable installation to prevent utf8_range export errors
|
||||
# This is a workaround for gRPC 1.67.1 where utf8_range tries to install targets
|
||||
# that depend on Abseil, but we have ABSL_ENABLE_INSTALL=OFF
|
||||
set(CMAKE_SKIP_INSTALL_RULES TRUE)
|
||||
|
||||
# Use CPM to fetch gRPC with bundled dependencies
|
||||
# GIT_SUBMODULES "" disables submodule recursion since gRPC handles its own deps via CMake
|
||||
|
||||
if(WIN32)
|
||||
set(GRPC_VERSION_TO_USE "1.67.1")
|
||||
else()
|
||||
set(GRPC_VERSION_TO_USE "1.76.0")
|
||||
endif()
|
||||
|
||||
message(STATUS "Selected gRPC version ${GRPC_VERSION_TO_USE} for platform ${CMAKE_SYSTEM_NAME}")
|
||||
|
||||
CPMAddPackage(
|
||||
NAME grpc
|
||||
VERSION ${GRPC_VERSION_TO_USE}
|
||||
GITHUB_REPOSITORY grpc/grpc
|
||||
GIT_TAG v${GRPC_VERSION_TO_USE}
|
||||
GIT_SUBMODULES ""
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
|
||||
# Re-enable installation rules after gRPC is loaded
|
||||
set(CMAKE_SKIP_INSTALL_RULES FALSE)
|
||||
|
||||
# Restore CPM lookup behaviour and toolchain detection environment early so
|
||||
# subsequent dependency configuration isn't polluted even if we hit errors.
|
||||
if("${_YAZE_GRPC_SAVED_CPM_USE_LOCAL_PACKAGES}" STREQUAL "__YAZE_UNSET__")
|
||||
unset(CPM_USE_LOCAL_PACKAGES)
|
||||
else()
|
||||
set(CPM_USE_LOCAL_PACKAGES "${_YAZE_GRPC_SAVED_CPM_USE_LOCAL_PACKAGES}")
|
||||
endif()
|
||||
|
||||
foreach(_yaze_pkg IN ITEMS gRPC Protobuf absl)
|
||||
string(TOUPPER "CMAKE_DISABLE_FIND_PACKAGE_${_yaze_pkg}" _yaze_disable_var)
|
||||
string(TOUPPER "_YAZE_GRPC_SAVE_${_yaze_disable_var}" _yaze_saved_key)
|
||||
if(NOT DEFINED ${_yaze_saved_key})
|
||||
continue()
|
||||
endif()
|
||||
if("${${_yaze_saved_key}}" STREQUAL "__YAZE_UNSET__")
|
||||
unset(${_yaze_disable_var})
|
||||
else()
|
||||
set(${_yaze_disable_var} "${${_yaze_saved_key}}")
|
||||
endif()
|
||||
unset(${_yaze_saved_key})
|
||||
endforeach()
|
||||
|
||||
if("${_YAZE_GRPC_SAVED_PKG_CONFIG_USE_CMAKE_PREFIX_PATH}" STREQUAL "__YAZE_UNSET__")
|
||||
unset(PKG_CONFIG_USE_CMAKE_PREFIX_PATH)
|
||||
else()
|
||||
set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH "${_YAZE_GRPC_SAVED_PKG_CONFIG_USE_CMAKE_PREFIX_PATH}")
|
||||
endif()
|
||||
unset(_YAZE_GRPC_SAVED_PKG_CONFIG_USE_CMAKE_PREFIX_PATH)
|
||||
|
||||
set(CMAKE_PREFIX_PATH "${_YAZE_GRPC_SAVED_PREFIX_PATH}")
|
||||
unset(_YAZE_GRPC_SAVED_PREFIX_PATH)
|
||||
|
||||
if("${_YAZE_GRPC_SAVED_CROSSCOMPILING}" STREQUAL "__YAZE_UNSET__")
|
||||
unset(CMAKE_CROSSCOMPILING)
|
||||
else()
|
||||
set(CMAKE_CROSSCOMPILING "${_YAZE_GRPC_SAVED_CROSSCOMPILING}")
|
||||
endif()
|
||||
unset(_YAZE_GRPC_SAVED_CROSSCOMPILING)
|
||||
|
||||
if("${_YAZE_GRPC_SAVED_CXX_STANDARD}" STREQUAL "__YAZE_UNSET__")
|
||||
unset(CMAKE_CXX_STANDARD)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD "${_YAZE_GRPC_SAVED_CXX_STANDARD}")
|
||||
endif()
|
||||
unset(_YAZE_GRPC_SAVED_CXX_STANDARD)
|
||||
|
||||
# Check which target naming convention is used
|
||||
if(TARGET grpc++)
|
||||
message(STATUS "Found non-namespaced gRPC target grpc++")
|
||||
if(NOT TARGET grpc::grpc++)
|
||||
add_library(grpc::grpc++ ALIAS grpc++)
|
||||
endif()
|
||||
if(NOT TARGET grpc::grpc++_reflection AND TARGET grpc++_reflection)
|
||||
add_library(grpc::grpc++_reflection ALIAS grpc++_reflection)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(_YAZE_GRPC_ERRORS "")
|
||||
|
||||
if(NOT TARGET grpc++ AND NOT TARGET grpc::grpc++)
|
||||
list(APPEND _YAZE_GRPC_ERRORS "gRPC target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET protoc)
|
||||
list(APPEND _YAZE_GRPC_ERRORS "protoc target not found after gRPC setup")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET grpc_cpp_plugin)
|
||||
list(APPEND _YAZE_GRPC_ERRORS "grpc_cpp_plugin target not found after gRPC setup")
|
||||
endif()
|
||||
|
||||
if(_YAZE_GRPC_ERRORS)
|
||||
list(JOIN _YAZE_GRPC_ERRORS "\n" _YAZE_GRPC_ERROR_MESSAGE)
|
||||
message(FATAL_ERROR "${_YAZE_GRPC_ERROR_MESSAGE}")
|
||||
endif()
|
||||
|
||||
# Create convenience interface for basic gRPC linking (renamed to avoid conflict with yaze_grpc_support STATIC library)
|
||||
add_library(yaze_grpc_deps INTERFACE)
|
||||
target_link_libraries(yaze_grpc_deps INTERFACE
|
||||
grpc::grpc++
|
||||
grpc::grpc++_reflection
|
||||
protobuf::libprotobuf
|
||||
)
|
||||
|
||||
# Define Windows macro guards once so protobuf-generated headers stay clean
|
||||
if(WIN32)
|
||||
add_compile_definitions(
|
||||
WIN32_LEAN_AND_MEAN
|
||||
NOMINMAX
|
||||
NOGDI
|
||||
)
|
||||
endif()
|
||||
|
||||
# Export Abseil targets from gRPC's bundled Abseil
|
||||
# When gRPC_ABSL_PROVIDER is "module", gRPC fetches and builds Abseil
|
||||
# All Abseil targets are available, we just need to list them
|
||||
# Note: All targets are available even if not listed here, but listing ensures consistency
|
||||
set(ABSL_TARGETS
|
||||
absl::base
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::utility
|
||||
absl::memory
|
||||
absl::container_memory
|
||||
absl::strings
|
||||
absl::strings_internal
|
||||
absl::str_format
|
||||
absl::str_format_internal
|
||||
absl::cord
|
||||
absl::hash
|
||||
absl::time
|
||||
absl::time_zone
|
||||
absl::status
|
||||
absl::statusor
|
||||
absl::flags
|
||||
absl::flags_parse
|
||||
absl::flags_usage
|
||||
absl::flags_commandlineflag
|
||||
absl::flags_marshalling
|
||||
absl::flags_private_handle_accessor
|
||||
absl::flags_program_name
|
||||
absl::flags_config
|
||||
absl::flags_reflection
|
||||
absl::examine_stack
|
||||
absl::stacktrace
|
||||
absl::failure_signal_handler
|
||||
absl::flat_hash_map
|
||||
absl::synchronization
|
||||
absl::symbolize
|
||||
absl::strerror
|
||||
)
|
||||
|
||||
# Only expose absl::int128 when it's supported without warnings
|
||||
if(NOT WIN32)
|
||||
list(APPEND ABSL_TARGETS absl::int128)
|
||||
endif()
|
||||
|
||||
# Export gRPC targets for use in other CMake files
|
||||
set(YAZE_GRPC_TARGETS
|
||||
grpc::grpc++
|
||||
grpc::grpc++_reflection
|
||||
protobuf::libprotobuf
|
||||
protoc
|
||||
grpc_cpp_plugin
|
||||
)
|
||||
|
||||
message(STATUS "gRPC setup complete - targets available: ${YAZE_GRPC_TARGETS}")
|
||||
|
||||
# Setup protobuf generation directory (use CACHE so it's available in functions)
|
||||
set(_gRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens CACHE INTERNAL "Protobuf generated files directory")
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/gens)
|
||||
|
||||
# Get protobuf include directories (extract from generator expression or direct path)
|
||||
if(TARGET libprotobuf)
|
||||
get_target_property(_PROTOBUF_INCLUDE_DIRS libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
|
||||
# Handle generator expressions
|
||||
string(REGEX REPLACE "\\$<BUILD_INTERFACE:([^>]+)>" "\\1" _PROTOBUF_INCLUDE_DIR_CLEAN "${_PROTOBUF_INCLUDE_DIRS}")
|
||||
list(GET _PROTOBUF_INCLUDE_DIR_CLEAN 0 _gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR)
|
||||
set(_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR ${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR} CACHE INTERNAL "Protobuf include directory")
|
||||
elseif(TARGET protobuf::libprotobuf)
|
||||
get_target_property(_PROTOBUF_INCLUDE_DIRS protobuf::libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
|
||||
string(REGEX REPLACE "\\$<BUILD_INTERFACE:([^>]+)>" "\\1" _PROTOBUF_INCLUDE_DIR_CLEAN "${_PROTOBUF_INCLUDE_DIRS}")
|
||||
list(GET _PROTOBUF_INCLUDE_DIR_CLEAN 0 _gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR)
|
||||
set(_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR ${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR} CACHE INTERNAL "Protobuf include directory")
|
||||
endif()
|
||||
|
||||
# Remove x86-only Abseil compile flags when building on ARM64 macOS runners
|
||||
set(_YAZE_PATCH_ABSL_FOR_APPLE FALSE)
|
||||
if(APPLE)
|
||||
if(CMAKE_OSX_ARCHITECTURES)
|
||||
string(TOLOWER "${CMAKE_OSX_ARCHITECTURES}" _yaze_osx_archs)
|
||||
if(_yaze_osx_archs MATCHES "arm64")
|
||||
set(_YAZE_PATCH_ABSL_FOR_APPLE TRUE)
|
||||
endif()
|
||||
else()
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _yaze_proc)
|
||||
if(_yaze_proc MATCHES "arm64" OR _yaze_proc MATCHES "aarch64")
|
||||
set(_YAZE_PATCH_ABSL_FOR_APPLE TRUE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(_YAZE_PATCH_ABSL_FOR_APPLE)
|
||||
set(_YAZE_ABSL_X86_TARGETS
|
||||
absl_random_internal_randen_hwaes
|
||||
absl_random_internal_randen_hwaes_impl
|
||||
absl_crc_internal_cpu_detect
|
||||
)
|
||||
|
||||
foreach(_yaze_absl_target IN LISTS _YAZE_ABSL_X86_TARGETS)
|
||||
if(TARGET ${_yaze_absl_target})
|
||||
get_target_property(_yaze_absl_opts ${_yaze_absl_target} COMPILE_OPTIONS)
|
||||
if(_yaze_absl_opts AND NOT _yaze_absl_opts STREQUAL "NOTFOUND")
|
||||
set(_yaze_filtered_opts)
|
||||
foreach(_yaze_opt IN LISTS _yaze_absl_opts)
|
||||
if(_yaze_opt STREQUAL "-Xarch_x86_64")
|
||||
continue()
|
||||
endif()
|
||||
if(_yaze_opt MATCHES "^-m(sse|avx)")
|
||||
continue()
|
||||
endif()
|
||||
if(_yaze_opt STREQUAL "-maes")
|
||||
continue()
|
||||
endif()
|
||||
list(APPEND _yaze_filtered_opts "${_yaze_opt}")
|
||||
endforeach()
|
||||
set_property(TARGET ${_yaze_absl_target} PROPERTY COMPILE_OPTIONS ${_yaze_filtered_opts})
|
||||
message(STATUS "Patched ${_yaze_absl_target} compile options for ARM64 macOS")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
unset(_YAZE_GRPC_SAVED_CPM_USE_LOCAL_PACKAGES)
|
||||
unset(_YAZE_GRPC_ERRORS)
|
||||
unset(_YAZE_GRPC_ERROR_MESSAGE)
|
||||
|
||||
message(STATUS "Protobuf gens dir: ${_gRPC_PROTO_GENS_DIR}")
|
||||
message(STATUS "Protobuf include dir: ${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR}")
|
||||
|
||||
# Export protobuf targets
|
||||
set(YAZE_PROTOBUF_TARGETS
|
||||
protobuf::libprotobuf
|
||||
)
|
||||
|
||||
endif() # End of CPM build path (if NOT _YAZE_USING_SYSTEM_GRPC)
|
||||
|
||||
# Function to add protobuf/gRPC code generation to a target
|
||||
# This function works with both system and CPM-built gRPC
|
||||
function(target_add_protobuf target)
|
||||
if(NOT TARGET ${target})
|
||||
message(FATAL_ERROR "Target ${target} doesn't exist")
|
||||
endif()
|
||||
if(NOT ARGN)
|
||||
message(SEND_ERROR "Error: target_add_protobuf() called without any proto files")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Determine protoc and grpc_cpp_plugin paths
|
||||
# For IMPORTED targets (system gRPC), use IMPORTED_LOCATION
|
||||
# For built targets (CPM gRPC), use TARGET_FILE generator expression
|
||||
get_target_property(_PROTOC_IMPORTED protoc IMPORTED)
|
||||
get_target_property(_GRPC_PLUGIN_IMPORTED grpc_cpp_plugin IMPORTED)
|
||||
|
||||
if(_PROTOC_IMPORTED)
|
||||
get_target_property(_PROTOC_EXECUTABLE protoc IMPORTED_LOCATION)
|
||||
set(_PROTOC_DEPENDS "") # No build dependency for system protoc
|
||||
else()
|
||||
set(_PROTOC_EXECUTABLE "$<TARGET_FILE:protoc>")
|
||||
set(_PROTOC_DEPENDS "protoc")
|
||||
endif()
|
||||
|
||||
if(_GRPC_PLUGIN_IMPORTED)
|
||||
get_target_property(_GRPC_PLUGIN_EXECUTABLE grpc_cpp_plugin IMPORTED_LOCATION)
|
||||
set(_GRPC_PLUGIN_DEPENDS "") # No build dependency for system plugin
|
||||
else()
|
||||
set(_GRPC_PLUGIN_EXECUTABLE "$<TARGET_FILE:grpc_cpp_plugin>")
|
||||
set(_GRPC_PLUGIN_DEPENDS "grpc_cpp_plugin")
|
||||
endif()
|
||||
|
||||
set(_protobuf_include_path -I ${CMAKE_SOURCE_DIR}/src -I ${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR})
|
||||
foreach(FIL ${ARGN})
|
||||
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
|
||||
get_filename_component(FIL_WE ${FIL} NAME_WE)
|
||||
file(RELATIVE_PATH REL_FIL ${CMAKE_SOURCE_DIR}/src ${ABS_FIL})
|
||||
get_filename_component(REL_DIR ${REL_FIL} DIRECTORY)
|
||||
if(NOT REL_DIR OR REL_DIR STREQUAL ".")
|
||||
set(RELFIL_WE "${FIL_WE}")
|
||||
else()
|
||||
set(RELFIL_WE "${REL_DIR}/${FIL_WE}")
|
||||
endif()
|
||||
|
||||
message(STATUS " Proto file: ${FIL_WE}")
|
||||
message(STATUS " ABS_FIL = ${ABS_FIL}")
|
||||
message(STATUS " REL_FIL = ${REL_FIL}")
|
||||
message(STATUS " REL_DIR = ${REL_DIR}")
|
||||
message(STATUS " RELFIL_WE = ${RELFIL_WE}")
|
||||
message(STATUS " Output = ${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}_mock.grpc.pb.h"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"
|
||||
COMMAND ${_PROTOC_EXECUTABLE}
|
||||
ARGS --grpc_out=generate_mock_code=true:${_gRPC_PROTO_GENS_DIR}
|
||||
--cpp_out=${_gRPC_PROTO_GENS_DIR}
|
||||
--plugin=protoc-gen-grpc=${_GRPC_PLUGIN_EXECUTABLE}
|
||||
${_protobuf_include_path}
|
||||
${ABS_FIL}
|
||||
DEPENDS ${ABS_FIL} ${_PROTOC_DEPENDS} ${_GRPC_PLUGIN_DEPENDS}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src
|
||||
COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}"
|
||||
VERBATIM)
|
||||
|
||||
target_sources(${target} PRIVATE
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}_mock.grpc.pb.h"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"
|
||||
)
|
||||
target_include_directories(${target} PUBLIC
|
||||
$<BUILD_INTERFACE:${_gRPC_PROTO_GENS_DIR}>
|
||||
$<BUILD_INTERFACE:${_gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR}>
|
||||
)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
78
cmake/dependencies/httplib.cmake
Normal file
78
cmake/dependencies/httplib.cmake
Normal file
@@ -0,0 +1,78 @@
|
||||
# cpp-httplib dependency management
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
set(YAZE_HTTPLIB_TARGETS "" CACHE INTERNAL "cpp-httplib targets")
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
message(STATUS "Setting up cpp-httplib ${HTTPLIB_VERSION}")
|
||||
|
||||
if(YAZE_PLATFORM_IOS)
|
||||
CPMAddPackage(
|
||||
NAME httplib
|
||||
VERSION ${HTTPLIB_VERSION}
|
||||
GITHUB_REPOSITORY yhirose/cpp-httplib
|
||||
GIT_TAG v${HTTPLIB_VERSION}
|
||||
DOWNLOAD_ONLY YES
|
||||
)
|
||||
|
||||
if(NOT TARGET httplib)
|
||||
add_library(httplib INTERFACE)
|
||||
target_include_directories(httplib INTERFACE ${httplib_SOURCE_DIR})
|
||||
endif()
|
||||
if(NOT TARGET httplib::httplib)
|
||||
add_library(httplib::httplib ALIAS httplib)
|
||||
endif()
|
||||
|
||||
set(YAZE_HTTPLIB_TARGETS httplib::httplib)
|
||||
set(YAZE_HTTPLIB_TARGETS httplib::httplib CACHE INTERNAL "cpp-httplib targets")
|
||||
message(STATUS "cpp-httplib configured as header-only for iOS")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_YAZE_USE_SYSTEM_HTTPLIB ${YAZE_USE_SYSTEM_DEPS})
|
||||
|
||||
# Try to use system packages first
|
||||
if(_YAZE_USE_SYSTEM_HTTPLIB)
|
||||
find_package(httplib QUIET)
|
||||
if(httplib_FOUND)
|
||||
message(STATUS "Using system httplib")
|
||||
set(YAZE_HTTPLIB_TARGETS httplib::httplib CACHE INTERNAL "cpp-httplib targets")
|
||||
return()
|
||||
elseif(YAZE_USE_SYSTEM_DEPS)
|
||||
message(WARNING "System httplib not found despite YAZE_USE_SYSTEM_DEPS=ON; falling back to CPM download")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
CPMAddPackage(
|
||||
NAME httplib
|
||||
VERSION ${HTTPLIB_VERSION}
|
||||
GITHUB_REPOSITORY yhirose/cpp-httplib
|
||||
GIT_TAG v${HTTPLIB_VERSION}
|
||||
OPTIONS
|
||||
"HTTPLIB_INSTALL OFF"
|
||||
"HTTPLIB_TEST OFF"
|
||||
"HTTPLIB_COMPILE OFF"
|
||||
"HTTPLIB_USE_OPENSSL_IF_AVAILABLE OFF"
|
||||
"HTTPLIB_USE_ZLIB_IF_AVAILABLE OFF"
|
||||
"HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF"
|
||||
"HTTPLIB_USE_ZSTD_IF_AVAILABLE OFF"
|
||||
)
|
||||
|
||||
# Verify target is available
|
||||
if(TARGET httplib::httplib)
|
||||
message(STATUS "httplib::httplib target found")
|
||||
elseif(TARGET httplib)
|
||||
add_library(httplib::httplib ALIAS httplib)
|
||||
message(STATUS "Created httplib::httplib alias")
|
||||
else()
|
||||
message(FATAL_ERROR "httplib target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
set(YAZE_HTTPLIB_TARGETS httplib::httplib)
|
||||
set(YAZE_HTTPLIB_TARGETS httplib::httplib CACHE INTERNAL "cpp-httplib targets")
|
||||
|
||||
message(STATUS "cpp-httplib setup complete")
|
||||
100
cmake/dependencies/imgui.cmake
Normal file
100
cmake/dependencies/imgui.cmake
Normal file
@@ -0,0 +1,100 @@
|
||||
# Dear ImGui dependency management
|
||||
# Uses the bundled ImGui in ext/imgui
|
||||
|
||||
message(STATUS "Setting up Dear ImGui from bundled sources")
|
||||
|
||||
# Use the bundled ImGui from ext/imgui
|
||||
set(IMGUI_DIR ${CMAKE_SOURCE_DIR}/ext/imgui)
|
||||
|
||||
# Select ImGui backend sources based on SDL version
|
||||
if(YAZE_USE_SDL3)
|
||||
set(IMGUI_BACKEND_SOURCES
|
||||
${IMGUI_DIR}/backends/imgui_impl_sdl3.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_sdlrenderer3.cpp
|
||||
)
|
||||
message(STATUS "Using ImGui SDL3 backend")
|
||||
else()
|
||||
set(IMGUI_BACKEND_SOURCES
|
||||
${IMGUI_DIR}/backends/imgui_impl_sdl2.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_sdlrenderer2.cpp
|
||||
)
|
||||
message(STATUS "Using ImGui SDL2 backend")
|
||||
endif()
|
||||
|
||||
if(YAZE_PLATFORM_IOS)
|
||||
list(APPEND IMGUI_BACKEND_SOURCES
|
||||
${IMGUI_DIR}/backends/imgui_impl_metal.mm
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create ImGui library with core files from bundled source
|
||||
add_library(ImGui STATIC
|
||||
${IMGUI_DIR}/imgui.cpp
|
||||
${IMGUI_DIR}/imgui_demo.cpp
|
||||
${IMGUI_DIR}/imgui_draw.cpp
|
||||
${IMGUI_DIR}/imgui_tables.cpp
|
||||
${IMGUI_DIR}/imgui_widgets.cpp
|
||||
# SDL backend (version-dependent)
|
||||
${IMGUI_BACKEND_SOURCES}
|
||||
# C++ stdlib helpers (for std::string support)
|
||||
${IMGUI_DIR}/misc/cpp/imgui_stdlib.cpp
|
||||
)
|
||||
|
||||
target_include_directories(ImGui PUBLIC
|
||||
${IMGUI_DIR}
|
||||
${IMGUI_DIR}/backends
|
||||
)
|
||||
|
||||
# Set C++ standard requirement (ImGui 1.90+ requires C++11, we use C++17 for consistency)
|
||||
target_compile_features(ImGui PUBLIC cxx_std_17)
|
||||
|
||||
# Link to SDL (version-dependent)
|
||||
if(YAZE_USE_SDL3)
|
||||
target_link_libraries(ImGui PUBLIC ${YAZE_SDL3_TARGETS})
|
||||
else()
|
||||
target_link_libraries(ImGui PUBLIC ${YAZE_SDL2_TARGETS})
|
||||
endif()
|
||||
|
||||
message(STATUS "Created ImGui target from bundled source at ${IMGUI_DIR}")
|
||||
|
||||
# Create ImGui Test Engine for test automation (if tests are enabled)
|
||||
if(YAZE_BUILD_TESTS)
|
||||
set(IMGUI_TEST_ENGINE_DIR ${CMAKE_SOURCE_DIR}/ext/imgui_test_engine/imgui_test_engine)
|
||||
|
||||
if(EXISTS ${IMGUI_TEST_ENGINE_DIR})
|
||||
set(IMGUI_TEST_ENGINE_SOURCES
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_te_context.cpp
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_te_coroutine.cpp
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_te_engine.cpp
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_te_exporters.cpp
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_te_perftool.cpp
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_te_ui.cpp
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_te_utils.cpp
|
||||
${IMGUI_TEST_ENGINE_DIR}/imgui_capture_tool.cpp
|
||||
)
|
||||
|
||||
add_library(ImGuiTestEngine STATIC ${IMGUI_TEST_ENGINE_SOURCES})
|
||||
target_include_directories(ImGuiTestEngine PUBLIC
|
||||
${IMGUI_DIR}
|
||||
${IMGUI_TEST_ENGINE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/ext
|
||||
)
|
||||
target_compile_features(ImGuiTestEngine PUBLIC cxx_std_17)
|
||||
if(YAZE_USE_SDL3)
|
||||
target_link_libraries(ImGuiTestEngine PUBLIC ImGui ${YAZE_SDL3_TARGETS})
|
||||
else()
|
||||
target_link_libraries(ImGuiTestEngine PUBLIC ImGui ${YAZE_SDL2_TARGETS})
|
||||
endif()
|
||||
target_compile_definitions(ImGuiTestEngine PUBLIC
|
||||
IMGUI_ENABLE_TEST_ENGINE=1
|
||||
IMGUI_TEST_ENGINE_ENABLE_COROUTINE_STDTHREAD_IMPL=1
|
||||
)
|
||||
|
||||
message(STATUS "Created ImGuiTestEngine target for test automation")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Export ImGui targets for use in other CMake files
|
||||
set(YAZE_IMGUI_TARGETS ImGui)
|
||||
|
||||
message(STATUS "Dear ImGui setup complete - YAZE_IMGUI_TARGETS = ${YAZE_IMGUI_TARGETS}")
|
||||
27
cmake/dependencies/implot.cmake
Normal file
27
cmake/dependencies/implot.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
# ImPlot dependency management
|
||||
# Uses the bundled ImPlot sources that ship with the ImGui Test Engine
|
||||
|
||||
set(YAZE_IMPLOT_TARGETS "")
|
||||
|
||||
set(IMPLOT_DIR ${CMAKE_SOURCE_DIR}/ext/imgui_test_engine/imgui_test_suite/thirdparty/implot)
|
||||
|
||||
if(EXISTS ${IMPLOT_DIR}/implot.h)
|
||||
message(STATUS "Setting up ImPlot from bundled sources")
|
||||
|
||||
add_library(ImPlot STATIC
|
||||
${IMPLOT_DIR}/implot.cpp
|
||||
${IMPLOT_DIR}/implot_items.cpp
|
||||
)
|
||||
|
||||
target_include_directories(ImPlot PUBLIC
|
||||
${IMPLOT_DIR}
|
||||
${IMGUI_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(ImPlot PUBLIC ImGui)
|
||||
target_compile_features(ImPlot PUBLIC cxx_std_17)
|
||||
|
||||
set(YAZE_IMPLOT_TARGETS ImPlot)
|
||||
else()
|
||||
message(WARNING "ImPlot sources not found at ${IMPLOT_DIR}. Plot widgets will be unavailable.")
|
||||
endif()
|
||||
60
cmake/dependencies/json.cmake
Normal file
60
cmake/dependencies/json.cmake
Normal file
@@ -0,0 +1,60 @@
|
||||
# nlohmann_json dependency management
|
||||
|
||||
if(NOT YAZE_ENABLE_JSON)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
message(STATUS "Setting up nlohmann_json ${NLOHMANN_JSON_VERSION}")
|
||||
|
||||
set(_YAZE_USE_SYSTEM_JSON ${YAZE_USE_SYSTEM_DEPS})
|
||||
|
||||
if(NOT _YAZE_USE_SYSTEM_JSON)
|
||||
unset(nlohmann_json_DIR CACHE)
|
||||
endif()
|
||||
|
||||
# Try to use system packages first
|
||||
if(_YAZE_USE_SYSTEM_JSON)
|
||||
find_package(nlohmann_json QUIET)
|
||||
if(nlohmann_json_FOUND)
|
||||
message(STATUS "Using system nlohmann_json")
|
||||
set(YAZE_JSON_TARGETS nlohmann_json::nlohmann_json CACHE INTERNAL "nlohmann_json targets")
|
||||
return()
|
||||
elseif(YAZE_USE_SYSTEM_DEPS)
|
||||
message(WARNING "System nlohmann_json not found despite YAZE_USE_SYSTEM_DEPS=ON; falling back to CPM download")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(JSON_BuildTests OFF CACHE BOOL "" FORCE)
|
||||
set(JSON_Install OFF CACHE BOOL "" FORCE)
|
||||
set(JSON_MultipleHeaders OFF CACHE BOOL "" FORCE)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME nlohmann_json
|
||||
VERSION ${NLOHMANN_JSON_VERSION}
|
||||
GITHUB_REPOSITORY nlohmann/json
|
||||
GIT_TAG v${NLOHMANN_JSON_VERSION}
|
||||
OPTIONS
|
||||
"JSON_BuildTests OFF"
|
||||
"JSON_Install OFF"
|
||||
"JSON_MultipleHeaders OFF"
|
||||
)
|
||||
|
||||
# Verify target is available
|
||||
if(TARGET nlohmann_json::nlohmann_json)
|
||||
message(STATUS "nlohmann_json target found")
|
||||
elseif(TARGET nlohmann_json)
|
||||
# Create alias if only non-namespaced target exists
|
||||
add_library(nlohmann_json::nlohmann_json ALIAS nlohmann_json)
|
||||
message(STATUS "Created nlohmann_json::nlohmann_json alias")
|
||||
else()
|
||||
message(FATAL_ERROR "nlohmann_json target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
# Export for use in other CMake files
|
||||
set(YAZE_JSON_TARGETS nlohmann_json::nlohmann_json)
|
||||
set(YAZE_JSON_TARGETS nlohmann_json::nlohmann_json CACHE INTERNAL "nlohmann_json targets")
|
||||
|
||||
message(STATUS "nlohmann_json setup complete")
|
||||
130
cmake/dependencies/sdl2.cmake
Normal file
130
cmake/dependencies/sdl2.cmake
Normal file
@@ -0,0 +1,130 @@
|
||||
# SDL2 dependency management
|
||||
# Uses CPM.cmake for consistent cross-platform builds
|
||||
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
# For Emscripten, use the built-in SDL2 port
|
||||
if(EMSCRIPTEN)
|
||||
message(STATUS "Using Emscripten built-in SDL2")
|
||||
if(NOT TARGET yaze_sdl2)
|
||||
add_library(yaze_sdl2 INTERFACE)
|
||||
# Flags are already set in CMakePresets.json or toolchain (-s USE_SDL=2)
|
||||
# But we can enforce them here too if needed, or just leave empty as an interface
|
||||
# to satisfy linking requirements of other targets.
|
||||
target_link_options(yaze_sdl2 INTERFACE "SHELL:-s USE_SDL=2")
|
||||
target_compile_options(yaze_sdl2 INTERFACE "SHELL:-s USE_SDL=2")
|
||||
endif()
|
||||
set(YAZE_SDL2_TARGETS yaze_sdl2)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Setting up SDL2 ${SDL2_VERSION} with CPM.cmake")
|
||||
|
||||
# Try to use system packages first if requested
|
||||
if(YAZE_USE_SYSTEM_DEPS)
|
||||
find_package(SDL2 QUIET)
|
||||
if(SDL2_FOUND)
|
||||
message(STATUS "Using system SDL2")
|
||||
if(NOT TARGET yaze_sdl2)
|
||||
add_library(yaze_sdl2 INTERFACE)
|
||||
target_link_libraries(yaze_sdl2 INTERFACE SDL2::SDL2)
|
||||
if(TARGET SDL2::SDL2main)
|
||||
target_link_libraries(yaze_sdl2 INTERFACE SDL2::SDL2main)
|
||||
endif()
|
||||
endif()
|
||||
set(YAZE_SDL2_TARGETS yaze_sdl2 CACHE INTERNAL "")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Use CPM to fetch SDL2
|
||||
CPMAddPackage(
|
||||
NAME SDL2
|
||||
VERSION ${SDL2_VERSION}
|
||||
GITHUB_REPOSITORY libsdl-org/SDL
|
||||
GIT_TAG release-${SDL2_VERSION}
|
||||
OPTIONS
|
||||
"SDL_SHARED OFF"
|
||||
"SDL_STATIC ON"
|
||||
"SDL_TEST OFF"
|
||||
"SDL_INSTALL OFF"
|
||||
"SDL_CMAKE_DEBUG_POSTFIX d"
|
||||
)
|
||||
|
||||
# Verify SDL2 targets are available
|
||||
if(NOT TARGET SDL2-static AND NOT TARGET SDL2::SDL2-static AND NOT TARGET SDL2::SDL2)
|
||||
message(FATAL_ERROR "SDL2 target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
# Create convenience targets for the rest of the project
|
||||
if(NOT TARGET yaze_sdl2)
|
||||
add_library(yaze_sdl2 INTERFACE)
|
||||
# SDL2 from CPM might use SDL2-static or SDL2::SDL2-static
|
||||
if(TARGET SDL2-static)
|
||||
message(STATUS "Using SDL2-static target")
|
||||
target_link_libraries(yaze_sdl2 INTERFACE SDL2-static)
|
||||
# Also explicitly add include directories if they exist
|
||||
if(SDL2_SOURCE_DIR)
|
||||
target_include_directories(yaze_sdl2 INTERFACE ${SDL2_SOURCE_DIR}/include)
|
||||
message(STATUS "Added SDL2 include: ${SDL2_SOURCE_DIR}/include")
|
||||
endif()
|
||||
elseif(TARGET SDL2::SDL2-static)
|
||||
message(STATUS "Using SDL2::SDL2-static target")
|
||||
target_link_libraries(yaze_sdl2 INTERFACE SDL2::SDL2-static)
|
||||
# For local Homebrew SDL2, also add include path explicitly
|
||||
# SDL headers are in the SDL2 subdirectory
|
||||
if(YAZE_PLATFORM_MACOS AND EXISTS "/opt/homebrew/opt/sdl2/include/SDL2")
|
||||
target_include_directories(yaze_sdl2 INTERFACE /opt/homebrew/opt/sdl2/include/SDL2)
|
||||
message(STATUS "Added Homebrew SDL2 include path: /opt/homebrew/opt/sdl2/include/SDL2")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using SDL2::SDL2 target")
|
||||
target_link_libraries(yaze_sdl2 INTERFACE SDL2::SDL2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add platform-specific libraries
|
||||
if(WIN32)
|
||||
target_link_libraries(yaze_sdl2 INTERFACE
|
||||
winmm
|
||||
imm32
|
||||
version
|
||||
setupapi
|
||||
wbemuuid
|
||||
)
|
||||
target_compile_definitions(yaze_sdl2 INTERFACE SDL_MAIN_HANDLED)
|
||||
elseif(YAZE_PLATFORM_MACOS)
|
||||
target_link_libraries(yaze_sdl2 INTERFACE
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
"-framework CoreVideo"
|
||||
"-framework ForceFeedback"
|
||||
)
|
||||
target_compile_definitions(yaze_sdl2 INTERFACE SDL_MAIN_HANDLED)
|
||||
elseif(YAZE_PLATFORM_IOS)
|
||||
target_link_libraries(yaze_sdl2 INTERFACE
|
||||
"-framework UIKit"
|
||||
"-framework Foundation"
|
||||
"-framework CoreGraphics"
|
||||
"-framework CoreVideo"
|
||||
"-framework CoreMotion"
|
||||
"-framework QuartzCore"
|
||||
"-framework AVFoundation"
|
||||
"-framework AudioToolbox"
|
||||
"-framework Metal"
|
||||
"-framework GameController"
|
||||
)
|
||||
target_compile_definitions(yaze_sdl2 INTERFACE SDL_MAIN_HANDLED)
|
||||
elseif(UNIX)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
||||
target_link_libraries(yaze_sdl2 INTERFACE ${GTK3_LIBRARIES})
|
||||
target_include_directories(yaze_sdl2 INTERFACE ${GTK3_INCLUDE_DIRS})
|
||||
target_compile_options(yaze_sdl2 INTERFACE ${GTK3_CFLAGS_OTHER})
|
||||
endif()
|
||||
|
||||
# Export SDL2 targets for use in other CMake files
|
||||
set(YAZE_SDL2_TARGETS yaze_sdl2)
|
||||
|
||||
message(STATUS "SDL2 setup complete - YAZE_SDL2_TARGETS = ${YAZE_SDL2_TARGETS}")
|
||||
124
cmake/dependencies/sdl3.cmake
Normal file
124
cmake/dependencies/sdl3.cmake
Normal file
@@ -0,0 +1,124 @@
|
||||
# SDL3 dependency management
|
||||
# Uses CPM.cmake for consistent cross-platform builds
|
||||
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
message(STATUS "Setting up SDL3 (experimental) with CPM.cmake")
|
||||
|
||||
# SDL3 specific version (using latest stable 3.2 release)
|
||||
set(SDL3_VERSION "3.2.26")
|
||||
|
||||
# Try to use system packages first if requested
|
||||
if(YAZE_USE_SYSTEM_DEPS)
|
||||
find_package(SDL3 QUIET)
|
||||
if(SDL3_FOUND)
|
||||
message(STATUS "Using system SDL3")
|
||||
if(NOT TARGET yaze_sdl3)
|
||||
add_library(yaze_sdl3 INTERFACE)
|
||||
target_link_libraries(yaze_sdl3 INTERFACE SDL3::SDL3)
|
||||
if(TARGET SDL3::SDL3main)
|
||||
target_link_libraries(yaze_sdl3 INTERFACE SDL3::SDL3main)
|
||||
endif()
|
||||
endif()
|
||||
set(YAZE_SDL3_TARGETS yaze_sdl3 CACHE INTERNAL "")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Use CPM to fetch SDL3
|
||||
CPMAddPackage(
|
||||
NAME SDL3
|
||||
VERSION ${SDL3_VERSION}
|
||||
GITHUB_REPOSITORY libsdl-org/SDL
|
||||
GIT_TAG release-${SDL3_VERSION}
|
||||
OPTIONS
|
||||
"SDL_SHARED OFF"
|
||||
"SDL_STATIC ON"
|
||||
"SDL_TEST OFF"
|
||||
"SDL_INSTALL OFF"
|
||||
"SDL_CMAKE_DEBUG_POSTFIX d"
|
||||
"SDL3_DISABLE_INSTALL ON"
|
||||
"SDL3_DISABLE_UNINSTALL ON"
|
||||
)
|
||||
|
||||
# Verify SDL3 targets are available
|
||||
if(NOT TARGET SDL3-static AND NOT TARGET SDL3::SDL3-static AND NOT TARGET SDL3::SDL3)
|
||||
message(FATAL_ERROR "SDL3 target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
# Create convenience targets for the rest of the project
|
||||
if(NOT TARGET yaze_sdl3)
|
||||
add_library(yaze_sdl3 INTERFACE)
|
||||
# SDL3 from CPM might use SDL3-static or SDL3::SDL3-static
|
||||
if(TARGET SDL3-static)
|
||||
message(STATUS "Using SDL3-static target")
|
||||
target_link_libraries(yaze_sdl3 INTERFACE SDL3-static)
|
||||
# Also explicitly add include directories if they exist
|
||||
if(SDL3_SOURCE_DIR)
|
||||
target_include_directories(yaze_sdl3 INTERFACE ${SDL3_SOURCE_DIR}/include)
|
||||
message(STATUS "Added SDL3 include: ${SDL3_SOURCE_DIR}/include")
|
||||
endif()
|
||||
elseif(TARGET SDL3::SDL3-static)
|
||||
message(STATUS "Using SDL3::SDL3-static target")
|
||||
target_link_libraries(yaze_sdl3 INTERFACE SDL3::SDL3-static)
|
||||
# For local Homebrew SDL3, also add include path explicitly
|
||||
if(YAZE_PLATFORM_MACOS AND EXISTS "/opt/homebrew/opt/sdl3/include/SDL3")
|
||||
target_include_directories(yaze_sdl3 INTERFACE /opt/homebrew/opt/sdl3/include/SDL3)
|
||||
message(STATUS "Added Homebrew SDL3 include path: /opt/homebrew/opt/sdl3/include/SDL3")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using SDL3::SDL3 target")
|
||||
target_link_libraries(yaze_sdl3 INTERFACE SDL3::SDL3)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add platform-specific libraries
|
||||
if(WIN32)
|
||||
target_link_libraries(yaze_sdl3 INTERFACE
|
||||
winmm
|
||||
imm32
|
||||
version
|
||||
setupapi
|
||||
wbemuuid
|
||||
)
|
||||
target_compile_definitions(yaze_sdl3 INTERFACE SDL_MAIN_HANDLED)
|
||||
elseif(YAZE_PLATFORM_MACOS)
|
||||
target_link_libraries(yaze_sdl3 INTERFACE
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
"-framework CoreVideo"
|
||||
"-framework CoreHaptics"
|
||||
"-framework ForceFeedback"
|
||||
"-framework GameController"
|
||||
)
|
||||
target_compile_definitions(yaze_sdl3 INTERFACE SDL_MAIN_HANDLED)
|
||||
elseif(YAZE_PLATFORM_IOS)
|
||||
target_link_libraries(yaze_sdl3 INTERFACE
|
||||
"-framework UIKit"
|
||||
"-framework Foundation"
|
||||
"-framework CoreGraphics"
|
||||
"-framework CoreVideo"
|
||||
"-framework CoreMotion"
|
||||
"-framework QuartzCore"
|
||||
"-framework AVFoundation"
|
||||
"-framework AudioToolbox"
|
||||
"-framework Metal"
|
||||
"-framework GameController"
|
||||
)
|
||||
target_compile_definitions(yaze_sdl3 INTERFACE SDL_MAIN_HANDLED)
|
||||
elseif(UNIX)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
|
||||
target_link_libraries(yaze_sdl3 INTERFACE ${GTK3_LIBRARIES})
|
||||
target_include_directories(yaze_sdl3 INTERFACE ${GTK3_INCLUDE_DIRS})
|
||||
target_compile_options(yaze_sdl3 INTERFACE ${GTK3_CFLAGS_OTHER})
|
||||
endif()
|
||||
|
||||
# Export SDL3 targets for use in other CMake files
|
||||
set(YAZE_SDL3_TARGETS yaze_sdl3)
|
||||
|
||||
# Set a flag to indicate SDL3 is being used
|
||||
set(YAZE_SDL2_TARGETS ${YAZE_SDL3_TARGETS}) # For compatibility with existing code
|
||||
|
||||
message(STATUS "SDL3 setup complete - YAZE_SDL3_TARGETS = ${YAZE_SDL3_TARGETS}")
|
||||
157
cmake/dependencies/testing.cmake
Normal file
157
cmake/dependencies/testing.cmake
Normal file
@@ -0,0 +1,157 @@
|
||||
# Testing dependencies (GTest, Benchmark)
|
||||
# Uses CPM.cmake for consistent cross-platform builds
|
||||
|
||||
if(NOT YAZE_BUILD_TESTS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
message(STATUS "Setting up testing dependencies with CPM.cmake")
|
||||
|
||||
set(_YAZE_USE_SYSTEM_GTEST ${YAZE_USE_SYSTEM_DEPS})
|
||||
|
||||
# Detect Homebrew installation automatically (helps offline builds)
|
||||
if(APPLE AND NOT _YAZE_USE_SYSTEM_GTEST)
|
||||
set(_YAZE_GTEST_PREFIX_CANDIDATES)
|
||||
set(_YAZE_HOST_ARCH "${CMAKE_SYSTEM_PROCESSOR}")
|
||||
if(NOT _YAZE_HOST_ARCH)
|
||||
execute_process(
|
||||
COMMAND uname -m
|
||||
OUTPUT_VARIABLE _YAZE_HOST_ARCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
endif()
|
||||
|
||||
if(_YAZE_HOST_ARCH STREQUAL "arm64")
|
||||
list(APPEND _YAZE_GTEST_PREFIX_CANDIDATES
|
||||
/opt/homebrew/opt/googletest)
|
||||
else()
|
||||
list(APPEND _YAZE_GTEST_PREFIX_CANDIDATES
|
||||
/usr/local/opt/googletest
|
||||
/opt/homebrew/opt/googletest)
|
||||
endif()
|
||||
|
||||
foreach(_prefix IN LISTS _YAZE_GTEST_PREFIX_CANDIDATES)
|
||||
if(EXISTS "${_prefix}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${_prefix}")
|
||||
message(STATUS "Added Homebrew googletest prefix: ${_prefix}")
|
||||
set(_YAZE_USE_SYSTEM_GTEST ON)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _YAZE_USE_SYSTEM_GTEST)
|
||||
find_program(HOMEBREW_EXECUTABLE brew)
|
||||
if(HOMEBREW_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND "${HOMEBREW_EXECUTABLE}" --prefix googletest
|
||||
OUTPUT_VARIABLE HOMEBREW_GTEST_PREFIX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE HOMEBREW_GTEST_RESULT
|
||||
ERROR_QUIET)
|
||||
if(HOMEBREW_GTEST_RESULT EQUAL 0 AND EXISTS "${HOMEBREW_GTEST_PREFIX}")
|
||||
if(_YAZE_HOST_ARCH STREQUAL "arm64" AND NOT HOMEBREW_GTEST_PREFIX MATCHES "^/opt/homebrew")
|
||||
message(STATUS "Skipping Homebrew googletest prefix on arm64: ${HOMEBREW_GTEST_PREFIX}")
|
||||
else()
|
||||
list(APPEND CMAKE_PREFIX_PATH "${HOMEBREW_GTEST_PREFIX}")
|
||||
message(STATUS "Added Homebrew googletest prefix: ${HOMEBREW_GTEST_PREFIX}")
|
||||
set(_YAZE_USE_SYSTEM_GTEST ON)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Try to use system packages first
|
||||
if(_YAZE_USE_SYSTEM_GTEST)
|
||||
find_package(GTest QUIET)
|
||||
if(GTest_FOUND)
|
||||
message(STATUS "Using system googletest")
|
||||
# GTest found, targets should already be available
|
||||
# Verify targets exist
|
||||
if(NOT TARGET GTest::gtest)
|
||||
message(WARNING "GTest::gtest target not found despite GTest_FOUND=TRUE; falling back to CPM download")
|
||||
set(_YAZE_USE_SYSTEM_GTEST OFF)
|
||||
else()
|
||||
# Create aliases to match CPM target names
|
||||
if(NOT TARGET gtest)
|
||||
add_library(gtest ALIAS GTest::gtest)
|
||||
endif()
|
||||
if(NOT TARGET gtest_main)
|
||||
add_library(gtest_main ALIAS GTest::gtest_main)
|
||||
endif()
|
||||
if(TARGET GTest::gmock AND NOT TARGET gmock)
|
||||
add_library(gmock ALIAS GTest::gmock)
|
||||
endif()
|
||||
if(TARGET GTest::gmock_main AND NOT TARGET gmock_main)
|
||||
add_library(gmock_main ALIAS GTest::gmock_main)
|
||||
endif()
|
||||
# Skip CPM fetch
|
||||
set(_YAZE_GTEST_SYSTEM_USED ON)
|
||||
endif()
|
||||
elseif(YAZE_USE_SYSTEM_DEPS)
|
||||
message(WARNING "System googletest not found despite YAZE_USE_SYSTEM_DEPS=ON; falling back to CPM download")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Use CPM to fetch googletest if not using system version
|
||||
if(NOT _YAZE_GTEST_SYSTEM_USED)
|
||||
CPMAddPackage(
|
||||
NAME googletest
|
||||
VERSION ${GTEST_VERSION}
|
||||
GITHUB_REPOSITORY google/googletest
|
||||
GIT_TAG v${GTEST_VERSION}
|
||||
OPTIONS
|
||||
"BUILD_GMOCK ON"
|
||||
"INSTALL_GTEST OFF"
|
||||
"gtest_force_shared_crt ON"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Verify GTest and GMock targets are available
|
||||
if(NOT TARGET gtest)
|
||||
message(FATAL_ERROR "GTest target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET gmock)
|
||||
message(FATAL_ERROR "GMock target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
# Google Benchmark (optional, for performance tests)
|
||||
if(YAZE_ENABLE_COVERAGE OR DEFINED ENV{YAZE_ENABLE_BENCHMARKS})
|
||||
CPMAddPackage(
|
||||
NAME benchmark
|
||||
VERSION ${BENCHMARK_VERSION}
|
||||
GITHUB_REPOSITORY google/benchmark
|
||||
GIT_TAG v${BENCHMARK_VERSION}
|
||||
OPTIONS
|
||||
"BENCHMARK_ENABLE_TESTING OFF"
|
||||
"BENCHMARK_ENABLE_INSTALL OFF"
|
||||
)
|
||||
|
||||
if(NOT TARGET benchmark::benchmark)
|
||||
message(FATAL_ERROR "Benchmark target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
set(YAZE_BENCHMARK_TARGETS benchmark::benchmark)
|
||||
endif()
|
||||
|
||||
# Create convenience targets for the rest of the project
|
||||
add_library(yaze_testing INTERFACE)
|
||||
target_link_libraries(yaze_testing INTERFACE
|
||||
gtest
|
||||
gtest_main
|
||||
gmock
|
||||
gmock_main
|
||||
)
|
||||
|
||||
if(TARGET benchmark::benchmark)
|
||||
target_link_libraries(yaze_testing INTERFACE benchmark::benchmark)
|
||||
endif()
|
||||
|
||||
# Export testing targets for use in other CMake files
|
||||
set(YAZE_TESTING_TARGETS yaze_testing)
|
||||
|
||||
message(STATUS "Testing dependencies setup complete - GTest + GMock available")
|
||||
105
cmake/dependencies/yaml.cmake
Normal file
105
cmake/dependencies/yaml.cmake
Normal file
@@ -0,0 +1,105 @@
|
||||
# yaml-cpp dependency management
|
||||
# Uses CPM.cmake for consistent cross-platform builds
|
||||
|
||||
include(cmake/CPM.cmake)
|
||||
include(cmake/dependencies.lock)
|
||||
|
||||
if(NOT YAZE_ENABLE_AI AND NOT YAZE_ENABLE_AI_RUNTIME)
|
||||
message(STATUS "Skipping yaml-cpp (AI runtime and CLI agent features disabled)")
|
||||
set(YAZE_YAML_TARGETS "")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Setting up yaml-cpp ${YAML_CPP_VERSION} with CPM.cmake")
|
||||
|
||||
set(_YAZE_USE_SYSTEM_YAML ${YAZE_USE_SYSTEM_DEPS})
|
||||
|
||||
# Detect Homebrew installation automatically (helps offline builds)
|
||||
if(APPLE AND NOT _YAZE_USE_SYSTEM_YAML)
|
||||
set(_YAZE_YAML_PREFIX_CANDIDATES
|
||||
/opt/homebrew/opt/yaml-cpp
|
||||
/usr/local/opt/yaml-cpp)
|
||||
|
||||
foreach(_prefix IN LISTS _YAZE_YAML_PREFIX_CANDIDATES)
|
||||
if(EXISTS "${_prefix}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${_prefix}")
|
||||
message(STATUS "Added Homebrew yaml-cpp prefix: ${_prefix}")
|
||||
set(_YAZE_USE_SYSTEM_YAML ON)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _YAZE_USE_SYSTEM_YAML)
|
||||
find_program(HOMEBREW_EXECUTABLE brew)
|
||||
if(HOMEBREW_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND "${HOMEBREW_EXECUTABLE}" --prefix yaml-cpp
|
||||
OUTPUT_VARIABLE HOMEBREW_YAML_PREFIX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE HOMEBREW_YAML_RESULT
|
||||
ERROR_QUIET)
|
||||
if(HOMEBREW_YAML_RESULT EQUAL 0 AND EXISTS "${HOMEBREW_YAML_PREFIX}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${HOMEBREW_YAML_PREFIX}")
|
||||
message(STATUS "Added Homebrew yaml-cpp prefix: ${HOMEBREW_YAML_PREFIX}")
|
||||
set(_YAZE_USE_SYSTEM_YAML ON)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Try to use system packages first
|
||||
if(_YAZE_USE_SYSTEM_YAML)
|
||||
find_package(yaml-cpp QUIET)
|
||||
if(yaml-cpp_FOUND)
|
||||
message(STATUS "Using system yaml-cpp")
|
||||
add_library(yaze_yaml INTERFACE)
|
||||
target_compile_definitions(yaze_yaml INTERFACE YAZE_HAS_YAML_CPP=1)
|
||||
if(TARGET yaml-cpp::yaml-cpp)
|
||||
message(STATUS "Linking yaze_yaml against yaml-cpp::yaml-cpp")
|
||||
target_link_libraries(yaze_yaml INTERFACE yaml-cpp::yaml-cpp)
|
||||
|
||||
# HACK: Explicitly add the library directory for Homebrew if detected
|
||||
# This fixes 'ld: library not found for -lyaml-cpp' when the imported target
|
||||
# doesn't propagate the library path correctly to the linker command line
|
||||
if(EXISTS "/opt/homebrew/opt/yaml-cpp/lib")
|
||||
link_directories("/opt/homebrew/opt/yaml-cpp/lib")
|
||||
message(STATUS "Added yaml-cpp link directory: /opt/homebrew/opt/yaml-cpp/lib")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Linking yaze_yaml against yaml-cpp (legacy)")
|
||||
target_link_libraries(yaze_yaml INTERFACE yaml-cpp)
|
||||
endif()
|
||||
set(YAZE_YAML_TARGETS yaze_yaml)
|
||||
return()
|
||||
elseif(YAZE_USE_SYSTEM_DEPS)
|
||||
message(WARNING "System yaml-cpp not found despite YAZE_USE_SYSTEM_DEPS=ON; falling back to CPM download")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Use CPM to fetch yaml-cpp
|
||||
CPMAddPackage(
|
||||
NAME yaml-cpp
|
||||
VERSION ${YAML_CPP_VERSION}
|
||||
GITHUB_REPOSITORY jbeder/yaml-cpp
|
||||
GIT_TAG 0.8.0
|
||||
OPTIONS
|
||||
"YAML_CPP_BUILD_TESTS OFF"
|
||||
"YAML_CPP_BUILD_CONTRIB OFF"
|
||||
"YAML_CPP_BUILD_TOOLS OFF"
|
||||
"YAML_CPP_INSTALL OFF"
|
||||
)
|
||||
|
||||
# Verify yaml-cpp targets are available
|
||||
if(NOT TARGET yaml-cpp)
|
||||
message(FATAL_ERROR "yaml-cpp target not found after CPM fetch")
|
||||
endif()
|
||||
|
||||
# Create convenience targets for the rest of the project
|
||||
add_library(yaze_yaml INTERFACE)
|
||||
target_link_libraries(yaze_yaml INTERFACE yaml-cpp)
|
||||
target_compile_definitions(yaze_yaml INTERFACE YAZE_HAS_YAML_CPP=1)
|
||||
|
||||
# Export yaml-cpp targets for use in other CMake files
|
||||
set(YAZE_YAML_TARGETS yaze_yaml)
|
||||
|
||||
message(STATUS "yaml-cpp setup complete")
|
||||
147
cmake/grpc.cmake
147
cmake/grpc.cmake
@@ -5,25 +5,6 @@ set(CMAKE_POLICY_DEFAULT_CMP0074 NEW)
|
||||
# Include FetchContent module
|
||||
include(FetchContent)
|
||||
|
||||
# Try Windows-optimized path first
|
||||
if(WIN32)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/grpc_windows.cmake)
|
||||
if(YAZE_GRPC_CONFIGURED)
|
||||
# Validate that grpc_windows.cmake properly exported required targets/variables
|
||||
if(NOT COMMAND target_add_protobuf)
|
||||
message(FATAL_ERROR "grpc_windows.cmake did not define target_add_protobuf function")
|
||||
endif()
|
||||
if(NOT DEFINED ABSL_TARGETS OR NOT ABSL_TARGETS)
|
||||
message(FATAL_ERROR "grpc_windows.cmake did not export ABSL_TARGETS")
|
||||
endif()
|
||||
if(NOT DEFINED YAZE_PROTOBUF_TARGETS OR NOT YAZE_PROTOBUF_TARGETS)
|
||||
message(FATAL_ERROR "grpc_windows.cmake did not export YAZE_PROTOBUF_TARGETS")
|
||||
endif()
|
||||
message(STATUS "✓ Windows vcpkg gRPC configuration validated")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set minimum CMake version for subprojects (fixes c-ares compatibility)
|
||||
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
|
||||
|
||||
@@ -32,44 +13,19 @@ set(FETCHCONTENT_QUIET OFF)
|
||||
# CRITICAL: Prevent CMake from finding system-installed protobuf/abseil
|
||||
# This ensures gRPC uses its own bundled versions
|
||||
set(CMAKE_DISABLE_FIND_PACKAGE_Protobuf TRUE)
|
||||
set(CMAKE_DISABLE_FIND_PACKAGE_gRPC TRUE)
|
||||
set(CMAKE_DISABLE_FIND_PACKAGE_absl TRUE)
|
||||
set(CMAKE_DISABLE_FIND_PACKAGE_gRPC TRUE)
|
||||
|
||||
# Also prevent pkg-config from finding system packages
|
||||
set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH FALSE)
|
||||
|
||||
# Add compiler flags for modern compiler compatibility
|
||||
# These flags are scoped to gRPC and its dependencies only
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Clang 15+ compatibility for gRPC
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=missing-template-arg-list-after-template-kw")
|
||||
add_compile_definitions(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS)
|
||||
elseif(MSVC)
|
||||
# MSVC/Visual Studio compatibility for gRPC templates
|
||||
# v1.67.1 fixes most issues, but these flags help with large template instantiations
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") # Large object files
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive-") # Standards conformance
|
||||
|
||||
# Suppress common gRPC warnings on MSVC (don't use add_compile_options to avoid affecting user code)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4244")
|
||||
|
||||
# Increase template instantiation depth for complex promise chains (MSVC 2019+)
|
||||
if(MSVC_VERSION GREATER_EQUAL 1920)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /constexpr:depth2048")
|
||||
endif()
|
||||
|
||||
# Prevent Windows macro pollution in protobuf-generated headers
|
||||
add_compile_definitions(
|
||||
WIN32_LEAN_AND_MEAN # Exclude rarely-used Windows headers
|
||||
NOMINMAX # Don't define min/max macros
|
||||
NOGDI # Exclude GDI (prevents DWORD and other macro conflicts)
|
||||
)
|
||||
endif()
|
||||
|
||||
# Save YAZE's C++ standard and temporarily set to C++17 for gRPC
|
||||
set(_SAVED_CMAKE_CXX_STANDARD ${CMAKE_CXX_STANDARD})
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# ZLIB is provided by gRPC module (gRPC_ZLIB_PROVIDER="module")
|
||||
# find_package(ZLIB REQUIRED) not needed - gRPC bundles its own ZLIB
|
||||
|
||||
# Configure gRPC build options before fetching
|
||||
set(gRPC_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_CODEGEN ON CACHE BOOL "" FORCE)
|
||||
@@ -81,16 +37,15 @@ set(gRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_PHP_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_PYTHON_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_RUBY_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
# Disable C++ reflection support (avoids extra proto generation)
|
||||
set(gRPC_BUILD_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPC_CPP_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
set(gRPC_BUILD_GRPCPP_REFLECTION OFF CACHE BOOL "" FORCE)
|
||||
|
||||
set(gRPC_BENCHMARK_PROVIDER "none" CACHE STRING "" FORCE)
|
||||
set(gRPC_ZLIB_PROVIDER "module" CACHE STRING "" FORCE)
|
||||
|
||||
# Skip install rule generation inside gRPC's dependency graph. This avoids
|
||||
# configure-time checks that require every transitive dependency (like Abseil
|
||||
# compatibility shims) to participate in install export sets, which we do not
|
||||
# need for the editor builds.
|
||||
set(CMAKE_SKIP_INSTALL_RULES ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Let gRPC fetch and build its own protobuf and abseil
|
||||
set(gRPC_PROTOBUF_PROVIDER "module" CACHE STRING "" FORCE)
|
||||
set(gRPC_ABSL_PROVIDER "module" CACHE STRING "" FORCE)
|
||||
@@ -101,32 +56,27 @@ set(protobuf_BUILD_CONFORMANCE OFF CACHE BOOL "" FORCE)
|
||||
set(protobuf_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
set(protobuf_BUILD_PROTOC_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(protobuf_WITH_ZLIB ON CACHE BOOL "" FORCE)
|
||||
set(protobuf_MSVC_STATIC_RUNTIME ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Abseil configuration
|
||||
set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "" FORCE)
|
||||
set(ABSL_ENABLE_INSTALL ON CACHE BOOL "" FORCE)
|
||||
set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
set(ABSL_BUILD_TESTING OFF CACHE BOOL "" FORCE)
|
||||
set(ABSL_MSVC_STATIC_RUNTIME ON CACHE BOOL "" FORCE)
|
||||
set(gRPC_MSVC_STATIC_RUNTIME ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Disable x86-specific optimizations for ARM64 macOS builds
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
set(ABSL_USE_EXTERNAL_GOOGLETEST OFF CACHE BOOL "" FORCE)
|
||||
set(ABSL_BUILD_TEST_HELPERS OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
# Additional protobuf settings to avoid export conflicts
|
||||
set(protobuf_BUILD_LIBPROTOC ON CACHE BOOL "" FORCE)
|
||||
set(protobuf_BUILD_LIBPROTOBUF ON CACHE BOOL "" FORCE)
|
||||
set(protobuf_BUILD_LIBPROTOBUF_LITE ON CACHE BOOL "" FORCE)
|
||||
set(protobuf_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
|
||||
set(utf8_range_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(utf8_range_INSTALL OFF CACHE BOOL "" FORCE)
|
||||
|
||||
# Declare gRPC with platform-specific versions
|
||||
# - macOS/Linux: v1.75.1 (has ARM64 + modern Clang fixes)
|
||||
# - Windows: v1.75.1 (better NASM/clang-cl support than v1.67.1)
|
||||
set(_GRPC_VERSION "v1.75.1")
|
||||
if(WIN32)
|
||||
set(_GRPC_VERSION_REASON "Windows clang-cl + MSVC compatibility")
|
||||
# Disable BoringSSL ASM to avoid NASM build issues on Windows
|
||||
# ASM optimizations cause NASM flag conflicts with clang-cl
|
||||
set(OPENSSL_NO_ASM ON CACHE BOOL "" FORCE)
|
||||
message(STATUS "Disabling BoringSSL ASM optimizations for Windows build compatibility")
|
||||
if(WIN32 AND MSVC)
|
||||
set(_GRPC_VERSION "v1.67.1")
|
||||
set(_GRPC_VERSION_REASON "MSVC-compatible, avoids linker regressions")
|
||||
else()
|
||||
set(_GRPC_VERSION "v1.75.1")
|
||||
set(_GRPC_VERSION_REASON "ARM64 macOS + modern Clang compatibility")
|
||||
endif()
|
||||
|
||||
@@ -146,9 +96,23 @@ FetchContent_Declare(
|
||||
set(_SAVED_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
|
||||
set(CMAKE_PREFIX_PATH "")
|
||||
|
||||
# Some toolchain presets set CMAKE_CROSSCOMPILING even when building for the
|
||||
# host (macOS arm64). gRPC treats that as a signal to locate host-side protoc
|
||||
# binaries via find_program, which fails since we rely on the bundled targets.
|
||||
# Suppress the flag when the host and target platforms match so the generator
|
||||
# expressions remain intact.
|
||||
set(_SAVED_CMAKE_CROSSCOMPILING ${CMAKE_CROSSCOMPILING})
|
||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL CMAKE_SYSTEM_NAME
|
||||
AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR)
|
||||
set(CMAKE_CROSSCOMPILING FALSE)
|
||||
endif()
|
||||
|
||||
# Download and build in isolation
|
||||
FetchContent_MakeAvailable(grpc)
|
||||
|
||||
# Restore cross-compiling flag
|
||||
set(CMAKE_CROSSCOMPILING ${_SAVED_CMAKE_CROSSCOMPILING})
|
||||
|
||||
# Restore CMAKE_PREFIX_PATH
|
||||
set(CMAKE_PREFIX_PATH ${_SAVED_CMAKE_PREFIX_PATH})
|
||||
|
||||
@@ -163,14 +127,15 @@ if(NOT TARGET grpc_cpp_plugin)
|
||||
message(FATAL_ERROR "Can not find target grpc_cpp_plugin")
|
||||
endif()
|
||||
|
||||
set(_gRPC_PROTOBUF_PROTOC_EXECUTABLE $<TARGET_FILE:protoc>)
|
||||
set(_gRPC_CPP_PLUGIN $<TARGET_FILE:grpc_cpp_plugin>)
|
||||
set(_gRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens)
|
||||
file(REMOVE_RECURSE ${_gRPC_PROTO_GENS_DIR})
|
||||
file(MAKE_DIRECTORY ${_gRPC_PROTO_GENS_DIR})
|
||||
|
||||
get_target_property(_PROTOBUF_INCLUDE_DIRS libprotobuf INTERFACE_INCLUDE_DIRECTORIES)
|
||||
list(GET _PROTOBUF_INCLUDE_DIRS 0 _gRPC_PROTOBUF_WELLKNOWN_INCLUDE_DIR)
|
||||
|
||||
message(STATUS "gRPC setup complete")
|
||||
|
||||
# Export Abseil targets from gRPC's bundled abseil for use by the rest of the project
|
||||
# This ensures version compatibility between gRPC and our project
|
||||
# Note: Order matters for some linkers - put base libraries first
|
||||
@@ -213,36 +178,6 @@ endif()
|
||||
|
||||
# ABSL_TARGETS is now available to the rest of the project via include()
|
||||
|
||||
# Fix Abseil ARM64 macOS compile flags (remove x86-specific flags)
|
||||
if(APPLE AND DEFINED CMAKE_OSX_ARCHITECTURES AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
foreach(_absl_target IN ITEMS absl_random_internal_randen_hwaes absl_random_internal_randen_hwaes_impl)
|
||||
if(TARGET ${_absl_target})
|
||||
get_target_property(_absl_opts ${_absl_target} COMPILE_OPTIONS)
|
||||
if(_absl_opts AND NOT _absl_opts STREQUAL "NOTFOUND")
|
||||
set(_absl_filtered_opts)
|
||||
set(_absl_skip_next FALSE)
|
||||
foreach(_absl_opt IN LISTS _absl_opts)
|
||||
if(_absl_skip_next)
|
||||
set(_absl_skip_next FALSE)
|
||||
continue()
|
||||
endif()
|
||||
if(_absl_opt STREQUAL "-Xarch_x86_64")
|
||||
set(_absl_skip_next TRUE)
|
||||
continue()
|
||||
endif()
|
||||
if(_absl_opt STREQUAL "-maes" OR _absl_opt STREQUAL "-msse4.1")
|
||||
continue()
|
||||
endif()
|
||||
list(APPEND _absl_filtered_opts ${_absl_opt})
|
||||
endforeach()
|
||||
set_property(TARGET ${_absl_target} PROPERTY COMPILE_OPTIONS ${_absl_filtered_opts})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
message(STATUS "gRPC setup complete (includes bundled Abseil)")
|
||||
|
||||
function(target_add_protobuf target)
|
||||
if(NOT TARGET ${target})
|
||||
message(FATAL_ERROR "Target ${target} doesn't exist")
|
||||
@@ -270,10 +205,10 @@ function(target_add_protobuf target)
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}_mock.grpc.pb.h"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"
|
||||
"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"
|
||||
COMMAND ${_gRPC_PROTOBUF_PROTOC_EXECUTABLE}
|
||||
COMMAND $<TARGET_FILE:protoc>
|
||||
ARGS --grpc_out=generate_mock_code=true:${_gRPC_PROTO_GENS_DIR}
|
||||
--cpp_out=${_gRPC_PROTO_GENS_DIR}
|
||||
--plugin=protoc-gen-grpc=${_gRPC_CPP_PLUGIN}
|
||||
--plugin=protoc-gen-grpc=$<TARGET_FILE:grpc_cpp_plugin>
|
||||
${_protobuf_include_path}
|
||||
${REL_FIL}
|
||||
DEPENDS ${ABS_FIL} protoc grpc_cpp_plugin
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# Option to use vcpkg for gRPC on Windows
|
||||
option(YAZE_USE_VCPKG_GRPC "Use vcpkg pre-compiled gRPC packages (Windows only)" ON)
|
||||
# Option to use vcpkg for gRPC on Windows (default OFF for CI reliability)
|
||||
option(YAZE_USE_VCPKG_GRPC "Use vcpkg pre-compiled gRPC packages (Windows only)" OFF)
|
||||
|
||||
if(WIN32 AND YAZE_USE_VCPKG_GRPC)
|
||||
if(WIN32 AND YAZE_USE_VCPKG_GRPC AND DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
message(STATUS "Attempting to use vcpkg gRPC packages for faster Windows builds...")
|
||||
message(STATUS " Note: If gRPC not in vcpkg.json, will fallback to FetchContent (recommended)")
|
||||
|
||||
@@ -144,10 +144,13 @@ if(WIN32 AND YAZE_USE_VCPKG_GRPC)
|
||||
absl::memory
|
||||
absl::container_memory
|
||||
absl::strings
|
||||
absl::strings_internal
|
||||
absl::str_format
|
||||
absl::str_format_internal
|
||||
absl::cord
|
||||
absl::hash
|
||||
absl::time
|
||||
absl::time_zone
|
||||
absl::status
|
||||
absl::statusor
|
||||
absl::flags
|
||||
@@ -165,12 +168,12 @@ if(WIN32 AND YAZE_USE_VCPKG_GRPC)
|
||||
absl::flat_hash_map
|
||||
absl::synchronization
|
||||
absl::symbolize
|
||||
absl::strerror
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
# Export protobuf targets (vcpkg uses protobuf:: namespace)
|
||||
set(YAZE_PROTOBUF_TARGETS protobuf::libprotobuf PARENT_SCOPE)
|
||||
set(YAZE_PROTOBUF_WHOLEARCHIVE_TARGETS protobuf::libprotobuf PARENT_SCOPE)
|
||||
|
||||
# Get protobuf include directories for proto generation
|
||||
get_target_property(_PROTOBUF_INCLUDE_DIRS protobuf::libprotobuf
|
||||
@@ -242,7 +245,7 @@ if(WIN32 AND YAZE_USE_VCPKG_GRPC)
|
||||
message(STATUS " vcpkg gRPC not found (expected if removed from vcpkg.json)")
|
||||
message(STATUS " Using FetchContent build (faster with caching)")
|
||||
message(STATUS " First build: ~10-15 min, subsequent: <1 min (cached)")
|
||||
message(STATUS " Using gRPC v1.75.1 with Windows compatibility fixes")
|
||||
message(STATUS " Using gRPC v1.75.1 (latest stable)")
|
||||
message(STATUS " Note: BoringSSL ASM disabled for clang-cl compatibility")
|
||||
message(STATUS "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
|
||||
endif()
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# gui libraries ---------------------------------------------------------------
|
||||
set(IMGUI_PATH ${CMAKE_SOURCE_DIR}/src/lib/imgui)
|
||||
file(GLOB IMGUI_SOURCES ${IMGUI_PATH}/*.cpp)
|
||||
set(IMGUI_BACKEND_SOURCES
|
||||
${IMGUI_PATH}/backends/imgui_impl_sdl2.cpp
|
||||
${IMGUI_PATH}/backends/imgui_impl_sdlrenderer2.cpp
|
||||
${IMGUI_PATH}/misc/cpp/imgui_stdlib.cpp
|
||||
)
|
||||
add_library("ImGui" STATIC ${IMGUI_SOURCES} ${IMGUI_BACKEND_SOURCES})
|
||||
target_include_directories("ImGui" PUBLIC ${IMGUI_PATH} ${IMGUI_PATH}/backends)
|
||||
target_include_directories(ImGui PUBLIC ${SDL2_INCLUDE_DIR})
|
||||
target_compile_definitions(ImGui PUBLIC
|
||||
IMGUI_IMPL_OPENGL_LOADER_CUSTOM=<SDL2/SDL_opengl.h> GL_GLEXT_PROTOTYPES=1)
|
||||
|
||||
# ImGui Test Engine - Always built when tests are enabled for simplified integration
|
||||
# The test infrastructure is tightly coupled with the editor, so we always include it
|
||||
if(YAZE_BUILD_TESTS)
|
||||
set(IMGUI_TEST_ENGINE_PATH ${CMAKE_SOURCE_DIR}/src/lib/imgui_test_engine/imgui_test_engine)
|
||||
file(GLOB IMGUI_TEST_ENGINE_SOURCES ${IMGUI_TEST_ENGINE_PATH}/*.cpp)
|
||||
add_library("ImGuiTestEngine" STATIC ${IMGUI_TEST_ENGINE_SOURCES})
|
||||
target_include_directories(ImGuiTestEngine PUBLIC ${IMGUI_PATH} ${CMAKE_SOURCE_DIR}/src/lib)
|
||||
target_link_libraries(ImGuiTestEngine PUBLIC ImGui)
|
||||
target_compile_definitions(ImGuiTestEngine PUBLIC
|
||||
IMGUI_ENABLE_TEST_ENGINE=1
|
||||
IMGUI_TEST_ENGINE_ENABLE_COROUTINE_STDTHREAD_IMPL=1)
|
||||
|
||||
message(STATUS "✓ ImGui Test Engine enabled (tests are ON)")
|
||||
else()
|
||||
message(STATUS "✗ ImGui Test Engine disabled (tests are OFF)")
|
||||
endif()
|
||||
|
||||
set(
|
||||
IMGUI_SRC
|
||||
${IMGUI_PATH}/imgui.cpp
|
||||
${IMGUI_PATH}/imgui_demo.cpp
|
||||
${IMGUI_PATH}/imgui_draw.cpp
|
||||
${IMGUI_PATH}/imgui_widgets.cpp
|
||||
${IMGUI_PATH}/backends/imgui_impl_sdl2.cpp
|
||||
${IMGUI_PATH}/backends/imgui_impl_sdlrenderer2.cpp
|
||||
${IMGUI_PATH}/misc/cpp/imgui_stdlib.cpp
|
||||
)
|
||||
|
||||
@@ -7,24 +7,64 @@
|
||||
# 1. Set the target system (macOS)
|
||||
set(CMAKE_SYSTEM_NAME Darwin)
|
||||
|
||||
# Ensure a non-empty system version for third-party CMake logic.
|
||||
if(NOT CMAKE_SYSTEM_VERSION)
|
||||
execute_process(
|
||||
COMMAND sw_vers -productVersion
|
||||
OUTPUT_VARIABLE _yaze_macos_version
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(_yaze_macos_version)
|
||||
set(CMAKE_SYSTEM_VERSION "${_yaze_macos_version}")
|
||||
else()
|
||||
set(CMAKE_SYSTEM_VERSION "0")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# 2. Find the Homebrew LLVM installation path
|
||||
# We use execute_process to make this portable across machine architectures.
|
||||
set(_yaze_llvm_candidates llvm@21 llvm@20 llvm@19 llvm@18 llvm)
|
||||
foreach(_yaze_llvm_candidate IN LISTS _yaze_llvm_candidates)
|
||||
execute_process(
|
||||
COMMAND brew --prefix llvm@18
|
||||
OUTPUT_VARIABLE HOMEBREW_LLVM_PREFIX
|
||||
COMMAND brew --prefix ${_yaze_llvm_candidate}
|
||||
OUTPUT_VARIABLE _yaze_llvm_prefix
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE _yaze_llvm_result
|
||||
)
|
||||
if(_yaze_llvm_result EQUAL 0 AND EXISTS "${_yaze_llvm_prefix}")
|
||||
set(HOMEBREW_LLVM_PREFIX "${_yaze_llvm_prefix}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT EXISTS "${HOMEBREW_LLVM_PREFIX}")
|
||||
message(FATAL_ERROR "Homebrew LLVM not found. Please run 'brew install llvm'. Path: ${HOMEBREW_LLVM_PREFIX}")
|
||||
message(FATAL_ERROR "Homebrew LLVM not found. Please run 'brew install llvm'.")
|
||||
endif()
|
||||
|
||||
# Cache this variable so it's available in the main CMakeLists.txt
|
||||
set(HOMEBREW_LLVM_PREFIX "${HOMEBREW_LLVM_PREFIX}" CACHE PATH "Path to Homebrew LLVM installation")
|
||||
|
||||
message(STATUS "Using Homebrew LLVM from: ${HOMEBREW_LLVM_PREFIX}")
|
||||
|
||||
# 3. Set the C and C++ compilers
|
||||
set(CMAKE_C_COMPILER "${HOMEBREW_LLVM_PREFIX}/bin/clang")
|
||||
set(CMAKE_CXX_COMPILER "${HOMEBREW_LLVM_PREFIX}/bin/clang++")
|
||||
|
||||
# 3.5 Find and configure clang-tidy
|
||||
find_program(CLANG_TIDY_EXE
|
||||
NAMES clang-tidy
|
||||
HINTS "${HOMEBREW_LLVM_PREFIX}/bin"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if(CLANG_TIDY_EXE)
|
||||
message(STATUS "Found Homebrew clang-tidy: ${CLANG_TIDY_EXE}")
|
||||
set(YAZE_CLANG_TIDY_EXE "${CLANG_TIDY_EXE}" CACHE FILEPATH "Path to clang-tidy executable")
|
||||
else()
|
||||
message(WARNING "clang-tidy not found in ${HOMEBREW_LLVM_PREFIX}/bin")
|
||||
endif()
|
||||
|
||||
# 4. Set the system root (sysroot) to the macOS SDK
|
||||
# This correctly points to the system-level headers and libraries.
|
||||
execute_process(
|
||||
@@ -35,11 +75,29 @@ execute_process(
|
||||
set(CMAKE_SYSROOT "${CMAKE_OSX_SYSROOT}")
|
||||
message(STATUS "Using macOS SDK at: ${CMAKE_SYSROOT}")
|
||||
|
||||
# 5. **[THE CRITICAL FIX]** Explicitly define the C++ standard library include directory.
|
||||
# This forces CMake to add Homebrew's libc++ headers to the search path *before*
|
||||
# any other system paths, resolving the header conflict for the main project
|
||||
# and all dependencies.
|
||||
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES "${HOMEBREW_LLVM_PREFIX}/include/c++/v1")
|
||||
# 5. Ensure Homebrew libc++ + Clang resource headers are searched before SDK headers.
|
||||
execute_process(
|
||||
COMMAND "${HOMEBREW_LLVM_PREFIX}/bin/clang++" -print-resource-dir
|
||||
OUTPUT_VARIABLE HOMEBREW_LLVM_RESOURCE_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
set(HOMEBREW_LLVM_RESOURCE_INCLUDE "${HOMEBREW_LLVM_RESOURCE_DIR}/include")
|
||||
|
||||
if(EXISTS "${HOMEBREW_LLVM_PREFIX}/include/c++/v1")
|
||||
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
|
||||
include_directories(BEFORE SYSTEM "${HOMEBREW_LLVM_PREFIX}/include/c++/v1")
|
||||
endif()
|
||||
if(EXISTS "${HOMEBREW_LLVM_RESOURCE_INCLUDE}")
|
||||
include_directories(BEFORE SYSTEM "${HOMEBREW_LLVM_RESOURCE_INCLUDE}")
|
||||
endif()
|
||||
|
||||
# 5.5 Ensure Homebrew libc++ is linked to avoid mixing ABI with system libc++.
|
||||
set(_yaze_llvm_lib_dir "${HOMEBREW_LLVM_PREFIX}/lib")
|
||||
set(_yaze_llvm_libcxx_dir "${HOMEBREW_LLVM_PREFIX}/lib/c++")
|
||||
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} -stdlib=libc++")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT} -L${_yaze_llvm_lib_dir} -Wl,-rpath,${_yaze_llvm_lib_dir} -L${_yaze_llvm_libcxx_dir} -Wl,-rpath,${_yaze_llvm_libcxx_dir}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "${CMAKE_SHARED_LINKER_FLAGS_INIT} -L${_yaze_llvm_lib_dir} -Wl,-rpath,${_yaze_llvm_lib_dir} -L${_yaze_llvm_libcxx_dir} -Wl,-rpath,${_yaze_llvm_libcxx_dir}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "${CMAKE_MODULE_LINKER_FLAGS_INIT} -L${_yaze_llvm_lib_dir} -Wl,-rpath,${_yaze_llvm_lib_dir} -L${_yaze_llvm_libcxx_dir} -Wl,-rpath,${_yaze_llvm_libcxx_dir}")
|
||||
|
||||
# 6. Set the default installation path for macOS frameworks
|
||||
set(CMAKE_FIND_FRAMEWORK FIRST)
|
||||
154
cmake/options.cmake
Normal file
154
cmake/options.cmake
Normal file
@@ -0,0 +1,154 @@
|
||||
# YAZE Build Options
|
||||
# Centralized feature flags and build configuration
|
||||
|
||||
# Core build options
|
||||
option(YAZE_BUILD_GUI "Build GUI application" ON)
|
||||
option(YAZE_BUILD_CLI "Build CLI tools (shared libraries)" ON)
|
||||
option(YAZE_BUILD_Z3ED "Build z3ed CLI executable" ON)
|
||||
option(YAZE_BUILD_EMU "Build emulator components" ON)
|
||||
option(YAZE_BUILD_LIB "Build static library" ON)
|
||||
option(YAZE_BUILD_TESTS "Build test suite" ON)
|
||||
option(YAZE_BUILD_TOOLS "Build development utility tools" ${YAZE_BUILD_TESTS})
|
||||
option(YAZE_BUILD_LAB "Build lab sandbox executable" OFF)
|
||||
|
||||
# Feature flags
|
||||
option(YAZE_ENABLE_GRPC "Enable gRPC agent support" ON)
|
||||
option(YAZE_ENABLE_JSON "Enable JSON support" ON)
|
||||
option(YAZE_ENABLE_AI "Enable AI agent features" OFF)
|
||||
option(YAZE_ENABLE_CLANG_TIDY "Enable clang-tidy linting during build" ON)
|
||||
option(YAZE_ENABLE_OPENCV "Enable OpenCV for advanced visual analysis" OFF)
|
||||
|
||||
# Advanced feature toggles
|
||||
option(YAZE_ENABLE_REMOTE_AUTOMATION
|
||||
"Enable remote automation services (gRPC/protobuf servers + GUI automation clients)"
|
||||
${YAZE_ENABLE_GRPC})
|
||||
option(YAZE_ENABLE_AI_RUNTIME
|
||||
"Enable AI runtime integrations (Gemini/Ollama, advanced routing, proposal planning)"
|
||||
${YAZE_ENABLE_AI})
|
||||
option(YAZE_BUILD_AGENT_UI
|
||||
"Build ImGui-based agent/chat panels inside the GUI"
|
||||
${YAZE_BUILD_GUI})
|
||||
option(YAZE_ENABLE_AGENT_CLI
|
||||
"Build the conversational agent CLI stack (z3ed agent commands)"
|
||||
${YAZE_BUILD_CLI})
|
||||
option(YAZE_ENABLE_HTTP_API
|
||||
"Enable HTTP REST API server for external agent access"
|
||||
${YAZE_ENABLE_AGENT_CLI})
|
||||
|
||||
if((YAZE_BUILD_CLI OR YAZE_BUILD_Z3ED) AND NOT YAZE_ENABLE_AGENT_CLI)
|
||||
set(YAZE_ENABLE_AGENT_CLI ON CACHE BOOL "Build the conversational agent CLI stack (z3ed agent commands)" FORCE)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_HTTP_API AND NOT YAZE_ENABLE_AGENT_CLI)
|
||||
set(YAZE_ENABLE_AGENT_CLI ON CACHE BOOL "Build the conversational agent CLI stack (z3ed agent commands)" FORCE)
|
||||
endif()
|
||||
|
||||
# Build optimizations
|
||||
option(YAZE_ENABLE_LTO "Enable link-time optimization" OFF)
|
||||
option(YAZE_ENABLE_SANITIZERS "Enable AddressSanitizer/UBSanitizer" OFF)
|
||||
option(YAZE_ENABLE_COVERAGE "Enable code coverage" OFF)
|
||||
option(YAZE_UNITY_BUILD "Enable Unity (Jumbo) builds" OFF)
|
||||
|
||||
# Platform-specific options
|
||||
option(YAZE_USE_VCPKG "Use vcpkg for Windows dependencies" OFF)
|
||||
option(YAZE_USE_SYSTEM_DEPS "Use system package manager for dependencies" OFF)
|
||||
option(YAZE_USE_SDL3 "Use SDL3 instead of SDL2 (experimental)" OFF)
|
||||
option(YAZE_WASM_TERMINAL "Build z3ed for WASM terminal mode (no TUI)" OFF)
|
||||
|
||||
# Development options
|
||||
option(YAZE_ENABLE_ROM_TESTS "Enable tests that require ROM files" OFF)
|
||||
option(YAZE_ENABLE_BENCHMARK_TESTS "Enable benchmark/performance tests" OFF)
|
||||
option(YAZE_MINIMAL_BUILD "Minimal build for CI (disable optional features)" OFF)
|
||||
option(YAZE_VERBOSE_BUILD "Verbose build output" OFF)
|
||||
|
||||
# Install options
|
||||
option(YAZE_INSTALL_LIB "Install static library" OFF)
|
||||
option(YAZE_INSTALL_HEADERS "Install public headers" ON)
|
||||
|
||||
# Set preprocessor definitions based on options
|
||||
if(YAZE_ENABLE_REMOTE_AUTOMATION AND NOT YAZE_ENABLE_GRPC)
|
||||
set(YAZE_ENABLE_GRPC ON CACHE BOOL "Enable gRPC agent support" FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT YAZE_ENABLE_REMOTE_AUTOMATION)
|
||||
set(YAZE_ENABLE_GRPC OFF CACHE BOOL "Enable gRPC agent support" FORCE)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_GRPC)
|
||||
add_compile_definitions(YAZE_WITH_GRPC)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_JSON)
|
||||
add_compile_definitions(YAZE_WITH_JSON)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_AI_RUNTIME AND NOT YAZE_ENABLE_AI)
|
||||
set(YAZE_ENABLE_AI ON CACHE BOOL "Enable AI agent features" FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT YAZE_ENABLE_AI_RUNTIME)
|
||||
set(YAZE_ENABLE_AI OFF CACHE BOOL "Enable AI agent features" FORCE)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_AI)
|
||||
add_compile_definitions(Z3ED_AI)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_AI_RUNTIME)
|
||||
add_compile_definitions(YAZE_AI_RUNTIME_AVAILABLE)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_HTTP_API)
|
||||
add_compile_definitions(YAZE_HTTP_API_ENABLED)
|
||||
endif()
|
||||
|
||||
if(YAZE_WASM_TERMINAL)
|
||||
add_compile_definitions(YAZE_WASM_TERMINAL_MODE)
|
||||
endif()
|
||||
|
||||
if(YAZE_USE_SDL3)
|
||||
add_compile_definitions(YAZE_USE_SDL3)
|
||||
endif()
|
||||
|
||||
if(YAZE_BUILD_AGENT_UI)
|
||||
add_compile_definitions(YAZE_BUILD_AGENT_UI)
|
||||
endif()
|
||||
|
||||
if(YAZE_ENABLE_OPENCV)
|
||||
find_package(OpenCV QUIET)
|
||||
if(OpenCV_FOUND)
|
||||
add_compile_definitions(YAZE_WITH_OPENCV)
|
||||
message(STATUS "✓ OpenCV found: ${OpenCV_VERSION}")
|
||||
else()
|
||||
message(WARNING "OpenCV requested but not found - visual analysis will use fallback")
|
||||
set(YAZE_ENABLE_OPENCV OFF CACHE BOOL "Enable OpenCV for advanced visual analysis" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Print configuration summary
|
||||
message(STATUS "=== YAZE Build Configuration ===")
|
||||
message(STATUS "GUI Application: ${YAZE_BUILD_GUI}")
|
||||
message(STATUS "CLI Tools: ${YAZE_BUILD_CLI}")
|
||||
message(STATUS "z3ed CLI: ${YAZE_BUILD_Z3ED}")
|
||||
message(STATUS "Emulator: ${YAZE_BUILD_EMU}")
|
||||
message(STATUS "Static Library: ${YAZE_BUILD_LIB}")
|
||||
message(STATUS "Tests: ${YAZE_BUILD_TESTS}")
|
||||
message(STATUS "Lab Sandbox: ${YAZE_BUILD_LAB}")
|
||||
if(YAZE_USE_SDL3)
|
||||
message(STATUS "SDL Version: SDL3 (experimental)")
|
||||
else()
|
||||
message(STATUS "SDL Version: SDL2 (stable)")
|
||||
endif()
|
||||
message(STATUS "gRPC Support: ${YAZE_ENABLE_GRPC}")
|
||||
message(STATUS "Remote Automation: ${YAZE_ENABLE_REMOTE_AUTOMATION}")
|
||||
message(STATUS "JSON Support: ${YAZE_ENABLE_JSON}")
|
||||
message(STATUS "AI Runtime: ${YAZE_ENABLE_AI_RUNTIME}")
|
||||
message(STATUS "AI Features (legacy): ${YAZE_ENABLE_AI}")
|
||||
message(STATUS "Agent UI Panels: ${YAZE_BUILD_AGENT_UI}")
|
||||
message(STATUS "Agent CLI Stack: ${YAZE_ENABLE_AGENT_CLI}")
|
||||
message(STATUS "HTTP API Server: ${YAZE_ENABLE_HTTP_API}")
|
||||
message(STATUS "LTO: ${YAZE_ENABLE_LTO}")
|
||||
message(STATUS "Sanitizers: ${YAZE_ENABLE_SANITIZERS}")
|
||||
message(STATUS "Coverage: ${YAZE_ENABLE_COVERAGE}")
|
||||
message(STATUS "OpenCV Visual Analysis: ${YAZE_ENABLE_OPENCV}")
|
||||
message(STATUS "=================================")
|
||||
@@ -141,23 +141,42 @@ set(CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "Documentation")
|
||||
set(CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION "User and developer documentation")
|
||||
set(CPACK_COMPONENT_DOCUMENTATION_REQUIRED FALSE)
|
||||
|
||||
# Platform-specific install paths
|
||||
# The asset paths must match what platform_paths.cc FindAsset() searches for
|
||||
if(WIN32)
|
||||
# Windows: flat structure (exe and assets/ at same level)
|
||||
set(YAZE_INSTALL_BINDIR ".")
|
||||
set(YAZE_INSTALL_DATADIR ".")
|
||||
set(YAZE_INSTALL_DOCDIR ".")
|
||||
elseif(APPLE)
|
||||
# macOS: flat structure for DMG (app bundle handles its own resources)
|
||||
set(YAZE_INSTALL_BINDIR ".")
|
||||
set(YAZE_INSTALL_DATADIR ".")
|
||||
set(YAZE_INSTALL_DOCDIR ".")
|
||||
else()
|
||||
# Linux: FHS structure - assets at share/yaze/assets (matches FindAsset search)
|
||||
set(YAZE_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
|
||||
set(YAZE_INSTALL_DATADIR "${CMAKE_INSTALL_DATADIR}/yaze")
|
||||
set(YAZE_INSTALL_DOCDIR "${CMAKE_INSTALL_DOCDIR}")
|
||||
endif()
|
||||
|
||||
# Installation components
|
||||
if(APPLE)
|
||||
install(TARGETS yaze
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
RUNTIME DESTINATION ${YAZE_INSTALL_BINDIR}
|
||||
BUNDLE DESTINATION ${YAZE_INSTALL_BINDIR}
|
||||
COMPONENT applications
|
||||
)
|
||||
else()
|
||||
install(TARGETS yaze
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
RUNTIME DESTINATION ${YAZE_INSTALL_BINDIR}
|
||||
COMPONENT applications
|
||||
)
|
||||
endif()
|
||||
|
||||
# Install assets
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/assets/
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/yaze/assets
|
||||
DESTINATION ${YAZE_INSTALL_DATADIR}/assets
|
||||
COMPONENT applications
|
||||
PATTERN "*.png"
|
||||
PATTERN "*.ttf"
|
||||
@@ -168,12 +187,12 @@ install(DIRECTORY ${CMAKE_SOURCE_DIR}/assets/
|
||||
install(FILES
|
||||
${CMAKE_SOURCE_DIR}/README.md
|
||||
${CMAKE_SOURCE_DIR}/LICENSE
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||
DESTINATION ${YAZE_INSTALL_DOCDIR}
|
||||
COMPONENT documentation
|
||||
)
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/docs/
|
||||
DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||
DESTINATION ${YAZE_INSTALL_DOCDIR}
|
||||
COMPONENT documentation
|
||||
PATTERN "*.md"
|
||||
PATTERN "*.html"
|
||||
|
||||
108
cmake/packaging/cpack.cmake
Normal file
108
cmake/packaging/cpack.cmake
Normal file
@@ -0,0 +1,108 @@
|
||||
# CPack Configuration - flat packages for all platforms
|
||||
#
|
||||
# Structure:
|
||||
# root/
|
||||
# yaze(.exe)
|
||||
# z3ed(.exe) (if built)
|
||||
# README.md
|
||||
# LICENSE
|
||||
# assets/...
|
||||
|
||||
set(CPACK_PACKAGE_NAME "yaze")
|
||||
set(CPACK_PACKAGE_VENDOR "scawful")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Yet Another Zelda3 Editor")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${YAZE_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${YAZE_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${YAZE_VERSION_PATCH})
|
||||
set(CPACK_PACKAGE_VERSION "${YAZE_VERSION_MAJOR}.${YAZE_VERSION_MINOR}.${YAZE_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/packages")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
|
||||
|
||||
set(CPACK_COMPONENTS_ALL yaze)
|
||||
set(CPACK_COMPONENT_YAZE_DISPLAY_NAME "YAZE Editor")
|
||||
set(CPACK_COMPONENT_YAZE_DESCRIPTION "Main YAZE application and libraries")
|
||||
|
||||
# Populate runtime library list (needed on Windows)
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON)
|
||||
set(CMAKE_INSTALL_UCRT_LIBRARIES ON)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
if(APPLE)
|
||||
include(cmake/packaging/macos.cmake)
|
||||
|
||||
install(TARGETS yaze
|
||||
BUNDLE DESTINATION .
|
||||
COMPONENT yaze)
|
||||
|
||||
if(TARGET z3ed)
|
||||
install(TARGETS z3ed
|
||||
RUNTIME DESTINATION .
|
||||
COMPONENT yaze)
|
||||
endif()
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/assets/
|
||||
DESTINATION assets
|
||||
COMPONENT yaze)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_SOURCE_DIR}/README.md
|
||||
${CMAKE_SOURCE_DIR}/LICENSE
|
||||
DESTINATION .
|
||||
COMPONENT yaze)
|
||||
|
||||
elseif(WIN32)
|
||||
include(cmake/packaging/windows.cmake)
|
||||
|
||||
install(TARGETS yaze
|
||||
RUNTIME DESTINATION .
|
||||
COMPONENT yaze)
|
||||
|
||||
if(TARGET z3ed)
|
||||
install(TARGETS z3ed
|
||||
RUNTIME DESTINATION .
|
||||
COMPONENT yaze)
|
||||
endif()
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/assets/
|
||||
DESTINATION assets
|
||||
COMPONENT yaze)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_SOURCE_DIR}/README.md
|
||||
${CMAKE_SOURCE_DIR}/LICENSE
|
||||
DESTINATION .
|
||||
COMPONENT yaze)
|
||||
|
||||
# Bundle MSVC/UCRT runtime dependencies if detected
|
||||
if(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
|
||||
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
|
||||
DESTINATION .
|
||||
COMPONENT yaze)
|
||||
endif()
|
||||
|
||||
else()
|
||||
include(cmake/packaging/linux.cmake)
|
||||
|
||||
install(TARGETS yaze
|
||||
RUNTIME DESTINATION .
|
||||
COMPONENT yaze)
|
||||
|
||||
if(TARGET z3ed)
|
||||
install(TARGETS z3ed
|
||||
RUNTIME DESTINATION .
|
||||
COMPONENT yaze)
|
||||
endif()
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/assets/
|
||||
DESTINATION assets
|
||||
COMPONENT yaze)
|
||||
|
||||
install(FILES
|
||||
${CMAKE_SOURCE_DIR}/README.md
|
||||
${CMAKE_SOURCE_DIR}/LICENSE
|
||||
DESTINATION .
|
||||
COMPONENT yaze)
|
||||
endif()
|
||||
|
||||
include(CPack)
|
||||
17
cmake/packaging/linux.cmake
Normal file
17
cmake/packaging/linux.cmake
Normal file
@@ -0,0 +1,17 @@
|
||||
# Linux Packaging Configuration
|
||||
|
||||
# DEB package
|
||||
set(CPACK_GENERATOR "DEB;TGZ")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "scawful")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libstdc++6, libsdl2-2.0-0")
|
||||
|
||||
# RPM package
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
set(CPACK_RPM_PACKAGE_GROUP "Applications/Games")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "glibc, libstdc++, SDL2")
|
||||
|
||||
# Tarball
|
||||
set(CPACK_TGZ_PACKAGE_NAME "yaze-${CPACK_PACKAGE_VERSION}-linux-x64")
|
||||
|
||||
24
cmake/packaging/macos.cmake
Normal file
24
cmake/packaging/macos.cmake
Normal file
@@ -0,0 +1,24 @@
|
||||
# macOS Packaging Configuration
|
||||
|
||||
# Create .dmg package
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
set(CPACK_DMG_VOLUME_NAME "yaze")
|
||||
set(CPACK_DMG_FORMAT "UDZO")
|
||||
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/assets/yaze.png")
|
||||
|
||||
# App bundle configuration
|
||||
set(CPACK_BUNDLE_NAME "yaze")
|
||||
set(CPACK_BUNDLE_PACKAGE_TYPE "APPL")
|
||||
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/assets/yaze.icns")
|
||||
|
||||
# Code signing (if available)
|
||||
if(DEFINED ENV{CODESIGN_IDENTITY})
|
||||
set(CPACK_BUNDLE_APPLE_CERT_APP "$ENV{CODESIGN_IDENTITY}")
|
||||
set(CPACK_BUNDLE_APPLE_CODESIGN_FORCE "ON")
|
||||
endif()
|
||||
|
||||
# Notarization (if available)
|
||||
if(DEFINED ENV{NOTARIZATION_CREDENTIALS})
|
||||
set(CPACK_BUNDLE_APPLE_NOTARIZATION_CREDENTIALS "$ENV{NOTARIZATION_CREDENTIALS}")
|
||||
endif()
|
||||
|
||||
22
cmake/packaging/windows.cmake
Normal file
22
cmake/packaging/windows.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
# Windows Packaging Configuration
|
||||
|
||||
# NSIS installer
|
||||
set(CPACK_GENERATOR "NSIS;ZIP")
|
||||
set(CPACK_NSIS_PACKAGE_NAME "YAZE Editor")
|
||||
set(CPACK_NSIS_DISPLAY_NAME "YAZE Editor v${CPACK_PACKAGE_VERSION}")
|
||||
set(CPACK_NSIS_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
|
||||
set(CPACK_NSIS_CONTACT "scawful")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/scawful/yaze")
|
||||
set(CPACK_NSIS_HELP_LINK "https://github.com/scawful/yaze")
|
||||
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/scawful/yaze")
|
||||
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
|
||||
|
||||
# ZIP package
|
||||
set(CPACK_ZIP_PACKAGE_NAME "yaze-${CPACK_PACKAGE_VERSION}-windows-x64")
|
||||
|
||||
# Code signing (if available)
|
||||
if(DEFINED ENV{SIGNTOOL_CERTIFICATE})
|
||||
set(CPACK_NSIS_SIGN_TOOL "signtool.exe")
|
||||
set(CPACK_NSIS_SIGN_COMMAND "${ENV{SIGNTOOL_CERTIFICATE}}")
|
||||
endif()
|
||||
|
||||
@@ -27,14 +27,14 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
# Fall back to bundled SDL if vcpkg not available or SDL2 not found
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/src/lib/SDL/CMakeLists.txt")
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/ext/SDL/CMakeLists.txt")
|
||||
message(STATUS "○ vcpkg SDL2 not found, using bundled SDL2")
|
||||
add_subdirectory(src/lib/SDL)
|
||||
add_subdirectory(ext/SDL)
|
||||
set(SDL_TARGETS SDL2-static)
|
||||
set(SDL2_INCLUDE_DIR
|
||||
${CMAKE_SOURCE_DIR}/src/lib/SDL/include
|
||||
${CMAKE_BINARY_DIR}/src/lib/SDL/include
|
||||
${CMAKE_BINARY_DIR}/src/lib/SDL/include-config-${CMAKE_BUILD_TYPE}
|
||||
${CMAKE_SOURCE_DIR}/ext/SDL/include
|
||||
${CMAKE_BINARY_DIR}/ext/SDL/include
|
||||
${CMAKE_BINARY_DIR}/ext/SDL/include-config-${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
|
||||
if(TARGET SDL2main)
|
||||
@@ -47,12 +47,12 @@ if(WIN32)
|
||||
endif()
|
||||
elseif(UNIX OR MINGW)
|
||||
# Non-Windows: use bundled SDL
|
||||
add_subdirectory(src/lib/SDL)
|
||||
add_subdirectory(ext/SDL)
|
||||
set(SDL_TARGETS SDL2-static)
|
||||
set(SDL2_INCLUDE_DIR
|
||||
${CMAKE_SOURCE_DIR}/src/lib/SDL/include
|
||||
${CMAKE_BINARY_DIR}/src/lib/SDL/include
|
||||
${CMAKE_BINARY_DIR}/src/lib/SDL/include-config-${CMAKE_BUILD_TYPE}
|
||||
${CMAKE_SOURCE_DIR}/ext/SDL/include
|
||||
${CMAKE_BINARY_DIR}/ext/SDL/include
|
||||
${CMAKE_BINARY_DIR}/ext/SDL/include-config-${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
|
||||
message(STATUS "Using bundled SDL2")
|
||||
|
||||
22
cmake/toolchains/linux-gcc.cmake
Normal file
22
cmake/toolchains/linux-gcc.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
# Linux GCC Toolchain
|
||||
# Optimized for Ubuntu 22.04+ with GCC 12+
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_C_COMPILER gcc)
|
||||
set(CMAKE_CXX_COMPILER g++)
|
||||
|
||||
# Set C++ standard
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Compiler flags
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG")
|
||||
|
||||
# Link flags
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
|
||||
|
||||
# Find packages
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
25
cmake/toolchains/macos-clang.cmake
Normal file
25
cmake/toolchains/macos-clang.cmake
Normal file
@@ -0,0 +1,25 @@
|
||||
# macOS Clang Toolchain
|
||||
# Optimized for macOS 14+ with Clang 18+
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Darwin)
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
set(CMAKE_CXX_COMPILER clang++)
|
||||
|
||||
# Set C++ standard
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# macOS deployment target
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "macOS deployment target")
|
||||
|
||||
# Compiler flags
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG")
|
||||
|
||||
# Link flags
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
|
||||
# Find packages
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
26
cmake/toolchains/windows-msvc.cmake
Normal file
26
cmake/toolchains/windows-msvc.cmake
Normal file
@@ -0,0 +1,26 @@
|
||||
# Windows MSVC Toolchain
|
||||
# Optimized for Visual Studio 2022 with MSVC 19.30+
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(CMAKE_C_COMPILER cl)
|
||||
set(CMAKE_CXX_COMPILER cl)
|
||||
|
||||
# Set C++ standard
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# MSVC runtime library (static)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
# Compiler flags
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /permissive-")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2 /Ob2 /DNDEBUG")
|
||||
|
||||
# Link flags
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
|
||||
# Windows-specific definitions
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-DNOMINMAX)
|
||||
|
||||
@@ -34,6 +34,8 @@ function(yaze_add_compiler_flags)
|
||||
target_compile_definitions(yaze_common INTERFACE linux stricmp=strcasecmp)
|
||||
elseif(YAZE_PLATFORM_MACOS)
|
||||
target_compile_definitions(yaze_common INTERFACE MACOS)
|
||||
elseif(YAZE_PLATFORM_IOS)
|
||||
target_compile_definitions(yaze_common INTERFACE YAZE_IOS)
|
||||
elseif(YAZE_PLATFORM_WINDOWS)
|
||||
target_compile_definitions(yaze_common INTERFACE WINDOWS)
|
||||
endif()
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# Getting Started
|
||||
|
||||
This software allows you to modify "The Legend of Zelda: A Link to the Past" (US or JP) ROMs. It is built for compatibility with ZScream projects and designed to be cross-platform.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Download** the latest release for your platform from the [releases page](https://github.com/scawful/yaze/releases).
|
||||
2. **Load ROM** via `File > Open ROM`.
|
||||
3. **Select an Editor** from the main toolbar (e.g., Overworld, Dungeon, Graphics).
|
||||
4. **Make Changes** and save your project.
|
||||
|
||||
## General Tips
|
||||
|
||||
- **Experiment Flags**: Enable or disable new features in `File > Options > Experiment Flags`.
|
||||
- **Backup Files**: Enabled by default. Each save creates a timestamped backup of your ROM.
|
||||
- **Extensions**: Load custom tools via the `Extensions` menu (C library and Python module support is planned).
|
||||
|
||||
## Feature Status
|
||||
|
||||
| Feature | State | Notes |
|
||||
|---|---|---|
|
||||
| Overworld Editor | Stable | Supports vanilla and ZSCustomOverworld v2/v3 projects. |
|
||||
| Dungeon Editor | Experimental | Requires extensive manual testing before production use. |
|
||||
| Tile16 Editor | Experimental | Palette and tile workflows are still being tuned. |
|
||||
| Palette Editor | Stable | Reference implementation for palette utilities. |
|
||||
| Graphics Editor | Experimental | Rendering pipeline under active refactor. |
|
||||
| Sprite Editor | Experimental | Card/UI patterns mid-migration. |
|
||||
| Message Editor | Stable | Re-test after recent palette fixes. |
|
||||
| Hex Editor | Stable | Direct ROM editing utility. |
|
||||
| Asar Patching | Stable | Wraps the bundled Asar assembler. |
|
||||
|
||||
## Command-Line Interface (`z3ed`)
|
||||
|
||||
`z3ed` provides scripted access to the same ROM editors.
|
||||
|
||||
### AI Agent Chat
|
||||
Chat with an AI to perform edits using natural language.
|
||||
|
||||
```bash
|
||||
# Start an interactive chat session with the AI agent
|
||||
z3ed agent chat --rom zelda3.sfc
|
||||
```
|
||||
> **Prompt:** "What sprites are in dungeon 2?"
|
||||
|
||||
### Resource Inspection
|
||||
Directly query ROM data.
|
||||
|
||||
```bash
|
||||
# List all sprites in the Eastern Palace (dungeon 2)
|
||||
z3ed dungeon list-sprites --rom zelda3.sfc --dungeon 2
|
||||
|
||||
# Get information about a specific overworld map area
|
||||
z3ed overworld describe-map --rom zelda3.sfc --map 80
|
||||
```
|
||||
|
||||
### Patching
|
||||
Apply assembly patches using the integrated Asar assembler.
|
||||
```bash
|
||||
# Apply an assembly patch to the ROM
|
||||
z3ed asar patch.asm --rom zelda3.sfc
|
||||
```
|
||||
|
||||
## Extending Functionality
|
||||
|
||||
YAZE exports a C API that is still evolving. Treat it as experimental and expect breaking changes while the plugin system is built out.
|
||||
@@ -1,150 +0,0 @@
|
||||
# A1 - Testing Guide
|
||||
|
||||
This guide provides a comprehensive overview of the testing framework for the yaze project, including the test organization, execution methods, and the end-to-end GUI automation system.
|
||||
|
||||
## 1. Test Organization
|
||||
|
||||
The test suite is organized into a clear directory structure that separates tests by their purpose and dependencies. This is the primary way to understand the nature of a test.
|
||||
|
||||
```
|
||||
test/
|
||||
├── unit/ # Unit tests for individual components
|
||||
│ ├── core/ # Core functionality (asar, hex utils)
|
||||
│ ├── cli/ # Command-line interface tests
|
||||
│ ├── emu/ # Emulator component tests
|
||||
│ ├── gfx/ # Graphics system (tiles, palettes)
|
||||
│ ├── gui/ # GUI widget tests
|
||||
│ ├── rom/ # ROM data structure tests
|
||||
│ └── zelda3/ # Game-specific logic tests
|
||||
├── integration/ # Tests for interactions between components
|
||||
│ ├── ai/ # AI agent and vision tests
|
||||
│ ├── editor/ # Editor integration tests
|
||||
│ └── zelda3/ # Game-specific integration tests (ROM-dependent)
|
||||
├── e2e/ # End-to-end user workflow tests (GUI-driven)
|
||||
│ ├── rom_dependent/ # E2E tests requiring a ROM
|
||||
│ └── zscustomoverworld/ # ZSCustomOverworld upgrade E2E tests
|
||||
├── benchmarks/ # Performance benchmarks
|
||||
├── mocks/ # Mock objects for isolating tests
|
||||
└── assets/ # Test assets (patches, data)
|
||||
```
|
||||
|
||||
## 2. Test Categories
|
||||
|
||||
Based on the directory structure, tests fall into the following categories:
|
||||
|
||||
### Unit Tests (`unit/`)
|
||||
- **Purpose**: To test individual classes or functions in isolation.
|
||||
- **Characteristics**:
|
||||
- Fast, self-contained, and reliable.
|
||||
- No external dependencies (e.g., ROM files, running GUI).
|
||||
- Form the core of the CI/CD validation pipeline.
|
||||
|
||||
### Integration Tests (`integration/`)
|
||||
- **Purpose**: To verify that different components of the application work together correctly.
|
||||
- **Characteristics**:
|
||||
- May require a real ROM file (especially those in `integration/zelda3/`). These are considered "ROM-dependent".
|
||||
- Test interactions between modules, such as the `asar` wrapper and the `Rom` class, or AI services with the GUI controller.
|
||||
- Slower than unit tests but crucial for catching bugs at module boundaries.
|
||||
|
||||
### End-to-End (E2E) Tests (`e2e/`)
|
||||
- **Purpose**: To simulate a full user workflow from start to finish.
|
||||
- **Characteristics**:
|
||||
- Driven by the **ImGui Test Engine**.
|
||||
- Almost always require a running GUI and often a real ROM.
|
||||
- The slowest but most comprehensive tests, validating the user experience.
|
||||
- Includes smoke tests, canvas interactions, and complex workflows like ZSCustomOverworld upgrades.
|
||||
|
||||
### Benchmarks (`benchmarks/`)
|
||||
- **Purpose**: To measure and track the performance of critical code paths, particularly in the graphics system.
|
||||
- **Characteristics**:
|
||||
- Not focused on correctness but on speed and efficiency.
|
||||
- Run manually or in specialized CI jobs to prevent performance regressions.
|
||||
|
||||
## 3. Running Tests
|
||||
|
||||
### Using the Enhanced Test Runner (`yaze_test`)
|
||||
|
||||
The most flexible way to run tests is by using the `yaze_test` executable directly. It provides flags to filter tests by category, which is ideal for development and AI agent workflows.
|
||||
|
||||
```bash
|
||||
# First, build the test executable
|
||||
cmake --build build_ai --target yaze_test
|
||||
|
||||
# Run all tests
|
||||
./build_ai/bin/yaze_test
|
||||
|
||||
# Run only unit tests
|
||||
./build_ai/bin/yaze_test --unit
|
||||
|
||||
# Run only integration tests
|
||||
./build_ai/bin/yaze_test --integration
|
||||
|
||||
# Run E2E tests (requires a GUI)
|
||||
./build_ai/bin/yaze_test --e2e --show-gui
|
||||
|
||||
# Run ROM-dependent tests with a specific ROM
|
||||
./build_ai/bin/yaze_test --rom-dependent --rom-path /path/to/zelda3.sfc
|
||||
|
||||
# Run tests matching a specific pattern (e.g., all Asar tests)
|
||||
./build_ai/bin/yaze_test "*Asar*"
|
||||
|
||||
# Get a full list of options
|
||||
./build_ai/bin/yaze_test --help
|
||||
```
|
||||
|
||||
### Using CTest and CMake Presets
|
||||
|
||||
For CI/CD or a more traditional workflow, you can use `ctest` with CMake presets.
|
||||
|
||||
```bash
|
||||
# Configure a development build (enables ROM-dependent tests)
|
||||
cmake --preset mac-dev -DYAZE_TEST_ROM_PATH=/path/to/your/zelda3.sfc
|
||||
|
||||
# Build the tests
|
||||
cmake --build --preset mac-dev --target yaze_test
|
||||
|
||||
# Run stable tests (fast, primarily unit tests)
|
||||
ctest --preset dev
|
||||
|
||||
# Run all tests, including ROM-dependent and E2E
|
||||
ctest --preset all
|
||||
```
|
||||
|
||||
## 4. Writing Tests
|
||||
|
||||
When adding new tests, place them in the appropriate directory based on their purpose and dependencies.
|
||||
|
||||
- **New class `MyClass`?** Add `test/unit/my_class_test.cc`.
|
||||
- **Testing `MyClass` with a real ROM?** Add `test/integration/my_class_rom_test.cc`.
|
||||
- **Testing a full UI workflow involving `MyClass`?** Add `test/e2e/my_class_workflow_test.cc`.
|
||||
|
||||
## 5. E2E GUI Testing Framework
|
||||
|
||||
The E2E framework uses `ImGuiTestEngine` to automate UI interactions.
|
||||
|
||||
### Architecture
|
||||
|
||||
- **`test/yaze_test.cc`**: The main test runner that can initialize a GUI for E2E tests.
|
||||
- **`test/e2e/`**: Contains all E2E test files, such as:
|
||||
- `framework_smoke_test.cc`: Basic infrastructure verification.
|
||||
- `canvas_selection_test.cc`: Canvas interaction tests.
|
||||
- `dungeon_editor_tests.cc`: UI tests for the dungeon editor.
|
||||
- **`test/test_utils.h`**: Provides high-level helper functions for common actions like loading a ROM (`LoadRomInTest`) or opening an editor (`OpenEditorInTest`).
|
||||
|
||||
### Running GUI Tests
|
||||
|
||||
To run E2E tests and see the GUI interactions, use the `--show-gui` flag.
|
||||
|
||||
```bash
|
||||
# Run all E2E tests with the GUI visible
|
||||
./build_ai/bin/yaze_test --e2e --show-gui
|
||||
|
||||
# Run a specific E2E test by name
|
||||
./build_ai/bin/yaze_test --show-gui --gtest_filter="*DungeonEditorSmokeTest"
|
||||
```
|
||||
|
||||
### Widget Discovery and AI Integration
|
||||
|
||||
The GUI testing framework is designed for AI agent automation. All major UI elements are registered with stable IDs, allowing an agent to "discover" and interact with them programmatically via the `z3ed` CLI.
|
||||
|
||||
Refer to the `z3ed` agent guide for details on using commands like `z3ed gui discover`, `z3ed gui click`, and `z3ed agent test replay`.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,206 +0,0 @@
|
||||
# Build Presets Guide
|
||||
|
||||
This document explains the reorganized CMake preset system for Yaze.
|
||||
|
||||
## Design Principles
|
||||
|
||||
1. **Short, memorable names** - No more `macos-dev-z3ed-ai`, just `mac-ai`
|
||||
2. **Warnings off by default** - Add `-v` suffix for verbose (e.g., `mac-dbg-v`)
|
||||
3. **Clear architecture support** - Explicit ARM64 and x86_64 presets
|
||||
4. **Platform prefixes** - `mac-`, `win-`, `lin-` for easy identification
|
||||
|
||||
## Quick Start
|
||||
|
||||
### macOS Development
|
||||
```bash
|
||||
# Most common: AI-enabled development
|
||||
cmake --preset mac-ai
|
||||
cmake --build --preset mac-ai
|
||||
|
||||
# Basic debug build (no AI)
|
||||
cmake --preset mac-dbg
|
||||
cmake --build --preset mac-dbg
|
||||
|
||||
# Verbose warnings for debugging
|
||||
cmake --preset mac-dbg-v
|
||||
cmake --build --preset mac-dbg-v
|
||||
|
||||
# Release build
|
||||
cmake --preset mac-rel
|
||||
cmake --build --preset mac-rel
|
||||
```
|
||||
|
||||
### Windows Development
|
||||
```bash
|
||||
# Debug build (x64)
|
||||
cmake --preset win-dbg
|
||||
cmake --build --preset win-dbg
|
||||
|
||||
# AI-enabled development
|
||||
cmake --preset win-ai
|
||||
cmake --build --preset win-ai
|
||||
|
||||
# ARM64 support
|
||||
cmake --preset win-arm
|
||||
cmake --build --preset win-arm
|
||||
```
|
||||
|
||||
## All Presets
|
||||
|
||||
### macOS Presets
|
||||
|
||||
| Preset | Description | Arch | Warnings | Features |
|
||||
|--------|-------------|------|----------|----------|
|
||||
| `mac-dbg` | Debug build | ARM64 | Off | Basic |
|
||||
| `mac-dbg-v` | Debug verbose | ARM64 | On | Basic |
|
||||
| `mac-rel` | Release | ARM64 | Off | Basic |
|
||||
| `mac-x64` | Debug x86_64 | x86_64 | Off | Basic |
|
||||
| `mac-uni` | Universal binary | Both | Off | Basic |
|
||||
| `mac-dev` | Development | ARM64 | Off | ROM tests |
|
||||
| `mac-ai` | AI development | ARM64 | Off | z3ed, JSON, gRPC, ROM tests |
|
||||
| `mac-z3ed` | z3ed CLI | ARM64 | Off | AI agent support |
|
||||
| `mac-rooms` | Dungeon editor | ARM64 | Off | Minimal build for room editing |
|
||||
|
||||
### Windows Presets
|
||||
|
||||
| Preset | Description | Arch | Warnings | Features |
|
||||
|--------|-------------|------|----------|----------|
|
||||
| `win-dbg` | Debug build | x64 | Off | Basic |
|
||||
| `win-dbg-v` | Debug verbose | x64 | On | Basic |
|
||||
| `win-rel` | Release | x64 | Off | Basic |
|
||||
| `win-arm` | Debug ARM64 | ARM64 | Off | Basic |
|
||||
| `win-arm-rel` | Release ARM64 | ARM64 | Off | Basic |
|
||||
| `win-dev` | Development | x64 | Off | ROM tests |
|
||||
| `win-ai` | AI development | x64 | Off | z3ed, JSON, gRPC, ROM tests |
|
||||
| `win-z3ed` | z3ed CLI | x64 | Off | AI agent support |
|
||||
|
||||
### Linux Presets
|
||||
|
||||
| Preset | Description | Compiler | Warnings |
|
||||
|--------|-------------|----------|----------|
|
||||
| `lin-dbg` | Debug | GCC | Off |
|
||||
| `lin-clang` | Debug | Clang | Off |
|
||||
|
||||
### Special Purpose
|
||||
|
||||
| Preset | Description |
|
||||
|--------|-------------|
|
||||
| `ci` | Continuous integration (no ROM tests) |
|
||||
| `asan` | AddressSanitizer build |
|
||||
| `coverage` | Code coverage build |
|
||||
|
||||
## Warning Control
|
||||
|
||||
By default, all presets suppress compiler warnings with `-w` for a cleaner build experience.
|
||||
|
||||
### To Enable Verbose Warnings:
|
||||
|
||||
1. Use a preset with `-v` suffix (e.g., `mac-dbg-v`, `win-dbg-v`)
|
||||
2. Or set `YAZE_SUPPRESS_WARNINGS=OFF` manually:
|
||||
```bash
|
||||
cmake --preset mac-dbg -DYAZE_SUPPRESS_WARNINGS=OFF
|
||||
```
|
||||
|
||||
## Architecture Support
|
||||
|
||||
### macOS
|
||||
- **ARM64 (Apple Silicon)**: `mac-dbg`, `mac-rel`, `mac-ai`, etc.
|
||||
- **x86_64 (Intel)**: `mac-x64`
|
||||
- **Universal Binary**: `mac-uni` (both ARM64 + x86_64)
|
||||
|
||||
### Windows
|
||||
- **x64**: `win-dbg`, `win-rel`, `win-ai`, etc.
|
||||
- **ARM64**: `win-arm`, `win-arm-rel`
|
||||
|
||||
## Build Directories
|
||||
|
||||
Most presets use `build/` directory. Exceptions:
|
||||
- `mac-rooms`: Uses `build_rooms/` to avoid conflicts
|
||||
|
||||
## Feature Flags
|
||||
|
||||
Common CMake options you can override:
|
||||
|
||||
```bash
|
||||
# Enable/disable components
|
||||
-DYAZE_BUILD_TESTS=ON/OFF
|
||||
-DYAZE_BUILD_Z3ED=ON/OFF
|
||||
-DYAZE_BUILD_EMU=ON/OFF
|
||||
-DYAZE_BUILD_APP=ON/OFF
|
||||
|
||||
# AI features
|
||||
-DZ3ED_AI=ON/OFF
|
||||
-DYAZE_WITH_JSON=ON/OFF
|
||||
-DYAZE_WITH_GRPC=ON/OFF
|
||||
|
||||
# Testing
|
||||
-DYAZE_ENABLE_ROM_TESTS=ON/OFF
|
||||
-DYAZE_TEST_ROM_PATH=/path/to/zelda3.sfc
|
||||
|
||||
# Build optimization
|
||||
-DYAZE_MINIMAL_BUILD=ON/OFF
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Development with AI features and verbose warnings
|
||||
```bash
|
||||
cmake --preset mac-dbg-v -DZ3ED_AI=ON -DYAZE_WITH_GRPC=ON
|
||||
cmake --build --preset mac-dbg-v
|
||||
```
|
||||
|
||||
### Release build for distribution (macOS Universal)
|
||||
```bash
|
||||
cmake --preset mac-uni
|
||||
cmake --build --preset mac-uni
|
||||
cpack --preset mac-uni
|
||||
```
|
||||
|
||||
### Quick minimal build for testing
|
||||
```bash
|
||||
cmake --preset mac-dbg -DYAZE_MINIMAL_BUILD=ON
|
||||
cmake --build --preset mac-dbg -j12
|
||||
```
|
||||
|
||||
## Updating compile_commands.json
|
||||
|
||||
After configuring with a new preset, copy the compile commands for IDE support:
|
||||
|
||||
```bash
|
||||
cp build/compile_commands.json .
|
||||
```
|
||||
|
||||
This ensures clangd and other LSP servers can find headers and understand build flags.
|
||||
|
||||
## Migration from Old Presets
|
||||
|
||||
Old preset names have been simplified:
|
||||
|
||||
| Old Name | New Name |
|
||||
|----------|----------|
|
||||
| `macos-dev-z3ed-ai` | `mac-ai` |
|
||||
| `macos-debug` | `mac-dbg` |
|
||||
| `macos-release` | `mac-rel` |
|
||||
| `macos-debug-universal` | `mac-uni` |
|
||||
| `macos-dungeon-dev` | `mac-rooms` |
|
||||
| `windows-debug` | `win-dbg` |
|
||||
| `windows-release` | `win-rel` |
|
||||
| `windows-arm64-debug` | `win-arm` |
|
||||
| `linux-debug` | `lin-dbg` |
|
||||
| `linux-clang` | `lin-clang` |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Warnings are still showing
|
||||
- Make sure you're using a preset without `-v` suffix
|
||||
- Check `cmake` output for `✓ Warnings suppressed` message
|
||||
- Reconfigure and rebuild: `rm -rf build && cmake --preset mac-dbg`
|
||||
|
||||
### clangd can't find nlohmann/json
|
||||
- Run `cmake --preset <your-preset>` to regenerate compile_commands.json
|
||||
- Copy to root: `cp build/compile_commands.json .`
|
||||
- Restart your IDE or LSP server
|
||||
|
||||
### Build fails with missing dependencies
|
||||
- Ensure submodules are initialized: `git submodule update --init --recursive`
|
||||
- For AI features, make sure you have OpenSSL: `brew install openssl` (macOS)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,263 +0,0 @@
|
||||
# F2: Dungeon Editor v2 - Complete Guide
|
||||
|
||||
**Last Updated**: October 10, 2025
|
||||
**Related**: [E2-development-guide.md](E2-development-guide.md), [E5-debugging-guide.md](E5-debugging-guide.md)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Dungeon Editor uses a modern card-based architecture (DungeonEditorV2) with self-contained room rendering. This guide covers the architecture, recent refactoring work, and next development steps.
|
||||
|
||||
### Key Features
|
||||
- **Visual room editing** with 512x512 canvas per room
|
||||
- **Object position visualization** - Colored outlines by layer (Red/Green/Blue)
|
||||
- **Per-room settings** - Independent BG1/BG2 visibility and layer types
|
||||
- **Flexible docking** - EditorCard system for custom workspace layouts
|
||||
- **Self-contained rooms** - Each room owns its bitmaps and palettes
|
||||
- **Overworld integration** - Double-click entrances to open dungeon rooms
|
||||
|
||||
---
|
||||
|
||||
### Architecture Improvements
|
||||
1. **Room Buffers Decoupled** - No dependency on Arena graphics sheets
|
||||
2. **ObjectRenderer Removed** - Standardized on ObjectDrawer (~1000 lines deleted)
|
||||
3. **LoadGraphicsSheetsIntoArena Removed** - Using per-room graphics (~66 lines)
|
||||
4. **Old Tab System Removed** - EditorCard is the standard
|
||||
5. **Texture Atlas Infrastructure** - Future-proof stub created
|
||||
6. **Test Suite Cleaned** - Deleted 1270 lines of redundant tests
|
||||
|
||||
### UI Improvements
|
||||
- Room ID in card title: `[003] Room Name`
|
||||
- Properties reorganized into clean 4-column table
|
||||
- Compact layer controls (1 row instead of 3)
|
||||
- Room graphics canvas height fixed (1025px → 257px)
|
||||
- Object count in status bar
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Component Overview
|
||||
|
||||
```
|
||||
DungeonEditorV2 (UI Layer)
|
||||
├─ Card-based UI system
|
||||
├─ Room window management
|
||||
├─ Component coordination
|
||||
└─ Lazy loading
|
||||
|
||||
DungeonEditorSystem (Backend Layer)
|
||||
├─ Sprite/Item/Entrance/Door/Chest management
|
||||
├─ Undo/Redo functionality
|
||||
├─ Room properties management
|
||||
└─ Dungeon-wide operations
|
||||
|
||||
Room (Data Layer)
|
||||
├─ Self-contained buffers (bg1_buffer_, bg2_buffer_)
|
||||
├─ Object storage (tile_objects_)
|
||||
├─ Graphics loading
|
||||
└─ Rendering pipeline
|
||||
```
|
||||
|
||||
### Room Rendering Pipeline
|
||||
|
||||
TODO: Update this to latest code.
|
||||
|
||||
```
|
||||
1. LoadRoomGraphics(blockset)
|
||||
└─> Reads blocks[] from ROM
|
||||
└─> Loads blockset data → current_gfx16_
|
||||
|
||||
2. LoadObjects()
|
||||
└─> Parses object data from ROM
|
||||
└─> Creates tile_objects_[]
|
||||
└─> SETS floor1_graphics_, floor2_graphics_ ← CRITICAL!
|
||||
|
||||
3. RenderRoomGraphics() [SELF-CONTAINED]
|
||||
├─> DrawFloor(floor1_graphics_, floor2_graphics_)
|
||||
├─> DrawBackground(current_gfx16_)
|
||||
├─> SetPalette(full_90_color_dungeon_palette)
|
||||
├─> RenderObjectsToBackground()
|
||||
│ └─> ObjectDrawer::DrawObjectList()
|
||||
└─> QueueTextureCommand(UPDATE/CREATE)
|
||||
|
||||
4. DrawRoomBackgroundLayers(room_id)
|
||||
└─> ProcessTextureQueue() → GPU textures
|
||||
└─> canvas_.DrawBitmap(bg1, bg2)
|
||||
|
||||
5. DrawObjectPositionOutlines(room)
|
||||
└─> Colored rectangles by layer
|
||||
└─> Object ID labels
|
||||
```
|
||||
|
||||
### Room Structure (Bottom to Top)
|
||||
|
||||
Understanding ALTTP dungeon composition is critical:
|
||||
|
||||
```
|
||||
Room Composition:
|
||||
├─ Room Layout (BASE LAYER - immovable)
|
||||
│ ├─ Walls (structural boundaries, 7 configurations of squares in 2x2 grid)
|
||||
│ ├─ Floors (walkable areas, repeated tile pattern set to BG1/BG2)
|
||||
├─ Layer 0 Objects (floor decorations, some walls)
|
||||
├─ Layer 1 Objects (chests, decorations)
|
||||
└─ Layer 2 Objects (stairs, transitions)
|
||||
|
||||
Doors: Positioned at room edges to connect rooms
|
||||
```
|
||||
|
||||
**Key Insight**: Layouts are immovable base structure. Objects are placed ON TOP and can be moved/edited. This allows for large rooms, 4-quadrant rooms, tall/wide rooms, etc.
|
||||
|
||||
---
|
||||
|
||||
## Next Development Steps
|
||||
|
||||
### High Priority (Must Do)
|
||||
|
||||
#### 1. Door Rendering at Room Edges
|
||||
**What**: Render doors with proper patterns at room connections
|
||||
|
||||
**Pattern Reference**: ZScream's door drawing patterns
|
||||
|
||||
**Implementation**:
|
||||
```cpp
|
||||
void DungeonCanvasViewer::DrawDoors(const zelda3::Room& room) {
|
||||
// Doors stored in room data
|
||||
// Position at room edges (North/South/East/West)
|
||||
// Use current_gfx16_ graphics data
|
||||
|
||||
// TODO: Get door data from room.GetDoors() or similar
|
||||
// TODO: Use ObjectDrawer patterns for door graphics
|
||||
// TODO: Draw at interpolation points between rooms
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. Object Name Labels from String Array
|
||||
**File**: `dungeon_canvas_viewer.cc:416` (DrawObjectPositionOutlines)
|
||||
|
||||
**What**: Show real object names instead of just IDs
|
||||
|
||||
**Implementation**:
|
||||
```cpp
|
||||
// Instead of:
|
||||
std::string label = absl::StrFormat("0x%02X", obj.id_);
|
||||
|
||||
// Use:
|
||||
std::string object_name = GetObjectName(obj.id_);
|
||||
std::string label = absl::StrFormat("%s\n0x%02X", object_name.c_str(), obj.id_);
|
||||
|
||||
// Helper function:
|
||||
std::string GetObjectName(int16_t object_id) {
|
||||
// TODO: Reference ZScream's object name arrays
|
||||
// TODO: Map object ID → name string
|
||||
// Example: 0x10 → "Wall (North)"
|
||||
return "Object";
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 4. Fix Plus Button to Select Any Room
|
||||
**File**: `dungeon_editor_v2.cc:228` (DrawToolset)
|
||||
|
||||
**Current Issue**: Opens Room 0x00 (Ganon) always
|
||||
|
||||
**Fix**:
|
||||
```cpp
|
||||
if (toolbar.AddAction(ICON_MD_ADD, "Open Room")) {
|
||||
// Show room selector dialog instead of opening room 0
|
||||
show_room_selector_ = true;
|
||||
// Or: show room picker popup
|
||||
ImGui::OpenPopup("SelectRoomToOpen");
|
||||
}
|
||||
|
||||
// Add popup:
|
||||
if (ImGui::BeginPopup("SelectRoomToOpen")) {
|
||||
static int selected_room = 0;
|
||||
ImGui::InputInt("Room ID", &selected_room);
|
||||
if (ImGui::Button("Open")) {
|
||||
OnRoomSelected(selected_room);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Medium Priority (Should Do)
|
||||
|
||||
#### 6. Fix InputHexByte +/- Button Events
|
||||
**File**: `src/app/gui/input.cc` (likely)
|
||||
|
||||
**Issue**: Buttons don't respond to clicks
|
||||
|
||||
**Investigation Needed**:
|
||||
- Check if button click events are being captured
|
||||
- Verify event logic matches working examples
|
||||
- Keep existing event style if it works elsewhere
|
||||
|
||||
|
||||
### Lower Priority (Nice to Have)
|
||||
|
||||
#### 9. Move Backend Logic to DungeonEditorSystem
|
||||
**What**: Separate UI (V2) from data operations (System)
|
||||
|
||||
**Migration**:
|
||||
- Sprite management → DungeonEditorSystem
|
||||
- Item management → DungeonEditorSystem
|
||||
- Entrance/Door/Chest → DungeonEditorSystem
|
||||
- Undo/Redo → DungeonEditorSystem
|
||||
|
||||
**Result**: DungeonEditorV2 becomes pure UI coordinator
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Build & Run
|
||||
```bash
|
||||
cd /Users/scawful/Code/yaze
|
||||
cmake --preset mac-ai -B build_ai
|
||||
cmake --build build_ai --target yaze -j12
|
||||
|
||||
# Run dungeon editor
|
||||
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon
|
||||
|
||||
# Open specific room
|
||||
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon --cards="Room 0x00"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing & Verification
|
||||
|
||||
### Debug Commands
|
||||
```bash
|
||||
# Verify floor values load correctly
|
||||
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon 2>&1 | grep "floor1="
|
||||
|
||||
# Expected: floor1=4, floor2=8 (NOT 0!)
|
||||
|
||||
# Check object rendering
|
||||
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon 2>&1 | grep "Drawing.*objects"
|
||||
|
||||
# Check object drawing details
|
||||
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon 2>&1 | grep "Writing Tile16"
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- **E2-development-guide.md** - Core architectural patterns
|
||||
- **E5-debugging-guide.md** - Debugging workflows
|
||||
- **F1-dungeon-editor-guide.md** - Original dungeon guide (may be outdated)
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: October 10, 2025
|
||||
**Contributors**: Dungeon Editor Refactoring Session
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
# Canvas System Overview
|
||||
|
||||
## Canvas Architecture
|
||||
- **Canvas States**: track `canvas`, `content`, and `draw` rectangles independently; expose size/scale through `CanvasState` inspection panel
|
||||
- **Layer Stack**: background ➝ bitmaps ➝ entity overlays ➝ selection/tooltip layers
|
||||
- **Interaction Modes**: Tile Paint, Tile Select, Rectangle Select, Entity Manipulation, Palette Editing, Diagnostics
|
||||
- **Context Menu**: persistent menu with material icon sections (Mode, View, Info, Bitmap, Palette, BPP, Performance, Layout, Custom)
|
||||
|
||||
## Core API Patterns
|
||||
- Modern usage: `Begin/End` (auto grid/overlay, persistent context menu)
|
||||
- Legacy helpers still available (`DrawBackground`, `DrawGrid`, `DrawSelectRect`, etc.)
|
||||
- Unified state snapshot: `CanvasState` exposes geometry, zoom, scroll
|
||||
- Interaction handler manages mode-specific tools (tile brush, select rect, entity gizmo)
|
||||
|
||||
## Context Menu Sections
|
||||
- **Mode Selector**: switch modes with icons (Brush, Select, Rect, Bitmap, Palette, BPP, Perf)
|
||||
- **View & Grid**: reset/zoom, toggle grid/labels, advanced/scaling dialogs
|
||||
- **Canvas Info**: real-time canvas/content size, scale, scroll, mouse position
|
||||
- **Bitmap/Palette/BPP**: format conversion, palette analysis, BPP workflows with persistent modals
|
||||
- **Performance**: profiler metrics, dashboard, usage report
|
||||
- **Layout**: draggable toggle, auto resize, grid step
|
||||
- **Custom Actions**: consumer-provided menu items
|
||||
|
||||
## Interaction Modes & Capabilities
|
||||
- **Tile Painting**: tile16 painter, brush size, finish stroke callbacks
|
||||
- Operations: finish_paint, reset_view, zoom, grid, scaling
|
||||
- **Tile Selection**: multi-select rectangle, copy/paste selection
|
||||
- Operations: select_all, clear_selection, reset_view, zoom, grid, scaling
|
||||
- **Rectangle Selection**: drag-select area, clear selection
|
||||
- Operations: clear_selection, reset_view, zoom, grid, scaling
|
||||
- **Bitmap Editing**: format conversion, bitmap manipulation
|
||||
- Operations: bitmap_convert, palette_edit, bpp_analysis, reset_view, zoom, grid, scaling
|
||||
- **Palette Editing**: inline palette editor, ROM palette picker, color analysis
|
||||
- Operations: palette_edit, palette_analysis, reset_palette, reset_view, zoom, grid, scaling
|
||||
- **BPP Conversion**: format analysis, conversion workflows
|
||||
- Operations: bpp_analysis, bpp_conversion, bitmap_convert, reset_view, zoom, grid, scaling
|
||||
- **Performance Mode**: diagnostics, texture queue, performance overlays
|
||||
- Operations: performance, usage_report, copy_metrics, reset_view, zoom, grid, scaling
|
||||
|
||||
## Debug & Diagnostics
|
||||
- Persistent modals (`View→Advanced`, `View→Scaling`, `Palette`, `BPP`) stay open until closed
|
||||
- Texture inspector shows current bitmap, VRAM sheet, palette group, usage stats
|
||||
- State overlay: canvas size, content size, global scale, scroll, highlight entity
|
||||
- Performance HUD: operation counts, timing graphs, usage recommendations
|
||||
|
||||
## Automation API
|
||||
- CanvasAutomationAPI: tile operations (`SetTileAt`, `SelectRect`), view control (`ScrollToTile`, `SetZoom`), entity manipulation hooks
|
||||
- Exposed through CLI (`z3ed`) and gRPC service, matching UI modes
|
||||
|
||||
## Integration Steps for Editors
|
||||
1. Construct `Canvas`, set renderer (optional) and ID
|
||||
2. Call `InitializePaletteEditor` and `SetUsageMode`
|
||||
3. Configure available modes: `SetAvailableModes({kTilePainting, kTileSelecting})`
|
||||
4. Register mode callbacks (tile paint finish, selection clear, etc.)
|
||||
5. During frame: `canvas.Begin(size)` → draw bitmaps/entities → `canvas.End()`
|
||||
6. Provide custom menu items via `AddMenuItem`/`AddMenuItem(item, usage)`
|
||||
7. Use `GetConfig()`/`GetSelection()` for state; respond to context menu commands via callback lambda in `Render`
|
||||
|
||||
## Migration Checklist
|
||||
- Replace direct `DrawContextMenu` logic with new render callback signature
|
||||
- Move palette/BPP helpers into `canvas/` module; update includes
|
||||
- Ensure persistent modals wired (advanced/scaling/palette/bpp/perf)
|
||||
- Update usage tracker integrations to record mode switches
|
||||
- Validate overworld/tile16/dungeon editors in tile paint, select, entity modes
|
||||
|
||||
## Testing Notes
|
||||
- Manual regression: overworld paint/select, tile16 painter, dungeon entity drag
|
||||
- Verify context menu persists and modals remain until closed
|
||||
- Ensure palette/BPP modals populate with correct bitmap/palette data
|
||||
- Automation: run CanvasAutomation API tests/end-to-end scripts for overworld edits
|
||||
@@ -1,401 +0,0 @@
|
||||
# Canvas Coordinate Synchronization and Scroll Fix
|
||||
|
||||
**Date**: October 10, 2025
|
||||
**Issues**:
|
||||
1. Overworld map highlighting regression after canvas refactoring
|
||||
2. Overworld canvas scrolling unexpectedly when selecting tiles
|
||||
3. Vanilla Dark/Special World large map outlines not displaying
|
||||
**Status**: Fixed
|
||||
|
||||
## Problem Summary
|
||||
|
||||
After the canvas refactoring (commits f538775954, 60ddf76331), two critical bugs appeared:
|
||||
|
||||
1. **Map highlighting broken**: The overworld editor stopped properly highlighting the current map when hovering. The map highlighting only worked during active tile painting, not during normal mouse hover.
|
||||
|
||||
2. **Wrong canvas scrolling**: When right-clicking to select tiles (especially on Dark World), the overworld canvas would scroll unexpectedly instead of the tile16 blockset selector.
|
||||
|
||||
## Root Cause
|
||||
|
||||
The regression had **FIVE** issues:
|
||||
|
||||
### Issue 1: Wrong Coordinate System (Line 1041)
|
||||
**File**: `src/app/editor/overworld/overworld_editor.cc:1041`
|
||||
|
||||
**Before (BROKEN)**:
|
||||
```cpp
|
||||
const auto mouse_position = ImGui::GetIO().MousePos; // ❌ Screen coordinates!
|
||||
const auto canvas_zero_point = ow_map_canvas_.zero_point();
|
||||
int map_x = (mouse_position.x - canvas_zero_point.x) / kOverworldMapSize;
|
||||
```
|
||||
|
||||
**After (FIXED)**:
|
||||
```cpp
|
||||
const auto mouse_position = ow_map_canvas_.hover_mouse_pos(); // World coordinates!
|
||||
int map_x = mouse_position.x / kOverworldMapSize;
|
||||
```
|
||||
|
||||
**Why This Was Wrong**:
|
||||
- `ImGui::GetIO().MousePos` returns **screen space** coordinates (absolute position on screen)
|
||||
- The canvas may be scrolled, scaled, or positioned anywhere on screen
|
||||
- Screen coordinates don't account for canvas scrolling/offset
|
||||
- `hover_mouse_pos()` returns **canvas/world space** coordinates (relative to canvas content)
|
||||
|
||||
### Issue 2: Hover Position Not Updated (Line 416)
|
||||
**File**: `src/app/gui/canvas.cc:416`
|
||||
|
||||
**Before (BROKEN)**:
|
||||
```cpp
|
||||
void Canvas::DrawBackground(ImVec2 canvas_size) {
|
||||
// ... setup code ...
|
||||
ImGui::InvisibleButton(canvas_id_.c_str(), scaled_size, kMouseFlags);
|
||||
|
||||
// ❌ mouse_pos_in_canvas_ only updated in DrawTilePainter() during painting!
|
||||
|
||||
if (config_.is_draggable && IsItemHovered()) {
|
||||
// ... pan handling ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`mouse_pos_in_canvas_` was only updated inside painting methods:
|
||||
- `DrawTilePainter()` at line 741
|
||||
- `DrawSolidTilePainter()` at line 860
|
||||
- `DrawTileSelector()` at line 929
|
||||
|
||||
**After (FIXED)**:
|
||||
```cpp
|
||||
void Canvas::DrawBackground(ImVec2 canvas_size) {
|
||||
// ... setup code ...
|
||||
ImGui::InvisibleButton(canvas_id_.c_str(), scaled_size, kMouseFlags);
|
||||
|
||||
// CRITICAL FIX: Always update hover position when hovering
|
||||
if (IsItemHovered()) {
|
||||
const ImGuiIO& io = GetIO();
|
||||
const ImVec2 origin(canvas_p0_.x + scrolling_.x, canvas_p0_.y + scrolling_.y);
|
||||
const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
|
||||
mouse_pos_in_canvas_ = mouse_pos; // Updated every frame during hover
|
||||
}
|
||||
|
||||
if (config_.is_draggable && IsItemHovered()) {
|
||||
// ... pan handling ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Details
|
||||
|
||||
### Coordinate Spaces
|
||||
|
||||
yaze has three coordinate spaces:
|
||||
|
||||
1. **Screen Space**: Absolute pixel coordinates on the monitor
|
||||
- `ImGui::GetIO().MousePos` returns this
|
||||
- Never use this for canvas operations!
|
||||
|
||||
2. **Canvas/World Space**: Coordinates relative to canvas content
|
||||
- Accounts for canvas scrolling and offset
|
||||
- `Canvas::hover_mouse_pos()` returns this
|
||||
- Use this for map calculations, entity positioning, etc.
|
||||
|
||||
3. **Tile/Grid Space**: Coordinates in tile units (not pixels)
|
||||
- `Canvas::CanvasToTile()` converts from canvas to grid space
|
||||
- Used by automation API
|
||||
|
||||
### Usage Patterns
|
||||
|
||||
**For Hover/Highlighting** (CheckForCurrentMap):
|
||||
```cpp
|
||||
auto hover_pos = canvas.hover_mouse_pos(); // Updates continuously
|
||||
int map_x = hover_pos.x / kOverworldMapSize;
|
||||
```
|
||||
|
||||
**For Active Painting** (DrawOverworldEdits):
|
||||
```cpp
|
||||
auto paint_pos = canvas.drawn_tile_position(); // Updates only during drag
|
||||
int map_x = paint_pos.x / kOverworldMapSize;
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Visual Testing
|
||||
|
||||
**Map Highlighting Test**:
|
||||
1. Open overworld editor
|
||||
2. Hover mouse over different maps (without clicking)
|
||||
3. Verify current map highlights correctly
|
||||
4. Test with different scale levels (0.25x - 4.0x)
|
||||
5. Test with scrolled canvas
|
||||
|
||||
**Scroll Regression Test**:
|
||||
1. Open overworld editor
|
||||
2. Switch to Dark World (or any world)
|
||||
3. Right-click on overworld canvas to select a tile
|
||||
4. **Expected**: Tile16 blockset selector scrolls to show the selected tile
|
||||
5. **Expected**: Overworld canvas does NOT scroll
|
||||
6. ❌ **Before fix**: Overworld canvas would scroll unexpectedly
|
||||
|
||||
### Unit Tests
|
||||
Created `test/unit/gui/canvas_coordinate_sync_test.cc` with regression tests:
|
||||
- `HoverMousePos_IndependentFromDrawnPos`: Verifies hover vs paint separation
|
||||
- `CoordinateSpace_WorldNotScreen`: Ensures world coordinates used
|
||||
- `MapCalculation_SmallMaps`: Tests 512x512 map boundaries
|
||||
- `MapCalculation_LargeMaps`: Tests 1024x1024 v3 ASM maps
|
||||
- `OverworldMapHighlight_UsesHoverNotDrawn`: Critical regression test
|
||||
- `OverworldMapIndex_From8x8Grid`: Tests all three worlds (Light/Dark/Special)
|
||||
|
||||
Run tests:
|
||||
```bash
|
||||
./build/bin/yaze_test --unit
|
||||
```
|
||||
|
||||
## Impact Analysis
|
||||
|
||||
### Files Changed
|
||||
1. `src/app/editor/overworld/overworld_editor.cc` (line 1041-1049)
|
||||
- Changed from screen coordinates to canvas hover coordinates
|
||||
- Removed incorrect `canvas_zero_point` subtraction
|
||||
|
||||
2. `src/app/gui/canvas.cc` (line 414-421)
|
||||
- Added continuous hover position tracking in `DrawBackground()`
|
||||
- Now updates `mouse_pos_in_canvas_` every frame when hovering
|
||||
|
||||
3. `src/app/editor/overworld/overworld_editor.cc` (line 2344-2360)
|
||||
- Removed fallback scroll code that scrolled the wrong canvas
|
||||
- Now only uses `blockset_selector_->ScrollToTile()` which targets the correct canvas
|
||||
|
||||
4. `src/app/editor/overworld/overworld_editor.cc` (line 1403-1408)
|
||||
- Changed from `ImGui::IsItemHovered()` (checks last drawn item)
|
||||
- To `ow_map_canvas_.IsMouseHovering()` (checks canvas hover state directly)
|
||||
|
||||
5. `src/app/editor/overworld/overworld_editor.cc` (line 1133-1151)
|
||||
- Added world offset subtraction for vanilla large map parent coordinates
|
||||
- Now properly accounts for Dark World (0x40-0x7F) and Special World (0x80-0x9F)
|
||||
|
||||
### Affected Functionality
|
||||
- **Fixed**: Overworld map highlighting during hover (all worlds, all ROM types)
|
||||
- **Fixed**: Vanilla Dark World large map highlighting (was drawing off-screen)
|
||||
- **Fixed**: Vanilla Special World large map highlighting (was drawing off-screen)
|
||||
- **Fixed**: Overworld canvas no longer scrolls when selecting tiles
|
||||
- **Fixed**: Tile16 selector properly scrolls to show selected tile (via blockset_selector_)
|
||||
- **Fixed**: Entity renderer using `hover_mouse_pos()` (already worked correctly)
|
||||
- **Preserved**: Tile painting using `drawn_tile_position()` (unchanged)
|
||||
- **Preserved**: Multi-area map support (512x512, 1024x1024)
|
||||
- **Preserved**: All three worlds (Light 0x00-0x3F, Dark 0x40-0x7F, Special 0x80+)
|
||||
- **Preserved**: ZSCustomOverworld v3 large maps (already worked correctly)
|
||||
|
||||
### Related Code That Works Correctly
|
||||
These files already use the correct pattern:
|
||||
- `src/app/editor/overworld/overworld_entity_renderer.cc:68-69` - Uses `hover_mouse_pos()` for entity placement
|
||||
- `src/app/editor/overworld/overworld_editor.cc:664` - Uses `drawn_tile_position()` for painting
|
||||
|
||||
## Multi-Area Map Support
|
||||
|
||||
The fix properly handles all area sizes:
|
||||
|
||||
### Standard Maps (512x512)
|
||||
```cpp
|
||||
int map_x = hover_pos.x / 512; // 0-7 range
|
||||
int map_y = hover_pos.y / 512; // 0-7 range
|
||||
int map_index = map_x + map_y * 8; // 0-63 (8x8 grid)
|
||||
```
|
||||
|
||||
### ZSCustomOverworld v3 Large Maps (1024x1024)
|
||||
```cpp
|
||||
int map_x = hover_pos.x / 1024; // Large map X
|
||||
int map_y = hover_pos.y / 1024; // Large map Y
|
||||
// Parent map calculation handled in lines 1073-1190
|
||||
```
|
||||
|
||||
The existing multi-area logic (lines 1068-1190) remains unchanged and works correctly with the fix.
|
||||
|
||||
## Issue 3: Wrong Canvas Being Scrolled (Line 2344-2366)
|
||||
|
||||
**File**: `src/app/editor/overworld/overworld_editor.cc:2344`
|
||||
|
||||
**Problem**: When selecting tiles with right-click on the overworld canvas, `ScrollBlocksetCanvasToCurrentTile()` was calling `ImGui::SetScrollX/Y()` which scrolls **the current ImGui window**, not a specific canvas.
|
||||
|
||||
**Call Stack**:
|
||||
```
|
||||
DrawOverworldCanvas() // Overworld canvas is current window
|
||||
└─ CheckForOverworldEdits() (line 1401)
|
||||
└─ CheckForSelectRectangle() (line 793)
|
||||
└─ ScrollBlocksetCanvasToCurrentTile() (line 916)
|
||||
└─ ImGui::SetScrollX/Y() (lines 2364-2365) // ❌ Scrolls CURRENT window!
|
||||
```
|
||||
|
||||
**Before (BROKEN)**:
|
||||
```cpp
|
||||
void OverworldEditor::ScrollBlocksetCanvasToCurrentTile() {
|
||||
if (blockset_selector_) {
|
||||
blockset_selector_->ScrollToTile(current_tile16_);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: maintain legacy behavior when the selector is unavailable.
|
||||
constexpr int kTilesPerRow = 8;
|
||||
constexpr int kTileDisplaySize = 32;
|
||||
|
||||
int tile_col = current_tile16_ % kTilesPerRow;
|
||||
int tile_row = current_tile16_ / kTilesPerRow;
|
||||
float tile_x = static_cast<float>(tile_col * kTileDisplaySize);
|
||||
float tile_y = static_cast<float>(tile_row * kTileDisplaySize);
|
||||
|
||||
const ImVec2 window_size = ImGui::GetWindowSize();
|
||||
float scroll_x = tile_x - (window_size.x / 2.0F) + (kTileDisplaySize / 2.0F);
|
||||
float scroll_y = tile_y - (window_size.y / 2.0F) + (kTileDisplaySize / 2.0F);
|
||||
|
||||
// ❌ BUG: This scrolls whatever ImGui window is currently active!
|
||||
// When called from overworld canvas, it scrolls the overworld instead of tile16 selector!
|
||||
ImGui::SetScrollX(std::max(0.0f, scroll_x));
|
||||
ImGui::SetScrollY(std::max(0.0f, scroll_y));
|
||||
}
|
||||
```
|
||||
|
||||
**After (FIXED)**:
|
||||
```cpp
|
||||
void OverworldEditor::ScrollBlocksetCanvasToCurrentTile() {
|
||||
if (blockset_selector_) {
|
||||
blockset_selector_->ScrollToTile(current_tile16_); // Correct: Targets specific canvas
|
||||
return;
|
||||
}
|
||||
|
||||
// CRITICAL FIX: Do NOT use fallback scrolling from overworld canvas context!
|
||||
// The fallback code uses ImGui::SetScrollX/Y which scrolls the CURRENT window,
|
||||
// and when called from CheckForSelectRectangle() during overworld canvas rendering,
|
||||
// it incorrectly scrolls the overworld canvas instead of the tile16 selector.
|
||||
//
|
||||
// The blockset_selector_ should always be available in modern code paths.
|
||||
// If it's not available, we skip scrolling rather than scroll the wrong window.
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Fixes It**:
|
||||
- The modern `blockset_selector_->ScrollToTile()` targets the specific tile16 selector canvas
|
||||
- The fallback `ImGui::SetScrollX/Y()` has no context - it just scrolls the active window
|
||||
- By removing the fallback, we prevent scrolling the wrong canvas
|
||||
- If `blockset_selector_` is null (shouldn't happen in modern builds), we safely do nothing instead of breaking user interaction
|
||||
|
||||
## Issue 4: Wrong Hover Check (Line 1403)
|
||||
|
||||
**File**: `src/app/editor/overworld/overworld_editor.cc:1403`
|
||||
|
||||
**Problem**: The code was using `ImGui::IsItemHovered()` to check if the mouse was over the canvas, but this checks the **last drawn ImGui item**, which could be entities, overlays, or anything drawn after the canvas's InvisibleButton. This meant hover detection was completely broken.
|
||||
|
||||
**Call Stack**:
|
||||
```
|
||||
DrawOverworldCanvas()
|
||||
└─ DrawBackground() at line 1350 // Creates InvisibleButton (item A)
|
||||
└─ DrawExits/Entrances/Items/Sprites() // Draws entities (items B, C, D...)
|
||||
└─ DrawOverlayPreviewOnMap() // Draws overlay (item E)
|
||||
└─ IsItemHovered() at line 1403 // ❌ Checks item E, not item A!
|
||||
```
|
||||
|
||||
**Before (BROKEN)**:
|
||||
```cpp
|
||||
if (current_mode == EditingMode::DRAW_TILE) {
|
||||
CheckForOverworldEdits();
|
||||
}
|
||||
if (IsItemHovered()) // ❌ Checks LAST item (overlay/entity), not canvas!
|
||||
status_ = CheckForCurrentMap();
|
||||
```
|
||||
|
||||
**After (FIXED)**:
|
||||
```cpp
|
||||
if (current_mode == EditingMode::DRAW_TILE) {
|
||||
CheckForOverworldEdits();
|
||||
}
|
||||
// CRITICAL FIX: Use canvas hover state, not ImGui::IsItemHovered()
|
||||
// IsItemHovered() checks the LAST drawn item, which could be entities/overlay,
|
||||
// not the canvas InvisibleButton. ow_map_canvas_.IsMouseHovering() correctly
|
||||
// tracks whether mouse is over the canvas area.
|
||||
if (ow_map_canvas_.IsMouseHovering()) // Checks canvas hover state directly
|
||||
status_ = CheckForCurrentMap();
|
||||
```
|
||||
|
||||
**Why This Fixes It**:
|
||||
- `IsItemHovered()` is context-sensitive - it checks whatever the last `ImGui::*()` call was
|
||||
- After drawing entities and overlays, the "last item" is NOT the canvas
|
||||
- `Canvas::IsMouseHovering()` tracks the hover state from the InvisibleButton in `DrawBackground()`
|
||||
- This state is set correctly when the InvisibleButton is hovered (line 416 in canvas.cc)
|
||||
|
||||
## Issue 5: Vanilla Large Map World Offset (Line 1132-1136)
|
||||
|
||||
**File**: `src/app/editor/overworld/overworld_editor.cc:1132-1136`
|
||||
|
||||
**Problem**: For vanilla ROMs, the large map highlighting logic wasn't accounting for world offsets when calculating parent map coordinates. Dark World maps (0x40-0x7F) and Special World maps (0x80-0x9F) use map IDs with offsets, but the display grid coordinates are 0-7.
|
||||
|
||||
**Before (BROKEN)**:
|
||||
```cpp
|
||||
if (overworld_.overworld_map(current_map_)->is_large_map() ||
|
||||
overworld_.overworld_map(current_map_)->large_index() != 0) {
|
||||
const int highlight_parent =
|
||||
overworld_.overworld_map(current_highlighted_map)->parent();
|
||||
const int parent_map_x = highlight_parent % 8; // ❌ Wrong for Dark/Special!
|
||||
const int parent_map_y = highlight_parent / 8;
|
||||
ow_map_canvas_.DrawOutline(parent_map_x * kOverworldMapSize,
|
||||
parent_map_y * kOverworldMapSize,
|
||||
large_map_size, large_map_size);
|
||||
}
|
||||
```
|
||||
|
||||
**Example Bug**:
|
||||
- Dark World map 0x42 (parent) → `0x42 % 8 = 2`, `0x42 / 8 = 8`
|
||||
- This draws the outline at grid position (2, 8) which is **off the screen**!
|
||||
- Correct position should be (2, 0) in the Dark World display grid
|
||||
|
||||
**After (FIXED)**:
|
||||
```cpp
|
||||
if (overworld_.overworld_map(current_map_)->is_large_map() ||
|
||||
overworld_.overworld_map(current_map_)->large_index() != 0) {
|
||||
const int highlight_parent =
|
||||
overworld_.overworld_map(current_highlighted_map)->parent();
|
||||
|
||||
// CRITICAL FIX: Account for world offset when calculating parent coordinates
|
||||
int parent_map_x;
|
||||
int parent_map_y;
|
||||
if (current_world_ == 0) {
|
||||
// Light World (0x00-0x3F)
|
||||
parent_map_x = highlight_parent % 8;
|
||||
parent_map_y = highlight_parent / 8;
|
||||
} else if (current_world_ == 1) {
|
||||
// Dark World (0x40-0x7F) - subtract 0x40 to get display coordinates
|
||||
parent_map_x = (highlight_parent - 0x40) % 8;
|
||||
parent_map_y = (highlight_parent - 0x40) / 8;
|
||||
} else {
|
||||
// Special World (0x80-0x9F) - subtract 0x80 to get display coordinates
|
||||
parent_map_x = (highlight_parent - 0x80) % 8;
|
||||
parent_map_y = (highlight_parent - 0x80) / 8;
|
||||
}
|
||||
|
||||
ow_map_canvas_.DrawOutline(parent_map_x * kOverworldMapSize,
|
||||
parent_map_y * kOverworldMapSize,
|
||||
large_map_size, large_map_size);
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Fixes It**:
|
||||
- Map IDs are **absolute**: Light World 0x00-0x3F, Dark World 0x40-0x7F, Special 0x80-0x9F
|
||||
- Display coordinates are **relative**: Each world displays in an 8x8 grid (0-7, 0-7)
|
||||
- Without subtracting the world offset, coordinates overflow the display grid
|
||||
- This matches the same logic used for v3 large maps (lines 1084-1096) and small maps (lines 1141-1172)
|
||||
|
||||
## Commit Reference
|
||||
|
||||
**Canvas Refactoring Commits**:
|
||||
- `f538775954` - Organize Canvas Utilities and BPP Format Management
|
||||
- `60ddf76331` - Integrate Canvas Automation API and Simplify Overworld Editor Controls
|
||||
|
||||
These commits moved canvas utilities to modular components but introduced the regression by not maintaining hover position tracking.
|
||||
|
||||
## Future Improvements
|
||||
|
||||
1. **Canvas Mode System**: Complete the interaction handler modes (tile paint, select, etc.)
|
||||
2. **Persistent Context Menus**: Implement mode switching through context menu popups
|
||||
3. **Debugging Visualization**: Add canvas coordinate overlay for debugging
|
||||
4. **E2E Tests**: Create end-to-end tests for overworld map highlighting workflow
|
||||
|
||||
## Related Documentation
|
||||
- `docs/G1-canvas-guide.md` - Canvas system architecture
|
||||
- `docs/E5-debugging-guide.md` - Debugging techniques
|
||||
- `docs/debugging-startup-flags.md` - CLI flags for editor testing
|
||||
@@ -1,104 +0,0 @@
|
||||
# Roadmap
|
||||
|
||||
**Last Updated: October 4, 2025**
|
||||
|
||||
This roadmap tracks upcoming releases and major ongoing initiatives.
|
||||
|
||||
## Current Focus
|
||||
|
||||
- Finish overworld editor parity (sprite workflows, performance tuning).
|
||||
- Resolve dungeon object rendering and tile painting gaps.
|
||||
- Close out Tile16 palette inconsistencies.
|
||||
- Harden the `z3ed` automation paths before expanding functionality.
|
||||
|
||||
## 0.4.0 (Next Major Release) - SDL3 Modernization & Core Improvements
|
||||
|
||||
**Status:** Planning
|
||||
**Type:** Major Breaking Release
|
||||
**Timeline:** 6-8 weeks
|
||||
|
||||
### Primary Goals
|
||||
|
||||
1. SDL3 migration across graphics, audio, and input
|
||||
2. Dependency reorganization (`src/lib/` + `third_party/` → `external/`)
|
||||
3. Backend abstraction layer for renderer/audio/input
|
||||
4. Editor polish and UX clean-up
|
||||
|
||||
### Phase 1: Infrastructure (Week 1-2)
|
||||
- Merge `src/lib/` and `third_party/` into `external/`
|
||||
- Update CMake, submodules, and CI presets
|
||||
- Validate builds on Windows, macOS, Linux
|
||||
|
||||
### Phase 2: SDL3 Core Migration (Week 3-4)
|
||||
- Switch to SDL3 with GPU-based rendering
|
||||
- Introduce `GraphicsBackend` abstraction
|
||||
- Restore window creation and baseline editor rendering
|
||||
- Update the ImGui SDL3 backend
|
||||
|
||||
### Phase 3: Complete SDL3 Integration (Week 5-6)
|
||||
- Port editors (Overworld, Dungeon, Graphics, Palette, Screen, Music) to the new backend
|
||||
- Implement SDL3 audio backend for the emulator
|
||||
- Implement SDL3 input backend with improved gamepad support
|
||||
- Benchmark and tune rendering performance
|
||||
|
||||
### Phase 4: Editor Features & UX (Week 7-8)
|
||||
- Resolve Tile16 palette inconsistencies
|
||||
- Complete overworld sprite add/remove/move workflow
|
||||
- Improve dungeon editor labels and tab management
|
||||
- Add lazy loading for rooms to cut load times
|
||||
|
||||
### Phase 5: AI Agent Enhancements (Throughout)
|
||||
- Vim-style editing in `simple-chat` (complete)
|
||||
- Autocomplete engine with fuzzy matching (complete)
|
||||
- Harden live LLM integration (Gemini function-calling, prompts)
|
||||
- Attach AI workflows to GUI regression harness
|
||||
- Extend tool coverage for dialogue, music, sprite data
|
||||
|
||||
### Success Criteria
|
||||
- SDL3 builds pass on Windows, macOS, Linux
|
||||
- No performance regression versus v0.3.x
|
||||
- Editors function on the new backend
|
||||
- Emulator audio/input verified
|
||||
- Documentation and migration guide updated
|
||||
|
||||
**Breaking Changes:**
|
||||
- SDL2 → SDL3 (requires recompilation)
|
||||
- Directory restructure (requires submodule re-init)
|
||||
- API changes in graphics backend (for extensions)
|
||||
|
||||
---
|
||||
|
||||
## 0.5.X - Feature Expansion
|
||||
|
||||
- **Plugin Architecture**: Design and implement the initial framework for community-developed extensions and custom tools.
|
||||
- **Advanced Graphics Editing**: Implement functionality to edit and re-import full graphics sheets.
|
||||
- **`z3ed` AI Agent Enhancements**:
|
||||
- **Collaborative Sessions**: Enhance the network collaboration mode with shared AI proposals and ROM synchronization.
|
||||
- **Multi-modal Input**: Integrate screenshot capabilities to send visual context to Gemini for more accurate, context-aware commands.
|
||||
|
||||
---
|
||||
|
||||
## 0.6.X - Content & Integration
|
||||
|
||||
- **Advanced Content Editors**:
|
||||
- Implement a user interface for the music editing system.
|
||||
- Enhance the Hex Editor with better search and data interpretation features.
|
||||
- **Documentation Overhaul**:
|
||||
- Implement a system to auto-generate C++ API documentation from Doxygen comments.
|
||||
- Write a comprehensive user guide for ROM hackers, covering all major editor workflows.
|
||||
|
||||
---
|
||||
|
||||
## Recently Completed (v0.3.3 - October 6, 2025)
|
||||
|
||||
- Vim mode for `simple-chat`: modal editing, navigation, history, autocomplete
|
||||
- Autocomplete engine with fuzzy matching and FTXUI dropdown
|
||||
- TUI enhancements: integrated autocomplete UI components and CMake wiring
|
||||
|
||||
## Recently Completed (v0.3.2)
|
||||
|
||||
- Dungeon editor: migrated to `TestRomManager`, resolved crash backlog
|
||||
- Windows build: fixed stack overflows and file dialog regressions
|
||||
- `z3ed learn`: added persistent storage for AI preferences and ROM metadata
|
||||
- Gemini integration: switched to native function calling API
|
||||
- Tile16 editor: refactored layout, added dynamic zoom controls
|
||||
109
docs/index.md
109
docs/index.md
@@ -1,104 +1,9 @@
|
||||
# yaze Documentation
|
||||
# Documentation Relocated
|
||||
|
||||
Welcome to the official documentation for yaze, a comprehensive ROM editor for The Legend of Zelda: A Link to the Past.
|
||||
The published documentation now lives under [`docs/public`](public/index.md) so that Doxygen can
|
||||
focus on the curated guides and references. All planning notes, AI/agent workflows, and research
|
||||
documents have been moved to the repository-level [`docs/internal/`](../docs/internal/README.md).
|
||||
|
||||
## A: Getting Started & Testing
|
||||
- [A1: Getting Started](A1-getting-started.md) - Basic setup and usage
|
||||
- [A1: Testing Guide](A1-testing-guide.md) - Testing framework and best practices
|
||||
- [A2: Test Dashboard Refactoring](A2-test-dashboard-refactoring.md) - In-app test dashboard architecture
|
||||
|
||||
## B: Build & Platform
|
||||
- [B1: Build Instructions](B1-build-instructions.md) - How to build yaze on Windows, macOS, and Linux
|
||||
- [B2: Platform Compatibility](B2-platform-compatibility.md) - Cross-platform support details
|
||||
- [B3: Build Presets](B3-build-presets.md) - CMake preset system guide
|
||||
- [B4: Git Workflow](B4-git-workflow.md) - Branching strategy, commit conventions, and release process
|
||||
- [B5: Architecture and Networking](B5-architecture-and-networking.md) - System architecture, gRPC, and networking
|
||||
- [B6: Zelda3 Library Refactoring](B6-zelda3-library-refactoring.md) - Core library modularization plan
|
||||
|
||||
## C: `z3ed` CLI
|
||||
- [C1: `z3ed` Agent Guide](C1-z3ed-agent-guide.md) - AI-powered command-line interface
|
||||
- [C2: Testing Without ROMs](C2-testing-without-roms.md) - Mock ROM mode for testing and CI/CD
|
||||
- [C3: Agent Architecture](C3-agent-architecture.md) - AI agent system architecture
|
||||
- [C4: z3ed Refactoring](C4-z3ed-refactoring.md) - CLI tool refactoring summary
|
||||
- [C5: z3ed Command Abstraction](C5-z3ed-command-abstraction.md) - Command system design
|
||||
|
||||
## E: Development & API
|
||||
- [E1: Assembly Style Guide](E1-asm-style-guide.md) - 65816 assembly coding standards
|
||||
- [E2: Development Guide](E2-development-guide.md) - Core architectural patterns, UI systems, and best practices
|
||||
- [E3: API Reference](E3-api-reference.md) - C/C++ API documentation for extensions
|
||||
- [E4: Emulator Development Guide](E4-Emulator-Development-Guide.md) - SNES emulator subsystem implementation guide
|
||||
- [E5: Debugging Guide](E5-debugging-guide.md) - Debugging techniques and workflows
|
||||
- [E6: Emulator Improvements](E6-emulator-improvements.md) - Core accuracy and performance improvements roadmap
|
||||
- [E7: Debugging Startup Flags](E7-debugging-startup-flags.md) - CLI flags for quick editor access and testing
|
||||
- [E8: Emulator Debugging Vision](E8-emulator-debugging-vision.md) - Long-term vision for Mesen2-level debugging features
|
||||
- [E9: AI Agent Debugging Guide](E9-ai-agent-debugging-guide.md) - Debugging AI agent integration
|
||||
- [E10: APU Timing Analysis](E10-apu-timing-analysis.md) - APU timing fix technical analysis
|
||||
|
||||
## F: Technical Documentation
|
||||
- [F1: Dungeon Editor Guide](F1-dungeon-editor-guide.md) - Master guide to the dungeon editing system
|
||||
- [F2: Tile16 Editor Palette System](F2-tile16-editor-palette-system.md) - Design of the palette system
|
||||
- [F3: Overworld Loading](F3-overworld-loading.md) - How vanilla and ZSCustomOverworld maps are loaded
|
||||
- [F4: Overworld Agent Guide](F4-overworld-agent-guide.md) - AI agent integration for overworld editing
|
||||
|
||||
## G: Graphics & GUI Systems
|
||||
- [G1: Canvas System and Automation](G1-canvas-guide.md) - Core GUI drawing and interaction system
|
||||
- [G2: Renderer Migration Plan](G2-renderer-migration-plan.md) - Historical plan for renderer refactoring
|
||||
- [G3: Palette System Overview](G3-palete-system-overview.md) - SNES palette system and editor integration
|
||||
- [G3: Renderer Migration Complete](G3-renderer-migration-complete.md) - Post-migration analysis and results
|
||||
- [G4: Canvas Coordinate Fix](G4-canvas-coordinate-fix.md) - Canvas coordinate synchronization bug fix
|
||||
- [G5: GUI Consistency Guide](G5-gui-consistency-guide.md) - Card-based architecture and UI standards
|
||||
|
||||
## H: Project Info
|
||||
- [H1: Changelog](H1-changelog.md)
|
||||
|
||||
## I: Roadmap & Vision
|
||||
- [I1: Roadmap](I1-roadmap.md) - Current development roadmap and planned releases
|
||||
- [I2: Future Improvements](I2-future-improvements.md) - Long-term vision and aspirational features
|
||||
|
||||
## R: ROM Reference
|
||||
- [R1: A Link to the Past ROM Reference](R1-alttp-rom-reference.md) - ALTTP ROM structures, graphics, palettes, and compression
|
||||
|
||||
---
|
||||
|
||||
## Documentation Standards
|
||||
|
||||
### Naming Convention
|
||||
- **A-series**: Getting Started & Testing
|
||||
- **B-series**: Build, Platform & Git Workflow
|
||||
- **C-series**: CLI Tools (`z3ed`)
|
||||
- **E-series**: Development, API & Emulator
|
||||
- **F-series**: Feature-Specific Technical Docs
|
||||
- **G-series**: Graphics & GUI Systems
|
||||
- **H-series**: Project Info (Changelog, etc.)
|
||||
- **I-series**: Roadmap & Vision
|
||||
- **R-series**: ROM Technical Reference
|
||||
|
||||
### File Naming
|
||||
- Use descriptive, kebab-case names
|
||||
- Prefix with series letter and number (e.g., `E4-emulator-development-guide.md`)
|
||||
- Keep filenames concise but clear
|
||||
|
||||
### Organization Tips
|
||||
For Doxygen integration, this index can be enhanced with:
|
||||
- `@mainpage` directive to make this the main documentation page
|
||||
- `@defgroup` to create logical groupings across files
|
||||
- `@tableofcontents` for automatic TOC generation
|
||||
- See individual files for `@page` and `@section` usage
|
||||
|
||||
### Doxygen Integration Tips
|
||||
- Add a short `@mainpage` block to `docs/index.md` so generated HTML mirrors the
|
||||
manual structure.
|
||||
- Define high-level groups with `@defgroup` (`getting_started`, `building`,
|
||||
`graphics_gui`, etc.) and attach individual docs using `@page ... @ingroup`.
|
||||
- Use `@subpage`, `@section`, and `@subsection` when a document benefits from
|
||||
nested navigation.
|
||||
- Configure `Doxyfile` with `USE_MDFILE_AS_MAINPAGE = docs/index.md`,
|
||||
`FILE_PATTERNS = *.md *.h *.cc`, and `EXTENSION_MAPPING = md=C++` to combine
|
||||
Markdown and source comments.
|
||||
- Keep Markdown reader-friendly—wrap Doxygen directives in comment fences (`/**`
|
||||
… `*/`) so they are ignored by GitHub while remaining visible to the
|
||||
generator.
|
||||
|
||||
---
|
||||
|
||||
*Last updated: October 13, 2025 - Version 0.3.2*
|
||||
Update your bookmarks:
|
||||
- Public site entry point: [`docs/public/index.md`](public/index.md)
|
||||
- Internal docs: [`docs/internal/README.md`](../docs/internal/README.md)
|
||||
|
||||
42
docs/internal/README.md
Normal file
42
docs/internal/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# YAZE Internal Documentation
|
||||
|
||||
**Last Updated**: December 8, 2025
|
||||
|
||||
Internal documentation for planning, AI agents, research, and historical build notes. These files are intentionally excluded from the public Doxygen site so they can remain verbose and speculative.
|
||||
|
||||
## Quick Links
|
||||
|
||||
- **Active Work**: [Coordination Board](agents/coordination-board.md)
|
||||
- **Roadmap**: [roadmap.md](roadmap.md)
|
||||
- **Doc Hygiene Rules**: [agents/doc-hygiene.md](agents/doc-hygiene.md)
|
||||
- **Templates**: [templates/](templates/)
|
||||
|
||||
## Directory Structure
|
||||
|
||||
| Directory | Purpose |
|
||||
|-----------|---------|
|
||||
| `agents/` | AI agent coordination, personas, and board |
|
||||
| `architecture/` | System design and architectural documentation |
|
||||
| `archive/` | Retired plans, completed features, closed investigations, and maintenance logs |
|
||||
| `debug/` | Debugging guides, active logs, and accuracy reports |
|
||||
| `hand-off/` | Active handoff documents for in-progress work |
|
||||
| `plans/` | Active implementation plans and roadmaps |
|
||||
| `research/` | Exploratory notes, ideas, and technical analysis |
|
||||
| `templates/` | Document templates (checklists, initiatives) |
|
||||
| `testing/` | Test infrastructure configuration and strategy |
|
||||
| `wasm/` | WASM/Web port documentation and guides |
|
||||
| `zelda3/` | Game-specific documentation (ALTTP internals) |
|
||||
| `roadmap.md` | Master project roadmap |
|
||||
|
||||
## Doc Hygiene
|
||||
|
||||
- **Single Source of Truth**: Maintain one canonical spec per initiative.
|
||||
- **Templates**: Use `templates/` for new initiatives and release checklists.
|
||||
- **Archiving**: Move completed specs to `archive/completed_features/` or `archive/investigations/`.
|
||||
- **Coordination**: Use the [Coordination Board](agents/coordination-board.md) for active tasks.
|
||||
|
||||
## Version Control & Safety
|
||||
|
||||
- **Coordinate before forceful changes**: Never rewrite history on shared branches.
|
||||
- **Back up ROMs and assets**: Work on copies, enable automatic backup.
|
||||
- **Run `scripts/verify-build-environment.*`** after pulling significant build changes.
|
||||
75
docs/internal/agents/README.md
Normal file
75
docs/internal/agents/README.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Agent Coordination Hub
|
||||
|
||||
Welcome to the `yaze` internal agent workspace. This directory contains the rules, roles, and records for AI agents contributing to the project.
|
||||
|
||||
## Quick Start
|
||||
1. **Identify Your Role**: Check [personas.md](./personas.md) to choose the correct Agent ID.
|
||||
2. **Load Your Prompt**: Open `.claude/agents/<agent-id>.md` for your persona’s system prompt (available to all agents).
|
||||
3. **Follow the Protocol**: Read [AGENTS.md](../../../AGENTS.md) for rules on communication, task logging, and handoffs.
|
||||
4. **Check Status**: Review the [coordination-board.md](./coordination-board.md) for active tasks and blockers.
|
||||
5. **Keep docs lean**: Use [doc-hygiene.md](./doc-hygiene.md) and avoid creating duplicate specs; archive idle docs.
|
||||
|
||||
## Documentation Index
|
||||
|
||||
### Core Coordination (Keep Visible)
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| [AGENTS.md](../../../AGENTS.md) | **The Core Protocol.** Read this first. Defines how to work. |
|
||||
| [personas.md](./personas.md) | **Who is Who.** Canonical list of Agent IDs and their scopes. |
|
||||
| [.claude/agents/*](../../../.claude/agents) | **System Prompts.** Persona-specific prompts for all agents. |
|
||||
| [coordination-board.md](./coordination-board.md) | **The Live Board.** Shared state, active tasks, and requests. |
|
||||
| [collaboration-framework.md](./collaboration-framework.md) | **Team Organization.** Architecture vs Automation team structure and protocols. |
|
||||
|
||||
### Active Projects
|
||||
| File | Purpose | Status |
|
||||
|------|---------|--------|
|
||||
| [initiative-v040.md](./initiative-v040.md) | v0.4.0 development plan with 5 parallel workstreams | ACTIVE |
|
||||
| [handoff-sidebar-menubar-sessions.md](./handoff-sidebar-menubar-sessions.md) | UI systems architecture reference | Active Reference |
|
||||
| [wasm-development-guide.md](./wasm-development-guide.md) | WASM build and development guide | UPDATED |
|
||||
| [wasm-antigravity-playbook.md](./wasm-antigravity-playbook.md) | WASM with Gemini integration and debugging | UPDATED |
|
||||
| [web-port-handoff.md](./web-port-handoff.md) | WASM web build status and blockers | IN_PROGRESS |
|
||||
|
||||
### Documentation Hygiene
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| [doc-hygiene.md](./doc-hygiene.md) | Rules to keep specs/notes lean and archived on time. |
|
||||
|
||||
## Tools
|
||||
Agents have built-in CLI capabilities to assist with this workflow:
|
||||
* `z3ed agent todo`: Manage your personal task list.
|
||||
* `z3ed agent handoff`: Generate context bundles for the next agent.
|
||||
* `z3ed agent chat`: (If enabled) Inter-agent communication channel.
|
||||
|
||||
## Picking the right agent
|
||||
- **ai-infra-architect**: AI/agent infra, MCP/gRPC, z3ed tooling, model plumbing.
|
||||
- **backend-infra-engineer**: Build/packaging/toolchains, CI reliability, release plumbing.
|
||||
- **imgui-frontend-engineer**: ImGui/editor UI, renderer/backends, canvas/docking UX.
|
||||
- **snes-emulator-expert**: Emulator core (CPU/APU/PPU), performance/accuracy/debugging.
|
||||
- **zelda3-hacking-expert**: Gameplay/ROM logic, data formats, hacking workflows.
|
||||
- **test-infrastructure-expert**: Test harnesses, CTest/gMock infra, flake/bloat triage.
|
||||
- **docs-janitor**: Docs/process hygiene, onboarding, checklists.
|
||||
Pick the persona that owns the dominant surface of your task; cross-surface work should add both owners to the board entry.
|
||||
|
||||
## Build & Test
|
||||
Default builds now share `build/` (native) and `build-wasm/` (WASM). If you need isolation, set `YAZE_BUILD_DIR` or create a local `CMakeUserPresets.json`.
|
||||
* **Build**: `./scripts/agent_build.sh [target]` (Default target: `yaze`)
|
||||
* **Test**: `./scripts/agent_build.sh yaze_test && ./build/bin/yaze_test`
|
||||
* **Directory**: `build/` by default (override via `YAZE_BUILD_DIR`).
|
||||
|
||||
## Archive
|
||||
|
||||
This directory maintains a **lean, active documentation set**. Historical or reference-only documents are organized in `archive/`:
|
||||
|
||||
### Archived Categories
|
||||
- **large-ref-docs/** (148KB) - Large reference documents (40KB+): dungeon rendering, ZSOW, design specs
|
||||
- **foundation-docs-old/** (68KB) - Older foundational docs (October) on agent architecture and CLI design
|
||||
- **utility-tools/** (52KB) - Tool documentation: filesystem, dev-assist, modularity, AI dev tools
|
||||
- **wasm-planning-2025/** (64KB) - Earlier WASM planning iterations
|
||||
- **testing-docs-2025/** (112KB) - Test infrastructure and CI documentation archives
|
||||
- **gemini-session-2025-11-23/** (40KB) - Gemini-specific session context and task planning
|
||||
- **plans-2025-11/** (56KB) - Completed or archived feature/project plans
|
||||
- **legacy-2025-11/** (28KB) - Completed initiatives and coordination improvements
|
||||
- **session-handoffs/** (24KB) - Agent handoff and onboarding documents
|
||||
- **reports/** (24KB) - Audit reports and documentation assessments
|
||||
|
||||
**Target: 10-15 active files in root directory. Archive completed work within 1-2 weeks of completion.**
|
||||
182
docs/internal/agents/archive/docs-cleanup-2025-11-27.md
Normal file
182
docs/internal/agents/archive/docs-cleanup-2025-11-27.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# Documentation Cleanup - November 27, 2025
|
||||
|
||||
## Summary
|
||||
|
||||
Comprehensive review and update of YAZE documentation, focusing on public-facing docs, web app support, and organizational cleanup.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. Web App Documentation
|
||||
|
||||
**Created: `docs/public/usage/web-app.md`**
|
||||
- Comprehensive guide for the WASM web application
|
||||
- Clearly marked as **Preview** status (not production-ready)
|
||||
- Detailed feature status table showing incomplete editors
|
||||
- Browser requirements and compatibility
|
||||
- Performance tips and troubleshooting
|
||||
- Comparison table: Web vs Desktop
|
||||
- Developer tools and API references
|
||||
- Deployment instructions
|
||||
- Privacy and storage information
|
||||
|
||||
**Key Points:**
|
||||
- ⚠️ Emphasized preview/experimental status throughout
|
||||
- Listed editor completeness accurately (Preview/Incomplete vs Working)
|
||||
- Recommended desktop build for serious ROM hacking
|
||||
- Linked to internal technical docs for developers
|
||||
|
||||
### 2. Main README Updates
|
||||
|
||||
**Updated: `README.md`**
|
||||
- Added web preview mention in highlights section
|
||||
- Added "Web App (Preview)" to Applications & Workflows
|
||||
- Clearly linked to web-app.md guide
|
||||
- Maintained focus on desktop as primary platform
|
||||
|
||||
### 3. Public Docs Index
|
||||
|
||||
**Updated: `docs/public/index.md`**
|
||||
- Added Web App (Preview) to Usage Guides section
|
||||
- Placed at top for visibility
|
||||
|
||||
### 4. Directory Organization
|
||||
|
||||
**Moved technical implementation docs to internal:**
|
||||
- `docs/web/drag-drop-rom-loading.md` → `docs/internal/web-drag-drop-implementation.md`
|
||||
- `docs/wasm/patch_export.md` → `docs/internal/wasm-patch-export-implementation.md`
|
||||
- Removed empty `docs/web/` and `docs/wasm/` directories
|
||||
|
||||
**Organized format documentation:**
|
||||
Moved to `docs/public/reference/` for better discoverability:
|
||||
- `SAVE_STATE_FORMAT.md`
|
||||
- `SNES_COMPRESSION.md`
|
||||
- `SNES_GRAPHICS.md`
|
||||
- `SYMBOL_FORMAT.md`
|
||||
- `ZSM_FORMAT.md`
|
||||
|
||||
**Updated: `docs/public/reference/rom-reference.md`**
|
||||
- Added "Additional Format Documentation" section
|
||||
- Linked to all format specification docs
|
||||
- Updated last modified date to November 27, 2025
|
||||
|
||||
### 5. Documentation Accuracy
|
||||
|
||||
**Updated: `docs/public/build/platform-compatibility.md`**
|
||||
- Updated "Last Updated" from October 9, 2025 to November 27, 2025
|
||||
|
||||
**Reviewed for accuracy:**
|
||||
- ✅ `docs/public/build/quick-reference.md` - Accurate
|
||||
- ✅ `docs/public/build/build-from-source.md` - Accurate
|
||||
- ✅ `docs/public/build/presets.md` - Accurate
|
||||
- ✅ `docs/public/developer/architecture.md` - Accurate (updated Nov 2025)
|
||||
- ✅ `docs/public/developer/testing-quick-start.md` - Accurate
|
||||
|
||||
### 6. Coordination Board
|
||||
|
||||
**Updated: `docs/internal/agents/coordination-board.md`**
|
||||
- Added entry for docs-janitor work session
|
||||
- Marked status as COMPLETE
|
||||
- Listed all changes made
|
||||
|
||||
## File Structure After Cleanup
|
||||
|
||||
```
|
||||
docs/
|
||||
├── public/
|
||||
│ ├── build/ [5 docs - build system]
|
||||
│ ├── deployment/ [1 doc - collaboration server]
|
||||
│ ├── developer/ [18 docs - developer guides]
|
||||
│ ├── examples/ [1 doc - code examples]
|
||||
│ ├── guides/ [1 doc - z3ed workflows]
|
||||
│ ├── overview/ [1 doc - getting started]
|
||||
│ ├── reference/ [8 docs - ROM & format specs] ⭐ IMPROVED
|
||||
│ │ ├── rom-reference.md
|
||||
│ │ ├── SAVE_STATE_FORMAT.md ⬅️ MOVED HERE
|
||||
│ │ ├── SNES_COMPRESSION.md ⬅️ MOVED HERE
|
||||
│ │ ├── SNES_GRAPHICS.md ⬅️ MOVED HERE
|
||||
│ │ ├── SYMBOL_FORMAT.md ⬅️ MOVED HERE
|
||||
│ │ └── ZSM_FORMAT.md ⬅️ MOVED HERE
|
||||
│ ├── usage/ [4 docs including web-app] ⭐ NEW
|
||||
│ │ ├── web-app.md ⬅️ NEW
|
||||
│ │ ├── dungeon-editor.md
|
||||
│ │ ├── overworld-loading.md
|
||||
│ │ └── z3ed-cli.md
|
||||
│ ├── index.md
|
||||
│ └── README.md
|
||||
├── internal/
|
||||
│ ├── agents/ [Agent coordination & playbooks]
|
||||
│ ├── architecture/ [System architecture docs]
|
||||
│ ├── blueprints/ [Refactoring plans]
|
||||
│ ├── plans/ [Implementation plans]
|
||||
│ ├── reports/ [Investigation reports]
|
||||
│ ├── roadmaps/ [Feature roadmaps]
|
||||
│ ├── testing/ [Test infrastructure]
|
||||
│ ├── web-drag-drop-implementation.md ⬅️ MOVED HERE
|
||||
│ ├── wasm-patch-export-implementation.md ⬅️ MOVED HERE
|
||||
│ └── [other internal docs]
|
||||
├── examples/ [Code examples]
|
||||
├── GIGALEAK_INTEGRATION.md
|
||||
└── index.md
|
||||
```
|
||||
|
||||
## Removed Directories
|
||||
|
||||
- ❌ `docs/web/` - consolidated into internal
|
||||
- ❌ `docs/wasm/` - consolidated into internal
|
||||
|
||||
## Documentation Principles Applied
|
||||
|
||||
1. **Public vs Internal Separation**
|
||||
- Public: User-facing, stable, external developers
|
||||
- Internal: AI agents, implementation details, planning
|
||||
|
||||
2. **Accuracy & Honesty**
|
||||
- Web app clearly marked as preview/experimental
|
||||
- Editor status accurately reflects incomplete state
|
||||
- Recommended desktop for production work
|
||||
|
||||
3. **Organization**
|
||||
- Format docs in reference section for easy discovery
|
||||
- Technical implementation in internal for developers
|
||||
- Clear navigation through index files
|
||||
|
||||
4. **Currency**
|
||||
- Updated "Last Modified" dates
|
||||
- Removed outdated content
|
||||
- Consolidated duplicate information
|
||||
|
||||
## Impact
|
||||
|
||||
### For Users
|
||||
- ✅ Clear understanding that web app is preview
|
||||
- ✅ Easy access to format documentation
|
||||
- ✅ Better organized public docs
|
||||
- ✅ Honest feature status
|
||||
|
||||
### For Developers
|
||||
- ✅ Technical docs in predictable locations
|
||||
- ✅ Format specs easy to find in reference/
|
||||
- ✅ Implementation details separated from user guides
|
||||
- ✅ Clear documentation hierarchy
|
||||
|
||||
### For AI Agents
|
||||
- ✅ Updated coordination board with session
|
||||
- ✅ Clear doc hygiene maintained
|
||||
- ✅ No doc sprawl in root directories
|
||||
|
||||
## Follow-up Actions
|
||||
|
||||
None required. Documentation is now:
|
||||
- Organized
|
||||
- Accurate
|
||||
- Complete for web app preview
|
||||
- Properly separated (public vs internal)
|
||||
- Up to date
|
||||
|
||||
## Agent
|
||||
|
||||
**Agent ID:** docs-janitor
|
||||
**Session Date:** November 27, 2025
|
||||
**Duration:** Single session
|
||||
**Status:** Complete
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# Draw Routine Fixes - Phase 2
|
||||
|
||||
## Status
|
||||
**Owner:** ai-dungeon-specialist
|
||||
**Created:** 2025-12-07
|
||||
**Status:** Partial Complete - Build Verified
|
||||
|
||||
## Summary
|
||||
|
||||
This document tracks fixes for specific dungeon object draw routines and outline sizing issues identified during testing. These issues complement the Phase 1 diagonal/edge/spacing fixes.
|
||||
|
||||
## Issues to Fix
|
||||
|
||||
### Issue 1: Block 0x5E Draw Routine Inverted
|
||||
**Object:** 0x5E (RoomDraw_RightwardsBlock2x2spaced2_1to16)
|
||||
**Problem:** Draw routine is inverted for the simple block pattern
|
||||
**ASM Reference:** bank_01.asm line 363
|
||||
**Fix Required:** Review tile ordering and column-major vs row-major layout
|
||||
|
||||
### Issue 2: Vertical Pegs Wrong Outline Shape
|
||||
**Objects:** 0x95 (DownwardsPots2x2), 0x96 (DownwardsHammerPegs2x2)
|
||||
**Problem:** Selection outline shows 2x2 square but should be vertical single row (1 tile wide)
|
||||
**ASM Reference:** RoomDraw_DownwardsPots2x2_1to16, RoomDraw_DownwardsHammerPegs2x2_1to16
|
||||
**Analysis:** The pots/pegs are 2x2 objects that repeat vertically with 2-row spacing (0x100). However, user reports they should display as 1-tile-wide vertical strips. Need to verify actual drawn dimensions from ASM.
|
||||
**Fix Required:** Update dimension calculations in CalculateObjectDimensions and ObjectDimensionTable
|
||||
|
||||
### Issue 3: Thick Rail Horizontal/Vertical Draw Issues
|
||||
**Objects:** 0x5D (RightwardsBigRail1x3), 0x88 (DownwardsBigRail3x1)
|
||||
**Problem:** Repeats far left edge rather than inner parts of the thick rail
|
||||
**ASM Reference:** RoomDraw_RightwardsBigRail1x3_1to16plus5, RoomDraw_DownwardsBigRail3x1_1to16plus5
|
||||
**Analysis:** ASM shows:
|
||||
- First draws a 2x2 block, then advances tile pointer by 8
|
||||
- Then draws middle section (1x3 tiles per iteration)
|
||||
- Finally draws end cap (2 tiles)
|
||||
**Fix Required:** Fix draw routine to draw: left cap → middle repeating → right cap
|
||||
|
||||
### Issue 4: Large Decor Outline Too Small, Draw Routine Repeats Incorrectly
|
||||
**Problem:** Large decoration objects have outlines that are too small and draw routines that repeat when they shouldn't
|
||||
**Fix Required:** Identify specific objects and verify repetition count logic (size+1 vs size)
|
||||
|
||||
### Issue 5: Ceiling 0xC0 Doesn't Draw Properly
|
||||
**Object:** 0xC0 (RoomDraw_4x4BlocksIn4x4SuperSquare)
|
||||
**Problem:** Object doesn't draw at all or draws incorrectly
|
||||
**ASM Reference:** bank_01.asm lines 1779-1831
|
||||
**Analysis:** Uses complex 4x4 super-square pattern with 8 buffer pointers ($BF through $D4). Draws 4x4 blocks in a grid pattern based on size parameters B2 and B4.
|
||||
**Fix Required:** Implement proper super-square drawing routine
|
||||
|
||||
### Issue 6: 0xF99 Chest Outline Correct But Draw Routine Repeats
|
||||
**Object:** 0xF99 (RoomDraw_Chest - Type 3 chest)
|
||||
**Problem:** Outline is correct but draw routine repeats when it shouldn't
|
||||
**ASM Reference:** RoomDraw_Chest at bank_01.asm line 4707
|
||||
**Analysis:** Chest should only draw once (single 2x2 pattern), not repeat based on size
|
||||
**Fix Required:** Remove size-based repetition from chest draw routine
|
||||
|
||||
### Issue 7: Pit Edges Outlines Too Thin
|
||||
**Problem:** Pit edge outlines shouldn't be single tile thin based on direction
|
||||
**Objects:** Various pit edge objects
|
||||
**Fix Required:** Update pit edge dimension calculations to include proper width based on direction
|
||||
|
||||
### Issue 8: 0x3D Tall Torches Wrong Top Half Graphics
|
||||
**Object:** 0x3D (mapped to RoomDraw_RightwardsPillar2x4spaced4_1to16)
|
||||
**Problem:** Bottom half draws correctly but top half with fire draws pegs instead
|
||||
**ASM Reference:** bank_01.asm line 330 - uses RoomDraw_RightwardsPillar2x4spaced4_1to16 (same as 0x39)
|
||||
**Analysis:** Object 0x3D and 0x39 share the same draw routine but use different tile data. Need to verify tile data offset is correct.
|
||||
**Fix Required:** Verify tile data loading for 0x3D or create dedicated draw routine
|
||||
|
||||
## Implementation Status
|
||||
|
||||
### Completed Fixes
|
||||
1. **Block 0x5E** ✅ - Fixed tile ordering in DrawRightwardsBlock2x2spaced2_1to16 to use column-major order
|
||||
2. **Thick Rails 0x5D/0x88** ✅ - Rewrote DrawRightwardsBigRail and DrawDownwardsBigRail to correctly draw cap-middle-cap pattern
|
||||
3. **Chest 0xF99** ✅ - Fixed chest to draw single 2x2 pattern without size-based repetition
|
||||
4. **Large Decor 0xFEB** ✅ - Created Single4x4 routine (routine 113) - no repetition, correct 32x32 outline
|
||||
5. **Water Grate 0xFED** ✅ - Created Single4x3 routine (routine 114) - no repetition, correct 32x24 outline
|
||||
6. **Big Chest 0xFB1** ✅ - Mapped to Single4x3 routine (routine 114) - no repetition
|
||||
7. **Blue Rupees 0xF92** ✅ - Created DrawRupeeFloor routine (routine 115) - special 6x8 pattern with gaps
|
||||
|
||||
### Pending Investigation
|
||||
8. **Rails 0x022** - Uses RoomDraw_RightwardsHasEdge1x1_1to16_plus3 - needs internal rail drawing
|
||||
9. **Ceiling 0xC0** - Draw4x4BlocksIn4x4SuperSquare may have tile loading issue
|
||||
10. **Vertical Pegs 0x95/0x96** - Current dimensions look correct. May be UI display issue.
|
||||
11. **Pit Edges** - Need specific object IDs to investigate
|
||||
12. **Torches 0x3D** - May be ROM tile data issue (verify data at 0x807A)
|
||||
|
||||
## New Routines Added
|
||||
- Routine 113: DrawSingle4x4 - Single 4x4 block, no repetition
|
||||
- Routine 114: DrawSingle4x3 - Single 4x3 block, no repetition
|
||||
- Routine 115: DrawRupeeFloor - Special 6x8 pattern with gaps at rows 2 and 5
|
||||
|
||||
## Files Modified
|
||||
|
||||
- `src/zelda3/dungeon/object_drawer.cc`
|
||||
- `src/zelda3/dungeon/object_drawer.h`
|
||||
- `docs/internal/agents/draw_routine_fixes_phase2.md`
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
# Draw Routine Fixes - Handoff Document
|
||||
|
||||
**Status:** Handoff
|
||||
**Owner:** draw-routine-engineer
|
||||
**Created:** 2025-12-07
|
||||
**Last Session:** 2025-12-07
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
This session made significant progress on dungeon object draw routines. Many fixes were completed, but some objects still have minor issues requiring further investigation.
|
||||
|
||||
---
|
||||
|
||||
## Completed Fixes ✅
|
||||
|
||||
| Object ID | Name | Fix Applied |
|
||||
|-----------|------|-------------|
|
||||
| 0x5E | Block | Fixed column-major tile ordering |
|
||||
| 0x5D/0x88 | Thick Rails | Fixed cap-middle-cap pattern |
|
||||
| 0xF99 | Chest | Changed to DrawSingle2x2 (no size-based repeat) |
|
||||
| 0xFB1 | Big Chest | Changed to DrawSingle4x3 (no repeat) |
|
||||
| 0xF92 | Blue Rupees | Implemented DrawRupeeFloor per ASM (3x8 pattern) |
|
||||
| 0xFED | Water Grate | Changed to DrawSingle4x3 (no repeat) |
|
||||
| 0x3A | Wall Decors | Fixed spacing from 6 to 8 tiles |
|
||||
| 0x39/0x3D | Pillars | Fixed spacing from 6 to 4 tiles |
|
||||
| 0xFEB | Large Decor | Now 64x64 (4x4 tile16s = 8x8 tile8s) |
|
||||
| 0x138-0x13B | Spiral Stairs | Fixed to 4x3 pattern per ASM |
|
||||
| 0xC0/0xC2 | SuperSquare Ceilings | Dimensions now use size parameter |
|
||||
| 0xFE6 | Pit | Uses DrawActual4x4 (32x32, no repeat) |
|
||||
| 0x55-0x56 | Wall Torches | Fixed to 1x8 column with 12-tile spacing |
|
||||
| 0x22 | Small Rails | Now CORNER+MIDDLE*count+END pattern |
|
||||
| 0x23-0x2E | Carpet Trim | Now CORNER+MIDDLE*count+END pattern |
|
||||
|
||||
---
|
||||
|
||||
## Known Issues - Need Further Work ⚠️
|
||||
|
||||
### 1. Horizontal vs Vertical Rails Asymmetry
|
||||
**Objects:** 0x22 (horizontal) vs vertical counterparts
|
||||
**Issue:** Horizontal rails now work with CORNER+MIDDLE+END pattern, but vertical rails may not be updated to match.
|
||||
**Files to check:**
|
||||
- `DrawDownwardsHasEdge1x1_*` routines
|
||||
- Look for routines mapped to 0x8A-0x8E (vertical equivalents)
|
||||
|
||||
### 2. Diagonal Ceiling Outlines (0xA0-0xA3)
|
||||
**Issue:** Draw routine is correct (triangular fill), but outline dimensions still too large for selection purposes.
|
||||
**Current state:**
|
||||
- Draw: `count = (size & 0x0F) + 4`
|
||||
- Outline: `count = (size & 0x0F) + 2` (still too big)
|
||||
**Suggestion:** May need special handling in selection code rather than dimension calculation, since triangles only fill half the bounding box.
|
||||
|
||||
### 3. Torch Object 0x3D
|
||||
**Issue:** Top half draws pegs instead of fire graphics.
|
||||
**Likely cause:** ROM tile data issue - tiles at offset 0x807A may be incorrect or tile loading is wrong.
|
||||
**Uses same routine as pillars (0x39).**
|
||||
|
||||
### 4. Vertical Pegs 0x95/0x96
|
||||
**Issue:** Outline appears square (2x2) but should be vertical single row.
|
||||
**May be UI/selection display issue rather than draw routine.**
|
||||
|
||||
---
|
||||
|
||||
## Pending Tasks 📋
|
||||
|
||||
### High Priority
|
||||
1. **0xDC Chest Platform** - Complex routine with multiple segments, not currently working
|
||||
2. **Staircases audit** - Objects 0x12D-0x137, 0x21B-0x221, 0x226-0x229, 0x233
|
||||
|
||||
### Medium Priority
|
||||
3. **Vertical rail patterns** - Match horizontal rail fixes
|
||||
4. **Pit edges** - Need specific object IDs to investigate
|
||||
|
||||
### Low Priority
|
||||
5. **Diagonal ceiling selection** - May need UI-level fix
|
||||
|
||||
---
|
||||
|
||||
## Key Formulas Reference
|
||||
|
||||
### Size Calculations (from ASM)
|
||||
|
||||
| Pattern | Formula |
|
||||
|---------|---------|
|
||||
| GetSize_1to16 | `count = (size & 0x0F) + 1` |
|
||||
| GetSize_1to16_timesA | `count = (size & 0x0F + 1) * A` |
|
||||
| GetSize_1to15or26 | `count = size; if 0, count = 26` |
|
||||
| GetSize_1to15or32 | `count = size; if 0, count = 32` |
|
||||
| SuperSquare | `size_x = (size & 0x0F) + 1; size_y = ((size >> 4) & 0x0F) + 1` |
|
||||
|
||||
### Rail Pattern Structure
|
||||
```
|
||||
[CORNER tile 0] -> [MIDDLE tile 1 × count] -> [END tile 2]
|
||||
```
|
||||
|
||||
### Tile Ordering
|
||||
Most routines use **COLUMN-MAJOR** order: tiles advance down each column, then right.
|
||||
|
||||
---
|
||||
|
||||
## Files Modified
|
||||
|
||||
- `src/zelda3/dungeon/object_drawer.cc` - Main draw routines and mappings
|
||||
- `src/zelda3/dungeon/object_drawer.h` - Added DrawActual4x4 declaration
|
||||
- `src/zelda3/dungeon/draw_routines/special_routines.cc` - Spiral stairs fix
|
||||
- `docs/internal/agents/draw_routine_tracker.md` - Tracking document
|
||||
|
||||
---
|
||||
|
||||
## Testing Notes
|
||||
|
||||
- Log file at `logs/dungeon-object-draw.log` shows object draw data
|
||||
- Most testing was done on limited room set - need broader room testing
|
||||
- Use grep on log file to find specific object draws: `grep "obj=0xXX" logs/dungeon-object-draw.log`
|
||||
|
||||
---
|
||||
|
||||
## Next Steps for Continuation
|
||||
|
||||
1. Test the rail fixes in rooms with both horizontal and vertical rails
|
||||
2. Find and fix the vertical rail equivalents (likely routines 23-28 or similar)
|
||||
3. Investigate 0xDC chest platform ASM in detail
|
||||
4. Consider UI-level fix for diagonal ceiling selection bounds
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user