Skip to content

Commit f344ede

Browse files
committed
Merge PR #143: correct Spanish Spheda and jump gate text
Apply anchored PAL Spanish script and event corrections without changing PS2 code. Review the implementation for native style, retail operand types and bounded growth. Invalidate motion storage across appended text and cache actual patched lengths. Add loader regressions and validate the retail text through the archive-aware VFS. Validation: Windows Debug build, clang-format, clang-tidy, and focused script text, script timing, data loader and character motion regression suites.
2 parents 4453641 + 40b9b13 commit f344ede

6 files changed

Lines changed: 817 additions & 6 deletions

File tree

‎docs/PC.md‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,30 @@ to move or throw away. `port/src/message_text.cpp` replaces the message in all
479479
five PAL languages with the translation's wording plus both, for example
480480
`You can only carry 999 "Thick Hide".`
481481

482+
The PAL disc's Spanish script for the map where Max learns Spheda
483+
(`map/s/s17/s17_5.stb`) is a byte-for-byte copy of the Italian one, so its
484+
Spheda tutorial, prompts and dialogue read in Italian. `port/src/script_text.cpp`
485+
gives those 19 strings Spanish text when the script is read from the data index
486+
(`ResolveFile` in `port/src/dataread.cpp`), after the NTSC timing conversion. Each
487+
line is anchored on its push instruction and the Italian text it must find there;
488+
a script that does not show every line is left unchanged with a warning. A text
489+
that fits is written over the Italian one, a longer one is appended after the
490+
script, so the file reads 1 KB or so longer and size queries report the same.
491+
The wording keeps the PAL Spanish names (Esfera, Esfeda, Bastón Multiusos, Ayuda).
492+
493+
The Spanish text of the Spheda lesson that follows (`event/e300/e314/e314_5.txt`)
494+
says there is nothing more to remember right before the colour rules, and has a
495+
Sphere turn black, a colour it never takes. The same file corrects those three
496+
lines by their exact text: "Tienes que acordarte de otra cosa más.", "De azul a
497+
rojo, de rojo a azul." and "...y cambiará el color.".
498+
499+
The Spanish jump gate menus in Gundorada (`map/f/f04/f04_5.stb` and
500+
`map/s/s30/s30_5.stb`) put East and West on one line, "Puerta de salto Este --
501+
Oeste", so they show one destination fewer than the script offers: the last
502+
choice is blank and the ones after North lead one destination further than they
503+
say. The same file gives the three menus the English menu's lines, with East and
504+
West apart and the time gate named "Puerta del tiempo".
505+
482506
### darkchronicle
483507

484508
```

‎port/src/dataread.cpp‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <cstdio>
1515
#include <cstring>
1616
#include <filesystem>
17+
#include <limits>
1718
#include <optional>
1819
#include <print>
1920
#include <span>
@@ -22,6 +23,7 @@
2223
#include <thread>
2324
#include <unordered_map>
2425
#include <unordered_set>
26+
#include <utility>
2527
#include <vector>
2628

2729
#include "bounded_text.hpp"
@@ -38,6 +40,7 @@
3840
#include "platform/texture_catalog.hpp"
3941
#include "platform/vfs.hpp"
4042
#include "profile.hpp"
43+
#include "script_text.hpp"
4144
#include "script_timing.hpp"
4245
#include "texture_copy.hpp"
4346
#include "texture_source.hpp"
@@ -261,6 +264,22 @@ bool ConvertScriptTiming(const std::string &key, void *buffer, int size) {
261264
return ok;
262265
}
263266

267+
/**
268+
* Corrects PAL text and records the complete patched buffer extent.
269+
*/
270+
int PatchScriptText(const std::string &key, void *buffer, int size) {
271+
if (size < 0 || (!key.ends_with(".stb") && !key.ends_with(".txt"))) {
272+
return size;
273+
}
274+
const auto extra = script_text::Extra(key);
275+
if (extra > 0) {
276+
ReportDestination(static_cast<unsigned char *>(buffer) + size, extra);
277+
}
278+
const auto patched = static_cast<int>(script_text::Patch(key, static_cast<unsigned char *>(buffer), static_cast<std::size_t>(size)));
279+
loaded_buffers[buffer] = static_cast<std::size_t>(patched);
280+
return patched;
281+
}
282+
264283
// sceOpen maps host0: onto the save tree, so this reads back whatever WriteFile put there. -1 when the
265284
// save tree does not have the file, which sends the caller on to the data index.
266285
int ReadSaveFile(const char *name, void *buffer, bool size_only) {
@@ -317,17 +336,23 @@ int ResolveFile(const char *name, const std::string &key, void *buffer, bool siz
317336
if (!file) {
318337
return -1;
319338
}
339+
const auto raw_size = FileSize(*file);
340+
const auto extra = script_text::Extra(key);
341+
if (!raw_size || std::cmp_greater(extra, std::numeric_limits<int>::max() - *raw_size)) {
342+
return -1;
343+
}
320344
if (!size_only) {
321-
const int size = ReadWhole(*file, buffer);
345+
int size = ReadWhole(*file, buffer);
322346
if (size >= 0) {
323347
if (!ConvertScriptTiming(key, buffer, size)) {
324348
return -1;
325349
}
350+
size = PatchScriptText(key, buffer, size);
326351
TextureSourceRegister(buffer, file->relative, static_cast<std::size_t>(size));
327352
}
328353
return size;
329354
}
330-
return FileSize(*file).value_or(-1);
355+
return *raw_size + static_cast<int>(extra);
331356
}
332357

333358
CacheSlot *CacheFind(const std::string &key) {
@@ -878,7 +903,7 @@ PORT_OVERRIDE int LoadFileCacheBG(char *path) {
878903
cache_next += quadwords;
879904
}
880905

881-
if (!LoadFileBG(path, buffer, nullptr)) {
906+
if (!LoadFileBG(path, buffer, &size)) {
882907
return 0;
883908
}
884909
return CacheRecord(key, buffer, size);

0 commit comments

Comments
 (0)