Commit Graph
979 Commits
Author SHA1 Message Date
a7dcdcaec3 let PlayJA2SampleFromFile take a filename it will not write to
The parameter was STR8, a mutable char*, for a filename the function only
reads: it runs strstr over it and hands it to SoundPlay. environment.cpp picks
between two of them at runtime,

    PlayJA2SampleFromFile( Chance( 50 ) ? "Sounds\\WATERSNAKE_ATTACK_01.WAV"
                                        : "Sounds\\WATERSNAKE_ATTACK_02.WAV", ... );

and the conditional is a const char*, which STR8 has no room for. Literals
passed on their own are still accepted under the MSVC rules, which is why only
these two calls ever failed.

The cast at the call to SoundPlay was already written as (STR) and is left as
it is. SoundPlay, SoundPlayStreamed and SoundLoadSample below it all still
take STR, so making them const is a separate piece of work and a much larger
one; until then that cast is where const stops.

No call site changes. The (char*) cast at LuaInitNPCs.cpp:11640 is now
unnecessary but still valid, and is left for whoever next edits that line.

Verification:

    ninja -C build parse         # both environment.cpp sites gone
    ninja -C build -k 0          # Release, four applications, green
    ninja -C build-debug -k 0    # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
aac53ce71d let ScreenMsg take a format string it will not write to
STR16 is CHAR16*, so ScreenMsg asked for a mutable format string it has no
intention of mutating: the body only hands it to va_start and vswprintf, and
vswprintf takes it as const.

Calls that pass a literal are accepted anyway under the MSVC rules clang-cl
applies. Calls that pass anything else are not, and DynamicDialogue.cpp picks
the format at runtime:

    ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE,
               ...sOpinionModifier >= 0 ? L"%s: %s +%d" : L"%s: %s %d", ... );

The conditional has type const wchar_t*, and there is nowhere for it to go.

Declaring the parameter const CHAR16* is what the function always meant. Every
existing caller still compiles: a literal and a CHAR16* both convert.

Verification:

    ninja -C build parse         # DynamicDialogue.cpp clean
    ninja -C build -k 0          # Release, four applications, green
    ninja -C build-debug -k 0    # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
1d6ff6be3c let CIniReader take its strings as pointers to const
STR8 is char*, so const STR8 is char* const: a const pointer to a mutable
string, which is not what any of these sixty parameters wanted. What they
wanted is const CHAR8*, a pointer to a string they will not write to, and
that is what all of them do.

Under the MSVC compatibility rules clang-cl applies, a string literal still
converts to char*, so most calls survive this mistake untouched. An expression
of type const char* does not, and Intro.cpp has thirteen of them:

    inireader.ReadString("INTRO_BEGINNING", "INTRO_REBEL_CRDT",
                         no_defaults ? "" : "INTRO\\Rebel_cr");

The conditional is a const char*, not a literal, so it has nowhere to bind and
the call does not compile. The other two arguments are literals and are
accepted, which is why only the third one was ever reported.

The invariant: in these two files, every parameter spelled const STR8 becomes
const CHAR8*, and nothing else changes. No body assigns to one of them, so
none needed rewriting; STR8 input_buffer in the five-argument ReadString is
genuinely an output and keeps its type. Three commented-out lines still say
const STR8 and were left as they are.

Verification:

    grep -n 'const[ \t]*STR8' Utils/INIReader.h Utils/INIReader.cpp
        # three hits, all on lines beginning with //

    git show HEAD -U0 | grep '^[+-][^+-]' |
      sed -E 's/const[ \t]+(STR8|CHAR8\*)/const/g; s/^[+-]//' |
      sort | uniq -c | awk '$1 % 2'          # no output

    ninja -C build parse         # ReadString class gone: 45 -> 32 sites
    ninja -C build -k 0          # Release, four applications, green
    ninja -C build-debug -k 0    # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
e56a372871 give the XML tag map and the writer buffer a name
Both of these bound a non-const reference to a temporary, which MSVC accepts
and clang does not, and which leaves the reference dangling once the full
expression ends.

PropertyContainer::initFromXMLFile and writeToXMLFile take their tag map by
non-const reference because the accessors on it insert default tag names as
they are asked for, so it cannot be const and it cannot be a temporary. All
eight call sites passed a freshly built one; they now declare it. Each keeps
its own object, so a map filled in by one call cannot leak into the next, the
same as when each call built its own temporary.

XMLWriter::writeToFile bound std::string& to what stringstream::str() returns
by value. Declared as a value it is initialised straight from the return with
no copy, and const because only c_str() and length() are asked of it.

Verification:

    grep -rn 'PropertyContainer::TagMap()' .   # nothing
    ninja -C build parse         # no i18n or XMLWriter sites remain
    ninja -C build -k 0          # Release, four applications, green
    ninja -C build-debug -k 0    # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
5e2982c509 take popup option names by const reference, not by pointer
POPUP_OPTION copies the name it is given -- `this->name = *newName` into a
std::wstring member -- but its constructor took a std::wstring*, so 64 call
sites spelled the argument `&std::wstring( pStr )`. Taking the address of a
temporary is ill-formed, and clang refuses it outright:

    error: taking the address of a temporary object of type 'std::wstring'

It happens to work under MSVC because the temporary outlives the call, dying
at the end of the full expression rather than before the copy. Nothing was
corrupt; the code was just spelling "pass me a string" in a way the language
does not allow.

A const reference says what these functions actually want, so the call sites
lose the &, and the two places that allocated a string purely to have an
address to pass -- POPUP_SUB_POPUP_OPTION's default constructor, which carried
a "TODO: possible memmory leak!" saying as much, and a "Dummy generator"
option -- stop leaking one.

Converted: POPUP_OPTION's constructor and setName, POPUP::addOption and
addSubMenuOption, and both POPUP_SUB_POPUP_OPTION constructors. The popupDef
family in popup_definition.* keeps its std::wstring* because it owns what it
is handed and stores the pointer; that is a different design and a different
change. The three calls it makes into the converted API now dereference.

Verification:
    grep -rn '&std::wstring' --include=*.cpp --include=*.h .   # nothing
    ninja -C build parse             # no popup_* or SkillMenu sites remain
    ninja -C build -k 0              # Release, four applications, green
    ninja -C build-debug -k 0        # Debug, four applications, green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 19:29:55 -03:00
Marco Antonio J. Costaandmajcosta 4ff2853b70 play smacker video with libsmacker instead of SMACKW32.DLL
Drops the last piece of the proprietary Smacker SDK: SMACKW32.LIB, its
header sgp/SMACK.H, and with them the SMACKW32.DLL the game needed at
runtime. Bink is untouched and still needs binkw32.

The two libraries divide the work differently, so Cinematics.cpp changes
more than the call names. SMACKW32.DLL played a file: it kept the playback
clock (SmackWait), blitted converted 16bpp pixels into a surface we handed
it (SmackToBuffer) and pushed the audio to DirectSound itself. libsmacker
only decodes, so this module now:

- keeps the clock. Frames are advanced against GetTickCount() from the
  moment the flic starts, skipping frames if the game fell behind, which
  is what SmackWait/SmackDoFrame did internally.
- blits itself. Frames come out 8bpp palettised, so the palette is
  converted with Get16BPPColor() and the frame is written into the frame
  buffer, clipped to the screen. The Y-scaling flags are not handled;
  none of the videos shipping with the game set them.
- plays the audio itself, through the SoundPlayFromBuffer() added earlier.
  libsmacker hands out audio a frame at a time, so the whole track is
  decoded up front, with the video track disabled to keep that pass cheap,
  and given a WAV header so the sound module can take it.

libsmacker reads from memory, which lets the file be read straight out of
the VFS. That removes the dance where the .smk was first copied to a real
file under Temp/ because SmackOpen() could only open a path.

SmkInitialize() loses its window and screen size arguments, which only
existed for SmackBufferOpen(). SmkOpenFlic(), SmkSetBlitPosition() and
SmkGetFreeFlic() are no longer declared in the header; nothing outside the
module called them. SMKFLIC is now opaque, Intro.cpp only holds pointers.

The unused SMACK.H include in Cinematics Bink.cpp goes away as well.

Tested by running the Sirtech splash screen (SPLASHSCREEN.SMK, 640x480,
15 fps, one 44.1kHz 16 bit stereo track) under Wine: picture, palette,
placement and playback speed are right.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

refactor
2026-07-23 19:01:37 -03:00
Marco Antonio J. Costaandmajcosta 738225d2a2 move ImportStrings to i18n 2026-07-21 18:39:50 -03:00
Marco Antonio J. Costaandmajcosta 506ea842b8 i18n: pull some TUs that do not belong in Utils 2026-07-21 18:39:50 -03:00
Marco Antonio J. Costaandmajcosta bada3ef31a cleanup: remove last remnants of language preprocessor definitions
good riddance
2026-07-21 09:46:41 -03:00
fd2c74727e Make LANGUAGE switchable in runtime (#653)
squashed into a single commit because doing it in steps that all
compiled involved a lot of boilerplate that is pointless to commit to
the repository. GH still has the PR for reference.

g_lang, MAX_MESSAGES_ON_MAP_BOTTOM, and GetLanguagePrefix() were
compile-time constants selected by the ENGLISH/GERMAN/... build
define. They're now runtime, defaulting to the same per-exe value the
define used to pick, and overridable at startup from [Ja2 Settings]
LANGUAGE in Ja2.ini.

-

XMLTacticalMessages is filled at runtime from NewTacticalMessages.xml,
never from compiled-in per-language data: all 8 per-language definitions
were the identical all-zero { L"" }. Delete them and define one shared
buffer in Utils/XML_Language.cpp (the loader) instead of pointer-rebinding
it like the static tables — this drops 9 dead 800KB zero-buffers (8
namespaced copies in LanguageStrings.cpp plus the standalone one) and
leaves no bind-ordering hazard for the XML load path.

-

ExportStrings.cpp privately recompiled one language's full text table
by #including the raw _<LANG>Text.cpp inside namespace Loc, keyed off
the exe-level ENGLISH/GERMAN/... compile macro (whichever the build
happened to select). That's redundant with the pointer globals every
other subsystem already uses (Text.h / LanguageStrings.cpp).

Drop the private copy; the unqualified table names in Loc::ExportStrings
now resolve to the global pointer externs, which BindLanguageStrings has
already rebound to the runtime g_lang by the time this runs (EXPORT_STRINGS
ini flag, checked after GetRuntimeSettings in sgp.cpp). gs_Lang (used only
by Loc::Translate for the Polish/Russian byte remap on raw .edt exports) is
now derived from g_lang via ToLocLanguage, so the export always matches
whatever language is actually active instead of a compile-time pick.

-

Editor/popupmenu.cpp and Strategic/Scheduling.cpp kept their own
call-site extern of gszScheduleActions as CHAR16[NUM_SCHEDULE_ACTIONS][20]
after the real definition changed into a rebindable pointer
(CHAR16 (*)[20], LanguageStrings.cpp). MSVC decays the outer array
dimension when mangling globals, so both declarations produce the same
symbol (?gszScheduleActions@@3PAY0BE@_WA) and the mismatch linked
silently -- but the array-typed TUs then indexed the 4-byte pointer
slot itself as string data, so the editor schedule popup and the map
schedule message text read garbage.

-

add text.def to be single-source of truth on symbol names and use it
 .much simpler, less error prone if adding more strings

-

add pseudo interface for language state. MAX_SAGES_ON_BOTTOM must always
 change in lockstep with g_lang. this isn't foolproof but better

---------

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-07-21 05:33:03 -03:00
JuqiandAsdow ef325c1cde (Chinese) Add support for line breaks in ITEMS.XML
Added detection of the NEWLINE_CHAR character "±" to enable line breaks not only when text exceeds display width, but also upon encountering NEWLINE_CHAR.
Note: This character has been conventionally adopted in the Chinese community as a line break marker within XML item descriptions. The modification affects Chinese text display only.
2026-05-02 09:39:03 +03:00
Marco Antonio J. Costaandmajcosta 332b267ae6 use en_US locale instead of user's, fallback to C if not found
most likely every windows install has en_US available, even if in other
languages. if not, bring back the insertcommas function from history, no
biggie
2025-10-11 09:02:11 -03:00
Marco Antonio J. Costaandmajcosta 0dd32c4670 move FormatMoney to Text Utils 2025-10-08 05:36:37 -03:00
Asdow 82aca548f5 Merge branch 'master' into ExtraMercs 2025-09-24 16:14:10 +03:00
Marco Antonio J. Costaandmajcosta e5d25810f6 nuke console 2025-08-31 13:50:19 -03:00
Marco Antonio J. Costaandmajcosta 5d3cc7969f fix code that relies on transitive includes 2025-08-30 19:09:06 -03:00
Marco Antonio J. Costaandmajcosta 272ba56fa1 remove unused function 2025-08-30 18:48:16 -03:00
BeatAroundTheBuscherandGitHub ed00830202 Fixes Upper/Lower Casing for include paths (#487)
* Fixing upper/lower case for includes

types.h, zconf.h and zlib.h were renamed so that global includes like Types.h
are not used.
2025-08-16 22:01:12 -03:00
Asdow c62d767622 Update to Master 2025-08-08 18:00:31 +03:00
Asdow 9b83d6a3bc Increase squad amount to 40 2025-08-08 16:39:52 +03:00
Asdow 9a78e7dfa0 Formatting changes 2025-06-24 22:54:44 +03:00
Asdow d95bae2bf6 Re-enable power generator fan sound effect for UB 2025-06-24 22:54:44 +03:00
Asdow 36a84ffe59 Remove pSecondColumnString
* Use the new columns added to Text instead
* Changed most functions to allow choosing a column
* Removed unneeded SecondColumn specific functions to lessen code duplication
* Lots of formatting changes to Popupbox.cpp, indentation was messed up in majority of the functions
2025-04-13 22:26:32 +03:00
Asdow 865288e622 Implement multicolumn popupbox
Mainly aimed for strategic movement popup box to accommodate increased team sizes
2025-04-13 19:11:45 +03:00
Asdow fffb3a45fb Remove 8bit mode
Obsolete and doesn't work

* Remove gbPixelDepth
* Remove 8-bit to 8-bit blitters
* FileNameForBPP now only calls strcopy
2025-02-24 21:42:36 +02:00
Asdow 222daead0e Remove unused ItemFlags
Detonator and Remote Detonator are specified by AttachmentClass
No items in items.xml actually even contained these flags.
2025-01-27 18:30:11 +02:00
Marco Antonio J. Costaandmajcosta ebd2e25e0f Fix a wrong #ifdef to runtime check conversion
I didn't get this right the first time, non-Chinese text was looking
funny in dialog boxes
2025-01-09 21:37:19 -03:00
Marco Antonio J. Costaandmajcosta 22e67f66fa Move wine.cpp into its own library
avoid extra compilations that way
2025-01-05 07:57:57 -03:00
FunkyFr3shandmajcosta fd6ffd8d69 automatically add needed dll override for Linux/macOS/Android (WINE) 2025-01-05 07:06:01 -03:00
Marco Antonio J. Costa 9ed713f952 move Utils/Multi Language Graphic Utils.* to i18n
has language preprocessor silliness, straight to jail
2024-12-31 16:28:44 -03:00
Marco Antonio J. Costa cccec0ef11 straggler in Utils/Font Control.cpp 2024-12-31 16:28:44 -03:00
Marco Antonio J. Costa b15c4ef96c the really gnarly CHINESE #ifdef conversions
these seem to be right, chinese text appears to be flowing correctly
2024-12-31 16:28:44 -03:00
Marco Antonio J. Costa 5fb989a1fc Move Text.h over to i18n too
Never use relative paths for #includes. Didn't touch the rest because
out of scope.
2024-12-31 16:28:44 -03:00
Marco Antonio J. Costa 33e8c1dc39 Move all the translated strings over to i18n
It's where all conditional language preprocessor goes
2024-12-31 16:28:44 -03:00
Marco Antonio J. Costa cd69f5f3ae Make Chinese specific strings compile-time instead of conditional
eventually we'll switch between CHINESE and other languages during
runtime, so even if language is not chinese, these symbols must still
be there

these symbol names aren't used so this is fine
2024-12-31 16:28:44 -03:00
Marco Antonio J. Costa 5d19c1fe25 make conditional CHINESE preprocessor def into global constant 2024-12-31 16:28:44 -03:00
Marco Antonio J. Costaandmajcosta 897f684705 remove all #include's for Language Defines
scripted diff:

find . -type f -iname "*.h" -exec sed -i -E '/#include.*language\ defines\.h/I d' {} \;
find . -type f -iname "*.cpp" -exec sed -i -E '/#include.*language\ defines\.h/I d' {} \;
2024-12-27 02:35:29 -03:00
Marco Antonio J. Costaandmajcosta 6b9997b9c5 we don't use USE_CODE_PAGE anymore 2024-12-26 11:51:31 -03:00
Asdow c30b1c1b25 Reimplement UB pricing for AIM 2024-12-24 22:48:41 +02:00
Asdow a580052e40 Read new tags
Maybe *this* time it'll finally be fixed. Sigh...
2024-12-23 19:26:37 +02:00
Asdow 7fa8ff930b Remove unused tag
PercentCounterForceFrequency is never read from items.xml and INVTYPE doesn't have a field for it either
2024-12-22 00:08:45 +02:00
Asdow c7d021f5f3 Read updated items.xml format
Requires accompanying GameDir change.

Removed ItemFlag as an xml tag and added  bitmask flags as their own individual tags. Makes modding easier when the flags can be modified without math in the xml files
2024-12-22 00:08:45 +02:00
kitty624 0bd932f20f Simplified rework foodsystem allowed items
simplified the previous commit, now no more need for a tag
when checking IsItemLegal for Food System, ontop of checking for foodpoints, now also check if is drug
as a result, as previously, all eatable food will be excluded without food system, but now only if it isn't a drug at the same time
and no more tag to check for that in items.xml needed
2024-12-17 13:13:37 +01:00
kitty624 2fcba8b9f7 Reworked foodsystem exclusive items:
no food items if the food system is off
whether the item is exclusive is defined by tag in items.xml
replaced previous way of decision, which used Item[usItemIndex].foodtype > 0 as criteria
that also restricted dual use items (i.e. drugs that also have a foodtype, like coffee, etc.)
2024-12-16 09:54:54 +01:00
Marco Antonio J. Costaandmajcosta 86ad401186 add newline at end of file where it's lacking
.editorconfig already enforces it but it's getting changed piecemeal in
every commit. just get it done with.

the script:
```

find . -type f -not -path "./.git/*" -not -path "./.vs/*" | while read -r file; do
	isFile=$(file -0 "$file" | cut -d $'\0' -f2)
	case "$isFile" in
		(*text*)
			echo "$file is text"
			if [[ $(tail -c 1 "$file" | wc -l) -ne 1 ]]; then
				echo "" >> "$file"
			fi
			;;
		(*)
			echo "file isn't text"
			;;
	esac
done
```
2024-12-14 19:05:48 -03:00
momoko-handGitHub 87f51f0f6e Fix warning C4715 in Music Control.cpp (#351) 2024-12-10 17:15:21 +02:00
Asdow 06936b71c9 Convert to SoldierID
Rearranged struct to optimize memory layout
2024-11-17 17:22:30 +02:00
Asdow ab94d33bec PlaySoldierJA2Sample() to SoldierID 2024-11-17 10:36:10 +02:00
Asdow 10250dc035 Merge branch 'master' into ExtraMercs 2024-11-09 13:44:53 +02:00
kitty624 85ad2e5e72 Text EDB Pop-up Disease Protection adjusted
- face protection had a misleading text, stating item should be worn at face
- that's no longer true, so adjusted text to avoid player confusion
- adjusted text to distinguish between both disease protections variations
2024-11-08 09:08:38 +01:00