Dated source reference. Current release status: handoff state. Full original relative paths are in the developer archive.
Native asset viewer — October 12, 2026
Historical supporting milestone. Runtime/build observations, paths and next-step statements below belong to their recorded source/date. They are not a current native-engine objective or current machine-installation inventory. Use current state, plan and API verification for active work; original research evidence remains unchanged.
Current scope (October13,2026): Windows-first deep editing and a public extension API; Mac/Linux compatibility follows later. Earlier native-port goals and next-step proposals in this evidence history are superseded. Technical observations and verification limits remain as recorded.
OpenHoops now has a small C++17 asset viewer that opens supported original IFF textures and displays them through SDL3. The local executable is native macOS ARM64, using SDL's Metal renderer. No NBA 2K14 executable, Windows DLL, Wine, or CPU emulator is involved in this viewer's execution. This is an asset research milestone; the reconstructed game still comprises only the six previously verified small routines.
What works and what was tested
- Uses the verified container reader and its narrow standalone DXT1/DXT5 top-mip exporter. It does not expand supported IFF layouts.
- Native BC1/BC3 decoding through pinned bcdec 0.985, with partial-block cropping, exact payload-length checks, aligned block storage, and a 256 MiB decoded-pixel cap.
- 77 original texture resources checked against Pillow 11.3.0 DDS decoding under ASan/UBSan. Alpha matches exactly. Maximum RGB difference is 1/255 in each channel. Output hashes and each resource's original-file identity are in pixel validation.
- 165 synthetic pixel fixtures and six rejection cases passed. These cover dimensions 1–9, both formats, BC1 transparency, both BC3 alpha interpolation modes, truncated/extra bytes, invalid format and output limits.
- SDL3 Metal and software renderer smoke tests ran. For
logo000.iffat 1:1 scale, the 512×512 Metal texture area matches Pillow's independent straight-alpha composite over our checkerboard byte-for-byte. SDL software differs by at most two RGB levels in blending. See renderer validation. - A fit-to-window Metal readback was visually inspected and shows the Philadelphia 76ers logo with the expected transparent surround. Metal/software scaled readbacks differ at nearest-neighbor sampling boundaries; they are not bit-identical. Preserved fit captures are under
analysis/iff/previews/viewer-*-logo000.*. - Existing capture files are refused; unsupported resources/files and invalid frame counts are rejected. Only read access to original IFF files is used.
- File-list navigation, resource navigation, reload, fit/actual-size toggles, checkerboard toggle and file-drop handling are implemented. Interactive desktop input and resizing remain untested: CUA reported the Mac locked. We did not unlock it or interrupt the user for this test.
Native RGBA decoding uses straight alpha and the original decoded row order. There is no color-space transformation, animation, geometry, game UI reconstruction, or in-game asset hot replacement here. Reload currently refreshes the viewer only.
Why the pixel hashes differ from Pillow
This difference was measured rather than hidden. Pillow's BC decoder, lines 45–95, expands RGB565 by bit replication and interpolates already expanded integer channels with truncating division. bcdec, bcdec.h lines 144 onward, uses rounded endpoint expansion and interpolation based on the quantized components. The measured one-level differences are consistent with these algorithms. We do not claim equality to the original game's GPU or assume all possible blocks have the same difference bound. The preserved DDS compressed payloads remain byte-identical to the original assets.
Build and use
The portable CMake entry point is native/CMakeLists.txt. Without the viewer, it builds the IFF tools, pixel decoder/test and both reconstruction experiments. Enabling OPENHOOPS_BUILD_VIEWER requires SDL3 3.4 or a local SDL3 source tree through OPENHOOPS_SDL_SOURCE; zlib is required either way. CMake does not download dependencies.
On this Mac, dependencies are already archived and installed locally. From the project directory:
.venv/bin/python tools/build_native.py
build/native-bin/openhoops_asset_viewer NBA2K14-extracted/logo000.iff NBA2K14-extracted/logo001.iff
build/native-bin/openhoops_iff_pixels NBA2K14-extracted/logo000.iff 0 /tmp/openhoops-new-logo.rgba
Viewer keys: Left/Right selects a supported resource; Up/Down selects a file; R reloads; F fits; 1 uses actual size; B toggles the background; Escape exits. Drop an IFF file to open it. Invalid files show an error rather than retaining a stale image under the new filename. Unsupported resource kinds are omitted from navigation; this is not a complete resource inspector.
For a reproducible renderer check:
.venv/bin/python tools/verify_native_pixels.py
.venv/bin/python tools/verify_native_viewer.py
The viewer accepts --resource INDEX, --renderer metal, --actual-size, --frames N, and --capture NEW.bmp. Capture reads the renderer before presentation, following SDL's API contract. The .rgba utility writes tightly packed RGBA8 bytes; dimensions are printed as JSON. It is a research output, not a self-describing image format.
Build failures and their resolution
The project directory contains a colon. SDL's file(TO_CMAKE_PATH ...) interpreted it as a path-list separator, breaking an unquoted string(FIND ...) argument. More subtly, CMake's own ABI-test source lived below the same colon-containing virtualenv path; generated Makefiles failed with target pattern contains no '%'. That left compiler ABI/implicit include detection empty and caused zlib's SDK include directory to precede libc++ headers. Setting the SDK alone did not fix the underlying failure.
The successful setup stages our small source trees, the pinned CMake runtime, and the SDL source under ~/.local/share/openhoops/, outside the colon-containing path. It sets the macOS SDK explicitly and builds there, then copies the seven executable outputs into build/native-bin. Original game files are never copied into the build stage. The build helper reproduces this setup and records source hashes, commands, tool versions and binary hashes in build evidence. Initial failure logs are retained alongside the successful logs. This is a local path workaround, not a modification to SDL or the original game.
Dependencies, attribution and scope
Dependency evidence records URLs, versions and SHA-256 hashes. Original packages are retained under resources/research-tools/packages.
- SDL 3.4.18, official release archive and zlib license. Source revision
SDL-release-3.4.18-0-g829a65d76. Archive SHA matches GitHub's published asset digest. - bcdec 0.985, Sergii “iOrange” Kudlai and credited contributors, commit
80859ed3b7afb1c527a2a99d70c61457bea72d0c. Unmodified header, README and dual license are in native/vendor/bcdec. We select the MIT alternative. Our adapter is separate. - CMake 4.1.2, archived universal2 PyPI wheel and local runtime.
- Pillow 11.3.0, independent test decoder/compositor only; not required to run the viewer. Its CC0
BcnDecode.cis archived as an explanation of the measured rounding differences. - IFF layout attribution and the statically decompiled Lotsbiss editor remain documented in container research. Game asset provenance is unchanged.
| Target | Build/execution evidence this milestone |
|---|---|
| macOS ARM64 | CMake Release build, CTest, native pixel sanitizer checks, SDL Cocoa + Metal/software renderer execution |
| macOS x64 | Not built or executed |
| Windows x86/x64 | Subsequent MSVC builds, pixel CTest, native comparisons and D3D11 readback passed; see Windows evidence |
| Linux | Not built or executed |
Windows verification found and fixed an explicit-success-return issue in the SDL-renamed entry point. Current viewer hashes are in analysis/windows/viewer-rebuild.json and mac-viewer-rebuild.json; earlier build/validation reports retain their original identities. No rendering behavior changed.
Current priority is the Windows deep-editing API and verified game integration. Additional standalone viewer features and unrelated asset expansion remain outside that work. This viewer is a preserved supporting tool; native boot/menu reconstruction and a whole-engine port are no longer delivery goals.