Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help setup install test lint shell run clean rebuild build-wasm serve-wasm
.PHONY: help setup install test lint shell run clean rebuild build-wasm serve-wasm check-sdl install-sdl run-sdl run-sdl-host

help: ## Show this help message
@echo 'Usage: make [target]'
Expand Down Expand Up @@ -121,3 +121,56 @@ serve-wasm: ## Serve WASM build locally (requires Python 3)
fi
@echo "Starting HTTP server on http://localhost:8080"
@cd dist && python3 -m http.server 8080

# SDL2 Native Frontend Targets

check-sdl: ## Check if SDL2 extension is installed
@echo "Checking SDL2 extension..."
@php -m | grep -q sdl && echo "✓ SDL2 extension is installed" || (echo "✗ SDL2 extension not found. See docs/sdl2-setup.md for installation." && exit 1)
@echo "SDL2 version: $$(php -r 'echo SDL_GetVersion();')"

install-sdl: ## Install SDL2 PHP extension (requires sudo)
@echo "Installing SDL2 PHP extension..."
@echo "This requires SDL2 development libraries to be installed first."
@echo ""
@echo "Ubuntu/Debian:"
@echo " sudo apt-get install libsdl2-dev"
@echo ""
@echo "macOS:"
@echo " brew install sdl2"
@echo ""
@echo "After installing SDL2 libraries, run:"
@echo " sudo pecl install sdl-beta"
@echo ""
@echo "Then add 'extension=sdl.so' to your php.ini"
@echo ""
@echo "See docs/sdl2-setup.md for detailed instructions."

run-sdl: ## Run emulator with SDL2 native frontend in Docker (usage: make run-sdl ROM=path/to/rom.gb)
@if [ -z "$(ROM)" ]; then \
echo "Error: ROM parameter is required. Usage: make run-sdl ROM=path/to/rom.gb"; \
exit 1; \
fi
@echo "Note: SDL2 GUI applications typically work better on host. Try: make run-sdl-host ROM=$(ROM)"
docker compose run --rm -e DISPLAY=$$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix phpboy php bin/phpboy.php $(ROM) --frontend=sdl

run-sdl-host: ## Run emulator with SDL2 on host (not in Docker) (usage: make run-sdl-host ROM=path/to/rom.gb)
@if [ -z "$(ROM)" ]; then \
echo "Error: ROM parameter is required. Usage: make run-sdl-host ROM=path/to/rom.gb"; \
exit 1; \
fi
@echo "Running SDL2 frontend on host..."
@php -m | grep -q sdl || (echo "Error: SDL2 extension not installed. Run 'make install-sdl' or see docs/sdl2-setup.md" && exit 1)
php bin/phpboy.php $(ROM) --frontend=sdl

test-sdl: ## Test SDL2 installation with simple window
@echo "Testing SDL2 installation..."
@php -m | grep -q sdl || (echo "Error: SDL2 extension not installed." && exit 1)
@php -r '\
if (!extension_loaded("sdl")) { die("SDL not loaded\n"); } \
SDL_Init(SDL_INIT_VIDEO); \
$$w = SDL_CreateWindow("SDL Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN); \
if ($$w) { echo "✓ SDL2 working! Window created.\n"; sleep(2); SDL_DestroyWindow($$w); } \
else { echo "✗ Failed: " . SDL_GetError() . "\n"; } \
SDL_Quit(); \
'
71 changes: 66 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# PHPBoy - Game Boy Color Emulator

A readable, well-architected Game Boy Color (GBC) emulator written in PHP 8.5 that runs in the CLI and, via WebAssembly, in the browser.
A readable, well-architected Game Boy Color (GBC) emulator written in PHP 8.5 with multiple frontend options: native SDL2 desktop, CLI terminal, and browser via WebAssembly.

## Features

- **Modern PHP 8.5 RC**: Leverages the latest PHP 8.5 release candidate features including strict types, readonly properties, enums, typed class constants, and property hooks
- **Browser Support**: Runs in the browser via WebAssembly using php-wasm - no backend required!
- **Multiple Frontends**:
- **SDL2 Native Desktop**: Hardware-accelerated rendering with true native performance ⭐ **NEW!**
- **Browser (WebAssembly)**: Runs in the browser via php-wasm - no backend required!
- **CLI Terminal**: ANSI color rendering in your terminal
- **Fully Dockerized Development**: All PHP/Composer/testing tools run exclusively in Docker containers for consistency
- **Comprehensive Testing**: PHPUnit 10 for unit and integration tests
- **Static Analysis**: PHPStan at maximum level (9) for type safety
Expand Down Expand Up @@ -77,6 +80,61 @@ For debugging or manual operations:
make shell
```

### Running with SDL2 Native Frontend

PHPBoy supports true native desktop rendering using SDL2 for hardware-accelerated, low-latency gameplay.

#### Prerequisites

1. Install SDL2 development libraries:
```bash
# Ubuntu/Debian
sudo apt-get install libsdl2-dev

# macOS
brew install sdl2
```

2. Install SDL2 PHP extension:
```bash
sudo pecl install sdl-beta
echo "extension=sdl.so" | sudo tee -a $(php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||")
```

3. Verify installation:
```bash
make check-sdl
```

#### Running a ROM

```bash
# Run with SDL2 frontend (on host machine)
make run-sdl-host ROM=path/to/rom.gb

# Or directly with PHP
php bin/phpboy.php path/to/rom.gb --frontend=sdl
```

**Features**:
- ✅ Hardware-accelerated rendering (GPU-based)
- ✅ VSync support for smooth 60fps
- ✅ Native desktop window
- ✅ Low-latency keyboard input
- ✅ Pixel-perfect integer scaling
- ✅ Cross-platform (Linux, macOS, Windows)

**Default Controls**:
- Arrow Keys: D-pad
- Z or A: A button
- X or S: B button
- Enter: Start
- Right Shift: Select

**Documentation**:
- [SDL2 Setup Guide](docs/sdl2-setup.md) - Installation instructions
- [SDL2 Usage Guide](docs/sdl2-usage.md) - Usage and customization

### Running in the Browser

PHPBoy can run entirely in the browser via WebAssembly using [php-wasm](https://github.com/seanmorris/php-wasm).
Expand Down Expand Up @@ -121,6 +179,8 @@ phpboy/
├── bin/ # CLI entry point
├── docs/ # Documentation
│ ├── research.md # Game Boy hardware research
│ ├── sdl2-setup.md # SDL2 native frontend setup
│ ├── sdl2-usage.md # SDL2 usage guide
│ ├── wasm-build.md # WebAssembly build guide
│ ├── browser-usage.md # Browser usage guide
│ └── wasm-options.md # WASM implementation options
Expand All @@ -129,9 +189,10 @@ phpboy/
│ ├── Bus/ # Memory bus
│ ├── Cartridge/ # ROM/MBC handling
│ ├── Cpu/ # CPU emulation
│ ├── Frontend/ # CLI and WASM frontends
│ │ ├── Cli/ # CLI implementation
│ │ └── Wasm/ # WASM adapters
│ ├── Frontend/ # Multiple frontend implementations
│ │ ├── Cli/ # CLI terminal frontend
│ │ ├── Sdl/ # SDL2 native desktop frontend
│ │ └── Wasm/ # WebAssembly browser frontend
│ ├── Ppu/ # Pixel Processing Unit
│ └── Support/ # Utilities and helpers
├── tests/ # Test suite
Expand Down
222 changes: 222 additions & 0 deletions docs/sdl2-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# SDL2 Native Frontend Setup

This guide covers setting up the SDL2 PHP extension for native desktop rendering in PHPBoy.

## Overview

The SDL2 frontend provides **true native rendering** using hardware acceleration through SDL2 (Simple DirectMedia Layer). This approach offers:

- ✅ Native desktop window with hardware-accelerated graphics
- ✅ Direct GPU rendering (60+ fps easily achievable)
- ✅ Keyboard and joystick input support
- ✅ Cross-platform (Linux, macOS, Windows)
- ✅ No browser/Electron wrapper needed
- ✅ Perfect for emulator development

## Prerequisites

- PHP 8.1+ with development headers
- SDL2 library (>= 2.0)
- C compiler and build tools
- Unix-like system (Linux, macOS, BSD)

## Installation

### Step 1: Install SDL2 Development Libraries

#### Ubuntu/Debian
```bash
sudo apt-get update
sudo apt-get install libsdl2-dev
```

#### macOS
```bash
brew install sdl2
```

#### Fedora/RHEL
```bash
sudo dnf install SDL2-devel
```

### Step 2: Install PHP SDL Extension

#### Option A: From PECL (Recommended)

```bash
pecl install sdl-beta
```

Then add to your `php.ini`:
```ini
extension=sdl.so
```

Verify installation:
```bash
php -m | grep sdl
```

#### Option B: Build from Source

```bash
# Clone the repository
git clone https://github.com/Ponup/php-sdl.git
cd php-sdl

# Build the extension
phpize
./configure --with-sdl
make
make test

# Install
sudo make install
```

Add to `php.ini`:
```ini
extension=sdl.so
```

### Step 3: Verify Installation

Create a test file `test-sdl.php`:

```php
<?php

if (!extension_loaded('sdl')) {
die("SDL extension not loaded!\n");
}

echo "SDL version: " . SDL_GetVersion() . "\n";

SDL_Init(SDL_INIT_VIDEO);

$window = SDL_CreateWindow(
"SDL Test",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640,
480,
SDL_WINDOW_SHOWN
);

if ($window) {
echo "✓ SDL2 working! Window created successfully.\n";
sleep(2);
SDL_DestroyWindow($window);
} else {
echo "✗ Failed to create window: " . SDL_GetError() . "\n";
}

SDL_Quit();
```

Run:
```bash
php test-sdl.php
```

You should see a window appear briefly.

## Docker Support

For Docker environments, add SDL2 to your Dockerfile:

```dockerfile
FROM php:8.4-cli

# Install SDL2 dependencies
RUN apt-get update && apt-get install -y \
libsdl2-dev \
libsdl2-2.0-0 \
&& rm -rf /var/lib/apt/lists/*

# Install PHP SDL extension
RUN pecl install sdl-beta \
&& docker-php-ext-enable sdl

# Install Composer dependencies
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY . .

CMD ["php", "bin/phpboy.php"]
```

**Note:** Running GUI applications in Docker requires X11 forwarding or similar display mechanisms.

## Running PHPBoy with SDL2

```bash
# Make sure SDL extension is loaded
php -m | grep sdl

# Run with SDL2 frontend
php bin/phpboy.php --frontend=sdl path/to/rom.gb
```

Or using Make:
```bash
make run-sdl ROM=path/to/rom.gb
```

## Troubleshooting

### SDL extension not found
```bash
# Check if extension is compiled
php -m | grep sdl

# Check php.ini location
php --ini

# Verify extension file exists
ls $(php-config --extension-dir)/sdl.so
```

### "undefined symbol" errors during build
Make sure you have SDL2 development headers:
```bash
# Ubuntu/Debian
dpkg -l | grep libsdl2-dev

# macOS
brew list sdl2
```

### Window not appearing
- Ensure `DISPLAY` environment variable is set (Linux)
- Check X11 is running
- Try running other SDL2 applications to verify SDL2 works

### "SDL_Init failed" errors
Check SDL2 video subsystem:
```bash
# Test SDL2 directly
sdl2-config --version
```

## Performance Notes

- SDL2 uses hardware acceleration by default (GPU rendering)
- Texture streaming is efficient for emulator framebuffers
- VSync can be enabled for smooth 60fps output
- Rendering 160x144 @ 60fps is trivial for modern GPUs

## API Documentation

For detailed SDL2 PHP API documentation, refer to:
- Official SDL2 C documentation (API is 1:1 with PHP bindings)
- https://wiki.libsdl.org/SDL2/FrontPage
- Examples in `php-sdl/examples/` directory

## Next Steps

- See [SDL2 Frontend Usage](sdl2-usage.md) for PHPBoy-specific usage
- Check `src/Frontend/Sdl/` for implementation details
- Review examples in the php-sdl repository
Loading