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;
85 a = *(
unsigned short *)rom_ptr;
96 b = *(
unsigned short *)(rom_ptr + 2);
99 if (addr >= b && addr - b < a) {
102 return rom_ptr + addr - b;
126 while (k--) spc_command[j].
next = j + 1, j++;
127 spc_command[j].
next = -1;
129 while (k--) spc_command[j].
prev = j - 1, j--;
130 spc_command[j].
prev = -1;
160 if (l == -1)
return 0;
163 if (spc_command[l].flag & 4) {
164 j = spc_command[l].
tim;
165 m = spc_command[l].
tim2;
171 if (spc_command[l].flag & 1) n = spc_command[l].
b1;
173 l = spc_command[l].
next;
192 spc_command2 = spc_command + i;
193 if (spc_command2->
cmd == 0xef) {
194 k = *(
short *)&(spc_command2->
p1);
196 printf(
"Invalid music address\n");
200 if (spc_command2->
flag & 1) {
204 j += spc_command[k].
tim2 * spc_command2->
b1;
205 j += (spc_command2->
p3 - 1) * spc_command[k].tim2 *
ss_lasttime;
208 spc_command2->
b1 * (m + spc_command[k].
tim2 * spc_command2->
p3);
215 j += (spc_command2->
p3 - 1) *
ss_lasttime * spc_command[k].tim2,
216 m = spc_command[k].tim2;
218 m += spc_command[k].
tim2 * spc_command2->
p3;
221 if (spc_command2->
cmd < 0xe0) m++;
222 if (spc_command2->
flag & 1) {
223 j += m * spc_command[i].
b1;
227 spc_command2->
tim = j;
228 spc_command2->
tim2 = m;
229 spc_command2->
flag |= 4;
233 i = spc_command2->
prev;
237 return spc_command[num].
tim + prevtime * spc_command[num].
tim2;
268 unsigned char *a =
nullptr;
273 if (!addr)
return -1;
278 printf(
"Address not found when loading track");
285 for (c = 0; c < e; c++) {
286 if (sr[c].bank == d) {
287 if (sr[c].start > addr) {
288 if (sr[c].start < f) f = sr[c].
start;
290 }
else if (sr[c].end > addr) {
291 for (f = sr[c].first; f != -1; f = spc_command[f].
next) {
292 if (spc_command[f].flag & 4)
293 m = spc_command[f].
tim, o = spc_command[f].
tim2;
294 if (spc_command[f].addr == addr) {
295 spc_command[f].
tim = m;
296 spc_command[f].
tim2 = o;
300 if (spc_command[f].flag & 1) k = spc_command[f].
b1;
301 if (spc_command[f].cmd < 0xca) {
309 printf(
"Misaligned music pointer");
322 for (g = addr; g < f;) {
323 spc_command2 = spc_command + i;
324 if (spc_command2->
next == -1) {
328 spc_command2 = spc_command + i;
330 while (l < n) spc_command[l].
next = l + 1, l++;
331 spc_command[l].
next = -1;
333 while (l > n) spc_command[l].
prev = l - 1, l--;
334 spc_command[l].
prev = i;
335 spc_command2->
next = l;
337 spc_command2->
addr = g;
340 if (m >= t && b != 0xf9)
break;
345 k = spc_command2->
b1 = b;
347 if (b < 128) j = 3, spc_command2->
b2 = b, b = a[g++];
356 spc_command2->
cmd = b;
357 spc_command2->
flag = j;
360 if (
op_len[b]) spc_command2->
p1 = a[g++];
361 if (
op_len[b] > 1) spc_command2->
p2 = a[g++];
362 if (
op_len[b] > 2) spc_command2->
p3 = a[g++];
365 spc_command[spc_command2->
next].
prev = -1;
368 spc_command2 = spc_command + i;
369 *(
short *)(&(spc_command2->
p1)) = l;
371 spc_command[spc_command2->
next].
prev = i;
373 if (spc_command[l].flag & 4)
375 (spc_command[l].
tim + spc_command[l].
tim2 * k) * spc_command2->
p3;
377 i = spc_command2->
next;
383 i = spc_command2->
next;
386 spc_command[h].
tim = m;
387 spc_command[h].
tim2 = o;
388 spc_command[h].
flag |= 4;
390 if (f == g && m < t) {
391 l = spc_command[i].
prev;
395 if (spc_command[l].flag & 4)
396 spc_command[h].
tim = spc_command[l].
tim + m + spc_command[l].
tim2 * k,
397 spc_command[h].
flag |= 4;
415 spc_command[spc_command[i].
prev].
next = -1;
418 spc_command[i].
prev = -1;
730 if (i == -1)
return 0;
738 if (spc_command[i].flag & 8)
return spc_command[i].
addr;
741 j = spc_command[i].
prev;
746 for (j = 0; j <
srnum; j++) {
747 if (sr[j].first == i) {
753 spc_command2 = spc_command + m;
754 if (spc_command2->
flag & 1) k++, n = spc_command2->
b1;
755 if (spc_command2->
flag & 2) k++;
756 if (spc_command2->
cmd >= 0xe0) k +=
op_len[spc_command2->
cmd - 0xe0];
757 m = spc_command2->
next;
762 l = (songtime + 126) / 127;
763 if (songtime % l) l += 2;
765 if (n && !songtime % n) {
778 spc_command2 = spc_command + i;
780 spc_command2->
flag |= 8;
781 if (spc_command2->
flag & 1) *(b++) = spc_command2->
b1;
782 if (spc_command2->
flag & 2) *(b++) = spc_command2->
b2;
783 *(b++) = spc_command2->
cmd;
784 if (spc_command2->
cmd >= 0xe0) {
786 if (spc_command2->
cmd == 0xef) {
789 if (b) AddSpcReloc(sbl, b - sbl->
buf);
790 b[2] = spc_command2->
p3;
793 if (o) *(b++) = spc_command2->
p1;
794 if (o > 1) *(b++) = spc_command2->
p2;
795 if (o > 2) *(b++) = spc_command2->
p3;
798 i = spc_command2->
next;
803 l = (songtime + 126) / 127;
811 for (; songtime >= n; songtime -= n) *(b++) = 0xc9;
814 *(b++) = (uint8_t)songtime;
819 return spc_command[num].
addr;
823 printf(
"Address %04X not found", num);
848 if (!len)
return addr;
850 if (((addr + len + 4) & 0x7fff) > 0x7ffb) {
851 if (addr + 5 > limit)
goto error;
852 *(
int *)(rom_data + addr) = 0x00010140;
853 rom_data[addr + 4] = 0xff;
857 if (addr + len + 4 > limit) {
859 printf(
"Not enough space for sound data");
864 *(
short *)(rom_data + addr) = len;
865 *(
short *)(rom_data + addr + 2) = spc;
867 memcpy(rom_data + addr + 4, buf, len);
869 return addr + len + 4;
1347 if (i == -1)
return;
1350 printf(
"Invalid address: %04X", i);
1355 if ((j = spc_command[i].prev) != -1)
1361 for (l = 0; l < k; l++)
1368 printf(
"Not found: %04X", i);
1405 spc_command->
prev = -1;
1406 spc_command->
next = -1;
1407 spc_command->
cmd = 128;
1408 spc_command->
flag = 0;
The Rom class is used to load, save, and modify Rom data.
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)
Main namespace for the application.
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...