Skip to content

Add HD terrain tile support (64->256px) with legacy-map fallback#208

Merged
fbraz3 merged 1 commit into
fbraz3:mainfrom
mrkinglollipop:hd-terrain-256
Jul 12, 2026
Merged

Add HD terrain tile support (64->256px) with legacy-map fallback#208
fbraz3 merged 1 commit into
fbraz3:mainfrom
mrkinglollipop:hd-terrain-256

Conversation

@mrkinglollipop

Copy link
Copy Markdown

Summary

Adds HD terrain support by lifting the hardcoded 64px terrain tile resolution to 256px, so terrain textures can be authored/upscaled at 4x. Stock and custom maps continue to work unchanged via a loader-side fallback.

Background

TILE_PIXEL_EXTENT (64) is baked into TileData's fixed-size mip arrays, and WorldHeightMap::countTiles/readTiles integer-divide a source TGA's width by it to infer the tile grid. As a result, simply supplying higher-resolution terrain TGAs does not render sharper — the loader reinterprets the larger image as extra 64px tile variants. Raising the ceiling requires engine changes.

Changes (all in shared Core/GameEngineDevice, so both Generals and Zero Hour build it)

  • Bumps TILE_PIXEL_EXTENT 64 -> 256 and the terrain atlas TEXTURE_WIDTH 2048 -> 8192 (within the 16384 Metal/D3D limit).
  • Restructures the TileData mip chain from 6 fixed levels (32/16/8/4/2/1) to 8 chained levels (128/64/32/16/8/4/2/1). This is the load-bearing part: a naive constant bump makes the first doMip() write a 128x128 result into the old 32x32 member buffer — a buffer overflow. The chain is rebuilt so each level is exactly half its parent down to 1x1.
  • Adds a loader-side fallback in countTiles/readTiles: legacy 64px-grid TGAs are detected (via the caller's INI-declared tile count) and nearest-neighbour expanded to 256px at load, so unmodified base terrain and existing custom maps keep working. HD terrain TGAs simply override the tiles they replace.

Compatibility & cost

  • Backward compatible: stock terrain and custom maps render via the fallback path; no map format change.
  • Per-terrain-tile working memory grows ~16x (about 21 MB -> 333 MB worst case for a ~1000 distinct-tile map). Acceptable on modern hardware; real maps rarely approach that tile count.

Testing

  • Builds clean on macOS arm64 (Apple Silicon), Zero Hour target (build-macos-zh.sh), no new warnings.
  • Boot-tested three ways, each ~100s to the shell with zero crash/assert markers: (1) patched engine + stock terrain (exercises the legacy fallback), (2) patched engine + 4x HD terrain pack (native 256px path), (3) full launcher run. Rendered-frame inspection of in-match terrain is still pending on the author's side.
  • The buffer-overflow trap noted above was specifically checked for and avoided.

AI-generated code disclosure

Per CONTRIBUTING: this change was developed with substantial LLM assistance (Claude Code) under my direction. Verification performed: full compile on the Zero Hour target, the runtime boot tests above, review of the diff against the engine's terrain/tile data flow, and confirmation the change is comment-and-logic scoped to the terrain tile path. I (the PR author) am responsible for its correctness and have kept the diff readable and commented in the project's // GeneralsX @keyword style. Happy to iterate on anything a maintainer flags.

Cut against the GeneralsX-Beta-13 base.

🤖 Generated with Claude Code

…legacy-TGA loader fallback

TILE_PIXEL_EXTENT 64->256 and atlas TEXTURE_WIDTH 2048->8192 (TileData.h, mirrored
in TileData.cpp's shadow macro copy). Mip chain restructured from 6 fixed levels
(32/16/8/4/2/1) to 8 chained levels (128/64/32/16/8/4/2/1) so updateMips/doMip keep
halving exactly once per level -- a naive constant bump alone would have made the
first doMip() write a 128x128 result into the old 32x32 buffer.

WorldHeightMap.cpp countTiles/readTiles gain a legacy-grid detection+scatter path
(ChooseTileGrid + LEGACY_TILE_PIXEL_EXTENT=64) so unmodified base-game and
custom-map TGAs, still packed as NxN grids of 64px cells, keep loading: each
source pixel is nearest-neighbor scattered into the corresponding 4x4 block of
the native 256px tile buffer during the existing single-pass scanline read. The
one genuinely ambiguous width (256px, valid as both a native 1x1 HD grid and a
legacy 4x4 grid of 16 tiles) is disambiguated using the texture class's
INI-declared tile count, threaded through from countTiles to readTiles.

Grep-audited TileData.*, WorldHeightMap.*, TerrainTex.* for remaining hardcoded
64/32/2048 literals -- none remain outside comments/unrelated constants
(VERTEX_BUFFER_TILE_LENGTH is a vertex-grid count, m_numBitmapTiles<2048 is a
tile-count sanity assert, both confirmed unaffected by the pixel-size change).

Builds clean via scripts/build/macos/build-macos-zh.sh (attempt 1/3).
@fbraz3 fbraz3 merged commit e212d92 into fbraz3:main Jul 12, 2026
8 checks passed
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