Ver 1.10. Supports both JPN and USA/EUR version.

This commit is contained in:
sy2zhao 2017-09-10 03:16:02 -04:00
parent 50f336721c
commit 3588806971
19 changed files with 919 additions and 609 deletions

View File

@ -6,29 +6,38 @@ using System.Linq;
using System.Text;
using System.Windows;
using MHSEC_G.Annotations;
using Microsoft.Win32;
namespace MHSEC_G
{
public class Armor : INotifyPropertyChanged
public class Armor : InMemoryObject
{
private const uint OFFSETA_ARM = 0x55F0;
private const uint OFFSETA_ARM_END = 0x720E;
// 200 armors
private const uint SIZE_ARM = 0x24;
private const uint OFFSETR_ARM_ID = 0x2;
private const uint OFFSETR_ARM_LEVEL = 0x4;
private const uint OFFSETR_ARM_14h = 0x14;
private const uint OFFSETR_ARM_18h = 0x18;
private const uint OFFSETR_ARM_1C = 0x1c;
public uint index => (_obj_offset - Offsets.OFFSETA_ARM) / Offsets.SIZE_ARM + 1;
private readonly uint _offset;
private readonly Model _model;
public uint index => (_offset - OFFSETA_ARM) / SIZE_ARM + 1;
public Armor(Model model, uint offset)
public Armor(byte[] save, uint objOffset) : base(save, objOffset, Offsets.SIZE_ARM)
{
_offset = offset;
_model = model;
}
public string type
{
set
{
uint parsed;
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ARM_TYPE, parsed);
}
else
{
MessageBox.Show("Malformed int - must be at most 0xFFFF", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(type));
}
get
{
return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ARM_TYPE).ToString("X4");
}
}
public string id
@ -36,9 +45,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_ARM_ID, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ARM_ID, parsed);
}
else
{
@ -48,7 +57,7 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ARM_ID).ToString("X4");
return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ARM_ID).ToString("X4");
}
}
@ -57,9 +66,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_ARM_LEVEL, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ARM_LEVEL, parsed);
}
else
{
@ -69,7 +78,7 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ARM_LEVEL).ToString("X4");
return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ARM_LEVEL).ToString("X4");
}
}
@ -79,9 +88,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed))
if (Helper.parse_hex_string(value, out parsed))
{
Model.write_uint32_le(_model.save_file, _offset + OFFSETR_ARM_14h, parsed);
Helper.write_uint32_le(_data, _obj_offset + Offsets.OFFSETR_ARM_14h, parsed);
}
else
{
@ -91,7 +100,7 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint32_le(_model.save_file, _offset + OFFSETR_ARM_14h).ToString("X8");
return Helper.byte_to_uint32_le(_data, _obj_offset + Offsets.OFFSETR_ARM_14h).ToString("X8");
}
}
@ -100,9 +109,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed))
if (Helper.parse_hex_string(value, out parsed))
{
Model.write_uint32_le(_model.save_file, _offset + OFFSETR_ARM_18h, parsed);
Helper.write_uint32_le(_data, _obj_offset + Offsets.OFFSETR_ARM_18h, parsed);
}
else
{
@ -112,7 +121,7 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint32_le(_model.save_file, _offset + OFFSETR_ARM_18h).ToString("X8");
return Helper.byte_to_uint32_le(_data, _obj_offset + Offsets.OFFSETR_ARM_18h).ToString("X8");
}
}
@ -121,9 +130,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed))
if (Helper.parse_hex_string(value, out parsed))
{
Model.write_uint32_le(_model.save_file, _offset + OFFSETR_ARM_1C, parsed);
Helper.write_uint32_le(_data, _obj_offset + Offsets.OFFSETR_ARM_1C, parsed);
}
else
{
@ -133,28 +142,18 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint32_le(_model.save_file, _offset + OFFSETR_ARM_1C).ToString("X8");
return Helper.byte_to_uint32_le(_data, _obj_offset + Offsets.OFFSETR_ARM_1C).ToString("X8");
}
}
public static ObservableCollection<Armor> read_all_armors(Model model)
public static ObservableCollection<Armor> read_all_armors(byte[] save)
{
ObservableCollection<Armor> ret = new ObservableCollection<Armor>();
for (uint i = OFFSETA_ARM; i < OFFSETA_ARM_END; i += SIZE_ARM)
for (uint i = Offsets.OFFSETA_ARM; i < Offsets.OFFSETA_ARM_END; i += Offsets.SIZE_ARM)
{
ret.Add(new Armor(model, i));
ret.Add(new Armor(save, i));
}
return ret;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -1,34 +1,24 @@
using System.ComponentModel;
using System;
using System.ComponentModel;
using System.Windows;
using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Character : INotifyPropertyChanged
public class Character : InMemoryObject
{
private const uint OFFSETA_CHAR_NAME = 0x9DA0;
private const uint LENGTH_CHAR_NAME = 6;
private const uint OFFSETA_CHAR_MONEY = 0x5B404;
private const uint OFFSETA_CHAR_EXP = 0x9E68;
private const uint OFFSETA_CHAR_LEVEL = 0x9E64;
public const uint LIMIT_LEVEL = 99;
public const uint LIMIT_MONEY = 9999999;
public const uint LIMIT_EXP = 25165822;
private readonly Model _model;
public uint level
{
get { return Model.byte_to_uint(_model.save_file[OFFSETA_CHAR_LEVEL]); }
get { return Helper.byte_to_uint(_data[Offsets.OFFSETA_CHAR_LEVEL]); }
set
{
if (value <= LIMIT_LEVEL)
if (value <= Offsets.LIMIT_LEVEL)
{
Model.write_byte(_model.save_file, OFFSETA_CHAR_LEVEL, value);
Helper.write_byte(_data, Offsets.OFFSETA_CHAR_LEVEL, value);
}
else
{
MessageBox.Show("Level must be less than " + LIMIT_LEVEL, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show("Level must be less than " + Offsets.LIMIT_LEVEL, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(level));
}
@ -36,16 +26,16 @@ namespace MHSEC_G
public uint exp
{
get { return Model.byte_to_uint32_le(_model.save_file, OFFSETA_CHAR_EXP); }
get { return Helper.byte_to_uint32_le(_data, Offsets.OFFSETA_CHAR_EXP); }
set
{
if (value <= LIMIT_EXP)
if (value <= Offsets.LIMIT_EXP)
{
Model.write_uint32_le(_model.save_file, OFFSETA_CHAR_EXP, value);
Helper.write_uint32_le(_data, Offsets.OFFSETA_CHAR_EXP, value);
}
else
{
MessageBox.Show("Exp must be less than " + LIMIT_EXP, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show("Exp must be less than " + Offsets.LIMIT_EXP, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(exp));
}
@ -53,16 +43,16 @@ namespace MHSEC_G
public uint money
{
get { return Model.byte_to_uint32_le(_model.save_file, OFFSETA_CHAR_MONEY); }
get { return Helper.byte_to_uint32_le(_data, Offsets.OFFSETA_CHAR_MONEY); }
set
{
if (value <= LIMIT_MONEY)
if (value <= Offsets.LIMIT_MONEY)
{
Model.write_uint32_le(_model.save_file, OFFSETA_CHAR_MONEY, value);
Helper.write_uint32_le(_data, Offsets.OFFSETA_CHAR_MONEY, value);
}
else
{
MessageBox.Show("Money must be less than " + LIMIT_MONEY, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show("Money must be less than " + Offsets.LIMIT_MONEY, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(money));
}
@ -70,33 +60,33 @@ namespace MHSEC_G
public string name
{
get { return Model.read_unicode_string(_model.save_file, OFFSETA_CHAR_NAME, LENGTH_CHAR_NAME); }
get { return Helper.read_unicode_string(_data, Offsets.OFFSETA_CHAR_NAME, Offsets.LENGTH_CHAR_NAME); }
set
{
if (value.Length <= LENGTH_CHAR_NAME && value.Length > 0)
if (value.Length <= Offsets.LENGTH_CHAR_NAME && value.Length > 0)
{
Model.write_unicode_string(_model.save_file, OFFSETA_CHAR_NAME, value, LENGTH_CHAR_NAME);
Helper.write_unicode_string(_data, Offsets.OFFSETA_CHAR_NAME, value, Offsets.LENGTH_CHAR_NAME);
}
else
{
MessageBox.Show("Name must be 1-" + LENGTH_CHAR_NAME + " characters.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show("Name must be 1-" + Offsets.LENGTH_CHAR_NAME + " characters.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
OnPropertyChanged(nameof(name));
}
}
public Character(Model model)
public Character(byte[] model) : base(model, Offsets.OFFSETA_CHAR_NAME, 0)
{
_model = model;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
public override byte[] toByteArray()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
throw new NotImplementedException();
}
public override void setByteArray(byte[] data)
{
throw new NotImplementedException();
}
}
}

View File

@ -6,28 +6,17 @@ using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Egg : INotifyPropertyChanged
public class Egg : InMemoryObject
{
private const int OFFSETA_EGG_START = 0x53EC0;
private const int OFFSETA_EGG_END = 0x54597;
private const int OFFSETR_EGG_GENE = 0x30;
private const int SIZE_EGG_GENE = 0x2;
private const int SIZE_EGG = 0x92;
private const int OFFSETR_SPE = 0x0;
private const int OFFSETR_WGT = 0x2E;
private readonly Genes _genes;
public Genes genes => _genes;
private readonly uint _offset;
private readonly Model _model;
public uint index => (_offset - OFFSETA_EGG_START) / SIZE_EGG + 1;
public uint index => (_obj_offset - Offsets.OFFSETA_EGG_START) / Offsets.SIZE_EGG + 1;
public Egg(Model model, uint offset)
public Egg(byte[] model, uint objOffset) : base(model, objOffset, Offsets.SIZE_EGG)
{
_offset = offset;
_model = model;
_genes = new Genes(model, offset + OFFSETR_EGG_GENE, SIZE_EGG_GENE);
_genes = new Genes(model, objOffset + Offsets.OFFSETR_EGG_GENE, Offsets.SIZE_EGG_GENE);
}
public string spe
@ -35,9 +24,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_SPE, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_SPE, parsed);
}
else
{
@ -47,7 +36,7 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_SPE]).ToString("X2");
return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_SPE]).ToString("X2");
}
}
@ -56,9 +45,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_WGT, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_WGT, parsed);
}
else
{
@ -68,34 +57,18 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_WGT]).ToString("X2");
return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_WGT]).ToString("X2");
}
}
public static ObservableCollection<Egg> read_all_eggs(Model model)
public static ObservableCollection<Egg> read_all_eggs(byte[] model)
{
ObservableCollection<Egg> ret = new ObservableCollection<Egg>();
for (uint i = OFFSETA_EGG_START; i < OFFSETA_EGG_END; i += SIZE_EGG)
for (uint i = Offsets.OFFSETA_EGG_START; i < Offsets.OFFSETA_EGG_END; i += Offsets.SIZE_EGG)
{
ret.Add(new Egg(model, i));
}
return ret;
}
public void setByteArray(byte[] ret)
{
Array.Copy(ret, 0, _model.save_file, _offset, SIZE_EGG);
OnPropertyChanged(null);
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -6,43 +6,23 @@ using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class EggFragment : INotifyPropertyChanged
public class EggFragment : InMemoryObject
{
private const uint OFFSETA_EGG_FRAGMENTS = 0x9790;
private const uint OFFSETA_EGG_FRAGMENTS_END = 0x9C3F;
private const uint SIZE_EGG_FRAGMENT = 0xC;
private const uint OFFSETR_EF_SPE = 0x0;
private const uint OFFSETR_EF_POS = 0x1;
private const uint OFFSETR_EF_NEW = 0x2;
private const uint OFFSETR_EF_RAR = 0x3;
private const uint OFFSETR_EF_COL = 0x4;
private const uint OFFSETR_EF_DLC = 0x5;
private const uint OFFSETR_EF_6H = 0x6;
private const uint OFFSETR_EF_7H = 0x7;
public uint idx => (_obj_offset - Offsets.OFFSETA_EGG_FRAGMENTS) / Offsets.SIZE_EGG_FRAGMENT + 1;
private readonly uint _offset;
public uint idx => (_offset - OFFSETA_EGG_FRAGMENTS) / SIZE_EGG_FRAGMENT + 1;
public uint offset
public EggFragment(byte[] model, uint objOffset) : base(model, objOffset, Offsets.SIZE_EGG_FRAGMENT)
{
get { return _offset;}
}
private readonly Model _model;
public EggFragment(uint offset, Model model)
{
_model = model;
_offset = offset;
}
public string spe
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_SPE]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_SPE]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0x0E)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0x0E)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_SPE, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_SPE, parsed);
}
else
{
@ -54,13 +34,13 @@ namespace MHSEC_G
public string pos
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_POS]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_POS]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0x08)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0x08)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_POS, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_POS, parsed);
}
else
{
@ -72,13 +52,13 @@ namespace MHSEC_G
public string new_flag
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_NEW]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_NEW]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0x01)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0x01)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_NEW, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_NEW, parsed);
}
else
{
@ -89,13 +69,13 @@ namespace MHSEC_G
}
public string rarity
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_RAR]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_RAR]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0x01)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0x01)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_RAR, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_RAR, parsed);
}
else
{
@ -107,13 +87,13 @@ namespace MHSEC_G
public string color
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_COL]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_COL]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_COL, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_COL, parsed);
}
else
{
@ -125,13 +105,13 @@ namespace MHSEC_G
public string dlc
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_DLC]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_DLC]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_DLC, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_DLC, parsed);
}
else
{
@ -143,13 +123,13 @@ namespace MHSEC_G
public string unknown_6h
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_6H]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_6H]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_6H, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_6H, parsed);
}
else
{
@ -161,13 +141,13 @@ namespace MHSEC_G
public string unknown_7h
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EF_7H]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EF_7H]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EF_7H, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EF_7H, parsed);
}
else
{
@ -177,55 +157,14 @@ namespace MHSEC_G
}
}
public static ObservableCollection<EggFragment> read_all_egg_fragments(Model model)
public static ObservableCollection<EggFragment> read_all_egg_fragments(byte[] model)
{
ObservableCollection<EggFragment> ret = new ObservableCollection<EggFragment>();
byte[] buffer = model.save_file;
for (uint offset = OFFSETA_EGG_FRAGMENTS; offset < OFFSETA_EGG_FRAGMENTS_END; offset += SIZE_EGG_FRAGMENT)
for (uint offset = Offsets.OFFSETA_EGG_FRAGMENTS; offset < Offsets.OFFSETA_EGG_FRAGMENTS_END; offset += Offsets.SIZE_EGG_FRAGMENT)
{
ret.Add(new EggFragment(offset, model));
ret.Add(new EggFragment(model, offset));
}
return ret;
}
private static EggFragment egg_frag_offset_exist(ObservableCollection<EggFragment> fragments, uint offset)
{
for (uint i = 0; i < fragments.Count; i++)
{
if(fragments.ElementAt((int)i).offset == offset)
return fragments.ElementAt((int)i);
}
return null;
}
public static void write_dlc_egg_fragment(ObservableCollection<EggFragment> fragments, Model model, uint dlc)
{
for (uint offset = OFFSETA_EGG_FRAGMENTS; offset < OFFSETA_EGG_FRAGMENTS + 9*SIZE_EGG_FRAGMENT ; offset += SIZE_EGG_FRAGMENT)
{
EggFragment each_frag = egg_frag_offset_exist(fragments, offset);
if (each_frag == null)
{
each_frag = new EggFragment(offset, model);
fragments.Insert((int)((offset - OFFSETA_EGG_FRAGMENTS) / SIZE_EGG_FRAGMENT), each_frag);
}
each_frag.new_flag = "0";
each_frag.spe = "08";
each_frag.pos = ((offset-OFFSETA_EGG_FRAGMENTS) / SIZE_EGG_FRAGMENT).ToString();
each_frag.rarity = "0";
each_frag.color = "0";
each_frag.dlc = dlc.ToString("X2");
each_frag.unknown_6h = "0";
each_frag.unknown_7h = "0";
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -9,40 +9,28 @@ using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Genes : INotifyPropertyChanged
public class Genes : InMemoryObject
{
public static readonly List<uint> GENE_ID = new List<uint>();
public static readonly List<string> GENE_NAME = new List<string>();
public List<string> gene_name => GENE_NAME;
private readonly uint _size;
private readonly Model _model;
private readonly uint _offset;
public Genes(Model model, uint offset, uint size)
public List<string> gene_name => Offsets.GENE_NAME;
private readonly uint _gene_size;
public Genes(byte[] model, uint objOffset, uint gene_size) : base(model, objOffset, 9 * gene_size)
{
this._size = size;
this._offset = offset;
this._model = model;
_gene_size = gene_size;
}
//
// Genes
//
private uint extract_gene(uint gene_idx)
{
if (gene_idx >= 9)
{
BugCheck.bug_check(BugCheck.ErrorCode.MON_GENE_IDX_OVERFLOW, "Invalid gene index: " + gene_idx);
}
return Model.byte_to_uint16_le(_model.save_file,
_offset + gene_idx * _size);
return Helper.byte_to_uint16_le(_data, _obj_offset + gene_idx * _gene_size);
}
private void set_gene_str(uint gene_idx, string val)
{
uint parsed;
if (Model.parse_hex_string(val, out parsed))
if (Helper.parse_hex_string(val, out parsed))
{
set_gene(gene_idx, parsed);
}
@ -61,7 +49,7 @@ namespace MHSEC_G
}
if (val <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + gene_idx * _size,
Helper.write_uint16_le(_data, _obj_offset + gene_idx * _gene_size,
val);
}
else
@ -74,20 +62,20 @@ namespace MHSEC_G
private int extract_gene_idx(uint gene_idx)
{
uint gene_id = extract_gene(gene_idx);
int idx = GENE_ID.IndexOf(gene_id);
int idx = Offsets.GENE_ID.IndexOf(gene_id);
if (idx == -1)
{
// unknown
return GENE_NAME.Count - 1;
return Offsets.GENE_NAME.Count - 1;
}
return idx;
}
private void set_gene_idx(uint gene_idx, int val)
{
if (val != -1 && val != GENE_NAME.Count - 1)
if (val != -1 && val != Offsets.GENE_NAME.Count - 1)
{
set_gene(gene_idx, GENE_ID.ElementAt(val));
set_gene(gene_idx, Offsets.GENE_ID.ElementAt(val));
}
}
@ -297,38 +285,5 @@ namespace MHSEC_G
OnPropertyChanged(nameof(gene9_selected));
}
}
public static void read_gene_mapping()
{
string line;
StringReader file = new StringReader(Properties.Resources.gene);
while ((line = file.ReadLine()) != null)
{
if (line.Length == 0)
continue;
string[] eachline = line.Split('\t');
if (eachline.Length != 2)
{
BugCheck.bug_check(BugCheck.ErrorCode.MON_GENE_MAPPING_CORRUPTED,
"Invalid gene mapping file line:\n" + line);
}
GENE_ID.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber));
GENE_NAME.Add(eachline[1]);
}
GENE_NAME.Add("Custom");
file.Close();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -4,26 +4,8 @@ using System.Text;
namespace MHSEC_G
{
public class Model
public static class Helper
{
public const uint SAVE_FILE_SIZE = 483976;
private readonly byte[] _save_file;
public byte[] save_file
{
get { return _save_file; }
}
public Model(byte[] save_file)
{
if (save_file.Length != SAVE_FILE_SIZE)
{
BugCheck.bug_check(BugCheck.ErrorCode.MODEL_INVALID_FILE_SIZE, "Invalid file size.\nExpected: " + SAVE_FILE_SIZE + " Got: " + save_file.Length);
}
_save_file = save_file;
}
public static uint byte_to_uint(byte b)
{
return (uint) (b) & 0xFF;

View File

@ -0,0 +1,48 @@
using System;
using System.ComponentModel;
using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class InMemoryObject : INotifyPropertyChanged
{
protected readonly uint _obj_offset;
protected readonly byte[] _data;
protected readonly uint _obj_size;
public InMemoryObject(byte[] data, uint objOffset, uint objSize)
{
_obj_offset = objOffset;
_data = data;
_obj_size = objSize;
}
public virtual byte[] toByteArray()
{
byte[] ret = new byte[_obj_size];
Array.Copy(_data, _obj_offset, ret, 0, _obj_size);
return ret;
}
public virtual void setByteArray(byte[] data)
{
if (data.Length != _obj_size)
{
BugCheck.bug_check(BugCheck.ErrorCode.MODEL_INVALID_FILE_SIZE, "Invalid data size in setByteArray.");
}
else
{
Array.Copy(data, 0, _data, _obj_offset, _obj_size);
OnPropertyChanged(null);
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -8,34 +8,16 @@ using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Item : INotifyPropertyChanged
public class Item : InMemoryObject
{
private static readonly uint OFFSETA_ITEM_BOX = 0x10;
private static readonly uint SIZE_ITEM = 0x8;
private static readonly uint OFFSETR_ITEM_ID = 0x0;
private static readonly uint OFFSETR_ITEM_COUNT = 0x2;
private static readonly uint OFFSETA_ITEM_BOX_END = 0x2EE7;
public static readonly uint OFFSETA_FIRST_KEY_ITEM = 0x17B0;
private static readonly Dictionary<uint, uint> OFFSET_ID_MAPPING = new Dictionary<uint, uint>();
private static readonly Dictionary<uint, string> OFFSET_NAME_MAPPING = new Dictionary<uint, string>();
private readonly uint _offset;
public uint offset
{
get { return _offset; }
}
private readonly Model _model;
public uint offset => _obj_offset;
public string name
{
get {
string name = _offset >= OFFSETA_FIRST_KEY_ITEM ? "Key Item [" + id.ToString("X4") + "]" : "Unknown";
if (OFFSET_NAME_MAPPING.ContainsKey(_offset))
string name = _obj_offset >= Offsets.OFFSETA_FIRST_KEY_ITEM ? "Key Item [" + id.ToString("X4") + "]" : "Unknown";
if (Offsets.OFFSET_NAME_MAPPING.ContainsKey(_obj_offset))
{
name = OFFSET_NAME_MAPPING[_offset];
name = Offsets.OFFSET_NAME_MAPPING[_obj_offset];
}
return name;
}
@ -44,12 +26,12 @@ namespace MHSEC_G
public uint count
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_COUNT); }
get { return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ITEM_COUNT); }
set
{
if (value <= 999)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_COUNT, value);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ITEM_COUNT, value);
}
else
{
@ -61,85 +43,52 @@ namespace MHSEC_G
public uint id
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ITEM_ID); }
get { return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ITEM_ID); }
}
public Item(uint offset, Model model)
public Item(byte[] model, uint objOffset) : base(model, objOffset, Offsets.SIZE_ITEM)
{
_offset = offset;
_model = model;
}
public static List<Item> read_all_items(Model model)
public static List<Item> read_all_items(byte[] model)
{
byte[] buffer = model.save_file;
List<Item> ret = new List<Item>();
for (uint offset = OFFSETA_ITEM_BOX; offset < OFFSETA_ITEM_BOX_END; offset += SIZE_ITEM)
for (uint offset = Offsets.OFFSETA_ITEM_BOX;
offset < Offsets.OFFSETA_ITEM_BOX_END;
offset += Offsets.SIZE_ITEM)
{
uint item_id = Model.byte_to_uint16_le(buffer, offset + OFFSETR_ITEM_ID);
uint item_id = Helper.byte_to_uint16_le(model, offset + Offsets.OFFSETR_ITEM_ID);
if (item_id == 0)
{
// if not obtained yet
if (!OFFSET_ID_MAPPING.ContainsKey(offset))
if (!Offsets.OFFSET_ID_MAPPING.ContainsKey(offset))
{
// well we dont know the id to this offset either. just ignore!
// continue
continue;
}
// if we know the id to the offset, just set it
Model.write_uint16_le(model.save_file, offset + OFFSETR_ITEM_ID, OFFSET_ID_MAPPING[offset]);
Helper.write_uint16_le(model, offset + Offsets.OFFSETR_ITEM_ID, Offsets.OFFSET_ID_MAPPING[offset]);
}
else
{
// already obtained
// validate
if (OFFSET_ID_MAPPING.ContainsKey(offset))
if (Offsets.OFFSET_ID_MAPPING.ContainsKey(offset))
{
if (item_id != OFFSET_ID_MAPPING[offset])
if (item_id != Offsets.OFFSET_ID_MAPPING[offset])
{
// correct to the correct id
// don't bug_check since too many people's files are broken
// TODO: BugCheck.bug_check(BugCheck.ErrorCode.ITEM_NO_CORRESPONDENCE, "Item offset " + offset.ToString("X") + " and item ID " + item_id.ToString("X") + " do not correspond.");
Model.write_uint16_le(model.save_file, offset + OFFSETR_ITEM_ID, OFFSET_ID_MAPPING[offset]);
Helper.write_uint16_le(model, offset + Offsets.OFFSETR_ITEM_ID, Offsets.OFFSET_ID_MAPPING[offset]);
}
}
}
// valid offset
ret.Add(new Item(offset, model));
ret.Add(new Item(model, offset));
}
return ret;
}
public static void read_item_mappings()
{
string line;
StringReader file = new StringReader(Properties.Resources.idmap);
while ((line = file.ReadLine()) != null)
{
if (line.Length == 0)
continue;
string[] eachline = line.Split('\t');
if (eachline.Length != 3)
{
BugCheck.bug_check(BugCheck.ErrorCode.ITEM_MAPPING_CORRUPTED, "Invalid mapping file line:\n" + line);
}
OFFSET_ID_MAPPING.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), uint.Parse(eachline[1], System.Globalization.NumberStyles.HexNumber));
OFFSET_NAME_MAPPING.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), eachline[2]);
}
file.Close();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -90,12 +90,14 @@
<Compile Include="GeneWindow.xaml.cs">
<DependentUpon>GeneWindow.xaml</DependentUpon>
</Compile>
<Compile Include="InMemoryObject.cs" />
<Compile Include="Item.cs" />
<Compile Include="Model.cs" />
<Compile Include="Helper.cs" />
<Compile Include="Monster.cs" />
<Compile Include="MonsterWindow.xaml.cs">
<DependentUpon>MonsterWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Offsets.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>

View File

@ -81,7 +81,7 @@
Header="Index" IsReadOnly="True"/>
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="50" Binding="{Binding spe}"
Header="Species" />
Header="Genus" />
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="60" Binding="{Binding pos}"
Header="Position" />
@ -109,8 +109,8 @@
</TabItem>
<TabItem Header="Eggs">
<Grid Background="#FFE5E5E5">
<DataGrid x:Name="egg_grid" HorizontalAlignment="Left" Margin="10,30,0,0"
VerticalAlignment="Top" Height="287" Width="417" CanUserAddRows="False"
<DataGrid x:Name="egg_grid" HorizontalAlignment="Left" Margin="10,54,0,0"
VerticalAlignment="Top" Height="263" Width="417" CanUserAddRows="False"
AutoGenerateColumns="False" ItemsSource="{Binding eggs}" SelectionMode="Single">
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
@ -123,15 +123,15 @@
Header="Index" IsReadOnly="True"/>
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="*" Binding="{Binding spe}"
Header="Hatched Monster Type" />
Header="Hatched Monster Species" />
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="*" Binding="{Binding wgt}"
Header="Weight" />
</DataGrid.Columns>
</DataGrid>
<Label x:Name="label_monster_Copy" Content="Double-click an entry to edit genes." HorizontalAlignment="Left" Margin="10,4,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.184,0.019"/>
<Button x:Name="button_eggs_delete" Content="Delete" HorizontalAlignment="Left" Margin="353,5,0,0" VerticalAlignment="Top" Width="74" RenderTransformOrigin="1.601,-0.2" Click="button_eggs_delete_Click"/>
<Button x:Name="button_eggs_dummy" Content="Set Dummy Egg" HorizontalAlignment="Left" Margin="240,5,0,0" VerticalAlignment="Top" Width="108" RenderTransformOrigin="1.601,-0.2" Click="button_eggs_dummy_Click"/>
<Label x:Name="label_monster_Copy" Content="Double-click an entry to edit genes. Click twice to edit the table entry." HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.184,0.019"/>
<Button x:Name="button_eggs_delete" Content="Delete" HorizontalAlignment="Left" Margin="319,29,0,0" VerticalAlignment="Top" Width="108" RenderTransformOrigin="1.601,-0.2" Click="button_eggs_delete_Click"/>
<Button x:Name="button_eggs_dummy" Content="Set Dummy Egg" HorizontalAlignment="Left" Margin="206,29,0,0" VerticalAlignment="Top" Width="108" RenderTransformOrigin="1.601,-0.2" Click="button_eggs_dummy_Click"/>
</Grid>
</TabItem>
@ -226,10 +226,13 @@
Width="40" Binding="{Binding index}"
Header="Index" IsReadOnly="True"/>
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="50" Binding="{Binding id}"
Width="40" Binding="{Binding type}"
Header="Type" />
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="40" Binding="{Binding id}"
Header="ID" />
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="50" Binding="{Binding level}"
Width="40" Binding="{Binding level}"
Header="Level" />
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="*" Binding="{Binding unknown_14h}"
@ -239,7 +242,7 @@
Header="Color2 (RGB)" />
<DataGridTextColumn CanUserReorder="False" CanUserResize="False" CanUserSort="False"
Width="*" Binding="{Binding unknown_1ch}"
Header="Unknown 1Ch" />
Header="0x1Ch" />
</DataGrid.Columns>
</DataGrid>
</Grid>
@ -250,6 +253,8 @@
<Button x:Name="button_load" Content="Load" HorizontalAlignment="Left" Margin="90,10,0,0"
VerticalAlignment="Top" Width="74" Click="button_load_click" />
<Button x:Name="button_about" Content="About" HorizontalAlignment="Left" Margin="379,10,0,0" VerticalAlignment="Top" Width="74" Click="button_about_Click"/>
<Label x:Name="label_save_ver_cap" Content="Save Version:" HorizontalAlignment="Left" Margin="164,7,0,0" VerticalAlignment="Top"/>
<Label x:Name="label_save_ver" Content="JPN" HorizontalAlignment="Left" Margin="235,7,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.237,0.519" FontWeight="Bold"/>
</Grid>
</Window>

View File

@ -16,8 +16,6 @@ namespace MHSEC_G
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private readonly byte[] _dummy_data = new byte[Model.SAVE_FILE_SIZE];
private static string get_app_version()
{
Version v = Assembly.GetExecutingAssembly().GetName().Version;
@ -29,11 +27,13 @@ namespace MHSEC_G
{
InitializeComponent();
button_save.IsEnabled = false;
Item.read_item_mappings();
Genes.read_gene_mapping();
Array.Clear(_dummy_data, 0, _dummy_data.Length);
byte[] dummy = new byte[Offsets.SAVE_FILE_SIZE_JPN];
Array.Clear(dummy, 0, dummy.Length);
this.Title = "MHSEC-G Ver " + get_app_version();
init(_dummy_data);
Offsets.init(dummy);
init(dummy);
DataContext = this;
}
@ -45,16 +45,25 @@ namespace MHSEC_G
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
byte[] buffer = File.ReadAllBytes(dialog.FileName);
if (buffer.Length != Model.SAVE_FILE_SIZE)
if (buffer.Length != Offsets.SAVE_FILE_SIZE_JPN && buffer.Length != Offsets.SAVE_FILE_SIZE_NA)
{
System.Windows.Forms.MessageBox.Show(
"Wrong save file size! Expected: " + Model.SAVE_FILE_SIZE + " Got: " + buffer.Length,
"Error",
"Unsupported save file!",
"MHSEC-G",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
else
{
if (buffer.Length == Offsets.SAVE_FILE_SIZE_JPN)
{
label_save_ver.Content = "JPN";
}
else
{
label_save_ver.Content = "EUR/USA";
}
Offsets.init(buffer);
init(buffer);
OnPropertyChanged(null);
button_save.IsEnabled = true;
@ -64,12 +73,12 @@ namespace MHSEC_G
private void button_char_money_Click(object sender, RoutedEventArgs e)
{
_character.money = Character.LIMIT_MONEY;
_character.money = Offsets.LIMIT_MONEY;
}
private void button_char_exp_Click(object sender, RoutedEventArgs e)
{
_character.exp = Character.LIMIT_EXP;
_character.exp = Offsets.LIMIT_EXP;
}
private void button_item_all_Click(object sender, RoutedEventArgs e)
@ -77,7 +86,7 @@ namespace MHSEC_G
List<Item> items = _items;
for (uint i = 0; i < items.Count; i++)
{
if (items.ElementAt((int) i).offset >= Item.OFFSETA_FIRST_KEY_ITEM)
if (items.ElementAt((int) i).offset >= Offsets.OFFSETA_FIRST_KEY_ITEM)
break;
items.ElementAt((int) i).count = 986;
@ -89,7 +98,7 @@ namespace MHSEC_G
List<Item> items = _items;
for (uint i = 0; i < items.Count; i++)
{
if (items.ElementAt((int) i).offset >= Item.OFFSETA_FIRST_KEY_ITEM)
if (items.ElementAt((int) i).offset >= Offsets.OFFSETA_FIRST_KEY_ITEM)
break;
if (items.ElementAt((int) i).count != 0)
@ -107,55 +116,20 @@ namespace MHSEC_G
dialog.FileName = "mhr_game0.sav";
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
File.WriteAllBytes(dialog.FileName, _model.save_file);
File.WriteAllBytes(dialog.FileName, _model);
MessageBox.Show("Saved to \"" + dialog.FileName + "\"", "MHSEC-G", MessageBoxButton.OK,
MessageBoxImage.Information);
}
}
private void button_give_epony_Click(object sender, RoutedEventArgs e)
{
EggFragment.write_dlc_egg_fragment(_egg_fragments, _model, 0x4);
}
private void button_give_bear_Click(object sender, RoutedEventArgs e)
{
EggFragment.write_dlc_egg_fragment(_egg_fragments, _model, 0x5);
}
private void button_give_mtiggy_Click(object sender, RoutedEventArgs e)
{
EggFragment.write_dlc_egg_fragment(_egg_fragments, _model, 0x20);
}
private void button_give_okirin_Click(object sender, RoutedEventArgs e)
{
EggFragment.write_dlc_egg_fragment(_egg_fragments, _model, 0x21);
}
private void button_give_dino_Click(object sender, RoutedEventArgs e)
{
EggFragment.write_dlc_egg_fragment(_egg_fragments, _model, 0x6);
}
private void button_give_wm_Click(object sender, RoutedEventArgs e)
{
EggFragment.write_dlc_egg_fragment(_egg_fragments, _model, 0x1F);
}
private void button_give_pd_Click(object sender, RoutedEventArgs e)
{
EggFragment.write_dlc_egg_fragment(_egg_fragments, _model, 0x3);
}
private void button_about_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("MHSEC-G Version " + get_app_version() + "\nDeveloped by secXsQuared", "About",
MessageBoxButton.OK, MessageBoxImage.Information);
}
private Model _model;
public Model model => _model;
private byte[] _model;
public byte[] model => _model;
private Character _character;
public Character character => _character;
@ -187,7 +161,7 @@ namespace MHSEC_G
{
BugCheck.bug_check(BugCheck.ErrorCode.VIEWMODEL_NULL_SAVE, "The save file reference is NULL.");
}
_model = new Model(save);
_model = save;
_character = new Character(_model);
_items = Item.read_all_items(_model);
_monsters = new ObservableCollection<Monster>(Monster.read_all_monsters(_model));

View File

@ -9,50 +9,23 @@ using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Monster : INotifyPropertyChanged
public class Monster : InMemoryObject
{
public const uint LIMIT_MONSTER_EXP = 0xFFFFFF;
public const uint SIZE_MONSTER = 0x478;
private const uint OFFSETA_MONSTER = 0xA150;
private const uint OFFSETR_MONSTER_GENE = 0x424;
private const uint SIZE_MONSTER_GENE = 0x4;
private const uint OFFSETR_MONSTER_EXP = 0xE0;
private const uint OFFSETR_MONSTER_HIV = 0xD8;
private const uint OFFSETR_MONSTER_AIV = 0xD9;
private const uint OFFSETR_MONSTER_DIV = 0xDA;
private const uint OFFSETR_MONSTER_HPU = 0xD4;
private const uint OFFSETR_MONSTER_APU = 0xD5;
private const uint OFFSETR_MONSTER_DPU = 0xD6;
private const uint OFFSETR_MONSTER_SKILL = 0x38;
private const uint OFFSETR_MONSTER_LEVEL = 0x5C;
private const uint LIMIT_MONSTER_LEVEL = 99;
private const uint OFFSETR_MONSTER_NAME = 0;
private const uint LIMIT_MONSTER_NAME = 10;
private const uint OFFSETR_MONSTER_SPE = 0x30;
private const uint OFFSETA_MONSTE_END = 0x4786F;
private const uint OFFSETR_MONSTER_ATK = 0x48;
private const uint OFFSETR_MONSTER_HP = 0x46;
private const uint OFFSETR_MONSTER_DEF = 0x4A;
private readonly Model _model;
private readonly uint _offset;
public uint offset => _offset;
public uint box => (_offset - OFFSETA_MONSTER) / SIZE_MONSTER / 18 + 1;
public uint slot => (_offset - OFFSETA_MONSTER) / SIZE_MONSTER % 18 + 1;
public uint box => (_obj_offset - Offsets.OFFSETA_MONSTER) / Offsets.SIZE_MONSTER / 18 + 1;
public uint slot => (_obj_offset - Offsets.OFFSETA_MONSTER) / Offsets.SIZE_MONSTER % 18 + 1;
private readonly Genes _genes;
public Genes genes => _genes;
public string spe
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_SPE]).ToString("X2");
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_SPE]).ToString("X2");
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_SPE] = (byte) (parsed & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_SPE] = (byte) (parsed & 0xFF);
}
else
{
@ -65,12 +38,12 @@ namespace MHSEC_G
public uint atk
{
get => Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_ATK);
get => Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_ATK);
set
{
if (value <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_ATK, value);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_ATK, value);
}
else
{
@ -83,12 +56,12 @@ namespace MHSEC_G
public uint def
{
get => Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_DEF);
get => Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_DEF);
set
{
if (value <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_DEF, value);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_DEF, value);
}
else
{
@ -101,12 +74,12 @@ namespace MHSEC_G
public uint hp
{
get => Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_HP);
get => Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_HP);
set
{
if (value <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_MONSTER_HP, value);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_HP, value);
}
else
{
@ -119,12 +92,12 @@ namespace MHSEC_G
public uint hiv
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_HIV]);
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_HIV]);
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_HIV] = (byte) (value & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_HIV] = (byte) (value & 0xFF);
}
else
{
@ -136,12 +109,12 @@ namespace MHSEC_G
public uint aiv
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_AIV]);
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_AIV]);
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_AIV] = (byte) (value & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_AIV] = (byte) (value & 0xFF);
}
else
{
@ -153,12 +126,12 @@ namespace MHSEC_G
public uint div
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_DIV]);
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_DIV]);
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_DIV] = (byte) (value & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_DIV] = (byte) (value & 0xFF);
}
else
{
@ -170,12 +143,12 @@ namespace MHSEC_G
public uint hpu
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_HPU]);
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_HPU]);
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_HPU] = (byte) (value & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_HPU] = (byte) (value & 0xFF);
}
else
{
@ -188,12 +161,12 @@ namespace MHSEC_G
public uint apu
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_APU]);
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_APU]);
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_APU] = (byte) (value & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_APU] = (byte) (value & 0xFF);
}
else
{
@ -206,12 +179,12 @@ namespace MHSEC_G
public uint dpu
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_DPU]);
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_DPU]);
set
{
if (value <= 0xFF)
{
_model.save_file[_offset + OFFSETR_MONSTER_DPU] = (byte) (value & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_DPU] = (byte) (value & 0xFF);
}
else
{
@ -224,13 +197,13 @@ namespace MHSEC_G
public string name
{
get => Model.read_unicode_string(_model.save_file, _offset + OFFSETR_MONSTER_NAME, LIMIT_MONSTER_NAME);
get => Helper.read_unicode_string(_data, _obj_offset + Offsets.OFFSETR_MONSTER_NAME, Offsets.LIMIT_MONSTER_NAME);
set
{
if (value.Length <= 10 && value.Length > 0)
{
Model.write_unicode_string(_model.save_file, _offset + OFFSETR_MONSTER_NAME, value,
LIMIT_MONSTER_NAME);
Helper.write_unicode_string(_data, _obj_offset + Offsets.OFFSETR_MONSTER_NAME, value,
Offsets.LIMIT_MONSTER_NAME);
}
else
{
@ -243,16 +216,16 @@ namespace MHSEC_G
public uint exp
{
get => Model.byte_to_uint32_le(_model.save_file, _offset + OFFSETR_MONSTER_EXP);
get => Helper.byte_to_uint32_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_EXP);
set
{
if (value <= LIMIT_MONSTER_EXP)
if (value <= Offsets.LIMIT_MONSTER_EXP)
{
Model.write_uint32_le(_model.save_file, _offset + OFFSETR_MONSTER_EXP, value);
Helper.write_uint32_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_EXP, value);
}
else
{
MessageBox.Show("Exp must be at most " + LIMIT_MONSTER_EXP, "Error", MessageBoxButton.OK,
MessageBox.Show("Exp must be at most " + Offsets.LIMIT_MONSTER_EXP, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
OnPropertyChanged(nameof(exp));
@ -261,16 +234,16 @@ namespace MHSEC_G
public uint level
{
get => Model.byte_to_uint(_model.save_file[_offset + OFFSETR_MONSTER_LEVEL]);
get => Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_MONSTER_LEVEL]);
set
{
if (value <= LIMIT_MONSTER_LEVEL)
if (value <= Offsets.LIMIT_MONSTER_LEVEL)
{
_model.save_file[_offset + OFFSETR_MONSTER_LEVEL] = (byte) (value & 0xFF);
_data[_obj_offset + Offsets.OFFSETR_MONSTER_LEVEL] = (byte) (value & 0xFF);
}
else
{
MessageBox.Show("Level must be at most " + LIMIT_MONSTER_LEVEL, "Error", MessageBoxButton.OK,
MessageBox.Show("Level must be at most " + Offsets.LIMIT_MONSTER_LEVEL, "Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
OnPropertyChanged(nameof(level));
@ -279,13 +252,13 @@ namespace MHSEC_G
public string skill
{
get => Model.byte_to_uint16_le(_model.save_file, offset + OFFSETR_MONSTER_SKILL).ToString("X4");
get => Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_SKILL).ToString("X4");
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed))
if (Helper.parse_hex_string(value, out parsed))
{
Model.write_uint16_le(_model.save_file, offset + OFFSETR_MONSTER_SKILL, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_MONSTER_SKILL, parsed);
}
else
{
@ -298,44 +271,20 @@ namespace MHSEC_G
}
public Monster(uint offset, Model model)
public Monster(byte[] model, uint objOffset) : base(model, objOffset, Offsets.SIZE_MONSTER)
{
_offset = offset;
_model = model;
_genes = new Genes(model, offset + OFFSETR_MONSTER_GENE, SIZE_MONSTER_GENE);
_genes = new Genes(model, objOffset + Offsets.OFFSETR_MONSTER_GENE, Offsets.SIZE_MONSTER_GENE);
}
public static List<Monster> read_all_monsters(Model model)
public static List<Monster> read_all_monsters(byte[] model)
{
byte[] save = model.save_file;
byte[] save = model;
List<Monster> ret = new List<Monster>();
for (uint i = OFFSETA_MONSTER; i < OFFSETA_MONSTE_END; i += SIZE_MONSTER)
for (uint i = Offsets.OFFSETA_MONSTER; i < Offsets.OFFSETA_MONSTE_END; i += Offsets.SIZE_MONSTER)
{
ret.Add(new Monster(i, model));
ret.Add(new Monster(model, i));
}
return ret;
}
public byte[] getByteArray()
{
byte[] ret = new byte[SIZE_MONSTER];
Array.Copy(_model.save_file, _offset, ret, 0, SIZE_MONSTER);
return ret;
}
public void setByteArray(byte[] ret)
{
Array.Copy(ret, 0, _model.save_file, _offset, SIZE_MONSTER);
OnPropertyChanged(null);
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -57,7 +57,7 @@
VerticalAlignment="Top" RenderTransformOrigin="-0.263,0.135" />
<Label x:Name="label_mex" Content="Exp" HorizontalAlignment="Left" Margin="172,69,0,0"
VerticalAlignment="Top" RenderTransformOrigin="-0.263,0.135" />
<Label x:Name="label_spe" Content="Type (Hex)" Margin="168,97,97,0"
<Label x:Name="label_spe" Content="Species (Hex)" Margin="156,97,94,0"
VerticalAlignment="Top" RenderTransformOrigin="-0.263,0.135" />
<TextBox x:Name="textbox_mlv" HorizontalAlignment="Left" Height="24" Margin="240,39,0,0"
TextWrapping="Wrap" Text="{Binding monster.level}" VerticalAlignment="Top"

View File

@ -32,7 +32,7 @@ namespace MHSEC_G
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
byte[] buffer = File.ReadAllBytes(dialog.FileName);
if (buffer.Length != Monster.SIZE_MONSTER)
if (buffer.Length != Offsets.SIZE_MONSTER)
{
System.Windows.Forms.MessageBox.Show(
"Wrong monster file size!",
@ -64,7 +64,7 @@ namespace MHSEC_G
dialog.FileName = _monster.name + ".bin";
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
byte[] binary = _monster.getByteArray();
byte[] binary = _monster.toByteArray();
File.WriteAllBytes(dialog.FileName, binary);
MessageBox.Show("Exported to \"" + dialog.FileName + "\"", "MHSEC-G", MessageBoxButton.OK,
MessageBoxImage.Information);
@ -73,7 +73,7 @@ namespace MHSEC_G
private void button_mexp_Click(object sender, RoutedEventArgs e)
{
_monster.exp = Monster.LIMIT_MONSTER_EXP;
_monster.exp = Offsets.LIMIT_MONSTER_EXP;
}
public event PropertyChangedEventHandler PropertyChanged;

593
MHSEC-G/MHSEC-G/Offsets.cs Normal file
View File

@ -0,0 +1,593 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text;
namespace MHSEC_G
{
public static class Offsets
{
//
// Save
//
public const uint SAVE_FILE_SIZE_JPN = 483976;
public const uint SAVE_FILE_SIZE_NA = 535736;
//
// Genes
//
private static List<uint> _GENE_ID;
private static List<string> _GENE_NAME;
public static List<uint> GENE_ID => _GENE_ID;
public static List<string> GENE_NAME => _GENE_NAME;
//
// Armors
//
private static uint _OFFSETA_ARM;
public static uint OFFSETA_ARM => _OFFSETA_ARM;
private static uint _SIZE_ARM;
public static uint SIZE_ARM => _SIZE_ARM;
private static uint _OFFSETR_ARM_ID;
public static uint OFFSETR_ARM_ID => _OFFSETR_ARM_ID;
private static uint _OFFSETR_ARM_LEVEL;
public static uint OFFSETR_ARM_LEVEL => _OFFSETR_ARM_LEVEL;
private static uint _OFFSETR_ARM_14h;
public static uint OFFSETR_ARM_14h => _OFFSETR_ARM_14h;
private static uint _OFFSETR_ARM_18h;
public static uint OFFSETR_ARM_18h => _OFFSETR_ARM_18h;
private static uint _OFFSETR_ARM_1C;
public static uint OFFSETR_ARM_1C => _OFFSETR_ARM_1C;
private static uint _OFFSETA_ARM_END;
public static uint OFFSETA_ARM_END => _OFFSETA_ARM_END;
private static uint _OFFSETR_ARM_TYPE;
public static uint OFFSETR_ARM_TYPE => _OFFSETR_ARM_TYPE;
//
// Character
//
private static uint _OFFSETA_CHAR_NAME;
public static uint OFFSETA_CHAR_NAME => _OFFSETA_CHAR_NAME;
private static uint _LENGTH_CHAR_NAME;
public static uint LENGTH_CHAR_NAME => _LENGTH_CHAR_NAME;
private static uint _OFFSETA_CHAR_MONEY;
public static uint OFFSETA_CHAR_MONEY => _OFFSETA_CHAR_MONEY;
private static uint _OFFSETA_CHAR_EXP;
public static uint OFFSETA_CHAR_EXP => _OFFSETA_CHAR_EXP;
private static uint _OFFSETA_CHAR_LEVEL;
public static uint OFFSETA_CHAR_LEVEL => _OFFSETA_CHAR_LEVEL;
private static uint _LIMIT_LEVEL;
public static uint LIMIT_LEVEL => _LIMIT_LEVEL;
private static uint _LIMIT_MONEY;
public static uint LIMIT_MONEY => _LIMIT_MONEY;
private static uint _LIMIT_EXP;
public static uint LIMIT_EXP => _LIMIT_EXP;
//
// Egg
//
private static uint _OFFSETA_EGG_START;
public static uint OFFSETA_EGG_START => _OFFSETA_EGG_START;
private static uint _OFFSETA_EGG_END;
public static uint OFFSETA_EGG_END => _OFFSETA_EGG_END;
private static uint _OFFSETR_EGG_GENE;
public static uint OFFSETR_EGG_GENE => _OFFSETR_EGG_GENE;
private static uint _SIZE_EGG_GENE;
public static uint SIZE_EGG_GENE => _SIZE_EGG_GENE;
private static uint _SIZE_EGG;
public static uint SIZE_EGG => _SIZE_EGG;
private static uint _OFFSETR_SPE;
public static uint OFFSETR_SPE => _OFFSETR_SPE;
private static uint _OFFSETR_WGT;
public static uint OFFSETR_WGT => _OFFSETR_WGT;
//
// Egg fragments
//
private static uint _OFFSETA_EGG_FRAGMENTS;
public static uint OFFSETA_EGG_FRAGMENTS => _OFFSETA_EGG_FRAGMENTS;
private static uint _OFFSETA_EGG_FRAGMENTS_END;
public static uint OFFSETA_EGG_FRAGMENTS_END => _OFFSETA_EGG_FRAGMENTS_END;
private static uint _SIZE_EGG_FRAGMENT;
public static uint SIZE_EGG_FRAGMENT => _SIZE_EGG_FRAGMENT;
private static uint _OFFSETR_EF_SPE;
public static uint OFFSETR_EF_SPE => _OFFSETR_EF_SPE;
private static uint _OFFSETR_EF_POS;
public static uint OFFSETR_EF_POS => _OFFSETR_EF_POS;
private static uint _OFFSETR_EF_NEW;
public static uint OFFSETR_EF_NEW => _OFFSETR_EF_NEW;
private static uint _OFFSETR_EF_RAR;
public static uint OFFSETR_EF_RAR => _OFFSETR_EF_RAR;
private static uint _OFFSETR_EF_COL;
public static uint OFFSETR_EF_COL => _OFFSETR_EF_COL;
private static uint _OFFSETR_EF_DLC;
public static uint OFFSETR_EF_DLC => _OFFSETR_EF_DLC;
private static uint _OFFSETR_EF_6H;
public static uint OFFSETR_EF_6H => _OFFSETR_EF_6H;
private static uint _OFFSETR_EF_7H;
public static uint OFFSETR_EF_7H => _OFFSETR_EF_7H;
//
// Items
//
private static Dictionary<uint, uint> _OFFSET_ID_MAPPING;
public static Dictionary<uint, uint> OFFSET_ID_MAPPING => _OFFSET_ID_MAPPING;
private static Dictionary<uint, string> _OFFSET_NAME_MAPPING;
public static Dictionary<uint, string> OFFSET_NAME_MAPPING => _OFFSET_NAME_MAPPING;
private static uint _OFFSETA_ITEM_BOX;
public static uint OFFSETA_ITEM_BOX => _OFFSETA_ITEM_BOX;
private static uint _SIZE_ITEM;
public static uint SIZE_ITEM => _SIZE_ITEM;
private static uint _OFFSETR_ITEM_ID;
public static uint OFFSETR_ITEM_ID => _OFFSETR_ITEM_ID;
private static uint _OFFSETR_ITEM_COUNT;
public static uint OFFSETR_ITEM_COUNT => _OFFSETR_ITEM_COUNT;
private static uint _OFFSETA_ITEM_BOX_END;
public static uint OFFSETA_ITEM_BOX_END => _OFFSETA_ITEM_BOX_END;
private static uint _OFFSETA_FIRST_KEY_ITEM;
public static uint OFFSETA_FIRST_KEY_ITEM => _OFFSETA_FIRST_KEY_ITEM;
//
// Monsters
//
private static uint _LIMIT_MONSTER_EXP;
public static uint LIMIT_MONSTER_EXP => _LIMIT_MONSTER_EXP;
private static uint _SIZE_MONSTER;
public static uint SIZE_MONSTER => _SIZE_MONSTER;
private static uint _OFFSETA_MONSTER;
public static uint OFFSETA_MONSTER => _OFFSETA_MONSTER;
private static uint _OFFSETR_MONSTER_GENE;
public static uint OFFSETR_MONSTER_GENE => _OFFSETR_MONSTER_GENE;
private static uint _SIZE_MONSTER_GENE;
public static uint SIZE_MONSTER_GENE => _SIZE_MONSTER_GENE;
private static uint _OFFSETR_MONSTER_EXP;
public static uint OFFSETR_MONSTER_EXP => _OFFSETR_MONSTER_EXP;
private static uint _OFFSETR_MONSTER_HIV;
public static uint OFFSETR_MONSTER_HIV => _OFFSETR_MONSTER_HIV;
private static uint _OFFSETR_MONSTER_AIV;
public static uint OFFSETR_MONSTER_AIV => _OFFSETR_MONSTER_AIV;
private static uint _OFFSETR_MONSTER_DIV;
public static uint OFFSETR_MONSTER_DIV => _OFFSETR_MONSTER_DIV;
private static uint _OFFSETR_MONSTER_HPU;
public static uint OFFSETR_MONSTER_HPU => _OFFSETR_MONSTER_HPU;
private static uint _OFFSETR_MONSTER_APU;
public static uint OFFSETR_MONSTER_APU => _OFFSETR_MONSTER_APU;
private static uint _OFFSETR_MONSTER_DPU;
public static uint OFFSETR_MONSTER_DPU => _OFFSETR_MONSTER_DPU;
private static uint _OFFSETR_MONSTER_SKILL;
public static uint OFFSETR_MONSTER_SKILL => _OFFSETR_MONSTER_SKILL;
private static uint _OFFSETR_MONSTER_LEVEL;
public static uint OFFSETR_MONSTER_LEVEL => _OFFSETR_MONSTER_LEVEL;
private static uint _LIMIT_MONSTER_LEVEL;
public static uint LIMIT_MONSTER_LEVEL => _LIMIT_MONSTER_LEVEL;
private static uint _OFFSETR_MONSTER_NAME;
public static uint OFFSETR_MONSTER_NAME => _OFFSETR_MONSTER_NAME;
private static uint _LIMIT_MONSTER_NAME;
public static uint LIMIT_MONSTER_NAME => _LIMIT_MONSTER_NAME;
private static uint _OFFSETR_MONSTER_SPE;
public static uint OFFSETR_MONSTER_SPE => _OFFSETR_MONSTER_SPE;
private static uint _OFFSETA_MONSTE_END;
public static uint OFFSETA_MONSTE_END => _OFFSETA_MONSTE_END;
private static uint _OFFSETR_MONSTER_ATK;
public static uint OFFSETR_MONSTER_ATK => _OFFSETR_MONSTER_ATK;
private static uint _OFFSETR_MONSTER_HP;
public static uint OFFSETR_MONSTER_HP => _OFFSETR_MONSTER_HP;
private static uint _OFFSETR_MONSTER_DEF;
public static uint OFFSETR_MONSTER_DEF => _OFFSETR_MONSTER_DEF;
//
// Talismans
//
private static uint _OFFSETA_TALI;
public static uint OFFSETA_TALI => _OFFSETA_TALI;
private static uint _OFFSETA_TALI_END;
public static uint OFFSETA_TALI_END => _OFFSETA_TALI_END;
private static uint _SIZE_TALI;
public static uint SIZE_TALI => _SIZE_TALI;
private static uint _OFFSETR_TALI_RARITY;
public static uint OFFSETR_TALI_RARITY => _OFFSETR_TALI_RARITY;
private static uint _OFFSETR_TALI_NEW;
public static uint OFFSETR_TALI_NEW => _OFFSETR_TALI_NEW;
private static uint _OFFSETR_TALI_SKILL1;
public static uint OFFSETR_TALI_SKILL1 => _OFFSETR_TALI_SKILL1;
private static uint _OFFSETR_TALI_SKILL2;
public static uint OFFSETR_TALI_SKILL2 => _OFFSETR_TALI_SKILL2;
private static uint _OFFSETR_TALI_ID;
public static uint OFFSETR_TALI_ID => _OFFSETR_TALI_ID;
private static uint _OFFSETR_EQUIPPED;
public static uint OFFSETR_EQUIPPED => _OFFSETR_EQUIPPED;
//
// Weapons
//
private static uint _OFFSETA_WEAPON_START;
public static uint OFFSETA_WEAPON_START => _OFFSETA_WEAPON_START;
private static uint _OFFSETA_WEAPON_END;
public static uint OFFSETA_WEAPON_END => _OFFSETA_WEAPON_END;
private static uint _SIZE_WEAPON;
public static uint SIZE_WEAPON => _SIZE_WEAPON;
private static uint _OFFSETR_CLASS;
public static uint OFFSETR_CLASS => _OFFSETR_CLASS;
private static uint _OFFSETR_ID;
public static uint OFFSETR_ID => _OFFSETR_ID;
private static uint _OFFSETR_LEVEL;
public static uint OFFSETR_LEVEL => _OFFSETR_LEVEL;
public static void init(byte[] save)
{
if (save.Length == SAVE_FILE_SIZE_JPN)
{
//
//Armors
//
_OFFSETA_ARM = 0x55F0;
_SIZE_ARM = 0x24;
_OFFSETR_ARM_ID = 0x2;
_OFFSETR_ARM_LEVEL = 0x4;
_OFFSETR_ARM_14h = 0x14;
_OFFSETR_ARM_18h = 0x18;
_OFFSETR_ARM_1C = 0x1c;
_OFFSETA_ARM_END = 0x720E;
_OFFSETR_ARM_TYPE = 0x0;
//
//Character
//
_OFFSETA_CHAR_NAME = 0x9DA0;
_LENGTH_CHAR_NAME = 6;
_OFFSETA_CHAR_MONEY = 0x5B404;
_OFFSETA_CHAR_EXP = 0x9E68;
_OFFSETA_CHAR_LEVEL = 0x9E64;
_LIMIT_LEVEL = 99;
_LIMIT_MONEY = 9999999;
_LIMIT_EXP = 25165822;
//
//Egg
//
_OFFSETA_EGG_START = 0x53EC0;
_OFFSETA_EGG_END = 0x54597;
_OFFSETR_EGG_GENE = 0x30;
_SIZE_EGG_GENE = 0x2;
_SIZE_EGG = 0x92;
_OFFSETR_SPE = 0x0;
_OFFSETR_WGT = 0x2E;
//
//Eggfragments
//
_OFFSETA_EGG_FRAGMENTS = 0x9790;
_OFFSETA_EGG_FRAGMENTS_END = 0x9C3F;
_SIZE_EGG_FRAGMENT = 0xC;
_OFFSETR_EF_SPE = 0x0;
_OFFSETR_EF_POS = 0x1;
_OFFSETR_EF_NEW = 0x2;
_OFFSETR_EF_RAR = 0x3;
_OFFSETR_EF_COL = 0x4;
_OFFSETR_EF_DLC = 0x5;
_OFFSETR_EF_6H = 0x6;
_OFFSETR_EF_7H = 0x7;
//
//Items
//
_OFFSETA_ITEM_BOX = 0x10;
_SIZE_ITEM = 0x8;
_OFFSETR_ITEM_ID = 0x0;
_OFFSETR_ITEM_COUNT = 0x2;
_OFFSETA_ITEM_BOX_END = 0x2EE7;
_OFFSETA_FIRST_KEY_ITEM = 0x17B0;
//
//Monsters
//
_LIMIT_MONSTER_EXP = 0xFFFFFF;
_SIZE_MONSTER = 0x478;
_OFFSETA_MONSTER = 0xA150;
_OFFSETR_MONSTER_GENE = 0x424;
_SIZE_MONSTER_GENE = 0x4;
_OFFSETR_MONSTER_EXP = 0xE0;
_OFFSETR_MONSTER_HIV = 0xD8;
_OFFSETR_MONSTER_AIV = 0xD9;
_OFFSETR_MONSTER_DIV = 0xDA;
_OFFSETR_MONSTER_HPU = 0xD4;
_OFFSETR_MONSTER_APU = 0xD5;
_OFFSETR_MONSTER_DPU = 0xD6;
_OFFSETR_MONSTER_SKILL = 0x38;
_OFFSETR_MONSTER_LEVEL = 0x5C;
_LIMIT_MONSTER_LEVEL = 99;
_OFFSETR_MONSTER_NAME = 0;
_LIMIT_MONSTER_NAME = 10;
_OFFSETR_MONSTER_SPE = 0x30;
_OFFSETA_MONSTE_END = 0x4786F;
_OFFSETR_MONSTER_ATK = 0x48;
_OFFSETR_MONSTER_HP = 0x46;
_OFFSETR_MONSTER_DEF = 0x4A;
//
//Talismans
//
_OFFSETA_TALI = 0x7210;
_OFFSETA_TALI_END = 0x978F;
_SIZE_TALI = 0x30;
_OFFSETR_TALI_RARITY = 0x24;
_OFFSETR_TALI_NEW = 0x12;
_OFFSETR_TALI_SKILL1 = 0x28;
_OFFSETR_TALI_SKILL2 = 0x2A;
_OFFSETR_TALI_ID = 0x2;
_OFFSETR_EQUIPPED = 0x11;
//
//Weapons
//
_OFFSETA_WEAPON_START = 0x39D0;
_OFFSETA_WEAPON_END = 0x55EF;
_SIZE_WEAPON = 0x24;
_OFFSETR_CLASS = 0x0;
_OFFSETR_ID = 0x2;
_OFFSETR_LEVEL = 0x4;
read_item_mappings(Properties.Resources.idmap);
read_gene_mapping(Properties.Resources.gene);
}
else
{
//
// Armors ok
//
_OFFSETA_ARM = 0x5694;
_SIZE_ARM = 0x24;
_OFFSETR_ARM_ID = 0x2;
_OFFSETR_ARM_LEVEL = 0x4;
_OFFSETR_ARM_14h = 0x14;
_OFFSETR_ARM_18h = 0x18;
_OFFSETR_ARM_1C = 0x1c;
_OFFSETA_ARM_END = 0x72B3;
_OFFSETR_ARM_TYPE = 0x0;
//
// Character ok
//
_OFFSETA_CHAR_NAME = 0x9E44;
_LENGTH_CHAR_NAME = 12;
_OFFSETA_CHAR_MONEY = 0x5E394;
_OFFSETA_CHAR_EXP = 0x9F14;
_OFFSETA_CHAR_LEVEL = 0x9F10;
_LIMIT_LEVEL = 99;
_LIMIT_MONEY = 9999999;
_LIMIT_EXP = 25165822;
//
// Egg ok
//
_OFFSETA_EGG_START = 0x56E50;
_OFFSETA_EGG_END = 0x57527;
_OFFSETR_EGG_GENE = 0x30;
_SIZE_EGG_GENE = 0x2;
_SIZE_EGG = 0x92;
_OFFSETR_SPE = 0x0;
_OFFSETR_WGT = 0x2E;
//
// Eggfragments ok
//
_OFFSETA_EGG_FRAGMENTS = 0x9834;
_OFFSETA_EGG_FRAGMENTS_END = 0x9CE3;
_SIZE_EGG_FRAGMENT = 0xC;
_OFFSETR_EF_SPE = 0x0;
_OFFSETR_EF_POS = 0x1;
_OFFSETR_EF_NEW = 0x2;
_OFFSETR_EF_RAR = 0x3;
_OFFSETR_EF_COL = 0x4;
_OFFSETR_EF_DLC = 0x5;
_OFFSETR_EF_6H = 0x6;
_OFFSETR_EF_7H = 0x7;
//
// Items ok
//
_OFFSETA_ITEM_BOX = 0x10;
_SIZE_ITEM = 0x8;
_OFFSETR_ITEM_ID = 0x0;
_OFFSETR_ITEM_COUNT = 0x2;
_OFFSETA_ITEM_BOX_END = 0x2EE7;
_OFFSETA_FIRST_KEY_ITEM = 0x17B0;
//
// Monsters ok
//
_LIMIT_MONSTER_EXP = 0xFFFFFF;
_SIZE_MONSTER = 0x4A0;
_OFFSETA_MONSTER = 0xA1FC;
_LIMIT_MONSTER_LEVEL = 99;
_OFFSETR_MONSTER_NAME = 0;
_LIMIT_MONSTER_NAME = 20;
_OFFSETA_MONSTE_END = 0x49B7B;
_SIZE_MONSTER_GENE = 0x4;
_OFFSETR_MONSTER_GENE = 0x424 + 0x28;
_OFFSETR_MONSTER_EXP = 0xE0 + 0x28;
_OFFSETR_MONSTER_HIV = 0xD8 + 0x28;
_OFFSETR_MONSTER_AIV = 0xD9 + 0x28;
_OFFSETR_MONSTER_DIV = 0xDA + 0x28;
_OFFSETR_MONSTER_HPU = 0xD4 + 0x28;
_OFFSETR_MONSTER_APU = 0xD5 + 0x28;
_OFFSETR_MONSTER_DPU = 0xD6 + 0x28;
_OFFSETR_MONSTER_SKILL = 0x38 + 0x28;
_OFFSETR_MONSTER_LEVEL = 0x5C + 0x28;
_OFFSETR_MONSTER_SPE = 0x30 + 0x28;
_OFFSETR_MONSTER_ATK = 0x48 + 0x28;
_OFFSETR_MONSTER_HP = 0x46 + 0x28;
_OFFSETR_MONSTER_DEF = 0x4A + 0x28;
//
// Talismans ok
//
_OFFSETA_TALI = 0x72B4;
_OFFSETA_TALI_END = 0x9833;
_SIZE_TALI = 0x30;
_OFFSETR_TALI_RARITY = 0x24;
_OFFSETR_TALI_NEW = 0x12;
_OFFSETR_TALI_SKILL1 = 0x28;
_OFFSETR_TALI_SKILL2 = 0x2A;
_OFFSETR_TALI_ID = 0x2;
_OFFSETR_EQUIPPED = 0x11;
//
// Weapons ok
//
_OFFSETA_WEAPON_START = 0x3A74;
_OFFSETA_WEAPON_END = 0x5693;
_SIZE_WEAPON = 0x24;
_OFFSETR_CLASS = 0x0;
_OFFSETR_ID = 0x2;
_OFFSETR_LEVEL = 0x4;
read_item_mappings(Properties.Resources.idmap);
read_gene_mapping(Properties.Resources.gene);
}
}
private static void read_item_mappings(string src)
{
_OFFSET_ID_MAPPING = new Dictionary<uint, uint>();
_OFFSET_NAME_MAPPING = new Dictionary<uint, string>();
string line;
StringReader file = new StringReader(src);
while ((line = file.ReadLine()) != null)
{
if (line.Length == 0)
continue;
string[] eachline = line.Split('\t');
if (eachline.Length != 3)
{
BugCheck.bug_check(BugCheck.ErrorCode.ITEM_MAPPING_CORRUPTED, "Invalid mapping file line:\n" + line);
}
_OFFSET_ID_MAPPING.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), uint.Parse(eachline[1], System.Globalization.NumberStyles.HexNumber));
_OFFSET_NAME_MAPPING.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber), eachline[2]);
}
file.Close();
}
public static void read_gene_mapping(string src)
{
_GENE_NAME = new List<string>();
_GENE_ID = new List<uint>();
string line;
StringReader file = new StringReader(src);
while ((line = file.ReadLine()) != null)
{
if (line.Length == 0)
continue;
string[] eachline = line.Split('\t');
if (eachline.Length != 2)
{
BugCheck.bug_check(BugCheck.ErrorCode.MON_GENE_MAPPING_CORRUPTED,
"Invalid gene mapping file line:\n" + line);
}
_GENE_ID.Add(uint.Parse(eachline[0], System.Globalization.NumberStyles.HexNumber));
_GENE_NAME.Add(eachline[1]);
}
_GENE_NAME.Add("Custom");
file.Close();
}
}
}

View File

@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]

Binary file not shown.

View File

@ -6,43 +6,24 @@ using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Talisman
public class Talisman : InMemoryObject
{
private const uint OFFSETA_TALI = 0x7210;
private const uint OFFSETA_TALI_END = 0x978F;
private const uint SIZE_TALI = 0x30;
private const uint OFFSETR_TALI_RARITY = 0x24;
private const uint OFFSETR_TALI_NEW = 0x12;
private const uint OFFSETR_TALI_SKILL1 = 0x28;
private const uint OFFSETR_TALI_SKILL2 = 0x2A;
private const uint OFFSETR_TALI_ID = 0x2;
private const uint OFFSETR_EQUIPPED = 0x11;
public uint index => (_obj_offset - Offsets.OFFSETA_TALI) / Offsets.SIZE_TALI + 1;
private readonly uint _offset;
public uint index => (_offset - OFFSETA_TALI) / SIZE_TALI + 1;
public uint offset
public Talisman(byte[] model, uint objOffset) : base(model, objOffset, Offsets.SIZE_TALI)
{
get { return _offset; }
}
private readonly Model _model;
public Talisman(uint offset, Model model)
{
_model = model;
_offset = offset;
}
public string rarity
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_TALI_RARITY]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_TALI_RARITY]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_TALI_RARITY, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_TALI_RARITY, parsed);
}
else
{
@ -54,13 +35,13 @@ namespace MHSEC_G
public string id
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_TALI_ID).ToString("X4"); }
get { return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_TALI_ID).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_TALI_ID, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_TALI_ID, parsed);
}
else
{
@ -72,13 +53,13 @@ namespace MHSEC_G
public string new_flag
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_TALI_NEW]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_TALI_NEW]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0x1)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0x1)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_TALI_NEW, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_TALI_NEW, parsed);
}
else
{
@ -89,13 +70,13 @@ namespace MHSEC_G
}
public string skill1
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_TALI_SKILL1).ToString("X4"); }
get { return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_TALI_SKILL1).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_TALI_SKILL1, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_TALI_SKILL1, parsed);
}
else
{
@ -107,13 +88,13 @@ namespace MHSEC_G
public string skill2
{
get { return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_TALI_SKILL2).ToString("X4"); }
get { return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_TALI_SKILL2).ToString("X4"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_TALI_SKILL2, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_TALI_SKILL2, parsed);
}
else
{
@ -125,13 +106,13 @@ namespace MHSEC_G
public string equipped
{
get { return Model.byte_to_uint(_model.save_file[_offset + OFFSETR_EQUIPPED]).ToString("X2"); }
get { return Helper.byte_to_uint(_data[_obj_offset + Offsets.OFFSETR_EQUIPPED]).ToString("X2"); }
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFF)
{
Model.write_byte(_model.save_file, _offset + OFFSETR_EQUIPPED, parsed);
Helper.write_byte(_data, _obj_offset + Offsets.OFFSETR_EQUIPPED, parsed);
}
else
{
@ -141,23 +122,15 @@ namespace MHSEC_G
}
}
public static ObservableCollection<Talisman> read_all_talismans(Model model)
public static ObservableCollection<Talisman> read_all_talismans(byte[] model)
{
ObservableCollection<Talisman> ret = new ObservableCollection<Talisman>();
for (uint offset = OFFSETA_TALI; offset < OFFSETA_TALI_END; offset += SIZE_TALI)
for (uint offset = Offsets.OFFSETA_TALI; offset < Offsets.OFFSETA_TALI_END; offset += Offsets.SIZE_TALI)
{
ret.Add(new Talisman(offset, model));
ret.Add(new Talisman(model, offset));
}
return ret;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@ -6,25 +6,12 @@ using MHSEC_G.Annotations;
namespace MHSEC_G
{
public class Weapon : INotifyPropertyChanged
public class Weapon : InMemoryObject
{
private const int OFFSETA_WEAPON_START = 0x39D0;
private const int OFFSETA_WEAPON_END = 0x55EF;
// 200 weapons
private const int SIZE_WEAPON = 0x24;
public uint index => (_obj_offset - Offsets.OFFSETA_WEAPON_START) / Offsets.SIZE_WEAPON + 1;
private const int OFFSETR_CLASS = 0x0;
private const int OFFSETR_ID = 0x2;
private const int OFFSETR_LEVEL = 0x4;
private readonly uint _offset;
private readonly Model _model;
public uint index => (_offset - OFFSETA_WEAPON_START) / SIZE_WEAPON + 1;
public Weapon(Model model, uint offset)
public Weapon(byte[] model, uint objOffset) : base(model, objOffset, Offsets.SIZE_WEAPON)
{
_offset = offset;
_model = model;
}
public string clazz
@ -32,9 +19,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_CLASS, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_CLASS, parsed);
}
else
{
@ -44,7 +31,7 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_CLASS).ToString("X4");
return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_CLASS).ToString("X4");
}
}
@ -53,9 +40,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_ID, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ID, parsed);
}
else
{
@ -65,7 +52,7 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_ID).ToString("X4");
return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_ID).ToString("X4");
}
}
@ -75,9 +62,9 @@ namespace MHSEC_G
set
{
uint parsed;
if (Model.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
if (Helper.parse_hex_string(value, out parsed) && parsed <= 0xFFFF)
{
Model.write_uint16_le(_model.save_file, _offset + OFFSETR_LEVEL, parsed);
Helper.write_uint16_le(_data, _obj_offset + Offsets.OFFSETR_LEVEL, parsed);
}
else
{
@ -87,26 +74,18 @@ namespace MHSEC_G
}
get
{
return Model.byte_to_uint16_le(_model.save_file, _offset + OFFSETR_LEVEL).ToString("X4");
return Helper.byte_to_uint16_le(_data, _obj_offset + Offsets.OFFSETR_LEVEL).ToString("X4");
}
}
public static ObservableCollection<Weapon> read_all_weapons(Model model)
public static ObservableCollection<Weapon> read_all_weapons(byte[] model)
{
ObservableCollection<Weapon> ret = new ObservableCollection<Weapon>();
for (uint i = OFFSETA_WEAPON_START; i < OFFSETA_WEAPON_END; i += SIZE_WEAPON)
for (uint i = Offsets.OFFSETA_WEAPON_START; i < Offsets.OFFSETA_WEAPON_END; i += Offsets.SIZE_WEAPON)
{
ret.Add(new Weapon(model, i));
}
return ret;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}