2020-10-03 01:08:40 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
namespace PKHeX.Core
|
|
|
|
|
{
|
2020-10-18 16:43:41 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Mainline format for Generation 1 & 2 <see cref="PKM"/> objects.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>This format stores <see cref="PKM.Nickname"/> and <see cref="PKM.OT_Name"/> in buffers separate from the rest of the details.</remarks>
|
2020-10-03 01:08:40 +00:00
|
|
|
|
public abstract class GBPKML : GBPKM
|
|
|
|
|
{
|
2021-05-29 22:31:47 +00:00
|
|
|
|
internal const int StringLengthJapanese = 6;
|
|
|
|
|
internal const int StringLengthNotJapan = 11;
|
2020-10-03 01:08:40 +00:00
|
|
|
|
public sealed override int OTLength => Japanese ? 5 : 7;
|
|
|
|
|
public sealed override int NickLength => Japanese ? 5 : 10;
|
2021-05-29 22:31:47 +00:00
|
|
|
|
public sealed override bool Japanese => RawOT.Length == StringLengthJapanese;
|
2020-10-03 01:08:40 +00:00
|
|
|
|
|
2021-05-29 22:31:47 +00:00
|
|
|
|
internal readonly byte[] RawOT;
|
|
|
|
|
internal readonly byte[] RawNickname;
|
2020-10-03 01:08:40 +00:00
|
|
|
|
|
|
|
|
|
// Trash Bytes
|
2021-05-29 22:31:47 +00:00
|
|
|
|
public sealed override byte[] Nickname_Trash { get => RawNickname; set { if (value.Length == RawNickname.Length) value.CopyTo(RawNickname, 0); } }
|
|
|
|
|
public sealed override byte[] OT_Trash { get => RawOT; set { if (value.Length == RawOT.Length) value.CopyTo(RawOT, 0); } }
|
2020-10-03 01:08:40 +00:00
|
|
|
|
|
|
|
|
|
protected GBPKML(int size, bool jp = false) : base(size)
|
|
|
|
|
{
|
2021-05-29 22:31:47 +00:00
|
|
|
|
int strLen = jp ? StringLengthJapanese : StringLengthNotJapan;
|
2020-10-03 01:08:40 +00:00
|
|
|
|
|
|
|
|
|
// initialize string buffers
|
2021-05-29 22:31:47 +00:00
|
|
|
|
RawOT = new byte[strLen];
|
|
|
|
|
RawNickname = new byte[strLen];
|
|
|
|
|
for (int i = 0; i < RawOT.Length; i++)
|
|
|
|
|
RawOT[i] = RawNickname[i] = StringConverter12.G1TerminatorCode;
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected GBPKML(byte[] data, bool jp = false) : base(data)
|
|
|
|
|
{
|
2021-05-29 22:31:47 +00:00
|
|
|
|
int strLen = jp ? StringLengthJapanese : StringLengthNotJapan;
|
2020-10-03 01:08:40 +00:00
|
|
|
|
|
|
|
|
|
// initialize string buffers
|
2021-05-29 22:31:47 +00:00
|
|
|
|
RawOT = new byte[strLen];
|
|
|
|
|
RawNickname = new byte[strLen];
|
|
|
|
|
for (int i = 0; i < RawOT.Length; i++)
|
|
|
|
|
RawOT[i] = RawNickname[i] = StringConverter12.G1TerminatorCode;
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-29 22:31:47 +00:00
|
|
|
|
public override void SetNotNicknamed(int language) => GetNonNickname(language).CopyTo(RawNickname);
|
2020-10-03 01:08:40 +00:00
|
|
|
|
|
2021-05-29 22:31:47 +00:00
|
|
|
|
protected override byte[] GetNonNickname(int language)
|
2020-10-03 01:08:40 +00:00
|
|
|
|
{
|
|
|
|
|
var name = SpeciesName.GetSpeciesNameGeneration(Species, language, Format);
|
|
|
|
|
var len = Nickname_Trash.Length;
|
2021-05-29 22:31:47 +00:00
|
|
|
|
var data = SetString(name, len, len, 0x50);
|
2020-10-03 01:08:40 +00:00
|
|
|
|
if (!Korean)
|
2021-05-29 22:31:47 +00:00
|
|
|
|
{
|
|
|
|
|
// Decimal point<->period fix
|
|
|
|
|
for (int i = 0; i < data.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (data[i] == 0xF2)
|
|
|
|
|
data[i] = 0xE8;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-03 01:08:40 +00:00
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-29 22:31:47 +00:00
|
|
|
|
private byte[] SetString(string value, int maxLength, int padTo = 0, byte padWith = 0)
|
2020-10-03 01:08:40 +00:00
|
|
|
|
{
|
|
|
|
|
if (Korean)
|
2021-05-29 22:31:47 +00:00
|
|
|
|
return StringConverter2KOR.SetString2KOR(value, maxLength - 1, padTo, padWith);
|
|
|
|
|
return StringConverter12.SetString1(value, maxLength - 1, Japanese, padTo, padWith);
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed override string Nickname
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (Korean)
|
2021-05-29 22:31:47 +00:00
|
|
|
|
return StringConverter2KOR.GetString2KOR(RawNickname, 0, RawNickname.Length);
|
|
|
|
|
return StringConverter12.GetString1(RawNickname, 0, RawNickname.Length, Japanese);
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (!IsNicknamed && Nickname == value)
|
|
|
|
|
return;
|
|
|
|
|
|
2021-05-29 22:31:47 +00:00
|
|
|
|
SetStringKeepTerminatorStyle(value, RawNickname);
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed override string OT_Name
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (Korean)
|
2021-05-29 22:31:47 +00:00
|
|
|
|
return StringConverter2KOR.GetString2KOR(RawOT, 0, RawOT.Length);
|
|
|
|
|
return StringConverter12.GetString1(RawOT, 0, RawOT.Length, Japanese);
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
2021-05-20 23:54:53 +00:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (value == OT_Name)
|
|
|
|
|
return;
|
2021-05-29 22:31:47 +00:00
|
|
|
|
SetStringKeepTerminatorStyle(value, RawOT);
|
2021-05-20 23:54:53 +00:00
|
|
|
|
}
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-16 21:56:37 +00:00
|
|
|
|
private void SetStringKeepTerminatorStyle(string value, byte[] exist)
|
2020-10-03 01:08:40 +00:00
|
|
|
|
{
|
2021-01-16 20:43:17 +00:00
|
|
|
|
// Reset the destination buffer based on the termination style of the existing string.
|
|
|
|
|
bool zeroed = Array.IndexOf(exist, (byte)0) != -1;
|
2021-03-29 07:14:44 +00:00
|
|
|
|
byte fill = zeroed ? (byte)0 : StringConverter12.G1TerminatorCode;
|
2021-01-16 20:43:17 +00:00
|
|
|
|
for (int i = 0; i < exist.Length; i++)
|
|
|
|
|
exist[i] = fill;
|
|
|
|
|
|
2021-01-16 21:56:37 +00:00
|
|
|
|
int finalLength = Math.Min(value.Length + 1, exist.Length);
|
2021-01-16 20:43:17 +00:00
|
|
|
|
byte[] strdata = SetString(value, finalLength);
|
|
|
|
|
strdata.CopyTo(exist, 0);
|
2020-10-03 01:08:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|