Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/nes-containers.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-11-04 09:54:34 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-11-04 09:57:58 +0300
commitbc05122b12da25b30f011d5ef6a2277863413b50 (patch)
tree97f3e5500983e64089e22223a12bc3bd9e0dc19f
parenta84c08415c43dad08c73e23f75e8d2cdd99174a9 (diff)
Comments and minor changes
-rw-r--r--Crc32Calculator.cs5
-rw-r--r--FdsBlockDiskInfo.cs660
-rw-r--r--FdsBlockFileAmount.cs45
-rw-r--r--FdsBlockFileData.cs40
-rw-r--r--FdsBlockFileHeader.cs79
-rw-r--r--FdsDiskFile.cs47
-rw-r--r--FdsDiskSide.cs48
-rw-r--r--FdsFile.cs32
-rw-r--r--IFdsBlock.cs16
-rw-r--r--NesContainers.csproj9
-rw-r--r--NesFile.cs42
-rw-r--r--NesHeaderFixer.cs23
-rw-r--r--UnifFile.cs34
13 files changed, 999 insertions, 81 deletions
diff --git a/Crc32Calculator.cs b/Crc32Calculator.cs
index 417cb37..3c6e0c7 100644
--- a/Crc32Calculator.cs
+++ b/Crc32Calculator.cs
@@ -1,6 +1,9 @@
namespace com.clusterrr.Famicom.Containers
{
- public static class Crc32Calculator
+ /// <summary>
+ /// CRC32 calculator
+ /// </summary>
+ internal static class Crc32Calculator
{
static readonly uint[] table = new uint[256];
diff --git a/FdsBlockDiskInfo.cs b/FdsBlockDiskInfo.cs
index 9fbf5df..acef5e3 100644
--- a/FdsBlockDiskInfo.cs
+++ b/FdsBlockDiskInfo.cs
@@ -1,76 +1,637 @@
using System;
+using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// Disk info FDS block (block type 1)
+ /// </summary>
[StructLayout(LayoutKind.Sequential, Size = 58, Pack = 1)]
public class FdsBlockDiskInfo : IFdsBlock, IEquatable<FdsBlockDiskInfo>
{
+ /// <summary>
+ /// Disk side
+ /// </summary>
public enum DiskSides
{
+ /// <summary>
+ /// Side A
+ /// </summary>
A = 0,
+ /// <summary>
+ /// Side B
+ /// </summary>
B = 1,
}
+ /// <summary>
+ /// Disk type
+ /// </summary>
public enum DiskTypes
{
- FMS = 0, // Normal
- FSC = 1, // With shutter
+ /// <summary>
+ /// Normal
+ /// </summary>
+ FMS = 0,
+ /// <summary>
+ /// With shutter
+ /// </summary>
+ FSC = 1,
}
+ /// <summary>
+ /// Country
+ /// </summary>
public enum Country
{
+ /// <summary>
+ /// Japan
+ /// </summary>
Japan = 0x49,
}
- public enum Manufacturer
+ /// <summary>
+ /// Company name, source: https://www.nesdev.org/wiki/Licensee_codes
+ /// </summary>
+ public enum Company
{
- Unlicensed = 0x00,
+ /// <summary>
+ /// Nintendo
+ /// </summary>
Nintendo = 0x01,
+ /// <summary>
+ /// Nomura Securities? (unverified)
+ /// </summary>
+ NomuraSecurities = 0x07,
+ /// <summary>
+ /// Capcom
+ /// </summary>
Capcom = 0x08,
+ /// <summary>
+ /// Hot-B
+ /// </summary>
+ HotB = 0x09,
+ /// <summary>
+ /// Jaleco
+ /// </summary>
Jaleco = 0x0A,
- Hudson_Soft = 0x18,
+ /// <summary>
+ /// Coconuts Japan Entertainment
+ /// </summary>
+ CoconutsJapanEntertainment = 0x0B,
+ /// <summary>
+ /// Electronic Arts (Japan)
+ /// </summary>
+ ElectronicArtsJap = 0x13,
+ /// <summary>
+ /// Hudson Soft
+ /// </summary>
+ HudsonSoft = 0x18,
+ /// <summary>
+ /// Tokai Engineering
+ /// </summary>
+ TokaiEngineering = 0x21,
+ /// <summary>
+ /// Kemco (Japan)
+ /// </summary>
+ KemcoJap = 0x28,
+ /// <summary>
+ /// SETA (Japan)
+ /// </summary>
+ SetaJap = 0x29,
+ /// <summary>
+ /// Tamtex
+ /// </summary>
+ Tamtex = 0x2B,
+ /// <summary>
+ /// Hector Playing Interface (Hect)
+ /// </summary>
+ HectorPlayingInterface = 0x35,
+ /// <summary>
+ /// Loriciel
+ /// </summary>
+ Loriciel = 0x3D,
+ /// <summary>
+ /// Gremlin
+ /// </summary>
+ Gremlin = 0x3E,
+ /// <summary>
+ /// Seika Corporation
+ /// </summary>
+ SeikaCorporation = 0x40,
+ /// <summary>
+ /// Ubisoft
+ /// </summary>
+ Ubisoft = 0x41,
+ /// <summary>
+ /// System 3
+ /// </summary>
+ System3 = 0x46,
+ /// <summary>
+ /// Irem
+ /// </summary>
Irem = 0x49,
+ /// <summary>
+ /// Gakken
+ /// </summary>
Gakken = 0x4A,
- BulletProof_Software = 0x8B,
- PackInVideo = 0x99,
+ /// <summary>
+ /// Absolute
+ /// </summary>
+ Absolute = 0x50,
+ /// <summary>
+ /// Acclaim (NA)
+ /// </summary>
+ AcclaimNA = 0x51,
+ /// <summary>
+ /// Activision
+ /// </summary>
+ Activision = 0x52,
+ /// <summary>
+ /// American Sammy
+ /// </summary>
+ AmericanSammy = 0x53,
+ /// <summary>
+ /// GameTek
+ /// </summary>
+ Gametek = 0x54,
+ /// <summary>
+ /// Hi Tech Expressions
+ /// </summary>
+ HITechExpressions = 0x55,
+ /// <summary>
+ /// LJN
+ /// </summary>
+ Ljn = 0x56,
+ /// <summary>
+ /// Matchbox Toys
+ /// </summary>
+ MatchboxToys = 0x57,
+ /// <summary>
+ /// Mattel
+ /// </summary>
+ Mattel = 0x58,
+ /// <summary>
+ /// Milton Bradley
+ /// </summary>
+ MiltonBradley = 0x59,
+ /// <summary>
+ /// Mindscape / Software Toolworks
+ /// </summary>
+ MindscapeSoftwareToolworks = 0x5A,
+ /// <summary>
+ /// SETA (NA)
+ /// </summary>
+ SetaNA = 0x5B,
+ /// <summary>
+ /// Taxan
+ /// </summary>
+ Taxan = 0x5C,
+ /// <summary>
+ /// Tradewest
+ /// </summary>
+ Tradewest = 0x5D,
+ /// <summary>
+ /// INTV Corporation
+ /// </summary>
+ IntvCorporation = 0x5E,
+ /// <summary>
+ /// Titus
+ /// </summary>
+ Titus = 0x60,
+ /// <summary>
+ /// Virgin Games
+ /// </summary>
+ VirginGames = 0x61,
+ /// <summary>
+ /// Ocean
+ /// </summary>
+ Ocean = 0x67,
+ /// <summary>
+ /// Electronic Arts (NA)
+ /// </summary>
+ ElectronicArtsNA = 0x69,
+ /// <summary>
+ /// Beam Software
+ /// </summary>
+ BeamSoftware = 0x6B,
+ /// <summary>
+ /// Elite Systems
+ /// </summary>
+ EliteSystems = 0x6E,
+ /// <summary>
+ /// Electro Brain
+ /// </summary>
+ ElectroBrain = 0x6F,
+ /// <summary>
+ /// Infogrames
+ /// </summary>
+ Infogrames = 0x70,
+ /// <summary>
+ /// JVC
+ /// </summary>
+ Jvc = 0x72,
+ /// <summary>
+ /// Parker Brothers
+ /// </summary>
+ ParkerBrothers = 0x73,
+ /// <summary>
+ /// The Sales Curve / SCi
+ /// </summary>
+ TheSalesCurveSci = 0x75,
+ /// <summary>
+ /// THQ
+ /// </summary>
+ Thq = 0x78,
+ /// <summary>
+ /// Accolade
+ /// </summary>
+ Accolade = 0x79,
+ /// <summary>
+ /// Triffix
+ /// </summary>
+ Triffix = 0x7A,
+ /// <summary>
+ /// Microprose Software
+ /// </summary>
+ MicroproseSoftware = 0x7C,
+ /// <summary>
+ /// Kemco (NA)
+ /// </summary>
+ KemcoNA = 0x7F,
+ /// <summary>
+ /// Misawa Entertainment
+ /// </summary>
+ MisawaEntertainment = 0x80,
+ /// <summary>
+ /// G. Amusements Co.
+ /// </summary>
+ GAmusementsCO = 0x83,
+ /// <summary>
+ /// G.O 1
+ /// </summary>
+ GO1 = 0x85,
+ /// <summary>
+ /// Tokuma Shoten Intermedia
+ /// </summary>
+ TokumaShotenIntermedia = 0x86,
+ /// <summary>
+ /// Nihon Maicom Kaihatsu (NMK)
+ /// </summary>
+ NihonMaicomKaihatsu = 0x89,
+ /// <summary>
+ /// BulletProof Software (BPS)
+ /// </summary>
+ BulletproofSoftware = 0x8B,
+ /// <summary>
+ /// VIC Tokai
+ /// </summary>
+ VicTokai = 0x8C,
+ /// <summary>
+ /// Sanritsu
+ /// </summary>
+ Sanritsu = 0x8D,
+ /// <summary>
+ /// Character Soft
+ /// </summary>
+ CharacterSoft = 0x8E,
+ /// <summary>
+ /// I'Max
+ /// </summary>
+ IMax = 0x8F,
+ /// <summary>
+ /// Toaplan
+ /// </summary>
+ Toaplan = 0x94,
+ /// <summary>
+ /// Varie
+ /// </summary>
+ Varie = 0x95,
+ /// <summary>
+ /// Yonezawa Party Room 21 / S'Pal
+ /// </summary>
+ YonezawaPartyRoom21SPal = 0x96,
+ /// <summary>
+ /// Pack-In-Video
+ /// </summary>
+ PackINVideo = 0x99,
+ /// <summary>
+ /// Nihon Bussan
+ /// </summary>
+ NihonBussan = 0x9A,
+ /// <summary>
+ /// Tecmo
+ /// </summary>
Tecmo = 0x9B,
+ /// <summary>
+ /// Imagineer
+ /// </summary>
Imagineer = 0x9C,
- Scorpion_Soft = 0xA2,
+ /// <summary>
+ /// Face
+ /// </summary>
+ Face = 0x9E,
+ /// <summary>
+ /// Scorpion Soft
+ /// </summary>
+ ScorpionSoft = 0xA2,
+ /// <summary>
+ /// Broderbund
+ /// </summary>
+ Broderbund = 0xA3,
+ /// <summary>
+ /// Konami
+ /// </summary>
Konami = 0xA4,
- Kawada_Co = 0xA6,
+ /// <summary>
+ /// K. Amusement Leasing Co. (KAC)
+ /// </summary>
+ KAmusementLeasingCO = 0xA5,
+ /// <summary>
+ /// Kawada Co., Ltd.
+ /// </summary>
+ KawadaCOLtd = 0xA6,
+ /// <summary>
+ /// Takara
+ /// </summary>
Takara = 0xA7,
- Royal_Industries = 0xA8,
- Toei_Animation = 0xAC,
+ /// <summary>
+ /// Royal Industries
+ /// </summary>
+ RoyalIndustries = 0xA8,
+ /// <summary>
+ /// Tecnos
+ /// </summary>
+ Tecnos = 0xA9,
+ /// <summary>
+ /// Victor Musical Industries
+ /// </summary>
+ VictorMusicalIndustries = 0xAA,
+ /// <summary>
+ /// Hi-Score Media Work
+ /// </summary>
+ HIScoreMediaWork = 0xAB,
+ /// <summary>
+ /// Toei Animation
+ /// </summary>
+ ToeiAnimation = 0xAC,
+ /// <summary>
+ /// Toho (Japan)
+ /// </summary>
+ TohoJap = 0xAD,
+ /// <summary>
+ /// TSS
+ /// </summary>
+ Tss = 0xAE,
+ /// <summary>
+ /// Namco
+ /// </summary>
Namco = 0xAF,
- ASCII_Corporation = 0xB1,
+ /// <summary>
+ /// Acclaim (Japan)
+ /// </summary>
+ AcclaimJap = 0xB0,
+ /// <summary>
+ /// ASCII Corporation / Nexoft
+ /// </summary>
+ AsciiCorporationNexoft = 0xB1,
+ /// <summary>
+ /// Bandai
+ /// </summary>
Bandai = 0xB2,
- Soft_Pro_Inc = 0xB3,
- HAL_Laboratory = 0xB6,
- Sunsoft_and_Ask_Co = 0xBB,
- Toshiba_EMI = 0xBC,
+ /// <summary>
+ /// Soft Pro Inc.
+ /// </summary>
+ SoftProInc = 0xB3,
+ /// <summary>
+ /// Enix
+ /// </summary>
+ Enix = 0xB4,
+ /// <summary>
+ /// dB-SOFT
+ /// </summary>
+ DBSoft = 0xB5,
+ /// <summary>
+ /// HAL Laboratory
+ /// </summary>
+ HalLaboratory = 0xB6,
+ /// <summary>
+ /// SNK
+ /// </summary>
+ Snk = 0xB7,
+ /// <summary>
+ /// Pony Canyon
+ /// </summary>
+ PonyCanyon = 0xB9,
+ /// <summary>
+ /// Culture Brain
+ /// </summary>
+ CultureBrain = 0xBA,
+ /// <summary>
+ /// Sunsoft
+ /// </summary>
+ Sunsoft = 0xBB,
+ /// <summary>
+ /// Toshiba EMI
+ /// </summary>
+ ToshibaEmi = 0xBC,
+ /// <summary>
+ /// CBS/Sony Group
+ /// </summary>
+ CbsSonyGroup = 0xBD,
+ /// <summary>
+ /// Sammy Corporation
+ /// </summary>
+ SammyCorporation = 0xBF,
+ /// <summary>
+ /// Taito
+ /// </summary>
Taito = 0xC0,
- Sunsoft = 0xC1,
+ /// <summary>
+ /// Sunsoft / Ask Co., Ltd.
+ /// </summary>
+ SunsoftAskCOLtd = 0xC1,
+ /// <summary>
+ /// Kemco
+ /// </summary>
Kemco = 0xC2,
- Square = 0xC3,
- Tokuma_Shoten = 0xC4,
- Data_East = 0xC5,
- Tonkin_House_and_Tokyo_Shoseki = 0xC6,
- East_Cube = 0xC7,
- Konami_and_Ultra_and_Palcom = 0xCA,
- NTVIC_and_VAP = 0xCB,
- Use_Co = 0xCC,
- Pony_Canyon_and_FCI = 0xCE,
+ /// <summary>
+ /// Square / Disk Original Group (DOG)
+ /// </summary>
+ SquareDiskOriginalGroup = 0xC3,
+ /// <summary>
+ /// Tokuma Shoten
+ /// </summary>
+ TokumaShoten = 0xC4,
+ /// <summary>
+ /// Data East
+ /// </summary>
+ DataEast = 0xC5,
+ /// <summary>
+ /// Tonkin House / Tokyo Shoseki
+ /// </summary>
+ TonkinHouseTokyoShoseki = 0xC6,
+ /// <summary>
+ /// East Cube / Toho (NA)
+ /// </summary>
+ EastCubeTohoNA = 0xC7,
+ /// <summary>
+ /// Koei
+ /// </summary>
+ Koei = 0xC8,
+ /// <summary>
+ /// UPL
+ /// </summary>
+ Upl = 0xC9,
+ /// <summary>
+ /// Konami / Ultra / Palcom
+ /// </summary>
+ KonamiUltraPalcom = 0xCA,
+ /// <summary>
+ /// NTVIC / VAP
+ /// </summary>
+ NtvicVap = 0xCB,
+ /// <summary>
+ /// Use Co., Ltd.
+ /// </summary>
+ UseCOLtd = 0xCC,
+ /// <summary>
+ /// Meldac
+ /// </summary>
+ Meldac = 0xCD,
+ /// <summary>
+ /// Pony Canyon / FCI
+ /// </summary>
+ PonyCanyonFci = 0xCE,
+ /// <summary>
+ /// Angel
+ /// </summary>
+ Angel = 0xCF,
+ /// <summary>
+ /// Disco
+ /// </summary>
+ Disco = 0xD0,
+ /// <summary>
+ /// Sofel
+ /// </summary>
Sofel = 0xD1,
- Bothtec_Inc = 0xD2,
- Hiro_Co = 0xDB,
+ /// <summary>
+ /// Bothtec, Inc. / Quest
+ /// </summary>
+ BothtecIncQuest = 0xD2,
+ /// <summary>
+ /// Sigma Enterprises
+ /// </summary>
+ SigmaEnterprises = 0xD3,
+ /// <summary>
+ /// Ask Corp.
+ /// </summary>
+ AskCorp = 0xD4,
+ /// <summary>
+ /// Kyugo Trading Co.
+ /// </summary>
+ KyugoTradingCO = 0xD5,
+ /// <summary>
+ /// Naxat Soft / Kaga Tech
+ /// </summary>
+ NaxatSoftKagaTech = 0xD6,
+ /// <summary>
+ /// Status
+ /// </summary>
+ Status = 0xD8,
+ /// <summary>
+ /// Banpresto
+ /// </summary>
+ Banpresto = 0xD9,
+ /// <summary>
+ /// Tomy
+ /// </summary>
+ Tomy = 0xDA,
+ /// <summary>
+ /// Hiro Co., Ltd.
+ /// </summary>
+ HiroCOLtd = 0xDB,
+ /// <summary>
+ /// Nippon Computer Systems (NCS) / Masaya Games
+ /// </summary>
+ NipponComputerSystemsMasayaGames = 0xDD,
+ /// <summary>
+ /// Human Creative
+ /// </summary>
+ HumanCreative = 0xDE,
+ /// <summary>
+ /// Altron
+ /// </summary>
+ Altron = 0xDF,
+ /// <summary>
+ /// K.K. DCE
+ /// </summary>
+ KKDce = 0xE0,
+ /// <summary>
+ /// Towa Chiki
+ /// </summary>
+ TowaChiki = 0xE1,
+ /// <summary>
+ /// Yutaka
+ /// </summary>
+ Yutaka = 0xE2,
+ /// <summary>
+ /// Kaken Corporation
+ /// </summary>
+ KakenCorporation = 0xE3,
+ /// <summary>
+ /// Epoch
+ /// </summary>
+ Epoch = 0xE5,
+ /// <summary>
+ /// Athena
+ /// </summary>
Athena = 0xE7,
+ /// <summary>
+ /// Asmik
+ /// </summary>
+ Asmik = 0xE8,
+ /// <summary>
+ /// Natsume
+ /// </summary>
+ Natsume = 0xE9,
+ /// <summary>
+ /// King Records
+ /// </summary>
+ KingRecords = 0xEA,
+ /// <summary>
+ /// Atlus
+ /// </summary>
Atlus = 0xEB,
+ /// <summary>
+ /// Sony Music Entertainment
+ /// </summary>
+ SonyMusicEntertainment = 0xEC,
+ /// <summary>
+ /// Pixel Corporation
+ /// </summary>
+ PixelCorporation = 0xED,
+ /// <summary>
+ /// Information Global Service (IGS)
+ /// </summary>
+ InformationGlobalService = 0xEE,
+ /// <summary>
+ /// Fujimic
+ /// </summary>
+ Fujimic = 0xEF,
+ /// <summary>
+ /// A-Wave
+ /// </summary>
+ AWave = 0xF0,
}
[MarshalAs(UnmanagedType.U1)]
// Raw byte: 0x01
private readonly byte blockType = 1;
+ /// <summary>
+ /// Valid block type ID
+ /// </summary>
public byte ValidTypeID { get => 1; }
/// <summary>
/// True if block type ID is valid
@@ -89,7 +650,7 @@ namespace com.clusterrr.Famicom.Containers
/// <summary>
/// Manufacturer code. = = 0x00, Unlicensed, = = 0x01, Nintendo
/// </summary>
- public Manufacturer ManufacturerCode { get => (Manufacturer)manufacturerCode; set => manufacturerCode = (byte)value; }
+ public Company LicenseeCode { get => (Company)manufacturerCode; set => manufacturerCode = (byte)value; }
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
byte[] gameName;
@@ -309,32 +870,46 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public bool EndOfHeadMeet { get => endOfHeadMeet; set => endOfHeadMeet = value; }
- public uint Length => 56;
+ /// <summary>
+ /// Length of the block
+ /// </summary>
+ public uint Length { get => 56; }
- public static FdsBlockDiskInfo FromBytes(byte[] rawData, int position = 0)
+ /// <summary>
+ /// Create FdsBlockDiskInfo object from raw data
+ /// </summary>
+ /// <param name="data">Data</param>
+ /// <param name="offset">Data offset</param>
+ /// <returns>FdsBlockDiskInfo object</returns>
+ /// <exception cref="InvalidDataException"></exception>
+ public static FdsBlockDiskInfo FromBytes(byte[] data, int offset = 0)
{
int rawsize = Marshal.SizeOf(typeof(FdsBlockDiskInfo));
- if (rawsize > rawData.Length - position)
+ if (rawsize > data.Length - offset)
{
- if (rawsize <= rawData.Length - position + 2)
+ if (rawsize <= data.Length - offset + 2)
{
var newRawData = new byte[rawsize];
- Array.Copy(rawData, position, newRawData, 0, rawsize - 2);
- rawData = newRawData;
- position = 0;
+ Array.Copy(data, offset, newRawData, 0, rawsize - 2);
+ data = newRawData;
+ offset = 0;
}
else
{
- throw new ArgumentException("Not enough data to fill FdsDiskInfoBlock class. Array length from position: " + (rawData.Length - position) + ", Struct length: " + rawsize);
+ throw new InvalidDataException("Not enough data to fill FdsDiskInfoBlock class. Array length from position: " + (data.Length - offset) + ", struct length: " + rawsize);
}
}
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
- Marshal.Copy(rawData, position, buffer, rawsize);
+ Marshal.Copy(data, offset, buffer, rawsize);
FdsBlockDiskInfo retobj = (FdsBlockDiskInfo)Marshal.PtrToStructure(buffer, typeof(FdsBlockDiskInfo));
Marshal.FreeHGlobal(buffer);
return retobj;
}
+ /// <summary>
+ /// Return raw data
+ /// </summary>
+ /// <returns>Data</returns>
public byte[] ToBytes()
{
int rawSize = Marshal.SizeOf(this);
@@ -346,8 +921,17 @@ namespace com.clusterrr.Famicom.Containers
return rawDatas;
}
+ /// <summary>
+ /// String representation
+ /// </summary>
+ /// <returns>Game name</returns>
public override string ToString() => GameName;
+ /// <summary>
+ /// Equality comparer
+ /// </summary>
+ /// <param name="other">Other FdsBlockDiskInfo object</param>
+ /// <returns>True if objects are equal</returns>
public bool Equals(FdsBlockDiskInfo other)
{
return Enumerable.SequenceEqual(this.ToBytes(), other.ToBytes());
diff --git a/FdsBlockFileAmount.cs b/FdsBlockFileAmount.cs
index 127f25f..47a9d55 100644
--- a/FdsBlockFileAmount.cs
+++ b/FdsBlockFileAmount.cs
@@ -1,11 +1,18 @@
using System;
+using System.IO;
using System.Linq;
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// File amount FDS block (block type 2)
+ /// </summary>
public class FdsBlockFileAmount : IFdsBlock, IEquatable<FdsBlockFileAmount>
{
private byte blockType = 2;
+ /// <summary>
+ /// Valid block type ID
+ /// </summary>
public byte ValidTypeID { get => 2; }
/// <summary>
/// True if block type ID is valid
@@ -13,6 +20,9 @@ namespace com.clusterrr.Famicom.Containers
public bool IsValid { get => blockType == ValidTypeID; }
private byte fileAmount;
+ /// <summary>
+ /// Amount of files
+ /// </summary>
public byte FileAmount { get => fileAmount; set => fileAmount = value; }
/// <summary>
@@ -25,22 +35,45 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public bool EndOfHeadMeet { get; set; } = false;
- public uint Length => 2;
+ /// <summary>
+ /// Length of the block
+ /// </summary>
+ public uint Length { get => 2; }
- public static FdsBlockFileAmount FromBytes(byte[] rawData, int position = 0)
+ /// <summary>
+ /// Create FdsBlockFileAmount object from raw data
+ /// </summary>
+ /// <param name="data">Data</param>
+ /// <param name="offset">Data offset</param>
+ /// <returns>FdsBlockFileAmount object</returns>
+ public static FdsBlockFileAmount FromBytes(byte[] data, int offset = 0)
{
- var retobj = new FdsBlockFileAmount
+ if (data.Length - offset < 2)
+ throw new InvalidDataException("Not enough data to fill FdsBlockFileAmount class. Array length from position: " + (data.Length - offset) + ", struct length: 2");
+ return new FdsBlockFileAmount
{
- blockType = rawData[position],
- fileAmount = rawData[position + 1]
+ blockType = data[offset],
+ fileAmount = data[offset + 1]
};
- return retobj;
}
+ /// <summary>
+ /// Return raw data
+ /// </summary>
+ /// <returns>Data</returns>
public byte[] ToBytes() => new byte[] { blockType, fileAmount };
+ /// <summary>
+ /// String representation
+ /// </summary>
+ /// <returns>File amount as string</returns>
public override string ToString() => $"{FileAmount}";
+ /// <summary>
+ /// Equality comparer
+ /// </summary>
+ /// <param name="other">Other FdsBlockFileAmount object</param>
+ /// <returns>True if objects are equal</returns>
public bool Equals(FdsBlockFileAmount other)
{
return Enumerable.SequenceEqual(this.ToBytes(), other.ToBytes());
diff --git a/FdsBlockFileData.cs b/FdsBlockFileData.cs
index 40f6e37..8ec31b4 100644
--- a/FdsBlockFileData.cs
+++ b/FdsBlockFileData.cs
@@ -4,9 +4,15 @@ using System.Linq;
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// File data FDS block (block type 4)
+ /// </summary>
public class FdsBlockFileData : IFdsBlock, IEquatable<FdsBlockFileData>
{
private byte blockType = 4;
+ /// <summary>
+ /// Valid block type ID
+ /// </summary>
public byte ValidTypeID { get => 4; }
/// <summary>
/// True if block type ID is valid
@@ -14,6 +20,9 @@ namespace com.clusterrr.Famicom.Containers
public bool IsValid { get => blockType == ValidTypeID; }
private byte[] data = new byte[0];
+ /// <summary>
+ /// File data
+ /// </summary>
public IEnumerable<byte> Data
{
get => Array.AsReadOnly(data);
@@ -30,19 +39,33 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public bool EndOfHeadMeet { get; set; } = false;
+ /// <summary>
+ /// Length of the block
+ /// </summary>
public uint Length => (uint)(data.Length + 1);
- public static FdsBlockFileData FromBytes(byte[] rawData, int position = 0, int size = -1)
+ /// <summary>
+ /// Create FdsBlockFileData object from raw data
+ /// </summary>
+ /// <param name="data">Data</param>
+ /// <param name="offset">Offset</param>
+ /// <param name="length">Length</param>
+ /// <returns>FdsBlockFileData object</returns>
+ public static FdsBlockFileData FromBytes(byte[] data, int offset = 0, int length = -1)
{
var retobj = new FdsBlockFileData
{
- blockType = rawData[position],
- data = new byte[size < 0 ? rawData.Length - position - 1 : size - 1]
+ blockType = data[offset],
+ data = new byte[length < 0 ? data.Length - offset - 1 : length - 1]
};
- Array.Copy(rawData, position + 1, retobj.data, 0, retobj.data.Length);
+ Array.Copy(data, offset + 1, retobj.data, 0, retobj.data.Length);
return retobj;
}
+ /// <summary>
+ /// Return raw data
+ /// </summary>
+ /// <returns>Data</returns>
public byte[] ToBytes()
{
var result = new List<byte>
@@ -53,8 +76,17 @@ namespace com.clusterrr.Famicom.Containers
return result.ToArray();
}
+ /// <summary>
+ /// String representation
+ /// </summary>
+ /// <returns>Number of bytes as string</returns>
public override string ToString() => $"{data.Length} bytes";
+ /// <summary>
+ /// Equality comparer
+ /// </summary>
+ /// <param name="other">Other FdsBlockFileData object</param>
+ /// <returns>True if objects are equal</returns>
public bool Equals(FdsBlockFileData other)
{
return Enumerable.SequenceEqual(this.ToBytes(), other.ToBytes());
diff --git a/FdsBlockFileHeader.cs b/FdsBlockFileHeader.cs
index 8d140e6..6de2f1b 100644
--- a/FdsBlockFileHeader.cs
+++ b/FdsBlockFileHeader.cs
@@ -1,22 +1,41 @@
using System;
+using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// File header FDS block (block type 3)
+ /// </summary>
[StructLayout(LayoutKind.Sequential, Size = 18, Pack = 1)]
public class FdsBlockFileHeader : IFdsBlock, IEquatable<FdsBlockFileHeader>
{
+ /// <summary>
+ /// Kind of the file
+ /// </summary>
public enum Kind
{
+ /// <summary>
+ /// PRG data
+ /// </summary>
Program = 0,
+ /// <summary>
+ /// CHR data
+ /// </summary>
Character = 1,
+ /// <summary>
+ /// Nametable data
+ /// </summary>
NameTable = 2
}
[MarshalAs(UnmanagedType.U1)]
private readonly byte blockType = 3;
+ /// <summary>
+ /// Valid block type ID
+ /// </summary>
public byte ValidTypeID { get => 3; }
/// <summary>
/// True if block type ID is valid
@@ -25,28 +44,45 @@ namespace com.clusterrr.Famicom.Containers
[MarshalAs(UnmanagedType.U1)]
private byte fileNumber;
+ /// <summary>
+ /// File number
+ /// </summary>
public byte FileNumber { get => fileNumber; set => fileNumber = value; }
[MarshalAs(UnmanagedType.U1)]
- // ID specified at disk-read function call
private byte fileIndicateCode;
+ /// <summary>
+ /// File indicate code (ID specified at disk-read function call)
+ /// </summary>
public byte FileIndicateCode { get => fileIndicateCode; set => fileIndicateCode = value; }
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
private byte[] fileName;
+ /// <summary>
+ /// Filename
+ /// </summary>
public string FileName { get => Encoding.ASCII.GetString(fileName).Trim(new char[] { '\0', ' ' }); set => fileName = Encoding.ASCII.GetBytes(value.PadRight(8)).Take(8).ToArray(); }
[MarshalAs(UnmanagedType.U2)]
// the destination address when loading
private ushort fileAddress;
+ /// <summary>
+ /// File address - the destination address when loading
+ /// </summary>
public ushort FileAddress { get => fileAddress; set => fileAddress = value; }
[MarshalAs(UnmanagedType.U2)]
private ushort fileSize;
+ /// <summary>
+ /// File size
+ /// </summary>
public ushort FileSize { get => fileSize; set => fileSize = value; }
[MarshalAs(UnmanagedType.U1)]
private byte fileKind;
+ /// <summary>
+ /// Kind of the file: program, character or nametable
+ /// </summary>
public Kind FileKind { get => (Kind)fileKind; set => fileKind = (byte)value; }
[MarshalAs(UnmanagedType.U1)]
@@ -63,32 +99,46 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public bool EndOfHeadMeet { get => endOfHeadMeet; set => endOfHeadMeet = value; }
- public uint Length => 16;
+ /// <summary>
+ /// Length of the block
+ /// </summary>
+ public uint Length { get => 16; }
- public static FdsBlockFileHeader FromBytes(byte[] rawData, int position = 0)
+ /// <summary>
+ /// Create FdsBlockFileHeader object from raw data
+ /// </summary>
+ /// <param name="data">Data</param>
+ /// <param name="offset">Offset</param>
+ /// <returns></returns>
+ /// <exception cref="InvalidDataException"></exception>
+ public static FdsBlockFileHeader FromBytes(byte[] data, int offset = 0)
{
int rawsize = Marshal.SizeOf(typeof(FdsBlockFileHeader));
- if (rawsize > rawData.Length - position)
+ if (rawsize > data.Length - offset)
{
- if (rawsize <= rawData.Length - position + 2)
+ if (rawsize <= data.Length - offset + 2)
{
var newRawData = new byte[rawsize];
- Array.Copy(rawData, position, newRawData, 0, rawsize - 2);
- rawData = newRawData;
- position = 0;
+ Array.Copy(data, offset, newRawData, 0, rawsize - 2);
+ data = newRawData;
+ offset = 0;
}
else
{
- throw new ArgumentException("Not enough data to fill FdsFileHeaderBlock class. Array length from position: " + (rawData.Length - position) + ", Struct length: " + rawsize);
+ throw new InvalidDataException("Not enough data to fill FdsFileHeaderBlock class. Array length from position: " + (data.Length - offset) + ", struct length: " + rawsize);
}
}
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
- Marshal.Copy(rawData, position, buffer, rawsize);
+ Marshal.Copy(data, offset, buffer, rawsize);
FdsBlockFileHeader retobj = (FdsBlockFileHeader)Marshal.PtrToStructure(buffer, typeof(FdsBlockFileHeader));
Marshal.FreeHGlobal(buffer);
return retobj;
}
+ /// <summary>
+ /// Return raw data
+ /// </summary>
+ /// <returns>Data</returns>
public byte[] ToBytes()
{
int rawSize = Marshal.SizeOf(this);
@@ -100,8 +150,17 @@ namespace com.clusterrr.Famicom.Containers
return rawDatas;
}
+ /// <summary>
+ /// String representation
+ /// </summary>
+ /// <returns>File name and file kind as string</returns>
public override string ToString() => $"{FileName} ({FileKind})";
+ /// <summary>
+ /// Equality comparer
+ /// </summary>
+ /// <param name="other">Other FdsBlockFileHeader object</param>
+ /// <returns>True if objects are equal</returns>
public bool Equals(FdsBlockFileHeader other)
{
return Enumerable.SequenceEqual(this.ToBytes(), other.ToBytes());
diff --git a/FdsDiskFile.cs b/FdsDiskFile.cs
index 14cd7ff..e05591b 100644
--- a/FdsDiskFile.cs
+++ b/FdsDiskFile.cs
@@ -3,19 +3,49 @@ using System.Linq;
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// FDS file - header and data
+ /// </summary>
public class FdsDiskFile
{
private FdsBlockFileHeader headerBlock;
private FdsBlockFileData dataBlock;
+ /// <summary>
+ /// FDS block with file header
+ /// </summary>
public FdsBlockFileHeader HeaderBlock { get => headerBlock; set => headerBlock = value; }
+ /// <summary>
+ /// FDS block with file contents
+ /// </summary>
public FdsBlockFileData DataBlock { get => dataBlock; set => dataBlock = value; }
+ /// <summary>
+ /// File number
+ /// </summary>
public byte FileNumber { get => HeaderBlock.FileNumber; set => HeaderBlock.FileNumber = value; }
+ /// <summary>
+ /// File indicate code (ID specified at disk-read function call)
+ /// </summary>
public byte FileIndicateCode { get => HeaderBlock.FileIndicateCode; set => HeaderBlock.FileIndicateCode = value; }
+ /// <summary>
+ /// Filename
+ /// </summary>
public string FileName { get => HeaderBlock.FileName; set => HeaderBlock.FileName = value; }
+ /// <summary>
+ /// File address - the destination address when loading
+ /// </summary>
public ushort FileAddress { get => HeaderBlock.FileAddress; set => HeaderBlock.FileAddress = value; }
+ /// <summary>
+ /// File size
+ /// </summary>
public ushort FileSize { get => (ushort)DataBlock.Data.Count(); }
+ /// <summary>
+ /// Kind of the file: program, character or nametable
+ /// </summary>
public FdsBlockFileHeader.Kind FileKind { get => HeaderBlock.FileKind; set => HeaderBlock.FileKind = value; }
+ /// <summary>
+ /// File contents
+ /// </summary>
public IEnumerable<byte> Data
{
get => DataBlock.Data;
@@ -25,7 +55,11 @@ namespace com.clusterrr.Famicom.Containers
HeaderBlock.FileSize = (ushort)DataBlock.Data.Count();
}
}
-
+ /// <summary>
+ /// Construcor
+ /// </summary>
+ /// <param name="headerBlock">File header block</param>
+ /// <param name="dataBlock">File data block</param>
public FdsDiskFile(FdsBlockFileHeader headerBlock, FdsBlockFileData dataBlock)
{
this.HeaderBlock = headerBlock;
@@ -33,6 +67,9 @@ namespace com.clusterrr.Famicom.Containers
headerBlock.FileSize = (ushort)dataBlock.Data.Count();
}
+ /// <summary>
+ /// Construcor for empty file
+ /// </summary>
public FdsDiskFile()
{
this.HeaderBlock = new FdsBlockFileHeader();
@@ -40,8 +77,16 @@ namespace com.clusterrr.Famicom.Containers
HeaderBlock.FileSize = (ushort)DataBlock.Data.Count();
}
+ /// <summary>
+ /// Returns raw file contents
+ /// </summary>
+ /// <returns>Raw file contents</returns>
public byte[] ToBytes() => Enumerable.Concat(HeaderBlock.ToBytes(), DataBlock.ToBytes()).ToArray();
+ /// <summary>
+ /// String representation: filename, file kind, data block info
+ /// </summary>
+ /// <returns>String representation of the file</returns>
public override string ToString() => $"{FileName} ({FileKind}, {dataBlock})";
}
}
diff --git a/FdsDiskSide.cs b/FdsDiskSide.cs
index 049b00a..1a373d9 100644
--- a/FdsDiskSide.cs
+++ b/FdsDiskSide.cs
@@ -4,6 +4,9 @@ using System.Linq;
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// Single FDS disk side: disk info block, file amount block and file blocks
+ /// </summary>
public class FdsDiskSide
{
readonly FdsBlockDiskInfo diskInfoBlock;
@@ -11,11 +14,14 @@ namespace com.clusterrr.Famicom.Containers
/// Disk info block
/// </summary>
public FdsBlockDiskInfo DiskInfoBlock { get => diskInfoBlock; }
+ /// <summary>
+ /// Literal ASCII string: *NINTENDO-HVC*
+ /// </summary>
public string DiskVerification { get => diskInfoBlock.DiskVerification; }
/// <summary>
/// Manufacturer code. $00 = Unlicensed, $01 = Nintendo
/// </summary>
- public FdsBlockDiskInfo.Manufacturer ManufacturerCode { get => diskInfoBlock.ManufacturerCode; set => diskInfoBlock.ManufacturerCode = value; }
+ public FdsBlockDiskInfo.Company ManufacturerCode { get => diskInfoBlock.LicenseeCode; set => diskInfoBlock.LicenseeCode = value; }
/// <summary>
/// 3-letter ASCII code per game (e.g. ZEL for The Legend of Zelda)
/// </summary>
@@ -89,6 +95,9 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public IList<FdsDiskFile> Files { get => files; }
+ /// <summary>
+ /// Constructor to create empty FdsDiskSide object
+ /// </summary>
public FdsDiskSide()
{
diskInfoBlock = new FdsBlockDiskInfo();
@@ -96,15 +105,23 @@ namespace com.clusterrr.Famicom.Containers
files = new List<FdsDiskFile>();
}
+ /// <summary>
+ /// Constructor to create FdsDiskSide object from blocks and files
+ /// </summary>
+ /// <param name="diskInfoBlock">Disk info block</param>
+ /// <param name="fileAmountBlock">File amount block</param>
+ /// <param name="files">Files</param>
public FdsDiskSide(FdsBlockDiskInfo diskInfoBlock, FdsBlockFileAmount fileAmountBlock, IEnumerable<FdsDiskFile> files)
{
this.diskInfoBlock = diskInfoBlock;
this.fileAmountBlock = fileAmountBlock;
this.files = files.ToList();
- //if (this.fileAmountBlock.FileAmount > this.files.Count)
- // throw new ArgumentOutOfRangeException("visibleFileAmount", "visibleFileAmount must be less or equal number of files");
}
+ /// <summary>
+ /// Constructor to create FdsDiskSide object from blocks
+ /// </summary>
+ /// <param name="blocks"></param>
public FdsDiskSide(IEnumerable<IFdsBlock> blocks)
{
this.diskInfoBlock = (FdsBlockDiskInfo)blocks.First();
@@ -117,6 +134,10 @@ namespace com.clusterrr.Famicom.Containers
}
}
+ /// <summary>
+ /// Constructor to create FdsDiskSide object from raw data
+ /// </summary>
+ /// <param name="data"></param>
public FdsDiskSide(byte[] data) : this()
{
int pos = 0;
@@ -146,12 +167,19 @@ namespace com.clusterrr.Famicom.Containers
}
}
+ /// <summary>
+ /// Change file's "file number" fields orderly
+ /// </summary>
public void FixFileNumbers()
{
for (var i = 0; i < files.Count; i++)
files[i].FileNumber = (byte)i;
}
+ /// <summary>
+ /// Get FDS blocks
+ /// </summary>
+ /// <returns></returns>
public IEnumerable<IFdsBlock> GetBlocks()
{
var blocks = new List<IFdsBlock>
@@ -163,17 +191,31 @@ namespace com.clusterrr.Famicom.Containers
return blocks;
}
+ /// <summary>
+ /// Create FdsDiskSide object from raw data
+ /// </summary>
+ /// <param name="data">Data</param>
+ /// <returns>FdsDiskSide object</returns>
+
public static FdsDiskSide FromBytes(byte[] data)
{
return new FdsDiskSide(data);
}
+ /// <summary>
+ /// Return raw data
+ /// </summary>
+ /// <returns></returns>
public byte[] ToBytes()
{
var data = Enumerable.Concat(Enumerable.Concat(diskInfoBlock.ToBytes(), fileAmountBlock.ToBytes()), files.SelectMany(f => f.ToBytes())).ToArray();
return Enumerable.Concat(data, new byte[65500 - data.Count()]).ToArray();
}
+ /// <summary>
+ /// String representation
+ /// </summary>
+ /// <returns>Game name, disk number, side number as string</returns>
public override string ToString() => $"{GameName} - disk {DiskNumber + 1}, side {DiskSide}";
}
}
diff --git a/FdsFile.cs b/FdsFile.cs
index b5ca2bb..2c798c2 100644
--- a/FdsFile.cs
+++ b/FdsFile.cs
@@ -4,6 +4,9 @@ using System.Linq;
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// Full .fds file, disk sides collection
+ /// </summary>
public class FdsFile
{
IList<FdsDiskSide> sides;
@@ -12,15 +15,26 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public IList<FdsDiskSide> Sides { get => sides; set => sides = value; }
+ /// <summary>
+ /// Constructor to create empty FdsFile object
+ /// </summary>
public FdsFile()
{
sides = new List<FdsDiskSide>();
}
+ /// <summary>
+ /// Create FdsFile object from the specified .nes file
+ /// </summary>
+ /// <param name="filename">Path to the .fds file</param>
public FdsFile(string filename) : this(File.ReadAllBytes(filename))
{
}
+ /// <summary>
+ /// Create FdsFile object from raw .fds file data
+ /// </summary>
+ /// <param name="data"></param>
public FdsFile(byte[] data) : this()
{
if (data[0] == (byte)'F' && data[1] == (byte)'D' && data[2] == (byte)'S' && data[3] == 0x1A)
@@ -32,16 +46,29 @@ namespace com.clusterrr.Famicom.Containers
}
}
+ /// <summary>
+ /// Create FdsFile object from set of FdsDiskSide objects
+ /// </summary>
+ /// <param name="sides"></param>
public FdsFile(IEnumerable<FdsDiskSide> sides)
{
this.sides = new List<FdsDiskSide>(sides);
}
+ /// <summary>
+ /// Create FdsFile object from raw .fds file contents
+ /// </summary>
+ /// <param name="data"></param>
+ /// <returns></returns>
public static FdsFile FromBytes(byte[] data)
{
return new FdsFile(data);
}
+ /// <summary>
+ /// Return FDS file contents
+ /// </summary>
+ /// <returns>FDS file contents</returns>
public byte[] ToBytes(bool useHeader = false)
{
var data = sides.SelectMany(s => s.ToBytes());
@@ -58,6 +85,11 @@ namespace com.clusterrr.Famicom.Containers
return data.ToArray();
}
+ /// <summary>
+ /// Save to .fds file
+ /// </summary>
+ /// <param name="filename">Target filename</param>
+ /// <param name="useHeader">Option to add .fds file header (ignored by most emulators)</param>
public void Save(string filename, bool useHeader = false)
{
File.WriteAllBytes(filename, ToBytes(useHeader));
diff --git a/IFdsBlock.cs b/IFdsBlock.cs
index 37a4ac0..836b670 100644
--- a/IFdsBlock.cs
+++ b/IFdsBlock.cs
@@ -1,10 +1,26 @@
namespace com.clusterrr.Famicom.Containers
{
+ /// <summary>
+ /// FDS block interface
+ /// </summary>
public interface IFdsBlock
{
+ /// <summary>
+ /// Returns the valid block type ID
+ /// </summary>
byte ValidTypeID { get; }
+ /// <summary>
+ /// Returns true if the block type ID is valid
+ /// </summary>
bool IsValid { get; }
+ /// <summary>
+ /// Length of raw block data
+ /// </summary>
uint Length { get; }
+ /// <summary>
+ /// Return raw data
+ /// </summary>
+ /// <returns></returns>
byte[] ToBytes();
}
}
diff --git a/NesContainers.csproj b/NesContainers.csproj
index 9dead37..fee36c1 100644
--- a/NesContainers.csproj
+++ b/NesContainers.csproj
@@ -4,6 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>NesContainers</AssemblyName>
<RootNamespace>com.clusterrr.Famicom.Containers</RootNamespace>
+ <LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -17,12 +18,4 @@
<DocumentationFile>NesContainers.xml</DocumentationFile>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
-
- <ItemGroup>
- <None Update="README.md">
- <Pack>True</Pack>
- <PackagePath>\</PackagePath>
- </None>
- </ItemGroup>
-
</Project>
diff --git a/NesFile.cs b/NesFile.cs
index ea77818..166af16 100644
--- a/NesFile.cs
+++ b/NesFile.cs
@@ -186,7 +186,13 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public enum iNesVersion
{
+ /// <summary>
+ /// Classic iNES format
+ /// </summary>
iNES = 1,
+ /// <summary>
+ /// NES 2.0 format
+ /// </summary>
NES20 = 2
}
/// <summary>
@@ -385,7 +391,7 @@ namespace com.clusterrr.Famicom.Containers
}
/// <summary>
- /// Type of expansion device connected to console
+ /// Type of expansion device connected to console, source: https://www.nesdev.org/wiki/NES_2.0#Default_Expansion_Device
/// </summary>
public enum ExpansionDevice
{
@@ -580,7 +586,27 @@ namespace com.clusterrr.Famicom.Containers
/// <summary>
/// City Patrolman Lightgun
/// </summary>
- CityPatrolmanLightgun = 0x2F
+ CityPatrolmanLightgun = 0x2F,
+ /// <summary>
+ /// Sharp C1 Cassette Interface
+ /// </summary>
+ SharpC1CassetteInterface = 0x30,
+ /// <summary>
+ /// Standard Controller with swapped Left-Right/Up-Down/B-A
+ /// </summary>
+ StandardControllerWithSwapped = 0x31,
+ /// <summary>
+ /// Excalibor Sudoku Pad
+ /// </summary>
+ ExcaliborSudokuPad = 0x32,
+ /// <summary>
+ /// ABL Pinball
+ /// </summary>
+ AblPinball = 0x33,
+ /// <summary>
+ /// Golden Nugget Casino extra buttons
+ /// </summary>
+ GoldenNuggetCasinoExtraButtons = 0x34,
}
/// <summary>
@@ -699,27 +725,27 @@ namespace com.clusterrr.Famicom.Containers
}
/// <summary>
- /// Create NesFile object from specified .nes file
+ /// Create NesFile object from the specified .nes file
/// </summary>
- /// <param name="fileName">Path to .nes file</param>
+ /// <param name="fileName">Path to the .nes file</param>
public NesFile(string fileName)
: this(File.ReadAllBytes(fileName))
{
}
/// <summary>
- /// Create NesFile object from specified .nes file
+ /// Create NesFile object from raw .nes file contents
/// </summary>
- /// <param name="fileName">Path to .nes file</param>
+ /// <param name="data">Raw ROM data</param>
public static NesFile FromBytes(byte[] data)
{
return new NesFile(data);
}
/// <summary>
- /// Returns iNES data (header + PRG + CHR)
+ /// Return iNES file contents (header + PRG + CHR)
/// </summary>
- /// <returns>iNES data</returns>
+ /// <returns>iNES file contents</returns>
public byte[] ToBytes()
{
var data = new List<byte>();
diff --git a/NesHeaderFixer.cs b/NesHeaderFixer.cs
index 6752ff6..1f428b1 100644
--- a/NesHeaderFixer.cs
+++ b/NesHeaderFixer.cs
@@ -3,15 +3,36 @@ using System.Linq;
namespace com.clusterrr.Famicom.Containers.HeaderFixer
{
+ /// <summary>
+ /// Static class that allows to fix known ROMs with bad header
+ /// </summary>
public static class NesHeaderFixer
{
+ /// <summary>
+ /// What was fixed in the ROM header
+ /// </summary>
[Flags]
public enum NesFixType
{
+ /// <summary>
+ /// Nothing
+ /// </summary>
NoFix = 0,
+ /// <summary>
+ /// Mapper
+ /// </summary>
Mapper = 1,
+ /// <summary>
+ /// Mirroring
+ /// </summary>
Mirroring = 2,
+ /// <summary>
+ /// Battery flag
+ /// </summary>
Battery = 4,
+ /// <summary>
+ /// No CHR
+ /// </summary>
NoChr = 8
};
@@ -76,7 +97,7 @@ namespace com.clusterrr.Famicom.Containers.HeaderFixer
ulong partialmd5 = 0;
for (int x = 0; x < 8; x++)
partialmd5 |= (ulong)md5[15 - x] << (x * 8);
- // maybe this games uses battery saves?
+ // maybe this game uses battery saves?
foreach (var sav in savie)
{
if (!nes.Battery && sav == partialmd5)
diff --git a/UnifFile.cs b/UnifFile.cs
index 4e36c12..b8532bf 100644
--- a/UnifFile.cs
+++ b/UnifFile.cs
@@ -21,6 +21,9 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
public int Version = 7;
+ /// <summary>
+ /// Constructor to create empty UnifFile object
+ /// </summary>
public UnifFile()
{
DumpDate = DateTime.Now;
@@ -59,6 +62,11 @@ namespace com.clusterrr.Famicom.Containers
{
}
+ /// <summary>
+ /// Create UnifFile object from raw .unf file contents
+ /// </summary>
+ /// <param name="data"></param>
+ /// <returns></returns>
public static UnifFile FromBytes(byte[] data)
{
return new UnifFile(data);
@@ -68,7 +76,6 @@ namespace com.clusterrr.Famicom.Containers
/// Save UNIF file
/// </summary>
/// <param name="fileName">Target filename</param>
- /// <param name="dumperName"></param>
public void Save(string fileName)
{
var data = new List<byte>();
@@ -112,6 +119,7 @@ namespace com.clusterrr.Famicom.Containers
/// </summary>
/// <param name="data">Input array of bytes</param>
/// <param name="maxLength">Maximum number of bytes to parse</param>
+ /// <param name="offset">Start offset</param>
/// <returns></returns>
private static string UTF8NToString(byte[] data, int maxLength = int.MaxValue, int offset = 0)
{
@@ -339,15 +347,39 @@ namespace com.clusterrr.Famicom.Containers
Fields.Where(k => k.Key.StartsWith("CHR")).OrderBy(k => k.Key).SelectMany(i => i.Value)).ToArray()
);
+ /// <summary>
+ /// Default game controller(s)
+ /// </summary>
[Flags]
public enum Controller
{
+ /// <summary>
+ /// None
+ /// </summary>
None = 0,
+ /// <summary>
+ /// Standatd Controller
+ /// </summary>
StandardController = 1,
+ /// <summary>
+ /// Zapper
+ /// </summary>
Zapper = 2,
+ /// <summary>
+ /// R.O.B.
+ /// </summary>
ROB = 4,
+ /// <summary>
+ /// Arkanoid Controller
+ /// </summary>
ArkanoidController = 8,
+ /// <summary>
+ /// Power Pad
+ /// </summary>
PowerPad = 16,
+ /// <summary>
+ /// Four Score
+ /// </summary>
FourScore = 32,
}
}