mirror of
https://github.com/AdAstra-LD/DS-Pokemon-Rom-Editor.git
synced 2026-05-09 12:51:54 -05:00
224 lines
8.2 KiB
C#
224 lines
8.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using static DSPRE.RomInfo;
|
|
|
|
namespace DSPRE.ROMFiles {
|
|
/* ---------------------- MATRIX DATA STRUCTURE (DPPtHGSS):-----------------------------
|
|
|
|
0x0 // byte: Matrix width (a.k.a row length) (x)
|
|
0x1 // byte: Matrix height (a.k.a number of rows per section) (y)
|
|
0x2 // byte: Headers section boolean (0 = not present, 1 = present)
|
|
0x3 // byte: Altitudes section flag (0 = not present, 1 = present)
|
|
0x4 // byte: Length of matrix name string
|
|
0x5 // string: Matrix name string (UTF-8 Encoded)
|
|
-- // [Header section if applicable: y blocks of length x]
|
|
-- // [Altitudes section if applicable: y blocks of length x]
|
|
-- // [Map files section: y blocks of length x]
|
|
|
|
-------------------------------------------------------------------------------------- */
|
|
|
|
/// <summary>
|
|
/// Class to store map matrix data from Pokémon NDS games
|
|
/// </summary>
|
|
public class GameMatrix: RomFile {
|
|
#region Fields (8)
|
|
public static readonly string DefaultFilter = "Game Matrix File (*.mtx)|*.mtx";
|
|
|
|
|
|
public bool hasHeadersSection { get; set; }
|
|
public bool hasHeightsSection { get; set; }
|
|
public string name { get; set; }
|
|
public byte width { get; set; }
|
|
public byte height { get; set; }
|
|
public int? id { get; } = null;
|
|
|
|
public ushort[,] headers;
|
|
public byte[,] altitudes;
|
|
public ushort[,] maps;
|
|
|
|
public static readonly ushort EMPTY = 65535;
|
|
#endregion Fields
|
|
|
|
#region Constructors(1)
|
|
public GameMatrix(Stream data) {
|
|
using (BinaryReader reader = new BinaryReader(data)) {
|
|
/* Read matrix size and sections included */
|
|
width = reader.ReadByte();
|
|
height = reader.ReadByte();
|
|
|
|
if (reader.ReadBoolean()) {
|
|
hasHeadersSection = true;
|
|
}
|
|
|
|
if (reader.ReadBoolean()) {
|
|
hasHeightsSection = true;
|
|
}
|
|
|
|
/* Read matrix's name */
|
|
byte nameLength = reader.ReadByte();
|
|
name = Encoding.UTF8.GetString(reader.ReadBytes(nameLength));
|
|
|
|
/* Initialize section arrays */
|
|
headers = new ushort[height, width];
|
|
altitudes = new byte[height, width];
|
|
maps = new ushort[height, width];
|
|
|
|
/* Read sections */
|
|
if (hasHeadersSection) {
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
headers[i, j] = reader.ReadUInt16();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hasHeightsSection) {
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
altitudes[i, j] = reader.ReadByte();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
maps[i, j] = reader.ReadUInt16();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public GameMatrix(int ID) : this (new FileStream(RomInfo.gameDirs[DirNames.matrices].unpackedDir + "\\" + ID.ToString("D4"), FileMode.Open)) {
|
|
this.id = ID;
|
|
}
|
|
|
|
public GameMatrix(GameMatrix copy, int newID) {
|
|
this.id = newID;
|
|
this.name = copy.name;
|
|
this.width = copy.width;
|
|
this.height = copy.height;
|
|
|
|
this.hasHeadersSection = copy.hasHeadersSection;
|
|
this.hasHeightsSection = copy.hasHeightsSection;
|
|
|
|
this.maps = (ushort[,])copy.maps.Clone();
|
|
this.altitudes = (byte[,])copy.altitudes.Clone();
|
|
this.headers = (ushort[,])copy.headers.Clone();
|
|
}
|
|
|
|
public GameMatrix() {
|
|
this.name = "newMatrix";
|
|
this.hasHeadersSection = false;
|
|
this.hasHeightsSection = false;
|
|
|
|
this.width = 1;
|
|
this.height = 1;
|
|
this.maps = new ushort[1, 1] { { 0 } };
|
|
}
|
|
#endregion
|
|
|
|
#region Methods (6)
|
|
public void ResizeMatrix(int newHeight, int newWidth)
|
|
{
|
|
/* Initialize new arrays */
|
|
ushort[,] newHeaders = new ushort[newHeight, newWidth];
|
|
byte[,] newAltitudes = new byte[newHeight, newWidth];
|
|
ushort[,] newMaps = new ushort[newHeight, newWidth];
|
|
|
|
/* Copy existing headers and altitudes rows into new arrays. If new matrix is greater in any dimension, new entries will be zero */
|
|
if (hasHeadersSection) {
|
|
for (int i = 0; i < Math.Min(height, newHeight); i++) {
|
|
for (int j = 0; j < Math.Min(width, newWidth); j++) {
|
|
newHeaders[i, j] = headers[i, j];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hasHeightsSection) {
|
|
for (int i = 0; i < Math.Min(height, newHeight); i++) {
|
|
for (int j = 0; j < Math.Min(width, newWidth); j++) {
|
|
newAltitudes[i, j] = altitudes[i, j];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Copy existing map rows into new array, and fill eventual new ones with Matrix.EMPTY (FF FF) */
|
|
for (int i = 0; i < Math.Min(height, newHeight); i++) {
|
|
for (int j = 0; j < Math.Min(width, newWidth); j++) {
|
|
newMaps[i, j] = maps[i, j];
|
|
}
|
|
}
|
|
|
|
if (newHeight > height) {
|
|
for (int i = height; i < newHeight; i++) {
|
|
for (int j = 0; j < newWidth; j++) {
|
|
newMaps[i, j] = GameMatrix.EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (newWidth > width) {
|
|
for (int j = width; j < newWidth; j++) {
|
|
for (int i = 0; i < newHeight; i++) {
|
|
newMaps[i, j] = GameMatrix.EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Substitute old arrays with new arrays */
|
|
headers = newHeaders;
|
|
altitudes = newAltitudes;
|
|
maps = newMaps;
|
|
|
|
/* Set new width and height */
|
|
height = (byte)newHeight;
|
|
width = (byte)newWidth;
|
|
}
|
|
|
|
public override string ToString() {
|
|
return (this.id == null ? "" : id.ToString()) + ": " + this.name;
|
|
}
|
|
public override byte[] ToByteArray() {
|
|
MemoryStream newData = new MemoryStream();
|
|
using (BinaryWriter writer = new BinaryWriter(newData)) {
|
|
writer.Write(width);
|
|
writer.Write(height);
|
|
writer.Write(hasHeadersSection);
|
|
writer.Write(hasHeightsSection);
|
|
writer.Write(name);
|
|
|
|
if (hasHeadersSection) {
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
writer.Write(headers[i, j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hasHeightsSection) {
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
writer.Write(altitudes[i, j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
writer.Write(maps[i, j]);
|
|
}
|
|
}
|
|
|
|
}
|
|
return newData.ToArray();
|
|
}
|
|
public void SaveToFileDefaultDir(int IDtoReplace, bool showSuccessMessage = true) {
|
|
SaveToFileDefaultDir(DirNames.matrices, IDtoReplace, showSuccessMessage);
|
|
}
|
|
public void SaveToFileExplorePath(string suggestedFileName, bool showSuccessMessage = true) {
|
|
SaveToFileExplorePath("Gen IV Matrix File", "mtx", suggestedFileName, showSuccessMessage);
|
|
}
|
|
#endregion
|
|
}
|
|
} |