45 printf(
"warning zero length block allocated");
55 sbl->
buf = (uint8_t*)malloc(len);
56 sbl->
relocs = (uint16_t*)malloc(32);
60 sbl->
flag = bank >> 3;
76 unsigned char* rom_ptr;
82 for (
int attempt = 0; attempt < 2; ++attempt) {
86 a = *(
unsigned short*)rom_ptr;
97 b = *(
unsigned short*)(rom_ptr + 2);
100 if (addr >= b && addr - b < a) {
102 return rom_ptr + addr - b;
130 spc_command[j].
next = j + 1, j++;
131 spc_command[j].
next = -1;
134 spc_command[j].
prev = j - 1, j--;
135 spc_command[j].
prev = -1;
170 if (spc_command[l].flag & 4) {
171 j = spc_command[l].
tim;
172 m = spc_command[l].
tim2;
179 if (spc_command[l].flag & 1)
180 n = spc_command[l].
b1;
182 l = spc_command[l].
next;
201 spc_command2 = spc_command + i;
202 if (spc_command2->
cmd == 0xef) {
203 k = *(
short*)&(spc_command2->
p1);
205 printf(
"Invalid music address\n");
209 if (spc_command2->
flag & 1) {
213 j += spc_command[k].
tim2 * spc_command2->
b1;
214 j += (spc_command2->
p3 - 1) * spc_command[k].tim2 *
ss_lasttime;
217 spc_command2->
b1 * (m + spc_command[k].
tim2 * spc_command2->
p3);
224 j += (spc_command2->
p3 - 1) *
ss_lasttime * spc_command[k].tim2,
225 m = spc_command[k].tim2;
227 m += spc_command[k].
tim2 * spc_command2->
p3;
230 if (spc_command2->
cmd < 0xe0)
232 if (spc_command2->
flag & 1) {
233 j += m * spc_command[i].
b1;
237 spc_command2->
tim = j;
238 spc_command2->
tim2 = m;
239 spc_command2->
flag |= 4;
244 i = spc_command2->
prev;
248 return spc_command[num].
tim + prevtime * spc_command[num].
tim2;
279 unsigned char* a =
nullptr;
290 printf(
"Address not found when loading track");
297 for (c = 0; c < e; c++) {
298 if (sr[c].bank == d) {
299 if (sr[c].start > addr) {
303 }
else if (sr[c].end > addr) {
304 for (f = sr[c].first; f != -1; f = spc_command[f].
next) {
305 if (spc_command[f].flag & 4)
306 m = spc_command[f].
tim, o = spc_command[f].
tim2;
307 if (spc_command[f].addr == addr) {
308 spc_command[f].
tim = m;
309 spc_command[f].
tim2 = o;
313 if (spc_command[f].flag & 1)
314 k = spc_command[f].
b1;
315 if (spc_command[f].cmd < 0xca) {
323 printf(
"Misaligned music pointer");
336 for (g = addr; g < f;) {
337 spc_command2 = spc_command + i;
338 if (spc_command2->
next == -1) {
342 spc_command2 = spc_command + i;
345 spc_command[l].
next = l + 1, l++;
346 spc_command[l].
next = -1;
349 spc_command[l].
prev = l - 1, l--;
350 spc_command[l].
prev = i;
351 spc_command2->
next = l;
353 spc_command2->
addr = g;
357 if (m >= t && b != 0xf9)
363 k = spc_command2->
b1 = b;
366 j = 3, spc_command2->
b2 = b, b = a[g++];
375 spc_command2->
cmd = b;
376 spc_command2->
flag = j;
380 spc_command2->
p1 = a[g++];
382 spc_command2->
p2 = a[g++];
384 spc_command2->
p3 = a[g++];
387 spc_command[spc_command2->
next].
prev = -1;
390 spc_command2 = spc_command + i;
391 *(
short*)(&(spc_command2->
p1)) = l;
393 spc_command[spc_command2->
next].
prev = i;
395 if (spc_command[l].flag & 4)
397 (spc_command[l].
tim + spc_command[l].
tim2 * k) * spc_command2->
p3;
399 i = spc_command2->
next;
406 i = spc_command2->
next;
409 spc_command[h].
tim = m;
410 spc_command[h].
tim2 = o;
411 spc_command[h].
flag |= 4;
413 if (f == g && m < t) {
414 l = spc_command[i].
prev;
418 if (spc_command[l].flag & 4)
419 spc_command[h].
tim = spc_command[l].
tim + m + spc_command[l].
tim2 * k,
420 spc_command[h].
flag |= 4;
438 spc_command[spc_command[i].
prev].
next = -1;
441 spc_command[i].
prev = -1;
762 if (spc_command[i].flag & 8)
763 return spc_command[i].
addr;
766 j = spc_command[i].
prev;
772 for (j = 0; j <
srnum; j++) {
773 if (sr[j].first == i) {
780 spc_command2 = spc_command + m;
781 if (spc_command2->
flag & 1)
782 k++, n = spc_command2->
b1;
783 if (spc_command2->
flag & 2)
785 if (spc_command2->
cmd >= 0xe0)
787 m = spc_command2->
next;
792 l = (songtime + 126) / 127;
796 if (n && !songtime % n) {
811 spc_command2 = spc_command + i;
813 spc_command2->
flag |= 8;
814 if (spc_command2->
flag & 1)
815 *(b++) = spc_command2->
b1;
816 if (spc_command2->
flag & 2)
817 *(b++) = spc_command2->
b2;
818 *(b++) = spc_command2->
cmd;
819 if (spc_command2->
cmd >= 0xe0) {
821 if (spc_command2->
cmd == 0xef) {
825 AddSpcReloc(sbl, b - sbl->
buf);
826 b[2] = spc_command2->
p3;
830 *(b++) = spc_command2->
p1;
832 *(b++) = spc_command2->
p2;
834 *(b++) = spc_command2->
p3;
837 i = spc_command2->
next;
842 l = (songtime + 126) / 127;
850 for (; songtime >= n; songtime -= n)
854 *(b++) = (uint8_t)songtime;
859 return spc_command[num].
addr;
863 printf(
"Address %04X not found", num);
891 auto report_space_error = [&]() ->
int {
892 printf(
"Not enough space for sound data");
897 if (((addr + len + 4) & 0x7fff) > 0x7ffb) {
898 if (addr + 5 > limit)
899 return report_space_error();
900 *(
int*)(rom_data + addr) = 0x00010140;
901 rom_data[addr + 4] = 0xff;
905 if (addr + len + 4 > limit)
906 return report_space_error();
908 *(
short*)(rom_data + addr) = len;
909 *(
short*)(rom_data + addr + 2) = spc;
911 memcpy(rom_data + addr + 4, buf, len);
913 return addr + len + 4;
1397 printf(
"Invalid address: %04X", i);
1403 if ((j = spc_command[i].prev) != -1)
1409 for (l = 0; l < k; l++)
1416 printf(
"Not found: %04X", i);
1452 spc_command->
prev = -1;
1453 spc_command->
next = -1;
1454 spc_command->
cmd = 128;
1455 spc_command->
flag = 0;
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
void EditTrack(Rom &rom, short i)
Opens an editor window for a specific track. (Legacy UI-related function)
unsigned char * GetSpcAddr(Rom &rom, unsigned short addr, short bank)
Gets a direct pointer to music data within the ROM. This function is critical for parsing....
short AllocSpcCommand()
Allocates a new SpcCommand from a pre-allocated pool. This uses a classic free-list implementation fo...
SongSpcBlock * AllocSpcBlock(int len, int bank)
Allocates a new SongSpcBlock for holding generated SPC data. These blocks are the building blocks for...
void SaveSongs(Rom &rom)
High-level function to save all modified song data back to the ROM. (Currently commented out,...
short LoadSpcCommand(Rom &rom, unsigned short addr, short bank, int t)
Loads a block of music data from a given ROM address. This is the main parser. It reads the raw byte ...
short GetBlockTime(Rom &rom, short num, short prevtime)
Calculates the total time (duration) of a block of SpcCommands. This is essential for synchronization...
int WriteSpcData(Rom &rom, void *buf, int len, int addr, int spc, int limit)
Writes a prepared data block into the ROM file. This is a utility for SaveSongs, formatting the data ...
short SaveSpcCommand(Rom &rom, short num, short songtime, short endtr)
Saves a block of edited SpcCommands back into a binary format. This is the serializer,...
void NewSR(Rom &rom, int bank)
Creates a new, empty song range (SongRange) and opens it for editing. (Legacy UI-related function)
SpcCommand * current_spc_command_
void LoadSongs(Rom &rom)
High-level function to load all song data from the ROM. (Currently commented out, but this would be t...
void AddSpcReloc(music::SongSpcBlock *sbl, short addr)
A metadata structure to keep track of parsed sections of the song data. Used to avoid re-parsing the ...
Represents a block of binary data destined for the APU (SPC700) RAM. This is the intermediate format ...
The core data structure representing a single command in a music track. A song track is a doubly-link...