6359a0b36e599b3a496019b5b034ff375dba4ae9
Audit pass 5 - five distinct cleanups bundled into one omnibus.
1. Element-stride byte-swapping for savestate fields (state.h, state.c,
fceu-endian.{h,c})
The SFORMAT 's' field was previously {bit 31 = RLSB, bits 0..30 =
byte size}. RLSB triggers FlipByteOrder() on MSB hosts, which
reverses the entire entry buffer end-to-end. That is correct for a
single primitive (size <= 8 bytes) but wrong for an array of
multi-byte primitives - reversing the whole buffer would swap
element 0 with element N-1 and reverse their bytes too, scrambling
the data.
The previous workaround was either splitting an N-element array
into N separate single-primitive entries with distinct chunk IDs
(n106 PlayIndex split into IDX0..IDX7) or skipping the entry
entirely on big-endian hosts (the GEKKO #ifndef in vrc6.c / vrc7.c).
Both approaches mean BE saves are not portable to LE and vice
versa, and force the same workaround at every new array site.
This pass adds proper stride support:
* SFORMAT 's' encoding is now {bit 31 = RLSB, bits 24..30 =
stride in bytes (0 = legacy/unset), bits 0..23 = byte size}.
16 MiB max size, well above any actual savestate field.
* FCEUSTATE_RLSB_ARRAY(stride) macro for the new pattern.
* FlipByteOrderStrided() byte-swaps each element of an array
independently. Round-trip identity verified: [01 00 00 00 ...]
-> [00 00 00 01 ...] -> [01 00 00 00 ...].
* state.c's SubWrite / ReadStateChunk / CheckS use new helpers
sf_size() / sf_stride() / sf_flip() that mask the size out of
the new bit layout and dispatch to the strided variant when
stride < size.
Backwards compatible: legacy single-primitive entries (size == 1,
2, 4, 8) leave the stride bits at zero, which sf_stride() reads
as "stride equals size" and falls through to FlipByteOrder() as
before. No on-disk format change. Existing single-primitive RLSB
sites are unchanged.
The infrastructure is now in place so any future SFORMAT entry
that is an array of multi-byte primitives can be expressed as a
single entry (e.g. "{ buf, sizeof(buf) | FCEUSTATE_RLSB_ARRAY(4),
"BUF." }") without splitting or skipping. The existing PlayIndex
split and GEKKO #ifndefs are intentionally left untouched -
migrating them would alter the on-disk savestate format and is a
separate decision.
2. iNES1-vs-iNES2 sizing helpers (cart.h)
Twelve sites across the codebase encoded the same conditional:
info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) : default
Sometimes for PRGRAM, sometimes for CHRRAM, sometimes in bytes,
sometimes after dividing by 1024. The pattern is verbose and easy
to write inconsistently.
Added two inline helpers in cart.h:
- CartInfo_PRGRAM_bytes(info, default_bytes)
- CartInfo_CHRRAM_bytes(info, default_bytes)
Migrated 9 of the 13 sites: cartram.c (2), 162.c, 163.c, 134.c,
399.c, 478.c, 480.c, 484.c. The remaining 4 are non-helper-fitting
variants (164.c special masking, 2 cartram SaveGameLen sites with
different fallback semantics, mmc3.c Boogerman submapper detection).
3. -Wundef enabled permanently (Makefile.libretro)
Zero warnings out of the box - no #if-on-undefined-macro footguns
in the codebase. Now part of WARNING_DEFINES alongside the existing
-Wsign-compare.
4. -Wmissing-prototypes enabled permanently (Makefile.libretro)
Started at 198 warnings, cleared all of them:
* Mass-static-ified ~96 functions across 75 files that were
defined non-static but only used within their own translation
unit. (See static_prototype_fixer.py in the development notes.)
* K&R-style empty-parens prototypes "()" replaced with explicit
"(void)" across all asic_*.{c,h} files - GCC treats "()" as
"any args" and refuses to match it against a separate K&R
definition.
* Added missing forward declarations to public headers:
- fds.h (FDSLoad)
- nsf.h (NSFLoad)
- ines.h (iNESLoad)
- unif.h (UNIFLoad)
- latch.h (LatchHardReset, K&R fix)
- eeprom_93Cx6.h (eeprom_93Cx6_read, K&R fix)
Each header gained an "#include "file.h"" where needed.
* fds_apu.c now includes its own fds_apu.h header (was missing).
* fds_apu.h: removed unused FDSSoundRead declaration (the function
is internal-static).
* cartram.h: removed unused CartRAM_close declaration (the function
is internal-static).
* input.h: added a centralised block of FCEU_Init* prototypes
(Zapper, Mouse, Powerpad, Arkanoid, VirtualBoy, FKB, SuborKB,
PEC586KB, HS, Mahjong, FamilyTrainerA/B, OekaKids, TopRider,
BarcodeWorld, BattleBox, QuizKing, FTrainerA/B, SpaceShadow,
LCDCompZapper, ArkanoidFC) plus FCEU_ZapperSetTolerance. These
were previously declared as "extern" inside src/input.c.
* Static-ified FP_FASTAPASS callbacks in 106.c, 65.c, 67.c,
asic_h3001.c, asic_vrc3.c (those with no external callers);
left non-static for those that have header decls or are
referenced from sibling .c files (asic_mmc1, asic_vrc6,
asic_vrc7, flashrom).
* For a small set of cross-file functions where adding a header
was disproportionate to the value (MMC5_hb, NSFMMC5_Close,
GetKeyboard, FCEU_GetJoyJoy), placed a forward declaration
immediately above the definition. This satisfies
-Wmissing-prototypes (which checks for any prior declaration
in scope) without churning the public-header layout.
5. -Wshadow partial cleanup (not enabled permanently)
Fixed five real shadows that were either bugs or actively
misleading:
* src/boards/476.c: removed an inner "int i" that shadowed the
outer loop counter.
* src/boards/mmc5.c MMC5_hb: parameter "scanline" renamed to
"sl_param" (was shadowing the global "scanline").
* src/boards/n106.c DoNamcoSound: parameter "Wave" renamed to
"WaveBuf" (was shadowing the global Wave audio buffer); also
updated the forward declaration and the matching parameter
on sound.h's NeoFill function pointer typedef.
* src/boards/vrc7.c UpdateOPLNEO: same Wave -> WaveBuf rename.
* src/ntsc/nes_ntsc_impl.h: renamed an inner loop counter "n"
that shadowed an outer "n".
* src/drivers/libretro/libretro.c FCEUD_RegionOverride: local
"pal" renamed to "is_pal" (was shadowing the typedef "pal" from
palette.h).
* src/palette.c FCEUI_SetPaletteArray: parameter "pal" renamed
to "data" (same shadow); driver.h declaration updated to match.
-Wshadow itself is NOT enabled permanently because the remaining
warnings are deliberate parameter naming conventions (XBuf in
draw functions, X in cpu hooks) and third-party blargg ntsc code.
In addition, four files were touched as part of an MSVC-build fix
that came up mid-pass: src/fds.c, src/nsf.c, src/ines.c, and
src/drivers/libretro/libretro_dipswitch.c had snprintf() calls
introduced in pass 4 that fail to link on pre-MSVC2015 toolchains
when STATIC_LINKING=1 (the libretro-common compat_snprintf.c shim
isn't compiled in those configurations). Replaced each snprintf with
either sprintf-into-bounded-buffer (the format strings have known
maximum output) or strlcpy/strlcat for the dipswitch key-build case.
All output is still bounded; truncation happens via strl*'s normal
truncation semantics where applicable.
All added code is C89-clean (top-of-block declarations only, no
mixed decls, no // comments, INLINE macro from fceu-types.h instead
of bare "inline"). Builds clean under -std=gnu11 with -Wno-write-
strings -Wsign-compare -Wundef -Wmissing-prototypes; zero errors,
zero warnings.
Determinism audit (audit_determinism.py): no rand/time/long
double/threads issues introduced.
FCE Ultra mappers modified
FCEU "mappers modified" is an unofficial build of FCEU Ultra by CaH4e3, which supports a lot of new mappers including some obscure mappers such as one for unlicensed NES ROM's.
Sequential targets Light Guns support added
Support for Sequential targets Light Guns has been added. "Gun Aux A" serves as light sensor logic input.
Description
Languages
C
97.7%
Python
2%
C++
0.2%