This is usually an error caused by a missing string index. I might end
up removing string indexes later, since I don't think it's actually
needed. Need to test reordering strings by changing indexes but keeping
the same string names later.
This bug was repoted by Jotaro Powered.
This eliminates having to create and destroy the u16string every
iteration.
Added msg_text.clear() to the case where byteswapping is needed but the
string is empty to ensure that it gets cleared. We were previously
depending on the string being reinitialized on every iteration for the
string to be cleared.
Always write three offsets per string, though only write two entries in
the differential offset table if the placeholder name isn't present.
vOffsetTblType is no longer necessary, since the string types are
inferred by the field names in WTXT_MsgPointer.
Removed the extra zero DWORD at the end of the offset table, since
this was actually the placeholder offset field of the last entry.
msg_mainmenu.e.mst converts to XML and back to MST perfectly,
as do msg_town_mission_shadow.j.mst and msg_town_mission_sonic.e.mst
common.h: Added for ASSERT_STRUCT() to ensure we have proper struct
size assertions. Will use it for ALIGN() later.
The three offsets:
- String name offset (Shift-JIS)
- String text offset (UTF-16)
- Placeholder name offset (Shift-JIS, may be zero)
Placeholder name offset is usually 0. This is still present in the
offset table, but the differential offset table *skips* it by using
'B'. The differential offset table is useless to us, but it's required
in order for Sonic'06 to parse it correctly and not crash.
saveXML(): The placeholder string is now saved as an attribute in the
relevant message instead of as its own message.
TODO: Update loadXML() and saveMST().
msg_town_mission_shadow.j.mst ends on a DWORD boundary and doesn't have
extra 0s, so this resulted in a non-matching file when converting from
MST to XML and back to MST.
Also for the initial WTXT/message count values in <mst06>.
For msg_mainmenu.e.xml: It seems that "AA" appears for messages that have
a button placeholder ('$'), and "A" appears for the button image string
immediately after that message. I might be able to use this information
later to properly generate the differential offset table instead of
including it in the XML file.
TODO: Remove <diffOffTbl> and use the per-message values.
If a string name is the same as the string table name, it's deduplicated.
msg_mainmenu.e.mst can now be converted to XML and back to MST, and the
resulting MST is identical to the original.
TODO: Do we need to deduplicate all strings, or just the string table name?
The resulting MST looks much closer to the original, though it seems
that the original MST tool used string deduplication, so the new one
has extra copies of strings. I don't know if this will break the game.
unescapeDiffOffTbl(): Unescape the XML-compatible differential offset
table and load it into a std::vector<uint8_t>.
TODO: Make use of the differential offset table in saveMST().
It seems that Sonic'06 doesn't like our custom-built differential
offset table, so we'll need to keep the original. This means that
we can't create our own string table from scratch, but that isn't
exactly a very common operation.
(...unless we figure out exactly what it doesn't like...)
Fixed some confusion between offset table names. The first table should
be the offset table, not the differential table.
TODO:
- loadXML(): Load the differential offset table.
- saveMST(): Use the in-memory differential offset table.
TextFuncs.hpp: Added cpN_to_utf8().
- TextFuncs_iconv.cpp: Copied this function from rom-properties.
- TextFuncs_win32.cpp: Removed `static` from this function.
TODO: Show warnings for strings with characters that can't be
converted to Shift-JIS?
This includes handling byteswapping properly for little-endian files,
though this hasn't been fully tested with programs. (Sonic'06 is
big-endian only, so we can't really test it there.)
TODO:
- Add more error checking, e.g. for skipped indexes.
- Add saveMST() to convert XML to MST.
main.cpp: Check the file type by looking at magic numbers and call the
appropriate load function.
The differential offset table must be DWORD-aligned, both for its starting
offset and for its total size. Message text and names *don't* have to be
DWORD-aligned, though text usually is, and names might be. (Names is
always WORD-aligned, since message text is encoded as UTF-16.)
There's two offset tables:
- Regular offset table, which points to strings.
- Differential offset table, which points to offsets in the first
offset table.
Rename the header fields that point to the differential offset table
in order to reduce confusion.
These functions escape and unescape backslash, newline ("\n"), and
form feed ("\f").
MST messages use newline for newlines (obviously), and form feed to
indicate a pause where the user has to press a button to continue
reading the message.
These should be escaped when editing to make it easier for the user
to manipulate things.
saveXML(): Escape string text.
Added an internal copy of TinyXML2 for Windows builds.
Based on the rom-properties build.
main.cpp: Replace the file extension on the source file with .xml and
use that as the destination filename.