# How Lighthouse Minimizes Input Lag in the Port: 4 Engine Techniques Explained

> Discover how Lighthouse minimizes input lag with 4 engine techniques: early polling, raw input, angle-lerp, and configurable buffers. Optimize your port performance today.

- Repository: [Harbour Masters/Lighthouse](https://github.com/HarbourMasters/Lighthouse)
- Tags: deep-dive
- Published: 2026-08-04

---

**Lighthouse minimizes input lag through early input polling, raw-input recording, angle-lerp interpolation, and configurable input-lag compensation buffers.**

The **HarbourMasters/Lighthouse** engine introduces several low-level techniques to reduce perceived delay between controller actions and on-screen response. These optimizations are critical for the port's networked multiplayer feature, where input lag can make or break the gameplay experience. Below is a detailed breakdown of how the engine achieves responsive input handling, with direct references to the source code implementation.

## Early Input Polling: Capturing Controller State First

**Early input polling** ensures the freshest controller data is available for each game tick. Rather than reading input after game logic or rendering—which would introduce a full frame of delay—the engine polls hardware immediately.

In [`src/core2/ba/bainput.c`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/core2/ba/bainput.c), the `bainput_update()` function performs this polling:

```c
/* src/core2/ba/bainput.c – early input update */
void bainput_update(void) {
    // Poll controller hardware first thing each frame
    controller_poll(&gControllerState);
    // Store raw values for later replay
    gRawInputBuffer[gCurrentFrame] = gControllerState;
}

```

This function is called at the start of each tick from [`src/core2/ba/bsmethods.c`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/core2/ba/bsmethods.c), guaranteeing that **input capture precedes all other frame processing**. By eliminating the one-frame "wait" common in engines that poll input later, Lighthouse achieves more responsive controls.

## Raw-Input Recording: Preserving Exact Controller State

To support networked multiplayer and demo playback, Lighthouse stores every frame's **raw stick axes and button flags** in a circular buffer. This **raw-input recording** captures unprocessed controller data rather than interpreted actions, enabling precise re-simulation during replay.

The recording occurs in [`src/core2/sprite/render.c`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/core2/sprite/render.c), with explicit comments noting its purpose for interpolation:

```c
/* src/core2/sprite/render.c – recording raw inputs for replay */
void render_frame(void) {
    // [port] Record the raw inputs so replay can angle-lerp them against
    record_raw_input(gRawInputBuffer[gCurrentFrame]);
    // …
}

```

Comments at lines 90 and 231 document this design decision, linking the recording phase directly to the interpolation system used during replay.

## Angle-Lerp Interpolation: Smoothing Networked Motion

When replaying recorded inputs—whether for LAN multiplayer or demo playback—Lighthouse applies **angle-lerp interpolation** to smooth timing differences caused by network latency or frame-rate variations. This technique linearly interpolates between stored input states, producing fluid motion even when replay runs at a different tick rate than original capture.

The interpolation uses angle-aware lerping to handle the circular nature of analog stick values:

```c
/* Simple angle-lerp used during replay */
static float lerp_angle(float a, float b, float t) {
    float diff = fmodf(b - a + 180.0f, 360.0f) - 180.0f;
    return a + diff * t;
}

/* Applying the lerp when replaying inputs */
void replay_input(Frame *prev, Frame *next, float alpha) {
    gReplayedStickX = lerp_angle(prev->stickX, next->stickX, alpha);
    gReplayedStickY = lerp_angle(prev->stickY, next->stickY, alpha);
    gReplayedButtons = (alpha < 0.5f) ? prev->buttons : next->buttons;
}

```

This interpolation eliminates visual stutter that would otherwise occur from discrete input samples, making **networked play feel responsive despite underlying latency**.

## Input-Lag Compensation Buffers: Absorbing Network Spikes

Lighthouse implements a **configurable input buffer** to absorb occasional latency spikes without stalling game state. Located in [`include/variables.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/include/variables.h), the `INPUT_LAG_BUFFER_FRAMES` setting controls buffer depth—typically a few frames.

The buffer flushes only when the replay catches up, maintaining responsive gameplay during transient network issues. Synchronization logic in [`src/core2/ba/bsmethods.c`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/core2/ba/bsmethods.c) handles this flushing behavior, ensuring the system recovers smoothly from input delays.

## Key Source Files for Input-Lag Minimization

| File | Role in Input-Lag Reduction |
|------|----------------------------|
| [`src/core2/ba/bainput.c`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/core2/ba/bainput.c) | Core input polling and raw-input buffer population |
| [`src/core2/ba/bsmethods.c`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/core2/ba/bsmethods.c) | Orchestrates `bainput_update()` calls; handles buffer flushing |
| [`src/core2/sprite/render.c`](https://github.com/HarbourMasters/Lighthouse/blob/main/src/core2/sprite/render.c) | Records raw inputs with interpolation hints |
| [`include/variables.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/include/variables.h) | Defines `INPUT_LAG_BUFFER_FRAMES` configuration |

## Summary

Lighthouse minimizes input lag in the port through four integrated techniques:

- **Early input polling** captures controller state before any frame processing begins
- **Raw-input recording** preserves exact analog and digital inputs for deterministic replay
- **Angle-lerp interpolation** smooths input replay across varying frame rates and network conditions
- **Configurable input buffers** absorb latency spikes without gameplay stalls

These mechanisms work together to **synchronize remote players with minimal visual delay**, preserving the responsive feel of the original console experience across networked connections.

## Frequently Asked Questions

### How does early input polling reduce input lag compared to standard engines?

Standard engines often poll input after game logic or rendering, forcing player actions to wait up to one full frame before affecting the game state. Lighthouse calls `bainput_update()` at the very start of each tick—before any processing—so controller data is immediately available for the current frame's simulation.

### What is angle-lerp interpolation and why does Lighthouse use it?

**Angle-lerp interpolation** is a specialized linear interpolation that correctly handles the circular wraparound of angle values (0° to 360°). Lighthouse uses it to smoothly transition between recorded analog stick positions during replay, preventing discontinuities that would cause jerky movement when network conditions vary.

### Can the input-lag buffer size be adjusted for different network conditions?

Yes. The `INPUT_LAG_BUFFER_FRAMES` variable in [`include/variables.h`](https://github.com/HarbourMasters/Lighthouse/blob/main/include/variables.h) allows developers or advanced users to tune buffer depth. Larger buffers tolerate more latency variance but increase baseline delay; smaller buffers maximize responsiveness but risk stalls on network spikes.

### Why does Lighthouse record raw inputs instead of processed game actions?

Raw inputs—uninterpreted stick axes and button flags—enable **deterministic replay** across different game builds and platforms. Recording processed actions would encode assumptions about control schemes and dead zones that might differ between original capture and replay environments.