docs: Enhance tracker.cc and tracker.h with detailed function and struct documentation
- Added comprehensive Doxygen-style comments for key functions in tracker.cc, including AllocSpcBlock, GetSpcAddr, and LoadSpcCommand, to improve code readability and maintainability. - Documented the purpose and parameters of various structs in tracker.h, such as SongSpcBlock, SongRange, and SpcCommand, providing clarity on their roles in the music data handling process. - Improved overall documentation quality to assist developers in understanding the music tracking system's architecture and functionality.
This commit is contained in:
@@ -31,6 +31,14 @@ void AddSpcReloc(music::SongSpcBlock *sbl, short addr) {
|
||||
} // namespace
|
||||
|
||||
namespace music {
|
||||
/**
|
||||
* @brief Allocates a new SongSpcBlock for holding generated SPC data.
|
||||
* These blocks are the building blocks for the final binary output that will be
|
||||
* written to the ROM and eventually loaded into the APU.
|
||||
* @param len The size of the data buffer to allocate for this block.
|
||||
* @param bank The target sound bank for this block.
|
||||
* @return A pointer to the newly allocated SongSpcBlock.
|
||||
*/
|
||||
SongSpcBlock *Tracker::AllocSpcBlock(int len, int bank) {
|
||||
SongSpcBlock *sbl;
|
||||
if (!len) {
|
||||
@@ -54,6 +62,16 @@ SongSpcBlock *Tracker::AllocSpcBlock(int len, int bank) {
|
||||
return sbl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a direct pointer to music data within the ROM.
|
||||
* This function is critical for parsing. It correctly resolves a virtual SPC
|
||||
* address and bank into a physical offset within the loaded ROM file, handling
|
||||
* the game's specific sound bank mapping.
|
||||
* @param rom The ROM object.
|
||||
* @param addr The 16-bit virtual address of the data.
|
||||
* @param bank The sound bank where the data resides.
|
||||
* @return A pointer to the data within the ROM buffer, or nullptr if not found.
|
||||
*/
|
||||
unsigned char *Tracker::GetSpcAddr(Rom &rom, unsigned short addr, short bank) {
|
||||
unsigned char *rom_ptr;
|
||||
unsigned short a;
|
||||
@@ -88,6 +106,12 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a new SpcCommand from a pre-allocated pool.
|
||||
* This uses a classic free-list implementation for efficient memory management
|
||||
* without repeated malloc/free calls.
|
||||
* @return The index of the newly allocated command.
|
||||
*/
|
||||
short Tracker::AllocSpcCommand() {
|
||||
int i = m_free;
|
||||
int j;
|
||||
@@ -112,6 +136,15 @@ short Tracker::AllocSpcCommand() {
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the total time (duration) of a block of SpcCommands.
|
||||
* This is essential for synchronization and editor display. It works backwards
|
||||
* from the end of a command list, calculating and caching the duration.
|
||||
* @param rom The ROM object.
|
||||
* @param num The starting command index.
|
||||
* @param prevtime The duration of the subsequent block.
|
||||
* @return The total duration in ticks.
|
||||
*/
|
||||
short Tracker::GetBlockTime(Rom &rom, short num, short prevtime) {
|
||||
SpcCommand *spc_command = current_spc_command_;
|
||||
SpcCommand *spc_command2;
|
||||
@@ -204,6 +237,16 @@ short Tracker::GetBlockTime(Rom &rom, short num, short prevtime) {
|
||||
return spc_command[num].tim + prevtime * spc_command[num].tim2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loads a block of music data from a given ROM address.
|
||||
* This is the main parser. It reads the raw byte stream from the ROM and
|
||||
* converts it into a doubly-linked list of SpcCommand structs.
|
||||
* @param rom The ROM object.
|
||||
* @param addr The starting address in the ROM.
|
||||
* @param bank The sound bank.
|
||||
* @param t A time limit for parsing, to handle potentially infinite loops.
|
||||
* @return The index of the first command in the newly loaded block.
|
||||
*/
|
||||
short Tracker::LoadSpcCommand(Rom &rom, unsigned short addr, short bank,
|
||||
int t) {
|
||||
int b = 0;
|
||||
@@ -378,6 +421,13 @@ short Tracker::LoadSpcCommand(Rom &rom, unsigned short addr, short bank,
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief High-level function to load all song data from the ROM.
|
||||
* (Currently commented out, but this would be the main entry point for parsing.)
|
||||
* It would iterate through the main song table in the ROM, and for each song,
|
||||
* recursively load all its parts and commands using LoadSpcCommand. It would
|
||||
* also load instrument and sample data.
|
||||
*/
|
||||
void Tracker::LoadSongs(Rom &rom) {
|
||||
// unsigned char *b;
|
||||
// unsigned char *c;
|
||||
@@ -648,6 +698,16 @@ void Tracker::LoadSongs(Rom &rom) {
|
||||
// w_modf = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Saves a block of edited SpcCommands back into a binary format.
|
||||
* This is the serializer, the inverse of LoadSpcCommand. It walks the linked
|
||||
* list of commands and writes the corresponding bytes into a new SongSpcBlock.
|
||||
* @param rom The ROM object.
|
||||
* @param num The index of the first command to save.
|
||||
* @param songtime The total duration of the song, used for padding.
|
||||
* @param endtr Flag indicating if this is the end of a track.
|
||||
* @return The new virtual address of the saved block.
|
||||
*/
|
||||
short Tracker::SaveSpcCommand(Rom &rom, short num, short songtime,
|
||||
short endtr) {
|
||||
SpcCommand *spc_command = current_spc_command_;
|
||||
@@ -769,6 +829,18 @@ short Tracker::SaveSpcCommand(Rom &rom, short num, short songtime,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a prepared data block into the ROM file.
|
||||
* This is a utility for SaveSongs, formatting the data with a header
|
||||
* containing the length and target SPC address.
|
||||
* @param rom The ROM object.
|
||||
* @param buf The data to write.
|
||||
* @param len The length of the data.
|
||||
* @param addr The ROM address to write to.
|
||||
* @param spc The target SPC address for this data.
|
||||
* @param limit The upper bound for writing in the ROM.
|
||||
* @return The next available ROM address after writing.
|
||||
*/
|
||||
int Tracker::WriteSpcData(Rom &rom, void *buf, int len, int addr, int spc,
|
||||
int limit) {
|
||||
unsigned char *rom_data = rom.mutable_data();
|
||||
@@ -797,6 +869,14 @@ int Tracker::WriteSpcData(Rom &rom, void *buf, int len, int addr, int spc,
|
||||
return addr + len + 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief High-level function to save all modified song data back to the ROM.
|
||||
* (Currently commented out, but this would orchestrate the entire save process.)
|
||||
* This function would be responsible for taking all the edited, in-memory
|
||||
* SongSpcBlocks, arranging them into a final binary layout, patching all the
|
||||
* relocated pointers, and writing the result back into the ROM file using
|
||||
* WriteSpcData.
|
||||
*/
|
||||
void Tracker::SaveSongs(Rom &rom) {
|
||||
// int i;
|
||||
// int j;
|
||||
@@ -1245,6 +1325,12 @@ void Tracker::SaveSongs(Rom &rom) {
|
||||
// free(ssblt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Opens an editor window for a specific track.
|
||||
* (Legacy UI-related function)
|
||||
* @param rom The ROM object.
|
||||
* @param i The index of the first command of the track to edit.
|
||||
*/
|
||||
void Tracker::EditTrack(Rom &rom, short i) {
|
||||
int j, k, l;
|
||||
SongRange *sr = song_range_;
|
||||
@@ -1295,6 +1381,12 @@ void Tracker::EditTrack(Rom &rom, short i) {
|
||||
// CRITICAL_SECTION cs_song;
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @brief Creates a new, empty song range (SongRange) and opens it for editing.
|
||||
* (Legacy UI-related function)
|
||||
* @param rom The ROM object.
|
||||
* @param bank The target bank for the new song.
|
||||
*/
|
||||
void Tracker::NewSR(Rom &rom, int bank) {
|
||||
SpcCommand *spc_command;
|
||||
SongRange *sr;
|
||||
|
||||
@@ -13,18 +13,21 @@ namespace zelda3 {
|
||||
* @namespace yaze::zelda3::music
|
||||
* @brief Contains classes and functions for handling music data in Zelda 3.
|
||||
*
|
||||
* Based off of the HyruleMagic tracker code.
|
||||
* Based off of the Hyrule Magic tracker code, this system is designed to parse
|
||||
* the game's complex, pointer-based music format into an editable in-memory
|
||||
* representation and then serialize it back into a binary format that the
|
||||
* SNES Audio Processing Unit (APU) can understand.
|
||||
*/
|
||||
namespace music {
|
||||
|
||||
// bank 19, 1A, 1B
|
||||
// iirc 1A is OW, 1B is dungeon
|
||||
// 19 is general spc stuff like samples, ects
|
||||
// Length of each SPC700 command opcode (0xE0-0xFF). Used for parsing.
|
||||
constexpr char op_len[32] = {1, 1, 2, 3, 0, 1, 2, 1, 2, 1, 1, 3, 0, 1, 2, 3,
|
||||
1, 3, 3, 0, 1, 3, 0, 3, 3, 3, 1, 2, 0, 0, 0, 0};
|
||||
|
||||
// Default ROM offsets for specific sound banks.
|
||||
static int sbank_ofs[] = {0xc8000, 0, 0xd8000, 0};
|
||||
|
||||
// Filter coefficients for BRR sample decoding.
|
||||
constexpr char fil1[4] = {0, 15, 61, 115};
|
||||
constexpr char fil2[4] = {0, 4, 5, 6};
|
||||
constexpr char fil3[4] = {0, 0, 15, 13};
|
||||
@@ -34,57 +37,83 @@ constexpr int kDungeonMusicBank = 0x0D8000;
|
||||
|
||||
using text_buf_ty = char[512];
|
||||
|
||||
/**
|
||||
* @struct SongSpcBlock
|
||||
* @brief Represents a block of binary data destined for the APU (SPC700) RAM.
|
||||
* This is the intermediate format used before writing data back to the ROM.
|
||||
*/
|
||||
struct SongSpcBlock {
|
||||
unsigned short start;
|
||||
unsigned short len;
|
||||
unsigned short relnum;
|
||||
unsigned short relsz;
|
||||
unsigned short *relocs;
|
||||
unsigned short bank;
|
||||
unsigned short addr;
|
||||
unsigned char *buf;
|
||||
int flag;
|
||||
unsigned short start; // The starting address of this block in the virtual SPC memory space.
|
||||
unsigned short len; // Length of the data buffer.
|
||||
unsigned short relnum; // Number of relocation entries.
|
||||
unsigned short relsz; // Allocated size of the relocation table.
|
||||
unsigned short *relocs; // Table of offsets within 'buf' that are pointers and need to be relocated.
|
||||
unsigned short bank; // The target sound bank.
|
||||
unsigned short addr; // The final, relocated address of this block.
|
||||
unsigned char *buf; // The raw binary data for this block.
|
||||
int flag; // Flags for managing the block's state.
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct SongRange
|
||||
* @brief A metadata structure to keep track of parsed sections of the song data.
|
||||
* Used to avoid re-parsing the same data from the ROM multiple times.
|
||||
*/
|
||||
struct SongRange {
|
||||
unsigned short start;
|
||||
unsigned short end;
|
||||
unsigned short start; // Start address of this range in the ROM.
|
||||
unsigned short end; // End address of this range in the ROM.
|
||||
|
||||
short first;
|
||||
short inst;
|
||||
short bank;
|
||||
short first; // Index of the first SpcCommand in this range.
|
||||
short inst; // Instance count, for tracking usage.
|
||||
short bank; // The ROM bank this range was loaded from.
|
||||
|
||||
unsigned char endtime;
|
||||
unsigned char endtime; // Default time/duration for this block.
|
||||
unsigned char filler;
|
||||
|
||||
int editor;
|
||||
int editor; // Window handle for an associated editor, if any.
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct SongPart
|
||||
* @brief Represents one of the 8 channels (tracks) in a song.
|
||||
*/
|
||||
struct SongPart {
|
||||
uint8_t flag;
|
||||
uint8_t inst;
|
||||
short tbl[8];
|
||||
unsigned short addr;
|
||||
uint8_t flag; // State flags for parsing and saving.
|
||||
uint8_t inst; // Instance count.
|
||||
short tbl[8]; // Pointers to the first SpcCommand for each of the 8 channels.
|
||||
unsigned short addr; // The address of this part's data in the ROM.
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct Song
|
||||
* @brief Represents a complete song, which is a collection of SongParts.
|
||||
*/
|
||||
struct Song {
|
||||
unsigned char flag;
|
||||
unsigned char inst;
|
||||
SongPart **tbl;
|
||||
short numparts;
|
||||
short lopst;
|
||||
unsigned short addr;
|
||||
bool in_use; // true
|
||||
unsigned char flag; // State flags.
|
||||
unsigned char inst; // Instance count.
|
||||
SongPart **tbl; // Table of pointers to the song's parts.
|
||||
short numparts; // Number of parts in the song.
|
||||
short lopst; // Loop start point.
|
||||
unsigned short addr; // Address of the song's main data table in the ROM.
|
||||
bool in_use; // Flag indicating if the song is currently loaded.
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct ZeldaWave
|
||||
* @brief Represents a decoded instrument sample (a waveform).
|
||||
*/
|
||||
struct ZeldaWave {
|
||||
int lopst;
|
||||
int end;
|
||||
short lflag;
|
||||
short copy;
|
||||
short *buf;
|
||||
int lopst; // Loop start point within the sample data.
|
||||
int end; // End of the sample data.
|
||||
short lflag; // Loop flag.
|
||||
short copy; // Index of another wave this is a copy of, to save memory.
|
||||
short *buf; // The buffer containing the decoded PCM sample data.
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct SampleEdit
|
||||
* @brief A state structure for a GUI sample editor.
|
||||
*/
|
||||
struct SampleEdit {
|
||||
unsigned short flag;
|
||||
unsigned short init;
|
||||
@@ -108,15 +137,23 @@ struct SampleEdit {
|
||||
ZeldaWave *zw;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct ZeldaInstrument
|
||||
* @brief Defines an instrument for a song, mapping to a sample and ADSR settings.
|
||||
*/
|
||||
struct ZeldaInstrument {
|
||||
unsigned char samp;
|
||||
unsigned char ad;
|
||||
unsigned char sr;
|
||||
unsigned char gain;
|
||||
unsigned char multhi;
|
||||
unsigned char multlo;
|
||||
unsigned char samp; // Index of the sample (ZeldaWave) to use.
|
||||
unsigned char ad; // Attack & Decay rates.
|
||||
unsigned char sr; // Sustain Rate.
|
||||
unsigned char gain; // Sustain Level & Gain.
|
||||
unsigned char multhi; // Pitch multiplier (high byte).
|
||||
unsigned char multlo; // Pitch multiplier (low byte).
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct ZeldaSfxInstrument
|
||||
* @brief Defines an instrument for a sound effect.
|
||||
*/
|
||||
struct ZeldaSfxInstrument {
|
||||
unsigned char voll;
|
||||
unsigned char volr;
|
||||
@@ -128,23 +165,29 @@ struct ZeldaSfxInstrument {
|
||||
unsigned char multhi;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct SpcCommand
|
||||
* @brief The core data structure representing a single command in a music track.
|
||||
* A song track is a doubly-linked list of these commands.
|
||||
*/
|
||||
struct SpcCommand {
|
||||
unsigned short addr;
|
||||
short next;
|
||||
short prev;
|
||||
unsigned char flag;
|
||||
unsigned char cmd;
|
||||
unsigned char p1;
|
||||
unsigned char p2;
|
||||
unsigned char p3;
|
||||
unsigned char b1;
|
||||
unsigned char b2;
|
||||
unsigned char tim2;
|
||||
unsigned short tim;
|
||||
unsigned short addr; // The ROM address this command was loaded from.
|
||||
short next; // Index of the next command in the list.
|
||||
short prev; // Index of the previous command in the list.
|
||||
unsigned char flag; // Bitfield for command properties (e.g., has duration).
|
||||
unsigned char cmd; // The actual command/opcode.
|
||||
unsigned char p1; // Parameter 1.
|
||||
unsigned char p2; // Parameter 2.
|
||||
unsigned char p3; // Parameter 3.
|
||||
unsigned char b1; // Note duration or first byte of a multi-byte duration.
|
||||
unsigned char b2; // Second byte of a multi-byte duration.
|
||||
unsigned char tim2; // Calculated time/duration component.
|
||||
unsigned short tim; // Calculated time/duration component.
|
||||
};
|
||||
|
||||
class Tracker {
|
||||
public:
|
||||
|
||||
SongSpcBlock *AllocSpcBlock(int len, int bank);
|
||||
|
||||
unsigned char *GetSpcAddr(Rom &rom, unsigned short addr, short bank);
|
||||
|
||||
Reference in New Issue
Block a user