Skip to content

feat: add Star Wars: Dark Forces (The Force Engine port) - #120

Merged
finger563 merged 9 commits into
mainfrom
feat/dark-forces
Sep 17, 2026
Merged

finger563 merged 9 commits into
mainfrom
feat/dark-forces

Conversation

@finger563

Copy link
Copy Markdown
Contributor

Description

Adds Star Wars: Dark Forces as a new system, built on The Force Engine (TFE), using BSzili's Amiga port as the base (already stripped of the desktop-only subsystems). The game plays from the original DOS data on the SD card. The PR also fixes shared issues found along the way (Doom crashes and sprite flicker, an LVGL race, and the 8MB ESP-BOX PSRAM budget).

Dark Forces

  • components/darkforces: vendored TFE subset (tfe/, changes listed in VENDOR.md) plus ESP32 platform code in src/platform (render backend, audio, threads, memory regions, allocator).
  • main/darkforces_cart.hpp: cart with gamepad mapping, emulator pause menu, and save/load to the emulator's save slots.
  • Rendering at 320x200 through the native RGB565 palette, double buffered to avoid tearing and flicker.
  • Audio at 11025 Hz: iMuse sound effects plus OPL3 music on core 1.
  • Controls and SD card setup are documented in the README. metadata.csv references darkforces/DARK.GOB.
  • Enable or disable the port with ENABLE_DARKFORCES in the top-level CMakeLists.txt.

Memory

Everything Dark Forces allocates lives in BoxEmu's 4MB ROM block while it runs, which is unused because the game reads its data from the SD card.

  • After the library builds, its malloc/free/new/delete calls are renamed to df_* functions (alloc_redirect.syms). Those functions allocate from the pool (src/platform/esp_alloc.cpp).
  • free/realloc are wrapped firmware-wide so pointers into the block always go back to the pool.
  • The block is only used inside Dark Forces entry points and threads. Each session gets a per-session magic value, and the exit report lists anything still live.
  • The engine's large statics, regions and renderer state also live in the block.
  • Static caches are released at shutdown, and each region block records its owner.
  • Startup peak drops from 5.1MB to 3MB: level sounds load on first play, and the escape menu frames load only while that menu is open.
  • pool_allocator: frees are now O(1) with lazy coalescing and a first-free hint. It also gains pool_block_size() and pool_walk().

Shared changes (affect all cores)

  • sdkconfig.defaults:
    • Read-only data stays in flash (CONFIG_SPIRAM_RODATA off). Copying it to PSRAM left the 8MB ESP-BOX with about 60 bytes of PSRAM at the menu; it now has about 1.48MB free.
    • LVGL uses the system heap instead of a fixed 50KB pool. That pool ran out in the pause menu, and LVGL halts when that happens.
    • CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is enabled.
  • LVGL race fix. Gui and Menu share one LVGL instance but locked separate mutexes, and both update LVGL from battery events. They now share BoxEmu::lvgl_mutex(), which fixes a double free and crash in lv_event_send.
  • Doom:
    • Tables written at runtime are no longer const. On IDF 6, rodata is write-protected, so those writes faulted.
    • Frames are copied into two present buffers, which fixes the long-standing sprite flicker.
  • SD card: max_files goes from 5 to 16, because the game keeps its archives open.

Motivation and Context

Adds a new game to the emulator. It also makes the 8MB ESP-BOX usable with the larger firmware, and fixes crashes that affect other cores.

How has this been tested?

Tested on hardware:

  • ESP32-S3-BOX-3 (16MB PSRAM): Dark Forces through cutscenes, the agent menu, and the first level at the 50 fps cap. Save, load, quit and relaunch. Then Doom, Genesis, NES and GBC.
  • ESP32-S3-BOX (8MB PSRAM): repeated Dark Forces sessions with save, quit, relaunch and load, followed by Doom and Sonic (Genesis).
  • Leak check: after start, load and quit, the exit report shows 0 allocations left in the ROM block.

Notes for review

  • License: TFE is GPL-2.0, and this repository is MIT. A firmware image that includes the Dark Forces component has to be distributed under GPL-2.0 terms. It may be worth keeping ENABLE_DARKFORCES off in published release builds, or deciding how you want to handle it.
  • Known limitations:
    • On the 8MB ESP-BOX, OPL3 music synthesis takes 15–24 ms per 23 ms chunk, so music can stutter. The system stays responsive because the audio task always yields.
    • After Dark Forces exits, the largest free PSRAM block is sometimes about 690KB, down from 1.4MB at boot.
  • Other cores may perform slightly differently with read-only data in flash. Genesis, Doom and NES were checked by hand, but FPS was not benchmarked.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation Update
  • Hardware (schematic, board, system design) change
  • Software change

Checklist:

  • My change requires a change to the documentation.
  • I have added / updated the documentation related to this change via either README or WIKI

🤖 Generated with Claude Code

https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1

finger563 and others added 9 commits September 13, 2026 10:49
Add a `darkforces` component built on BSzili's Amiga branch of The Force
Engine (TFE v1.09.410, commit d116b7a9), which already strips the desktop
subsystems and provides low-spec code paths. The `__AMIGA__` guards are
renamed to `TFE_ESPBOX`; provenance and the list of vendored changes are in
components/darkforces/VENDOR.md.

ESP32 platform layer (components/darkforces/src/platform):
- esp_render: the classic fixed-point renderer draws into BoxEmu frame
  buffer 0 (8-bit 320x200) and the palette is converted to RGB565.
- esp_audio: FreeRTOS task mixing the iMuse 8-bit sound effects with the
  OPL3 (Nuked) MIDI music at 11025 Hz into the I2S output.
- esp_thread / esp_memory / esp_stubs: FreeRTOS threads, PSRAM-backed
  memory regions, and stubs for the console, front end, GPU renderers,
  SF2/system MIDI, captions and reticle.
- Large static engine state is placed in PSRAM through a linker fragment
  (CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY).

Integration: DarkForcesCart (mirrors DoomCart), `.gob` ROM detection
(point metadata.csv at DARK.GOB), gamepad mapping with a SELECT modifier
and a d-pad driven virtual mouse for the game's menus, and README docs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Allocating the engine's memory regions and the ~320KB classic renderer
state from the 4MB ROM block (unused while Dark Forces runs), drop the
unused float-renderer state stub (300KB), and size-optimize everything
except the renderer/synth hot paths. PSRAM heap after boot goes from
3.8MB (ROM block allocation failed) to 4.5MB.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Fixes found while testing on hardware:
- Endian shim: the Amiga branch's SDL_endian.h declared a big-endian CPU, so
  every value read from the game files was byte swapped (crash opening DARK.GOB).
- SD card mount allowed only 5 open files, but the engine keeps its GOB and LFD
  archives open; raise to 16 and guard the escape-menu loader.
- Palette: hand BoxEmu native RGB565 like the other cores (colors were wrong).
- Double-buffer the display: copy each finished frame into alternating display
  buffers so the display task never samples a frame mid-draw (flicker/tearing).
- Audio: keep the I2S stream buffer a couple of chunks ahead of the box's fixed
  60Hz consumer and lower mix levels (pops/clipping).
- Cap the game loop at 50 fps and always block for a tick so the low priority
  touch/gamepad polling and LVGL tasks get CPU (pause menu took seconds to open).
- Gamepad text entry for the agent name (SELECT + d-pad).
- Saves go straight to the emulator's slot files (so the slot shows as used and
  the screenshot appears), loads no longer tear down the MIDI player (mutex
  destroyed while the load path still locks it), and the save system now nulls
  its buffers on shutdown (dangling realloc on the next launch).
- Skip freeing a GPU-only model field after the level region has been cleared
  (use-after-free at level end / load).
- Serialize the memory regions and pool allocator with a mutex: the iMuse MIDI
  thread and the game thread both allocate through them.
- Force the palette to be re-applied after a load (screen stayed black).
- Hang detector (prints last stage + task list through esp_rom_printf) and
  optional task watchdog hooks for diagnosing freezes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Heap tracing showed the retained memory was one-time, not per-launch growth:
- ~800KB of static file read buffers in the level, texture, INF, sprite, model
  and VUE loaders that keep the capacity of the largest file loaded; add
  espbox_free_*_scratch() hooks and call them at shutdown.
- 7 cached GOB/LFD archives never closed at exit (each open FILE holds a 16KB
  stdio buffer): call Archive::freeAllArchives() at shutdown.
- The Landru sound effects archive (jedisfx.lfd) lives in a static object that
  is never destructed: close it in lsystem_destroy().

Retained memory after quit goes from ~980KB to ~13KB.
Heap tracing hooks stay in the glue under CONFIG_HEAP_TRACING_STANDALONE.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Dark Forces (measured with per-caller region attribution on a BOX-3):
- Free the Landru cutscene/menu sounds (~0.4MB) and the agent menu images
  (~0.8MB) when a mission starts, on both the normal and the load-from-save
  paths; the agent menu reloads its images on demand.
- Release the loaders' scratch read buffers (~0.8MB) as soon as a level has
  loaded instead of only at shutdown.
- Region memory accounting (per-caller table printed on pause, pool/heap
  totals in the fps line) for further tuning.
In-level free PSRAM goes from 6.3MB to 7.6MB.

Doom: several tables are declared const but written at runtime
(default_comp, the menu_t definitions, helpstrings, the intermission
animation tables). IDF 6 write-protects rodata mapped into PSRAM, so these
writes now fault (Cache error in M_LoadDefaults / M_Init). Make exactly the
written objects non-const (~3KB).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Dark Forces: map all of libdarkforces' .bss/COMMON to external RAM instead of
listing a few objects. The engine has ~150 objects with static state, which
kept ~46KB of .bss in internal DRAM permanently, whether or not the game is
running, reducing the internal RAM every other core can use for hot data.
Component internal DRAM goes from 52KB to 11KB (the rest is initialized .data).

Doom: I_FinishUpdate pushed the render buffer itself to the display task and
kept rendering the next frame into it, so the display could convert rows that
were already being redrawn; sprites (drawn last) flickered. Doom can't swap
render targets (the status bar and border are drawn incrementally), so copy
each finished frame into one of two 8-bit present buffers carved out of
frame_buffer1 and push the copy, the same fix used for Dark Forces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Like the other cores, the port's large static buffers now live in the
emulator's shared memory system and only take up RAM while Dark Forces is
running. Each converted static keeps its name but becomes a pointer; the
owning file provides an espbox_shared_*(bool alloc) hook (see
tfe/TFE_System/espboxShared.h) and darkforces_shared_memory.cpp allocates
them at game init and releases them with shared_mem_clear() at exit.

Converted (24 objects, ~115KB): file stream work buffers and writeString
scratch, OPL3 chip state, MIDI player note table and command buffer, Landru
music sequences, parser line buffer, weapon table, palettes, settings and
save-system path buffers, the wall renderer's sprite column buffer, the
platform audio mix buffers, and the region attribution table.

Left static: iMuse tables linked into lists that are not all reset on
shutdown, objects with constructors, initialized tables, the OPL3 pan table
(built once behind a flag) and the log buffer (used after shutdown).

Permanent PSRAM .bss of the component: 163KB -> 51KB (internal DRAM unchanged
at 11KB of initialized data).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
… the ROM block

Dark Forces reads its data from the SD card, so BoxEmu's 4MB ROM block is free
while it runs. Everything the port allocates now lives there:
- libdarkforces.a's malloc/calloc/realloc/strdup/new/delete are renamed after
  the build (alloc_redirect.syms) to an allocator backed by the block
  (src/platform/esp_alloc.cpp); free/realloc are wrapped firmware-wide so block
  pointers always return to it. The block is only used inside Dark Forces entry
  points and threads, allocations carry a per-session magic, and the exit report
  lists anything still live.
- The engine's large statics, regions and renderer state use the block too
  (replacing the shared_memory buffers, which could not be allocated on 8MB).
- Static STL caches (textures, sprites, models, paths, settings, ...) are
  released at shutdown so nothing dangles into the block on relaunch.
- Level sounds load on first play and the escape menu frames only while it is
  open (startup peak 5.1MB -> 3MB).
- The audio task always yields a tick (it starved core 1 when OPL3 synthesis
  fell behind); OPL3 tables are in internal RAM.
- GOB directory reads are validated.

pool_allocator: O(1) frees with lazy coalescing and a first-free hint, plus
pool_block_size() and pool_walk().

Shared fixes needed on the 8MB box:
- sdkconfig.defaults: read-only data stays in flash (CONFIG_SPIRAM_RODATA off),
  freeing ~1.5MB of PSRAM heap; LVGL uses the system heap instead of a fixed
  50KB pool, which ran out in the pause menu and halted LVGL.
- The GUI and the emulator menu share one LVGL instance but locked separate
  mutexes, and both update LVGL from battery events: they now share
  BoxEmu::lvgl_mutex() (fixes a double free / crash in lv_event_send).

Verified on the 8MB ESP-BOX: repeated Dark Forces sessions with save, quit,
relaunch and load, followed by Doom and Sonic.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Landru allocates and frees with whichever region is current (persistent
"Landru" or "Cutscene"), so blocks are sometimes freed through the other
region. The port's region allocator unlinked the block from the region it was
given, which corrupted both lists: 18 cutscene film and palette blocks were
then never released and stayed in the 4MB ROM block after every session that
played a cutscene or loaded a save.

Each block now records its owning region; frees and reallocs always use it.
The exit report also identifies region blocks and their allocating code.

Verified on the BOX-3: start, load, quit leaves 0 blocks in the ROM block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AWhoGwibqcKDhcG17mjVT1
Copilot AI lite review requested due to automatic review settings September 17, 2026 04:37
@finger563
finger563 merged commit 5f84894 into main Sep 17, 2026
2 of 4 checks passed
@finger563
finger563 deleted the feat/dark-forces branch September 17, 2026 04:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical and moderate findings remain across build gating, lifecycle synchronization, rendering, parsing, and LVGL safety.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds Star Wars: Dark Forces through a vendored The Force Engine port, with ESP32 platform integration and shared memory, rendering, audio, LVGL, and Doom updates.

Changes:

  • Integrates Dark Forces cartridge handling, metadata, controls, save/load, and documentation.
  • Adds TFE allocation, rendering, audio, threading, and platform support.
  • Updates PSRAM/LVGL/SD configuration and Doom presentation handling.
File summaries
File Description
sdkconfig.defaults Updates PSRAM, LVGL, and external-memory configuration.
metadata.csv Registers Dark Forces data.
main/carts.hpp Adds cartridge dispatch.
components/rom_info/src/rom_info.cpp Implements ROM information handling.
components/rom_info/include/rom_info.hpp Defines ROM information interfaces.
components/pool_allocator/include/pool_allocator.h Defines pool allocator APIs.
components/menu/include/menu.hpp Updates menu LVGL synchronization.
components/gui/include/gui.hpp Updates GUI LVGL synchronization.
components/doom/src/doom.cpp Updates Doom rendering and presentation buffers.
components/doom/prboom/wi_stuff.c Updates Doom platform integration.
components/doom/prboom/doomstat.h Updates Doom runtime declarations.
components/doom/prboom/doomstat.c Updates Doom runtime state.
components/darkforces/tfe/TFE_System/Threads/Win32/threadWin32.h Provides Win32 thread compatibility definitions.
components/darkforces/tfe/TFE_System/Threads/Win32/signalWin32.h Provides Win32 signal compatibility definitions.
components/darkforces/tfe/TFE_System/Threads/Win32/mutexWin32.h Provides Win32 mutex compatibility definitions.
components/darkforces/tfe/TFE_System/Threads/thread.h Defines TFE thread interfaces.
components/darkforces/tfe/TFE_System/Threads/signal.h Defines TFE signal interfaces.
components/darkforces/tfe/TFE_System/Threads/mutex.h Defines TFE mutex interfaces.
components/darkforces/tfe/TFE_System/Threads/Linux/threadLinux.h Provides Linux thread compatibility definitions.
components/darkforces/tfe/TFE_System/Threads/Linux/mutexLinux.h Provides Linux mutex compatibility definitions.
components/darkforces/tfe/TFE_System/tfeMessage.h Defines TFE messaging support.
components/darkforces/tfe/TFE_System/parser.h Defines parser interfaces.
components/darkforces/tfe/TFE_System/memoryPool.h Defines TFE memory pool support.
components/darkforces/tfe/TFE_System/log.cpp Implements TFE logging.
components/darkforces/tfe/TFE_System/frameLimiter.h Defines frame limiting support.
components/darkforces/tfe/TFE_System/espboxShared.h Defines ESP-BOX shared platform helpers.
components/darkforces/tfe/TFE_System/endian.h Defines endian utilities.
components/darkforces/tfe/TFE_System/CrashHandler/crashHandler.h Defines crash handler interfaces.
components/darkforces/tfe/TFE_RenderShared/quadDraw2d.h Defines 2D quad drawing support.
components/darkforces/tfe/TFE_RenderShared/lineDraw2d.h Defines 2D line drawing support.
components/darkforces/tfe/TFE_RenderBackend/vertexBuffer.h Defines vertex buffer support.
components/darkforces/tfe/TFE_RenderBackend/textureGpu.h Defines GPU texture support.
components/darkforces/tfe/TFE_RenderBackend/shaderBuffer.h Defines shader buffer support.
components/darkforces/tfe/TFE_RenderBackend/indexBuffer.h Defines index buffer support.
components/darkforces/tfe/TFE_RenderBackend/dynamicTexture.h Defines dynamic texture support.
components/darkforces/tfe/TFE_PostProcess/postprocesseffect.h Defines post-processing effects.
components/darkforces/tfe/TFE_PostProcess/postprocess.h Defines post-processing support.
components/darkforces/tfe/TFE_PostProcess/overlay.h Defines post-processing overlays.
components/darkforces/tfe/TFE_PostProcess/bloomThreshold.h Defines bloom threshold processing.
components/darkforces/tfe/TFE_PostProcess/bloomMerge.h Defines bloom merge processing.
components/darkforces/tfe/TFE_PostProcess/bloomDownsample.h Defines bloom downsampling.
components/darkforces/tfe/TFE_PostProcess/blit.h Defines post-process blitting.
components/darkforces/tfe/TFE_Polygon/polygon.h Defines polygon rendering support.
components/darkforces/tfe/TFE_Outlaws/outlawsMain.h Defines Outlaws compatibility interfaces.
components/darkforces/tfe/TFE_Outlaws/outlawsMain.cpp Implements Outlaws compatibility support.
components/darkforces/tfe/TFE_Memory/memoryRegion.h Defines memory region management.
components/darkforces/tfe/TFE_Memory/chunkedArray.h Defines chunked array storage.
components/darkforces/tfe/TFE_Jedi/Task/taskMacros.h Defines task macros.
components/darkforces/tfe/TFE_Jedi/Renderer/textureInfo.h Defines renderer texture information.
components/darkforces/tfe/TFE_Jedi/Renderer/rwallSegment.h Defines wall segment rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/rwallRender.h Defines wall rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/rsectorRender.cpp Implements sector rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/rscanline.h Defines scanline rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/robjectRender.h Defines object rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/rlimits.h Defines renderer limits.
components/darkforces/tfe/TFE_Jedi/Renderer/redgePair.h Defines edge pair handling.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_GPU/spriteDisplayList.h Defines GPU sprite display lists.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_GPU/rsectorGPU.h Defines GPU sector rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_GPU/renderDebug.h Defines GPU renderer debugging.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_GPU/rclassicGPU.h Defines classic GPU rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_GPU/objectPortalPlanes.h Defines GPU portal planes.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_GPU/modelGPU.h Defines GPU model rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_GPU/debug.h Defines renderer debug support.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/screenDraw.h Defines floating-point screen drawing.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/rsectorFloat.h Defines floating-point sector rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/robj3d_float/robj3dFloat.h Defines floating-point 3D object rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/robj3d_float/robj3dFloat_TransformAndLighting.h Defines floating-point transforms and lighting.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/robj3d_float/robj3dFloat_PolygonSetup.h Defines floating-point polygon setup.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/robj3d_float/robj3dFloat_PolygonDraw.h Defines floating-point polygon drawing.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/robj3d_float/robj3dFloat_Culling.h Defines floating-point culling.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/robj3d_float/robj3dFloat_Clipping.h Defines floating-point clipping.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/rlightingFloat.h Defines floating-point lighting.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/rflatFloat.h Defines floating-point flat rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/redgePairFloat.h Defines floating-point edge pairs.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Float/rclassicFloat.h Defines classic floating-point rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/rwallFixed.h Defines fixed-point wall rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/rsectorFixed.h Defines fixed-point sector rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/robj3d_fixed/robj3dFixed.h Defines fixed-point 3D object rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/robj3d_fixed/robj3dFixed_TransformAndLighting.h Defines fixed-point transforms and lighting.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/robj3d_fixed/robj3dFixed_PolygonSetup.h Defines fixed-point polygon setup.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/robj3d_fixed/robj3dFixed_PolygonDraw.h Defines fixed-point polygon drawing.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/robj3d_fixed/robj3dFixed_Culling.h Defines fixed-point culling.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/robj3d_fixed/robj3dFixed_Clipping.h Defines fixed-point clipping.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/rlightingFixed.h Defines fixed-point lighting.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/rflatFixed.h Defines fixed-point flat rendering.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/redgePairFixed.h Defines fixed-point edge pairs.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/redgePairFixed.cpp Implements fixed-point edge pairs.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/rclassicFixedSharedState.cpp Implements shared fixed renderer state.
components/darkforces/tfe/TFE_Jedi/Renderer/RClassic_Fixed/rclassicFixed.h Defines classic fixed-point rendering.
components/darkforces/tfe/TFE_Jedi/Memory/list.h Defines TFE list storage.
components/darkforces/tfe/TFE_Jedi/Memory/allocator.h Defines TFE allocation interfaces.
components/darkforces/tfe/TFE_Jedi/Math/cosTable.h Provides cosine table data.
components/darkforces/tfe/TFE_Jedi/Level/roffscreenBuffer.h Defines level offscreen buffers.
components/darkforces/tfe/TFE_Jedi/Level/robject.h Defines level objects.
components/darkforces/tfe/TFE_Jedi/Level/rfont.h Defines level font support.
components/darkforces/tfe/TFE_Jedi/Level/levelTextures.h Defines level textures.
components/darkforces/tfe/TFE_Jedi/Level/level.h Defines level management.
components/darkforces/tfe/TFE_Jedi/InfSystem/infState.h Defines information system state.
components/darkforces/tfe/TFE_Jedi/InfSystem/infElevatorUpdateFunc.h Defines elevator update behavior.
components/darkforces/tfe/TFE_Jedi/IMuse/midiData.h Defines MIDI data structures.
components/darkforces/tfe/TFE_Jedi/IMuse/imTrigger.h Defines iMuse triggers.
components/darkforces/tfe/TFE_Jedi/IMuse/imSoundFader.h Defines iMuse sound fading.
components/darkforces/tfe/TFE_Jedi/IMuse/imList.h Defines iMuse lists.
components/darkforces/tfe/TFE_Jedi/IMuse/imList.cpp Implements iMuse lists.
components/darkforces/tfe/TFE_Jedi/IMuse/imDigitalSound.h Defines iMuse digital sound.
components/darkforces/tfe/TFE_Jedi/IMuse/imConst.cpp Implements iMuse constants.
components/darkforces/tfe/TFE_Game/saveSystem.h Defines save system support.
components/darkforces/tfe/TFE_Game/reticle.h Defines reticle support.
components/darkforces/tfe/TFE_Game/igame.h Defines game interfaces.
components/darkforces/tfe/TFE_FrontEndUI/profilerView.h Defines profiler UI support.
components/darkforces/tfe/TFE_FrontEndUI/modLoader.h Defines mod loading support.
components/darkforces/tfe/TFE_FrontEndUI/frontEndUi.h Defines front-end UI support.
components/darkforces/tfe/TFE_FrontEndUI/editorTexture.h Defines editor texture support.
components/darkforces/tfe/TFE_FileSystem/filewriterAsync.h Defines asynchronous file writing.
components/darkforces/tfe/TFE_FileSystem/fileutil.h Defines file utilities.
components/darkforces/tfe/TFE_DarkForces/weaponFireFunc.h Defines weapon firing behavior.
components/darkforces/tfe/TFE_DarkForces/vueLogic.h Defines VUE logic.
components/darkforces/tfe/TFE_DarkForces/util.h Defines Dark Forces utilities.
components/darkforces/tfe/TFE_DarkForces/util.cpp Implements Dark Forces utilities.
components/darkforces/tfe/TFE_DarkForces/updateLogic.h Defines update logic.
components/darkforces/tfe/TFE_DarkForces/random.h Defines random number support.
components/darkforces/tfe/TFE_DarkForces/random.cpp Implements random number support.
components/darkforces/tfe/TFE_DarkForces/playerLogic.h Defines player logic.
components/darkforces/tfe/TFE_DarkForces/playerCollision.h Defines player collision handling.
components/darkforces/tfe/TFE_DarkForces/pickup.h Defines pickup behavior.
components/darkforces/tfe/TFE_DarkForces/mission.h Defines mission support.
components/darkforces/tfe/TFE_DarkForces/Landru/textCrawl.h Defines text crawl support.
components/darkforces/tfe/TFE_DarkForces/Landru/ltimer.h Defines Landru timing support.
components/darkforces/tfe/TFE_DarkForces/Landru/lsystem.h Defines Landru system support.
components/darkforces/tfe/TFE_DarkForces/Landru/lrect.h Defines Landru rectangles.
components/darkforces/tfe/TFE_DarkForces/Landru/lmusic.h Defines Landru music support.
components/darkforces/tfe/TFE_DarkForces/Landru/lfont.h Defines Landru font support.
components/darkforces/tfe/TFE_DarkForces/Landru/ldraw.h Defines Landru drawing support.
components/darkforces/tfe/TFE_DarkForces/Landru/lcanvas.h Defines Landru canvas support.
components/darkforces/tfe/TFE_DarkForces/Landru/lactorDelt.h Defines Landru delta actors.
components/darkforces/tfe/TFE_DarkForces/Landru/lactorCust.h Defines Landru custom actors.
components/darkforces/tfe/TFE_DarkForces/Landru/lactorAnim.h Defines Landru animated actors.
components/darkforces/tfe/TFE_DarkForces/Landru/cutsceneList.h Defines cutscene lists.
components/darkforces/tfe/TFE_DarkForces/Landru/cutscene.h Defines cutscene support.
components/darkforces/tfe/TFE_DarkForces/Landru/cutscene_player.h Defines cutscene playback.
components/darkforces/tfe/TFE_DarkForces/hud.h Defines the game HUD.
components/darkforces/tfe/TFE_DarkForces/generator.h Defines generator behavior.
components/darkforces/tfe/TFE_DarkForces/GameUI/uiDraw.h Defines game UI drawing.
components/darkforces/tfe/TFE_DarkForces/GameUI/pda.h Defines PDA UI support.
components/darkforces/tfe/TFE_DarkForces/GameUI/missionBriefing.h Defines mission briefing UI.
components/darkforces/tfe/TFE_DarkForces/GameUI/menu.h Defines game menu UI.
components/darkforces/tfe/TFE_DarkForces/GameUI/escapeMenu.h Defines escape menu UI.
components/darkforces/tfe/TFE_DarkForces/GameUI/editBox.h Defines edit box UI.
components/darkforces/tfe/TFE_DarkForces/GameUI/delt.h Defines DELT UI assets.
components/darkforces/tfe/TFE_DarkForces/GameUI/agentMenu.h Defines agent menu UI.
components/darkforces/tfe/TFE_DarkForces/gameMusic.h Defines game music support.
components/darkforces/tfe/TFE_DarkForces/gameMessage.h Defines game messages.
components/darkforces/tfe/TFE_DarkForces/darkForcesMain.h Defines Dark Forces entry points.
components/darkforces/tfe/TFE_DarkForces/config.h Defines game configuration.
components/darkforces/tfe/TFE_DarkForces/config.cpp Implements game configuration.
components/darkforces/tfe/TFE_DarkForces/cheats.h Defines cheat support.
components/darkforces/tfe/TFE_DarkForces/briefingList.h Defines briefing lists.
components/darkforces/tfe/TFE_DarkForces/automap.h Defines automap support.
components/darkforces/tfe/TFE_DarkForces/animLogic.h Defines animation logic.
components/darkforces/tfe/TFE_DarkForces/Actor/welder.h Defines welder actors.
components/darkforces/tfe/TFE_DarkForces/Actor/turret.h Defines turret actors.
components/darkforces/tfe/TFE_DarkForces/Actor/troopers.h Defines trooper actors.
components/darkforces/tfe/TFE_DarkForces/Actor/sewer.h Defines sewer actors.
components/darkforces/tfe/TFE_DarkForces/Actor/scenery.h Defines scenery actors.
components/darkforces/tfe/TFE_DarkForces/Actor/phaseTwo.h Defines phase-two actors.
components/darkforces/tfe/TFE_DarkForces/Actor/phaseThree.h Defines phase-three actors.
components/darkforces/tfe/TFE_DarkForces/Actor/phaseOne.h Defines phase-one actors.
components/darkforces/tfe/TFE_DarkForces/Actor/mousebot.h Defines mousebot actors.
components/darkforces/tfe/TFE_DarkForces/Actor/flyers.h Defines flyer actors.
components/darkforces/tfe/TFE_DarkForces/Actor/exploders.h Defines exploder actors.
components/darkforces/tfe/TFE_DarkForces/Actor/enemies.h Defines enemy actors.
components/darkforces/tfe/TFE_DarkForces/Actor/dragon.h Defines dragon actors.
components/darkforces/tfe/TFE_DarkForces/Actor/bobaFett.h Defines Boba Fett actors.
components/darkforces/tfe/TFE_DarkForces/Actor/animTables.h Defines actor animation tables.
components/darkforces/tfe/TFE_Audio/systemMidiDevice.h Defines system MIDI device support.
components/darkforces/tfe/TFE_Audio/MidiSynth/soundFontDevice.h Defines SoundFont device support.
components/darkforces/tfe/TFE_Audio/midiPlayer.h Defines MIDI playback.
components/darkforces/tfe/TFE_Audio/midiDevice.h Defines MIDI device interfaces.
components/darkforces/tfe/TFE_Audio/audioOutput.h Defines audio output.
components/darkforces/tfe/TFE_Audio/audioFilters.h Defines audio filters.
components/darkforces/tfe/TFE_Audio/audioDevice.h Defines audio device interfaces.
components/darkforces/tfe/TFE_Asset/vueAsset.h Defines VUE assets.
components/darkforces/tfe/TFE_Asset/vocAsset.h Defines VOC assets.
components/darkforces/tfe/TFE_Asset/textureAsset.h Defines texture assets.
components/darkforces/tfe/TFE_Asset/spriteAsset.h Defines sprite assets.
components/darkforces/tfe/TFE_Asset/paletteAsset.h Defines palette assets.
components/darkforces/tfe/TFE_Asset/levelList.h Defines level lists.
components/darkforces/tfe/TFE_Asset/imageAsset.h Defines image assets.
components/darkforces/tfe/TFE_Asset/gmidAsset.h Defines GMID assets.
components/darkforces/tfe/TFE_Asset/gifWriter.h Defines GIF writing support.
components/darkforces/tfe/TFE_Asset/gameMessages.h Defines asset game messages.
components/darkforces/tfe/TFE_Asset/fontAsset.h Defines font assets.
components/darkforces/tfe/TFE_Asset/colormapAsset.h Defines colormap assets.
components/darkforces/tfe/TFE_Asset/assetSystem.h Defines asset system interfaces.
components/darkforces/tfe/TFE_Archive/zipArchive.h Defines ZIP archive support.
components/darkforces/tfe/TFE_Archive/labArchive.h Defines LAB archive support.
components/darkforces/tfe/TFE_Archive/gobMemoryArchive.h Defines GOB memory archives.
components/darkforces/tfe/TFE_A11y/accessibility.h Defines accessibility support.
components/darkforces/src/platform/esp_platform.h Defines ESP32 platform integration.
components/darkforces/linker.lf Defines Dark Forces linker placement.
components/darkforces/include/darkforces.hpp Exposes Dark Forces integration APIs.
components/darkforces/alloc_redirect.syms Defines allocator symbol redirection.
components/box-emu/src/box-emu.cpp Updates shared emulator behavior.
components/box-emu/include/box-emu.hpp Updates shared emulator interfaces.
CMakeLists.txt Integrates the Dark Forces component.
Review details

Suppressed comments (1)

components/darkforces/src/platform/esp_render.cpp:95

  • The display queue stores only this raw pointer and push_frame() is nonblocking, so the display task may still be converting the previous buffer when the two-frame toggle returns here and memcpy overwrites it. A queue-full/drop does not establish ownership either, so this can still tear or corrupt frames under display lag. Add buffer-release/acknowledgement or otherwise prevent reuse until consumption finishes.
  • Files reviewed: 82/449 changed files
  • Comments generated: 13
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread CMakeLists.txt
set(DOOM_COMPONENTS "doom")

### DARK FORCES ###
set(DARKFORCES_COMPONENTS "darkforces")
{
TFE_Memory::DfAllocScope allocScope;
deinit_darkforces();
init_darkforces(s_gobPath, nullptr, 0);
Comment on lines +76 to +79
s_curFrameBuffer = nullptr;
BoxEmu::get().palette(nullptr);
freeDisplayBuffers();
}
static Thread* s_thread = nullptr;

#ifdef TFE_ESPBOX
static bool s_runMusicThread;
Comment on lines +136 to +140
}
}
}
}
s_line[linePos] = 0;
Comment on lines +98 to +103
if (s_audioThreadCallback)
{
lock();
s_audioThreadCallback((f32*)s_sfxBuffer, AUDIO_CALLBACK_BUFFER_SIZE, 1.0f);
unlock();
haveSfx = true;
Comment on lines +57 to +58
thread->m_isRunning = false;
xSemaphoreGive(thread->m_done);
{
m_blockComment = false;
}
else if (m_enableBlockComments && m_buffer[i] == '/' && m_buffer[i+1] == '*')
Comment on lines +218 to +222
uint8_t* dst = presentBuffer[presentIndex];
if (dst) {
memcpy(dst, framebuffer, SCREENWIDTH * SCREENHEIGHT);
box.push_frame(dst);
presentIndex ^= 1;
Comment on lines +24 to +25
// Enable : as a seperator but do not remove it.
void enableColonSeperator();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants