DS-Pokemon-Rom-Editor/DS_Map/Matrix.cs
2021-02-02 01:27:22 +01:00

170 lines
6.8 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace DSPRE
{
/* ---------------------- 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 Matrix
{
#region Fields (8)
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 ushort[,] headers;
public byte[,] altitudes;
public ushort[,] maps;
public static readonly ushort EMPTY = 65535;
#endregion Fields
#region Constructors(1)
public Matrix(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 Matrix(int ID) : this (new FileStream(RomInfo.matrixDirPath + "\\" + ID.ToString("D4"), FileMode.Open)) { }
#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] = Matrix.EMPTY;
if (newWidth > width)
for (int j = width; j < newWidth; j++)
for (int i = 0; i < newHeight; i++)
newMaps[i, j] = Matrix.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 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 SaveToFile(string path) {
using (BinaryWriter writer = new BinaryWriter(new FileStream(path, FileMode.Create)))
writer.Write(this.ToByteArray());
}
public void SaveToFileDefaultDir(int IDtoReplace) {
string path = RomInfo.matrixDirPath + "\\" + IDtoReplace.ToString("D4");
this.SaveToFile(path);
}
public void SaveToFileExplorePath(string suggestedFileName) {
SaveFileDialog sf = new SaveFileDialog();
sf.Filter = "Gen IV Matrix File (*.mtx)|*.mtx";
if (!string.IsNullOrEmpty(suggestedFileName))
sf.FileName = suggestedFileName;
if (sf.ShowDialog() != DialogResult.OK)
return;
this.SaveToFile(sf.FileName);
}
#endregion
}
}