mirror of
https://github.com/GerbilSoft/rom-properties.git
synced 2025-06-19 03:55:43 -04:00
[libromdata/tests] GcnFstPrint, WiiUFstPrint: Use libgsvt.
The Unicode text printing on Windows via _fputts() was causing the console output to lock up on Windows 7. Switching to libgsvt fixes it. Code size difference: (64-bit Gentoo Linux, gcc-15.1.0, release build, no LTO) text data bss dec hex filename 16247 1032 48 17327 43af GcnFstPrint [before] 19006 1160 80 20246 4f16 GcnFstPrint [after] +2759 +128 +32 +2919 +b67 Difference text data bss dec hex filename 15417 1016 48 16481 4061 WiiUFstPrint [before] 18210 1144 80 19434 4bea WiiUFstPrint [after] +2793 +128 +32 +2953 +b89 Difference
This commit is contained in:
parent
665a9f878c
commit
43a7bd4a49
@ -40,6 +40,7 @@ ADD_EXECUTABLE(GcnFstPrint
|
|||||||
disc/FstPrint.hpp
|
disc/FstPrint.hpp
|
||||||
)
|
)
|
||||||
TARGET_LINK_LIBRARIES(GcnFstPrint PRIVATE rpsecure romdata)
|
TARGET_LINK_LIBRARIES(GcnFstPrint PRIVATE rpsecure romdata)
|
||||||
|
TARGET_LINK_LIBRARIES(GcnFstPrint PRIVATE gsvt)
|
||||||
IF(ENABLE_NLS)
|
IF(ENABLE_NLS)
|
||||||
TARGET_LINK_LIBRARIES(GcnFstPrint PRIVATE i18n)
|
TARGET_LINK_LIBRARIES(GcnFstPrint PRIVATE i18n)
|
||||||
ENDIF(ENABLE_NLS)
|
ENDIF(ENABLE_NLS)
|
||||||
@ -87,6 +88,7 @@ ADD_EXECUTABLE(WiiUFstPrint
|
|||||||
disc/FstPrint.hpp
|
disc/FstPrint.hpp
|
||||||
)
|
)
|
||||||
TARGET_LINK_LIBRARIES(WiiUFstPrint PRIVATE rpsecure romdata)
|
TARGET_LINK_LIBRARIES(WiiUFstPrint PRIVATE rpsecure romdata)
|
||||||
|
TARGET_LINK_LIBRARIES(WiiUFstPrint PRIVATE gsvt)
|
||||||
IF(ENABLE_NLS)
|
IF(ENABLE_NLS)
|
||||||
TARGET_LINK_LIBRARIES(WiiUFstPrint PRIVATE i18n)
|
TARGET_LINK_LIBRARIES(WiiUFstPrint PRIVATE i18n)
|
||||||
ENDIF(ENABLE_NLS)
|
ENDIF(ENABLE_NLS)
|
||||||
|
@ -14,6 +14,9 @@ using LibRomData::GcnFst;
|
|||||||
// i18n
|
// i18n
|
||||||
#include "libi18n/i18n.h"
|
#include "libi18n/i18n.h"
|
||||||
|
|
||||||
|
// libgsvt for VT handling
|
||||||
|
#include "gsvtpp.hpp"
|
||||||
|
|
||||||
// C includes (C++ namespace)
|
// C includes (C++ namespace)
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@ -68,14 +71,19 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
setlocale(LC_CTYPE, "C");
|
setlocale(LC_CTYPE, "C");
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
// Detect console information.
|
||||||
|
// NOTE: Technically not needed, since Gsvt::Console access
|
||||||
|
// will call this for us...
|
||||||
|
gsvt_init();
|
||||||
|
|
||||||
// Initialize i18n.
|
// Initialize i18n.
|
||||||
rp_i18n_init();
|
rp_i18n_init();
|
||||||
|
|
||||||
if (argc < 2 || argc > 3) {
|
if (argc < 2 || argc > 3) {
|
||||||
fmt::print(stderr, FRUN(C_("GcnFstPrint", "Syntax: {:s} fst.bin [offsetShift]")), argv[0]);
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("GcnFstPrint", "Syntax: {:s} fst.bin [offsetShift]")), argv[0]));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
fputs(C_("GcnFstPrint", "offsetShift should be 0 for GameCube, 2 for Wii. (default is 0)"), stderr);
|
Gsvt::StdErr.fputs(C_("GcnFstPrint", "offsetShift should be 0 for GameCube, 2 for Wii. (default is 0)"));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,10 +93,10 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
char *endptr = nullptr;
|
char *endptr = nullptr;
|
||||||
long ltmp = strtol(argv[2], &endptr, 10);
|
long ltmp = strtol(argv[2], &endptr, 10);
|
||||||
if (*endptr != '\0' || (ltmp != 0 && ltmp != 2)) {
|
if (*endptr != '\0' || (ltmp != 0 && ltmp != 2)) {
|
||||||
fmt::print(stderr, FRUN(C_("GcnFstPrint", "Invalid offset shift '{:s}' specified.")), argv[2]);
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("GcnFstPrint", "Invalid offset shift '{:s}' specified.")), argv[2]));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
fputs(C_("GcnFstPrint", "offsetShift should be 0 for GameCube, 2 for Wii. (default is 0)"), stderr);
|
Gsvt::StdErr.fputs(C_("GcnFstPrint", "offsetShift should be 0 for GameCube, 2 for Wii. (default is 0)"));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
offsetShift = static_cast<uint8_t>(ltmp);
|
offsetShift = static_cast<uint8_t>(ltmp);
|
||||||
@ -98,8 +106,8 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
FILE *f = fopen(argv[1], "rb");
|
FILE *f = fopen(argv[1], "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
// tr: {0:s} == filename, {1:s} == error message
|
// tr: {0:s} == filename, {1:s} == error message
|
||||||
fmt::print(stderr, FRUN(C_("GcnFstPrint", "Error opening '{0:s}': '{1:s}'")), argv[1], strerror(errno));
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("GcnFstPrint", "Error opening '{0:s}': '{1:s}'")), argv[1], strerror(errno)));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,8 +115,8 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
fseeko(f, 0, SEEK_END);
|
fseeko(f, 0, SEEK_END);
|
||||||
const off64_t fileSize_o = ftello(f);
|
const off64_t fileSize_o = ftello(f);
|
||||||
if (fileSize_o > (16*1024*1024)) {
|
if (fileSize_o > (16*1024*1024)) {
|
||||||
fputs(C_("GcnFstPrint", "ERROR: FST is too big. (Maximum of 16 MB.)"), stderr);
|
Gsvt::StdErr.fputs(C_("GcnFstPrint", "ERROR: FST is too big. (Maximum of 16 MB.)"));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -121,9 +129,9 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
if (rd_size != fileSize) {
|
if (rd_size != fileSize) {
|
||||||
// tr: {0:d} == number of bytes read, {1:d} == number of bytes expected to read
|
// tr: {0:d} == number of bytes read, {1:d} == number of bytes expected to read
|
||||||
fmt::print(stderr, FRUN(C_("GcnFstPrint", "ERROR: Read {0:Ld} bytes, expected {1:Ld} bytes.")),
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("GcnFstPrint", "ERROR: Read {0:Ld} bytes, expected {1:Ld} bytes.")),
|
||||||
rd_size, fileSize);
|
rd_size, fileSize));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,35 +153,20 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
unique_ptr<IFst> fst(new GcnFst(&fstData[fst_start_offset],
|
unique_ptr<IFst> fst(new GcnFst(&fstData[fst_start_offset],
|
||||||
static_cast<uint32_t>(fileSize - fst_start_offset), offsetShift));
|
static_cast<uint32_t>(fileSize - fst_start_offset), offsetShift));
|
||||||
if (!fst->isOpen()) {
|
if (!fst->isOpen()) {
|
||||||
fmt::print(stderr, FRUN(C_("GcnFstPrint", "*** ERROR: Could not parse '{:s}' as GcnFst.")), argv[1]);
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("GcnFstPrint", "*** ERROR: Could not parse '{:s}' as GcnFst.")), argv[1]));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the FST to an ostringstream.
|
// Print the FST to an ostringstream.
|
||||||
ostringstream oss;
|
ostringstream oss;
|
||||||
LibRomData::fstPrint(fst.get(), oss);
|
LibRomData::fstPrint(fst.get(), oss);
|
||||||
const string fst_str = oss.str();
|
Gsvt::StdOut.fputs(oss.str());
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// FIXME: isatty() might not work properly on Win8+ with MinGW.
|
|
||||||
// Reference: https://lists.gnu.org/archive/html/bug-gnulib/2013-01/msg00007.html
|
|
||||||
if (isatty(fileno(stdout))) {
|
|
||||||
// Convert to wchar_t, then print it.
|
|
||||||
_fputts(U82T_s(fst_str), stdout);
|
|
||||||
} else {
|
|
||||||
// Writing to file. Print the original UTF-8.
|
|
||||||
fputs(fst_str.c_str(), stdout);
|
|
||||||
}
|
|
||||||
#else /* !_WIN32 */
|
|
||||||
// Print the FST.
|
|
||||||
fputs(fst_str.c_str(), stdout);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fst->hasErrors()) {
|
if (fst->hasErrors()) {
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
fputs(C_("GcnFstPrint", "*** WARNING: FST has errors and may be unusable."), stderr);
|
Gsvt::StdErr.fputs(C_("GcnFstPrint", "*** WARNING: FST has errors and may be unusable."));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
|
@ -16,6 +16,9 @@ using LibRomData::WiiUFst;
|
|||||||
// i18n
|
// i18n
|
||||||
#include "libi18n/i18n.h"
|
#include "libi18n/i18n.h"
|
||||||
|
|
||||||
|
// libgsvt for VT handling
|
||||||
|
#include "gsvtpp.hpp"
|
||||||
|
|
||||||
// C includes (C++ namespace)
|
// C includes (C++ namespace)
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@ -69,12 +72,17 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
setlocale(LC_CTYPE, "C");
|
setlocale(LC_CTYPE, "C");
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
// Detect console information.
|
||||||
|
// NOTE: Technically not needed, since Gsvt::Console access
|
||||||
|
// will call this for us...
|
||||||
|
gsvt_init();
|
||||||
|
|
||||||
// Initialize i18n.
|
// Initialize i18n.
|
||||||
rp_i18n_init();
|
rp_i18n_init();
|
||||||
|
|
||||||
if (argc < 2 || argc > 3) {
|
if (argc < 2 || argc > 3) {
|
||||||
fmt::print(stderr, FRUN(C_("WiiUFstPrint", "Syntax: {:s} fst.bin")), argv[0]);
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("WiiUFstPrint", "Syntax: {:s} fst.bin")), argv[0]));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,8 +90,8 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
FILE *f = fopen(argv[1], "rb");
|
FILE *f = fopen(argv[1], "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
// tr: {0:s} == filename, {1:s} == error message
|
// tr: {0:s} == filename, {1:s} == error message
|
||||||
fmt::print(stderr, FRUN(C_("GcnFstPrint", "Error opening '{0:s}': '{1:s}'")), argv[1], strerror(errno));
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("GcnFstPrint", "Error opening '{0:s}': '{1:s}'")), argv[1], strerror(errno)));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +99,8 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
fseeko(f, 0, SEEK_END);
|
fseeko(f, 0, SEEK_END);
|
||||||
const off64_t fileSize_o = ftello(f);
|
const off64_t fileSize_o = ftello(f);
|
||||||
if (fileSize_o > (16*1024*1024)) {
|
if (fileSize_o > (16*1024*1024)) {
|
||||||
fputs(C_("GcnFstPrint", "ERROR: FST is too big. (Maximum of 16 MB.)"), stderr);
|
Gsvt::StdErr.fputs(C_("GcnFstPrint", "ERROR: FST is too big. (Maximum of 16 MB.)"));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -105,9 +113,9 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
if (rd_size != fileSize) {
|
if (rd_size != fileSize) {
|
||||||
// tr: {0:Ld} == number of bytes read, {1:Ld} == number of bytes expected to read
|
// tr: {0:Ld} == number of bytes read, {1:Ld} == number of bytes expected to read
|
||||||
fmt::print(stderr, FRUN(C_("GcnFstPrint", "ERROR: Read {0:Ld} bytes, expected {1:Ld} bytes.")),
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("GcnFstPrint", "ERROR: Read {0:Ld} bytes, expected {1:Ld} bytes.")),
|
||||||
rd_size, fileSize);
|
rd_size, fileSize));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +124,8 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
// "look" like an FST?
|
// "look" like an FST?
|
||||||
unique_ptr<IFst> fst(new WiiUFst(fstData.get(), static_cast<uint32_t>(fileSize)));
|
unique_ptr<IFst> fst(new WiiUFst(fstData.get(), static_cast<uint32_t>(fileSize)));
|
||||||
if (!fst->isOpen()) {
|
if (!fst->isOpen()) {
|
||||||
fmt::print(stderr, FRUN(C_("WiiUFstPrint", "*** ERROR: Could not parse '{:s}' as WiiUFst.")), argv[1]);
|
Gsvt::StdErr.fputs(fmt::format(FRUN(C_("WiiUFstPrint", "*** ERROR: Could not parse '{:s}' as WiiUFst.")), argv[1]));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,26 +133,12 @@ int RP_C_API main(int argc, char *argv[])
|
|||||||
ostringstream oss;
|
ostringstream oss;
|
||||||
LibRomData::fstPrint(fst.get(), oss, true);
|
LibRomData::fstPrint(fst.get(), oss, true);
|
||||||
const string fst_str = oss.str();
|
const string fst_str = oss.str();
|
||||||
|
Gsvt::StdOut.fputs(oss.str());
|
||||||
#ifdef _WIN32
|
|
||||||
// FIXME: isatty() might not work properly on Win8+ with MinGW.
|
|
||||||
// Reference: https://lists.gnu.org/archive/html/bug-gnulib/2013-01/msg00007.html
|
|
||||||
if (isatty(fileno(stdout))) {
|
|
||||||
// Convert to wchar_t, then print it.
|
|
||||||
_fputts(U82T_s(fst_str), stdout);
|
|
||||||
} else {
|
|
||||||
// Writing to file. Print the original UTF-8.
|
|
||||||
fputs(fst_str.c_str(), stdout);
|
|
||||||
}
|
|
||||||
#else /* !_WIN32 */
|
|
||||||
// Print the FST.
|
|
||||||
fputs(fst_str.c_str(), stdout);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fst->hasErrors()) {
|
if (fst->hasErrors()) {
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
fputs(C_("WiiUFstPrint", "*** WARNING: FST has errors and may be unusable."), stderr);
|
Gsvt::StdErr.fputs(C_("WiiUFstPrint", "*** WARNING: FST has errors and may be unusable."));
|
||||||
fputc('\n', stderr);
|
Gsvt::StdErr.newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup.
|
// Cleanup.
|
||||||
|
Loading…
Reference in New Issue
Block a user