mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-09 15:20:01 +03:00
Gpx2Plus.CopyStretchReduceAMap behaves differently in the English version. Fixes an issue with text being squashed horizontally on the regional phase menus.
132 lines
4.0 KiB
C
132 lines
4.0 KiB
C
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "system4.h"
|
|
#include "system4/ain.h"
|
|
#include "system4/buffer.h"
|
|
#include "system4/instructions.h"
|
|
#include "system4/string.h"
|
|
#include "system4/utfsjis.h"
|
|
|
|
#include "gfx/gfx.h"
|
|
#include "xsystem4.h"
|
|
|
|
#include "hll/hll.h"
|
|
|
|
bool game_daibanchou_en = false;
|
|
bool game_rance02_mg = false;
|
|
|
|
static void write_instruction0(struct buffer *out, enum opcode op)
|
|
{
|
|
buffer_write_int16(out, op);
|
|
}
|
|
|
|
static void write_instruction1(struct buffer *out, enum opcode op, int32_t arg)
|
|
{
|
|
buffer_write_int16(out, op);
|
|
buffer_write_int32(out, arg);
|
|
}
|
|
|
|
// Rance 02 (MangaGamer version)
|
|
// -----------------------------
|
|
// Uses a custom proportional font implementation which makes assumptions
|
|
// about the font. We replace the _CalculateWidth function with a font-generic
|
|
// implementation.
|
|
//
|
|
// This causes quite a bit of text overflow, but there's not much that can be
|
|
// done about it. Using TTF_SizeUTF8 to calculate the width actually makes it
|
|
// worse.
|
|
static void apply_rance02_hacks(struct ain *ain)
|
|
{
|
|
int fno = ain_get_function(ain, "_CalculateWidth");
|
|
if (fno <= 0) {
|
|
WARNING("No '_CalculateWidth' function when applying Rance 02 compatibility hack");
|
|
return;
|
|
}
|
|
struct ain_function *f = &ain->functions[fno];
|
|
|
|
// rewrite function
|
|
struct buffer out;
|
|
buffer_init(&out, ain->code, ain->code_size);
|
|
buffer_seek(&out, f->address);
|
|
|
|
// _CalculateWidth(ref string str, int nFontSize, int nWeightSize) {
|
|
// if (str[0] > 255 || str[0] == '}')
|
|
// return nFontSize + nWeightSize;
|
|
// return nFontSize / 2 + nWeightSize;
|
|
// }
|
|
|
|
// if (str[0] > 255 || str[0] == '}')
|
|
write_instruction1(&out, SH_LOCALREF, 0);
|
|
write_instruction1(&out, PUSH, 0);
|
|
write_instruction0(&out, C_REF);
|
|
write_instruction0(&out, DUP);
|
|
write_instruction1(&out, PUSH, 255);
|
|
write_instruction0(&out, GT);
|
|
write_instruction0(&out, SWAP);
|
|
write_instruction1(&out, PUSH, '}');
|
|
write_instruction0(&out, EQUALE);
|
|
write_instruction0(&out, OR);
|
|
int ifz_addr = out.index;
|
|
write_instruction1(&out, IFZ, 0);
|
|
|
|
// return nFontSize + nWeightSize
|
|
write_instruction1(&out, SH_LOCALREF, 1);
|
|
write_instruction1(&out, SH_LOCALREF, 2);
|
|
write_instruction0(&out, ADD);
|
|
write_instruction0(&out, RETURN);
|
|
|
|
// return nFontSize / 2 + nWeightSize;
|
|
buffer_write_int32_at(&out, ifz_addr + 2, out.index);
|
|
write_instruction1(&out, SH_LOCALREF, 1);
|
|
write_instruction1(&out, PUSH, 2);
|
|
write_instruction0(&out, DIV);
|
|
write_instruction1(&out, SH_LOCALREF, 2);
|
|
write_instruction0(&out, ADD);
|
|
write_instruction0(&out, RETURN);
|
|
|
|
write_instruction1(&out, ENDFUNC, fno);
|
|
|
|
game_rance02_mg = true;
|
|
}
|
|
|
|
// Daibanchou (English fan translation)
|
|
// ------------------------------------
|
|
// Gpx2Plus.CopyStretchReduceAMap behaves differently in order to work around
|
|
// text rendering issues caused by how the game calculates text width in
|
|
// StructRegionalSelect::DrawMenuItem.
|
|
static void apply_daibanchou_hacks(struct ain *ain)
|
|
{
|
|
if (ain->nr_strings > 2 && !strcmp(ain->strings[2]->text, "Seijou Academy")) {
|
|
game_daibanchou_en = true;
|
|
}
|
|
}
|
|
|
|
void apply_game_specific_hacks(struct ain *ain)
|
|
{
|
|
char *game_name = sjis2utf(config.game_name, 0);
|
|
if (!strcmp(game_name, "大番長")) {
|
|
apply_daibanchou_hacks(ain);
|
|
} else if (!strcmp(game_name, "Rance 02")) {
|
|
apply_rance02_hacks(ain);
|
|
}
|
|
free(game_name);
|
|
}
|