Last Updated: 2025-11-04 (Updated with batch build system)
Purpose: Comprehensive guide for building SWF tests to WebAssembly and native executables using the NO_GRAPHICS runtime
Automated Build System (2025-11-04):
- ✅ Batch build scripts for WASM and native builds
- ✅ Shared exclude list configuration (
excluded_tests.conf) - ✅ Auto-generated documentation index
- ✅ Automated deployment to docs site
- ✅ 48/51 tests building successfully
- ✅ Config files added to all tests
The WASM build process uses SWFModernRuntime in NO_GRAPHICS mode, enabling console-only tests to compile to WebAssembly without SDL3/Vulkan dependencies. This process generates three files:
<test_name>.wasm- WebAssembly binary (~19 KB for simple tests)<test_name>.js- Emscripten JavaScript loader (~14 KB)index.html- Browser interface (~6 KB)
One-time setup:
# Clone Emscripten SDK (if not already installed)
git clone https://github.com/emscripten-core/emsdk.git ~/tools/emsdk
cd ~/tools/emsdk
# Install latest version
./emsdk install latest
./emsdk activate latestVerify installation:
source ~/tools/emsdk/emsdk_env.sh
emcc --versionExpected output:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.18
cd ~/projects/SWFRecomp
mkdir -p build && cd build
cmake ..
makeEnsure projects are organized as sibling directories:
~/projects/
├── SWFRecomp/ # Recompiler tool
├── SWFModernRuntime/ # Runtime library
└── SWFRecompDocs/ # Documentation
# 1. Activate Emscripten (required for each new shell session)
source ~/tools/emsdk/emsdk_env.sh
# 2. Navigate to SWFRecomp directory
cd ~/projects/SWFRecomp
# 3. Build test for WASM
./scripts/build_test.sh trace_swf_4 wasmOutput:
Setting up build directory...
Copying SWFModernRuntime sources...
Using NO_GRAPHICS mode for WASM build...
Copying generated files...
Building WASM with SWFModernRuntime...
✅ WASM build complete!
Output: /home/user/projects/SWFRecomp/tests/trace_swf_4/build/wasm/trace_swf_4.wasm
To test:
cd /home/user/projects/SWFRecomp/tests/trace_swf_4/build/wasm
python3 -m http.server 8000
Open http://localhost:8000/index.html
# Navigate to build directory
cd ~/projects/SWFRecomp/tests/trace_swf_4/build/wasm
# Start local web server
python3 -m http.server 8000
# Open browser to:
# http://localhost:8000/index.htmlEvery shell session must activate Emscripten before building:
source ~/tools/emsdk/emsdk_env.shWhat this does:
- Adds
emcccompiler to PATH - Sets environment variables (EMSDK, EMSDK_NODE)
- Configures Emscripten cache paths
To suppress activation messages:
EMSDK_QUIET=1 source ~/tools/emsdk/emsdk_env.shTo activate automatically on shell startup (optional):
Add to ~/.bashrc or ~/.zshrc:
# Activate Emscripten automatically
source ~/tools/emsdk/emsdk_env.sh > /dev/null 2>&1If the test hasn't been recompiled yet, or you've modified the SWF:
cd ~/projects/SWFRecomp/tests/trace_swf_4
../../build/SWFRecomp config.tomlThis generates:
RecompiledScripts/- Translated ActionScriptRecompiledTags/- Frame execution code
cd ~/projects/SWFRecomp
./scripts/build_test.sh trace_swf_4 wasmWhat the script does:
-
Validates inputs
- Checks test directory exists
- Verifies Emscripten is available
-
Sets up build directory
- Creates
tests/<test_name>/build/wasm/ - Cleans previous build (fresh start)
- Creates
-
Copies WASM wrapper files
wasm_wrappers/main.c→ Entry point with Emscripten exportswasm_wrappers/index_template.html→ Browser interface- Substitutes
{{TEST_NAME}}with actual test name
-
Copies SWFModernRuntime sources
- Core:
action.c,variables.c,utils.c - NO_GRAPHICS:
swf_core.c,tag_stubs.c - Dependencies:
map.c(hashmap)
- Core:
-
Copies generated files
- From
RecompiledScripts/:script_*.c - From
RecompiledTags/:tagMain.c,constants.c, etc.
- From
-
Compiles with Emscripten
- Compiler:
emcc - Flags:
-DNO_GRAPHICS,-O2,-s WASM=1 - Output:
<test_name>.wasm+<test_name>.js
- Compiler:
Build output directory:
tests/trace_swf_4/build/wasm/
├── trace_swf_4.wasm # WebAssembly binary (19 KB)
├── trace_swf_4.js # JavaScript loader (14 KB)
├── index.html # Browser interface (6 KB)
└── *.c # Source files (for debugging)
Both native and WASM builds currently use NO_GRAPHICS mode (console-only).
./scripts/build_test.sh trace_swf_4 nativeCompiles with:
- NO_GRAPHICS mode (console-only)
swf_core.candtag_stubs.c(stub implementations)- No flashbang/SDL3/Vulkan
- Uses gcc/clang
Output: Native executable (~36 KB)
Example:
./tests/trace_swf_4/build/native/trace_swf_4Output:
SWF Runtime Loaded (Native Build)
=== SWF Execution Started (NO_GRAPHICS mode) ===
[Frame 0]
[Tag] SetBackgroundColor(255, 255, 255)
sup from SWF 4
[Tag] ShowFrame()
=== SWF Execution Completed ===
./scripts/build_test.sh trace_swf_4 wasmCompiles with:
- NO_GRAPHICS mode (console-only)
swf_core.candtag_stubs.c(stub implementations)- No flashbang/SDL3/Vulkan
- Uses emcc (Emscripten)
Output: WebAssembly binary (~19-35 KB) + JavaScript loader
Note: Graphics mode with SDL3/Vulkan/WebGPU support is planned for future implementation.
✅ Full ActionScript VM:
- Stack operations (PUSH, POP)
- Arithmetic (add, subtract, multiply, divide)
- String operations (concatenate, length)
- Variables (get, set)
- Control flow (if, goto)
- Trace output
✅ Core Runtime:
- 24-byte typed stack entries
- HashMap-based variable storage
- Array optimization for string IDs
- Proper memory management
✅ Tag Stubs:
tagShowFrame()- Prints to consoletagSetBackgroundColor()- Prints to console- Other graphics tags ignored
❌ Graphics Rendering:
- No SDL3 window creation
- No Vulkan/WebGPU rendering
- No shape drawing
- No bitmap loading
❌ Input Handling:
- No keyboard input
- No mouse input
- No touch events
This makes the WASM binary much smaller and faster to load.
emcc \
*.c \ # All C source files
-DNO_GRAPHICS \ # Enable NO_GRAPHICS mode
-I. \ # Include current directory
-I"${SWFMODERN_INC}" \ # SWFModernRuntime headers
-I"${SWFMODERN_INC}/actionmodern" \ # ActionScript VM headers
-I"${SWFMODERN_INC}/libswf" \ # Runtime headers
-I"${SWFMODERN_ROOT}/lib/c-hashmap" \ # HashMap library headers
-o "${TEST_NAME}.js" \ # Output filename (.js + .wasm)
-s WASM=1 \ # Enable WebAssembly output
-s EXPORTED_FUNCTIONS='["_main","_runSWF"]' \ # Functions callable from JS
-s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]' \ # JS-C bridge methods
-s ALLOW_MEMORY_GROWTH=1 \ # Dynamic memory allocation
-s INITIAL_MEMORY=16MB \ # Starting memory size
-O2 # Optimization level 2Key points:
-DNO_GRAPHICS- Conditional compilation flag-s WASM=1- Generate WebAssembly (not asm.js)-s EXPORTED_FUNCTIONS- Functions visible to JavaScript-s ALLOW_MEMORY_GROWTH=1- Memory can grow dynamically-O2- Balance between size and performance
| Level | Size | Speed | Build Time | Use Case |
|---|---|---|---|---|
-O0 |
Large | Slow | Fast | Debugging |
-O1 |
Medium | Medium | Medium | Development |
-O2 |
Small | Fast | Slow | Production (default) |
-O3 |
Smallest | Fastest | Slowest | Performance critical |
-Os |
Smallest | Medium | Slow | Size critical |
Recommendation: Use -O2 for production builds (current default).
1. Start HTTP server:
cd ~/projects/SWFRecomp/tests/trace_swf_4/build/wasm
python3 -m http.server 8000Alternative servers:
# Node.js (if installed)
npx http-server -p 8000
# PHP (if installed)
php -S localhost:80002. Open browser:
Navigate to: http://localhost:8000/index.html
3. Expected behavior:
- Page loads with "WASM SWF Runtime Loaded!" message
- Click "Run SWF" button
- Output appears in console display area
- Should see: "sup from SWF 4" (for trace_swf_4 test)
Open browser developer tools (F12) to see:
WASM SWF Runtime Loaded!
This is a recompiled Flash SWF running in WebAssembly.
Call runSWF() from JavaScript to execute the SWF.
Starting SWF execution from JavaScript...
=== SWF Execution Started (NO_GRAPHICS mode) ===
[Frame 0]
[Tag] SetBackgroundColor(255, 255, 255)
sup from SWF 4
[Tag] ShowFrame()
=== SWF Execution Completed ===
cd ~/projects/SWFRecomp
./scripts/deploy_example.sh trace_swf_4 ../SWFRecompDocs/docs/examplesWhat this does:
- Creates directory:
SWFRecompDocs/docs/examples/trace_swf_4/ - Copies WASM files:
trace_swf_4.wasmtrace_swf_4.jsindex.html
Result: Live example at docs site
Build and deploy all examples with a single command:
# Activate Emscripten first
source ~/tools/emsdk/emsdk_env.sh
# Build and deploy all non-excluded tests
./scripts/build_all_examples.sh ../SWFRecompDocs/docs/examplesWhat this does:
- Auto-discovers all tests with
config.toml - Excludes tests in
scripts/excluded_tests.conf - Builds each test to WASM
- Deploys to docs/examples/
- Auto-updates docs/index.html with example links
Output:
Auto-discovered 48 tests with config.toml
Excluded 3 tests: if_swf_4 if_false_swf_4 speed_test_swf_4
Building all tests for WASM deployment...
=========================================
Building: trace_swf_4 (1/48)
=========================================
✅ trace_swf_4 - built and deployed
[... builds continue ...]
=========================================
Build Summary
=========================================
✅ Successful: 48
❌ Failed: 0
⏱️ Timeout: 0
Total: 48
Features:
- 60-second timeout per test
- Continues on failures
- Detailed progress tracking
- Summary report at end
SWFRecomp includes automated scripts for building all tests:
source ~/tools/emsdk/emsdk_env.sh
./scripts/build_all_examples.shBuilds all tests to WebAssembly and deploys them to the documentation site.
./scripts/build_all_native.shBuilds all tests as native executables in tests/<name>/build/native/.
File: scripts/excluded_tests.conf
Tests that are known to fail or take too long are listed here:
# Format: test_name:reason
if_swf_4:Missing evaluateCondition() function in runtime
if_false_swf_4:Missing evaluateCondition() function in runtime
speed_test_swf_4:Build timeout - generates 811KB of code (stress test)
Usage:
- Batch build scripts automatically skip these tests
- Excluded tests are shown in a separate section on the docs site
- Edit this file to add/remove exclusions
The documentation index is automatically updated when examples are deployed:
File: scripts/generate_examples_index.sh
Features:
- Scans
docs/examples/for deployed tests - Generates demo cards for each example
- Creates "Excluded Tests" section with reasons
- Updates
docs/index.htmlautomatically
Manual regeneration:
./scripts/generate_examples_index.sh ../SWFRecompDocs/docsTo prepare tests for batch building:
./scripts/add_configs_to_all_tests.shThis creates config.toml in any test directory that has test.swf but no configuration.
Error:
Error: Emscripten (emcc) not found!
Run: source ~/tools/emsdk/emsdk_env.sh
Solution:
source ~/tools/emsdk/emsdk_env.shPermanent fix: Add to ~/.bashrc
Error:
Error: SWFModernRuntime not found at: /path/to/SWFModernRuntime
Solution: Verify directory structure:
ls ~/projects/SWFModernRuntimeProjects must be siblings: SWFRecomp/ and SWFModernRuntime/ in same parent directory.
Error:
fatal error: 'SDL3/SDL.h' file not found
Cause: Old build artifacts or wrong source files
Solution:
# Clean build directory
rm -rf tests/<test_name>/build/wasm
# Rebuild
./scripts/build_test.sh <test_name> wasmError: "Failed to fetch" or CORS error
Cause: Opening index.html directly (file://) instead of via HTTP server
Solution: Always use HTTP server:
python3 -m http.server 8000Check:
- Browser console (F12) for JavaScript errors
- Network tab - verify .wasm file loads
- Try clicking "Run SWF" button again
- Clear browser cache and reload
# Edit build_test.sh temporarily, change:
-O2 # to
-O3 # or -Os for size optimizationAdd flags to the emcc command in scripts/build_test.sh:
emcc \
*.c \
-DNO_GRAPHICS \
-s ASSERTIONS=1 \ # Add runtime assertions (debugging)
-s SAFE_HEAP=1 \ # Memory safety checks (debugging)
-g \ # Include debug info
--source-map-base ./ \ # Generate source maps
-o "${TEST_NAME}.js"With source maps:
emcc *.c -DNO_GRAPHICS -g --source-map-base ./ -o test.jsBrowser DevTools will show original C source.
With assertions:
emcc *.c -DNO_GRAPHICS -s ASSERTIONS=1 -s SAFE_HEAP=1 -o test.jsCatches memory errors and assertion failures.
SWFRecomp/
├── tests/
│ └── trace_swf_4/
│ ├── test.swf # Original Flash file
│ ├── config.toml # SWFRecomp config
│ ├── RecompiledScripts/ # Generated by SWFRecomp
│ ├── RecompiledTags/ # Generated by SWFRecomp
│ └── build/
│ └── wasm/ # WASM build output
│ ├── *.c # Source files (copied here)
│ ├── *.wasm # WebAssembly binary
│ ├── *.js # JavaScript loader
│ └── index.html # Browser interface
├── wasm_wrappers/ # Shared WASM code
│ ├── main.c # Entry point
│ └── index_template.html # HTML template
└── scripts/
├── build_test.sh # Single test builder
├── build_all_examples.sh # Batch builder
└── deploy_example.sh # Deployment script
WASM builds use:
SWFModernRuntime/src/actionmodern/(always)SWFModernRuntime/src/libswf/swf_core.c(NO_GRAPHICS)SWFModernRuntime/src/libswf/tag_stubs.c(NO_GRAPHICS)SWFModernRuntime/src/utils.c(always)SWFModernRuntime/lib/c-hashmap/map.c(always)
Native builds use:
SWFModernRuntime/src/actionmodern/(always)SWFModernRuntime/src/libswf/swf.c(graphics)SWFModernRuntime/src/libswf/tag.c(graphics)SWFModernRuntime/src/flashbang/flashbang.c(graphics)SWFModernRuntime/src/utils.c(always)
| Test Complexity | Emscripten Compile | Total Build Time |
|---|---|---|
| Simple (trace) | 1-2 seconds | 3-4 seconds |
| Medium (variables) | 2-3 seconds | 4-5 seconds |
| Complex (arithmetic) | 3-4 seconds | 5-6 seconds |
Factors:
- Number of ActionScript operations
- Variable usage
- String handling complexity
| Test Type | WASM Size | JS Size | Total |
|---|---|---|---|
| Simple trace | 15-20 KB | 12-15 KB | 30-35 KB |
| Variables | 18-22 KB | 13-16 KB | 35-40 KB |
| Complex math | 20-25 KB | 14-17 KB | 40-45 KB |
Comparison:
- Flash Player plugin: ~15-20 MB
- Our WASM runtime: ~30-45 KB
- ~500x smaller!
On typical broadband:
- WASM binary: < 0.1 seconds
- JavaScript loader: < 0.1 seconds
- Total page load: < 0.5 seconds
On mobile 4G:
- WASM binary: < 0.2 seconds
- JavaScript loader: < 0.2 seconds
- Total page load: < 1 second
Trace tests:
- trace_swf_4
- trace_swf_5
- trace_multiple
- trace_empty
- trace_escape
Arithmetic tests:
- add_floats
- subtract_floats
- multiply_floats
- divide_floats
- modulo
- increment
- decrement
- negate
- bitwise_and
- bitwise_or
- bitwise_xor
String tests:
- string_add
- string_concat
- string_length
- string_equals
- string_less_than
- substring
- char_to_ascii
- ascii_to_char
Variable tests:
- float_vars
- dyna_string_vars_swf_4
- set_variable
- get_variable
- variable_scope
- undefined_variable
Control flow tests:
- if_statement
- goto
- loop_simple
- loop_complex
These need WebGPU/Canvas rendering (future work):
Shape tests:
- define_shape
- draw_rectangle
- draw_circle
- fill_gradient
MovieClip tests:
- place_object
- remove_object
- movieclip_control
Transform tests:
- matrix_transform
- rotation
- scaling
- Test in browser - Verify output is correct
- Deploy to docs - Make example publicly available
- Build more tests - Try other console-only tests
- Batch build - Generate multiple examples
Phase 2: Canvas2D Rendering
- Implement shape rendering
- Use HTML5 Canvas 2D API
- Remove NO_GRAPHICS flag for graphics tests
Phase 3: WebGPU Rendering
- Full graphics support
- GPU-accelerated rendering
- Feature parity with native builds
# 1. Activate Emscripten
source ~/tools/emsdk/emsdk_env.sh
# 2. Build test
cd ~/projects/SWFRecomp
./scripts/build_test.sh trace_swf_4 wasm
# 3. Test locally
cd tests/trace_swf_4/build/wasm
python3 -m http.server 8000
# Open http://localhost:8000/index.html
# 4. Deploy to docs
cd ~/projects/SWFRecomp
./scripts/deploy_example.sh trace_swf_4 ../SWFRecompDocs/docs/examples# Clean and rebuild
rm -rf tests/<test_name>/build/wasm
./scripts/build_test.sh <test_name> wasm
# Build multiple tests
for test in trace_swf_4 add_floats string_concat; do
./scripts/build_test.sh $test wasm
done| Script | Purpose | Usage |
|---|---|---|
build_test.sh |
Build single test (WASM or native) | ./scripts/build_test.sh <name> [wasm|native] |
build_all_examples.sh |
Batch build all tests to WASM and deploy | ./scripts/build_all_examples.sh [docs_dir] |
build_all_native.sh |
Batch build all tests to native executables | ./scripts/build_all_native.sh |
| Script | Purpose | Usage |
|---|---|---|
deploy_example.sh |
Deploy single WASM test to docs | ./scripts/deploy_example.sh <name> [docs_dir] |
generate_examples_index.sh |
Update docs index.html | ./scripts/generate_examples_index.sh [docs_dir] |
| Script | Purpose | Usage |
|---|---|---|
add_configs_to_all_tests.sh |
Add config.toml to all tests | ./scripts/add_configs_to_all_tests.sh |
| File | Purpose |
|---|---|
excluded_tests.conf |
List of tests to skip in batch builds with reasons |
tests/*/config.toml |
Per-test configuration for SWFRecomp |
Build and deploy single test:
source ~/tools/emsdk/emsdk_env.sh
./scripts/build_test.sh trace_swf_4 wasm
./scripts/deploy_example.sh trace_swf_4Batch build all tests:
source ~/tools/emsdk/emsdk_env.sh
./scripts/build_all_examples.shBuild native executables:
./scripts/build_all_native.shUpdate documentation index:
./scripts/generate_examples_index.sh- Implementation Status:
status/2025-11-04-no-graphics-mode-implementation.md - Original Design:
plans/swfmodernruntime-no-graphics-mode.md - Build System Plan:
plans/streamline-test-builds.md - WASM Generation:
reference/trace-swf4-wasm-generation.md
The WASM build process is fully automated and production-ready:
Single test:
source ~/tools/emsdk/emsdk_env.sh
./scripts/build_test.sh <test_name> wasm
./scripts/deploy_example.sh <test_name>All tests:
source ~/tools/emsdk/emsdk_env.sh
./scripts/build_all_examples.sh- ✅ Automated batch builds - Build all 48 working tests with one command
- ✅ Auto-deployment - Tests automatically deployed to docs site
- ✅ Auto-generated index - Documentation updated automatically
- ✅ Exclude list - Known issues documented and skipped
- ✅ Native support - Build native executables for testing
- ✅ Config management - All tests have config.toml files
- Tests building: 48/51 (94%)
- Build time: ~4 seconds/test (WASM), ~2 seconds/test (native)
- Output size: 19-35 KB WASM + 14 KB JS (~500x smaller than Flash Player!)
- Excluded tests: 3 (documented in excluded_tests.conf)
Console-only tests now build to both WASM and native executables without SDL3/Vulkan dependencies, enabling deployment of 48 interactive web demos and comprehensive automated testing.