patterns: Improvements to NES & IPS, add SNES, NSF, NSFe (#455)

* Add credit to ne.hexpat

* Add many changes to nes.hexpat

* Fixing dependance on variables declared in if statement

* Added mappers and inline to NES 2.0 header, removed needless parenthesises

* Add files via upload

* Add files via upload

* Create nsf.hexpat

* Used full name of the SNES on description

* Add SNES, NSF & NSFe, new description for NES

* Removing erroneous condition in ips.hexpat's truncatedSize

* Removing unnecessary std.string import in ips.hexpat

* Added both locations for sections in PE, clearer variable names, reorganized DOS stub

* Delete patterns/nsfe.hexpat

* Delete patterns/nsfmetadata.hexpat

* Added chunks from NSFe to NSF

* Added NSFe

* Fix size of truncatedSize in ips.hexpat

---------

Co-authored-by: Nik <werwolv98@gmail.com>
This commit is contained in:
gmestanley
2025-12-05 17:15:50 -03:00
committed by GitHub
parent a525160243
commit 0d8bd76c2c
7 changed files with 1357 additions and 942 deletions

109
patterns/nsf.hexpat Normal file
View File

@@ -0,0 +1,109 @@
#pragma author gmestanley
#pragma description NES Sound Format file
import std.string;
struct ChunkMetadata {
u32 length;
char ID[4];
} [[inline]];
struct TimeChunkData {
u32 trackLengths[while($<addressof(parent.metadata)+6+parent.metadata.length)];
} [[inline]];
fn formatMetadataName(str string) {
return "\"" + std::string::substr(string, 0, sizeof(string)-1) + "\"";
};
struct Name {
char trackName[] [[format("formatMetadataName")]];
};
struct TlblChunkData {
Name trackNames[while($<addressof(parent.metadata)+6+parent.metadata.length)];
} [[inline]];
struct AuthChunkData {
char gameTitle[] [[format("formatMetadataName")]];
char songwriting[] [[format("formatMetadataName")]];
char copyright[] [[format("formatMetadataName")]];
char ripper[] [[format("formatMetadataName")]];
} [[inline]];
struct TextChunkData {
char text[parent.metadata.length];
} [[inline]];
struct Chunk {
ChunkMetadata metadata;
if (metadata.ID == "time") TimeChunkData timeChunkData;
else if (metadata.ID == "text") TextChunkData textChunkData;
else if (metadata.ID == "tlbl") TlblChunkData tlblChunkData;
else if (metadata.ID == "auth") AuthChunkData authChunkData;
else u8 data[metadata.length];
};
bitfield NSF2Flags {
padding : 4;
irq : 1;
nonReturningInitNotUsed : 1;
playSubroutineNotUsed : 1;
playbackNSFeChunk : 1;
};
bitfield Region {
isPAL : 1;
palNTSCDual : 1;
};
enum ExtraSoundChipSupport : u8 {
None,
VRC6,
VRC7,
FDS = 4,
MMC5 = 8,
Namco163 = 16,
Sunsoft5B = 32,
VTxx = 64
};
fn formatName(str string) {
for (u8 nameIndex = 0, nameIndex < 32, nameIndex += 1) {
if (!$[$+nameIndex] || nameIndex == 31)
return "\"" + std::string::substr(string, 0, nameIndex) + "\"";
}
};
fn renderEOF(str value) {
return "\"NESM<EOF>\"";
};
struct Header {
char signature[5] [[format("renderEOF")]];
u8 version;
u8 songAmount;
u8 startingSong;
u16 dataLoadAddress;
u16 dataInitAddress;
u16 dataPlayAddress;
char gameName[32] [[format("formatName")]];
char songwriting[32] [[format("formatName")]];
char copyrightHolder[32] [[format("formatName")]];
u16 ntscPlaySpeed;
u8 bankswitchInitValues[8];
u16 palPlaySpeed;
Region region;
ExtraSoundChipSupport extraSoundChipSupport;
NSF2Flags nsf2flags;
u24 dataLength;
};
Header header @ 0x00;
struct Chunks {
if (header.dataLength)
NSFEChunk chunks[while($<std::mem::size())];
};
Chunks metadata @ 0x80+header.dataLength;