Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codechange: use StringParameters for remapping the NewGRF string control codes #11004

Merged
merged 1 commit into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 20 additions & 21 deletions src/newgrf_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -842,12 +842,11 @@ void RewindTextRefStack()
* FormatString for NewGRF specific "magic" string control codes
* @param scc the string control code that has been read
* @param str the string that we need to write
* @param argv the OpenTTD stack of values
* @param argv_size space on the stack \a argv
* @param modify_argv When true, modify the OpenTTD stack.
* @param parameters the OpenTTD string formatting parameters
* @param modify_parameters When true, modify the OpenTTD string formatting parameters.
* @return the string control code to "execute" now
*/
uint RemapNewGRFStringControlCode(uint scc, const char **str, int64 *argv, uint argv_size, bool modify_argv)
uint RemapNewGRFStringControlCode(uint scc, const char **str, StringParameters &parameters, bool modify_parameters)
{
switch (scc) {
default: break;
Expand Down Expand Up @@ -877,7 +876,7 @@ uint RemapNewGRFStringControlCode(uint scc, const char **str, int64 *argv, uint
case SCC_NEWGRF_PRINT_DWORD_FORCE:
case SCC_NEWGRF_PRINT_WORD_STATION_NAME:
case SCC_NEWGRF_PRINT_WORD_CARGO_NAME:
if (argv_size < 1) {
if (parameters.GetDataLeft() < 1) {
Debug(misc, 0, "Too many NewGRF string parameters.");
return 0;
}
Expand All @@ -887,47 +886,47 @@ uint RemapNewGRFStringControlCode(uint scc, const char **str, int64 *argv, uint
case SCC_NEWGRF_PRINT_WORD_CARGO_LONG:
case SCC_NEWGRF_PRINT_WORD_CARGO_SHORT:
case SCC_NEWGRF_PRINT_WORD_CARGO_TINY:
if (argv_size < 2) {
if (parameters.GetDataLeft() < 2) {
Debug(misc, 0, "Too many NewGRF string parameters.");
return 0;
}
break;
}

if (_newgrf_textrefstack.used && modify_argv) {
if (_newgrf_textrefstack.used && modify_parameters) {
/* There is data on the NewGRF text stack, and we want to move them to OpenTTD's string stack.
* After this call, a new call is made with `modify_argv` set to false when the string is finally formatted. */
* After this call, a new call is made with `modify_parameters` set to false when the string is finally formatted. */
switch (scc) {
default: NOT_REACHED();
case SCC_NEWGRF_PRINT_BYTE_SIGNED: *argv = _newgrf_textrefstack.PopSignedByte(); break;
case SCC_NEWGRF_PRINT_QWORD_CURRENCY: *argv = _newgrf_textrefstack.PopSignedQWord(); break;
case SCC_NEWGRF_PRINT_BYTE_SIGNED: parameters.SetParam(0, _newgrf_textrefstack.PopSignedByte()); break;
case SCC_NEWGRF_PRINT_QWORD_CURRENCY: parameters.SetParam(0, _newgrf_textrefstack.PopSignedQWord()); break;

case SCC_NEWGRF_PRINT_DWORD_CURRENCY:
case SCC_NEWGRF_PRINT_DWORD_SIGNED: *argv = _newgrf_textrefstack.PopSignedDWord(); break;
case SCC_NEWGRF_PRINT_DWORD_SIGNED: parameters.SetParam(0, _newgrf_textrefstack.PopSignedDWord()); break;

case SCC_NEWGRF_PRINT_BYTE_HEX: *argv = _newgrf_textrefstack.PopUnsignedByte(); break;
case SCC_NEWGRF_PRINT_QWORD_HEX: *argv = _newgrf_textrefstack.PopUnsignedQWord(); break;
case SCC_NEWGRF_PRINT_BYTE_HEX: parameters.SetParam(0, _newgrf_textrefstack.PopUnsignedByte()); break;
case SCC_NEWGRF_PRINT_QWORD_HEX: parameters.SetParam(0, _newgrf_textrefstack.PopUnsignedQWord()); break;

case SCC_NEWGRF_PRINT_WORD_SPEED:
case SCC_NEWGRF_PRINT_WORD_VOLUME_LONG:
case SCC_NEWGRF_PRINT_WORD_VOLUME_SHORT:
case SCC_NEWGRF_PRINT_WORD_SIGNED: *argv = _newgrf_textrefstack.PopSignedWord(); break;
case SCC_NEWGRF_PRINT_WORD_SIGNED: parameters.SetParam(0, _newgrf_textrefstack.PopSignedWord()); break;

case SCC_NEWGRF_PRINT_WORD_HEX:
case SCC_NEWGRF_PRINT_WORD_WEIGHT_LONG:
case SCC_NEWGRF_PRINT_WORD_WEIGHT_SHORT:
case SCC_NEWGRF_PRINT_WORD_POWER:
case SCC_NEWGRF_PRINT_WORD_STATION_NAME:
case SCC_NEWGRF_PRINT_WORD_UNSIGNED: *argv = _newgrf_textrefstack.PopUnsignedWord(); break;
case SCC_NEWGRF_PRINT_WORD_UNSIGNED: parameters.SetParam(0, _newgrf_textrefstack.PopUnsignedWord()); break;

case SCC_NEWGRF_PRINT_DWORD_FORCE:
case SCC_NEWGRF_PRINT_DWORD_DATE_LONG:
case SCC_NEWGRF_PRINT_DWORD_DATE_SHORT:
case SCC_NEWGRF_PRINT_DWORD_HEX: *argv = _newgrf_textrefstack.PopUnsignedDWord(); break;
case SCC_NEWGRF_PRINT_DWORD_HEX: parameters.SetParam(0, _newgrf_textrefstack.PopUnsignedDWord()); break;

/* Dates from NewGRFs have 1920-01-01 as their zero point, convert it to OpenTTD's epoch. */
case SCC_NEWGRF_PRINT_WORD_DATE_LONG:
case SCC_NEWGRF_PRINT_WORD_DATE_SHORT: *argv = _newgrf_textrefstack.PopUnsignedWord() + DAYS_TILL_ORIGINAL_BASE_YEAR; break;
case SCC_NEWGRF_PRINT_WORD_DATE_SHORT: parameters.SetParam(0, _newgrf_textrefstack.PopUnsignedWord() + DAYS_TILL_ORIGINAL_BASE_YEAR); break;

case SCC_NEWGRF_DISCARD_WORD: _newgrf_textrefstack.PopUnsignedWord(); break;

Expand All @@ -937,17 +936,17 @@ uint RemapNewGRFStringControlCode(uint scc, const char **str, int64 *argv, uint
case SCC_NEWGRF_PRINT_WORD_CARGO_LONG:
case SCC_NEWGRF_PRINT_WORD_CARGO_SHORT:
case SCC_NEWGRF_PRINT_WORD_CARGO_TINY:
argv[0] = GetCargoTranslation(_newgrf_textrefstack.PopUnsignedWord(), _newgrf_textrefstack.grffile);
argv[1] = _newgrf_textrefstack.PopUnsignedWord();
parameters.SetParam(0, GetCargoTranslation(_newgrf_textrefstack.PopUnsignedWord(), _newgrf_textrefstack.grffile));
parameters.SetParam(1, _newgrf_textrefstack.PopUnsignedWord());
break;

case SCC_NEWGRF_PRINT_WORD_STRING_ID:
*argv = MapGRFStringID(_newgrf_textrefstack.grffile->grfid, _newgrf_textrefstack.PopUnsignedWord());
parameters.SetParam(0, MapGRFStringID(_newgrf_textrefstack.grffile->grfid, _newgrf_textrefstack.PopUnsignedWord()));
break;

case SCC_NEWGRF_PRINT_WORD_CARGO_NAME: {
CargoID cargo = GetCargoTranslation(_newgrf_textrefstack.PopUnsignedWord(), _newgrf_textrefstack.grffile);
*argv = cargo < NUM_CARGO ? 1ULL << cargo : 0;
parameters.SetParam(0, cargo < NUM_CARGO ? 1ULL << cargo : 0);
break;
}
}
Expand Down
1 change: 0 additions & 1 deletion src/newgrf_text.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ void RewindTextRefStack();
bool UsingNewGRFTextStack();
struct TextRefStack *CreateTextRefStackBackup();
void RestoreTextRefStackBackup(struct TextRefStack *backup);
uint RemapNewGRFStringControlCode(uint scc, const char **str, int64 *argv, uint argv_size, bool modify_argv);

/** Mapping of language data between a NewGRF and OpenTTD. */
struct LanguageMap {
Expand Down
4 changes: 2 additions & 2 deletions src/strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,8 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara

if (SCC_NEWGRF_FIRST <= b && b <= SCC_NEWGRF_LAST) {
/* We need to pass some stuff as it might be modified. */
//todo: should argve be passed here too?
b = RemapNewGRFStringControlCode(b, &str, (int64 *)args->GetDataPointer(), args->GetDataLeft(), dry_run);
StringParameters remaining = args->GetRemainingParameters();
b = RemapNewGRFStringControlCode(b, &str, remaining, dry_run);
if (b == 0) continue;
}

Expand Down
14 changes: 14 additions & 0 deletions src/strings_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ class StringParameters {
return &this->data[this->offset];
}

/**
* Get a new instance of StringParameters that is a "range" into the
* parameters existing parameters. Upon destruction the offset in the parent
* is not updated. However, calls to SetDParam do update the parameters.
*
* The returned StringParameters must not outlive this StringParameters.
* @return A "range" of the string parameters.
*/
StringParameters GetRemainingParameters()
{
return StringParameters(&this->data[this->offset], GetDataLeft(),
this->type == nullptr ? nullptr : &this->type[this->offset]);
}

/** Return the amount of elements which can still be read. */
uint GetDataLeft() const
{
Expand Down
2 changes: 2 additions & 0 deletions src/strings_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,6 @@ void GenerateTownNameString(StringBuilder &builder, size_t lang, uint32_t seed);
void GetTownName(StringBuilder &builder, const struct Town *t);
void GRFTownNameGenerate(StringBuilder &builder, uint32 grfid, uint16 gen, uint32 seed);

uint RemapNewGRFStringControlCode(uint scc, const char **str, StringParameters &parameters, bool modify_parameters);

#endif /* STRINGS_INTERNAL_H */