yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
tracker.cc
Go to the documentation of this file.
1
10#include "tracker.h"
11
12#include <cstdint>
13#include <cstdio>
14#include <vector>
15
16#include "rom/rom.h"
17#include "util/hyrule_magic.h"
18#include "util/macro.h"
19
20namespace yaze {
21namespace zelda3 {
22
23namespace {
24void AddSpcReloc(music::SongSpcBlock* sbl, short addr) {
25 sbl->relocs[sbl->relnum++] = addr;
26 if (sbl->relnum == sbl->relsz) {
27 sbl->relsz += 16;
28 sbl->relocs = (unsigned short*)realloc(sbl->relocs, sbl->relsz << 1);
29 }
30}
31} // namespace
32
33namespace music {
43 SongSpcBlock* sbl;
44 if (!len) {
45 printf("warning zero length block allocated");
46 }
47 if (ss_num == ss_size) {
48 ss_size += 512;
49 ssblt = (SongSpcBlock**)realloc(ssblt, ss_size << 2);
50 }
51 ssblt[ss_num] = sbl = (SongSpcBlock*)malloc(sizeof(SongSpcBlock));
52 ss_num++;
53 sbl->start = ss_next;
54 sbl->len = len;
55 sbl->buf = (uint8_t*)malloc(len);
56 sbl->relocs = (uint16_t*)malloc(32);
57 sbl->relsz = 16;
58 sbl->relnum = 0;
59 sbl->bank = bank & 7;
60 sbl->flag = bank >> 3;
61 ss_next += len;
62 return sbl;
63}
64
75unsigned char* Tracker::GetSpcAddr(Rom& rom, unsigned short addr, short bank) {
76 unsigned char* rom_ptr;
77 unsigned short a;
78 unsigned short b;
79 spcbank = bank + 1;
80
81 // Try the requested bank first, then fall back to bank 0
82 for (int attempt = 0; attempt < 2; ++attempt) {
83 rom_ptr = rom.mutable_data() + sbank_ofs[spcbank];
84
85 for (;;) {
86 a = *(unsigned short*)rom_ptr;
87
88 if (!a) {
89 if (spcbank) {
90 spcbank = 0;
91 break; // retry with bank 0
92 } else {
93 return nullptr;
94 }
95 }
96
97 b = *(unsigned short*)(rom_ptr + 2);
98 rom_ptr += 4;
99
100 if (addr >= b && addr - b < a) {
101 spclen = a;
102 return rom_ptr + addr - b;
103 }
104
105 rom_ptr += a;
106 }
107 }
108
109 return nullptr;
110}
111
119 int i = m_free;
120 int j;
121 int k;
122 SpcCommand* spc_command;
123 if (i == -1) {
124 j = m_size;
125 m_size += 1024;
126 spc_command = current_spc_command_ =
127 (SpcCommand*)realloc(current_spc_command_, m_size * sizeof(SpcCommand));
128 k = 1023;
129 while (k--)
130 spc_command[j].next = j + 1, j++;
131 spc_command[j].next = -1;
132 k = 1023;
133 while (k--)
134 spc_command[j].prev = j - 1, j--;
135 spc_command[j].prev = -1;
136 i = j;
137 } else
138 spc_command = current_spc_command_;
139 m_free = spc_command[m_free].next;
140 if (m_free != -1)
141 spc_command[m_free].prev = -1;
142 return i;
143}
144
154short Tracker::GetBlockTime(Rom& rom, short num, short prevtime) {
155 SpcCommand* spc_command = current_spc_command_;
156 SpcCommand* spc_command2;
157
158 int i = -1;
159 int j = 0;
160 int k = 0;
161 int l;
162 int m = 0;
163 int n = prevtime;
164 l = num;
165
166 if (l == -1)
167 return 0;
168
169 for (;;) {
170 if (spc_command[l].flag & 4) {
171 j = spc_command[l].tim;
172 m = spc_command[l].tim2;
173 k = 1;
174 }
175
176 if (!k)
177 i = l;
178
179 if (spc_command[l].flag & 1)
180 n = spc_command[l].b1;
181
182 l = spc_command[l].next;
183
184 if (l == -1) {
185 if (!k) {
186 m = 0;
187 j = 0;
188 }
189
190 break;
191 }
192 }
193
194 if (i != -1)
195 for (;;) {
196 if (i == -1) {
197 printf("Error");
198 m_modf = 1;
199 return 0;
200 }
201 spc_command2 = spc_command + i;
202 if (spc_command2->cmd == 0xef) {
203 k = *(short*)&(spc_command2->p1);
204 if (k >= m_size) {
205 printf("Invalid music address\n");
206 m_modf = 1;
207 return 0;
208 }
209 if (spc_command2->flag & 1) {
210 j += GetBlockTime(rom, k, 0) * spc_command2->p3;
211 if (ss_lasttime) {
212 j += ss_lasttime * m;
213 j += spc_command[k].tim2 * spc_command2->b1;
214 j += (spc_command2->p3 - 1) * spc_command[k].tim2 * ss_lasttime;
215 } else {
216 j +=
217 spc_command2->b1 * (m + spc_command[k].tim2 * spc_command2->p3);
218 }
219 m = 0;
220 } else {
221 j += GetBlockTime(rom, k, 0) * spc_command2->p3;
222 j += ss_lasttime * m;
223 if (ss_lasttime)
224 j += (spc_command2->p3 - 1) * ss_lasttime * spc_command[k].tim2,
225 m = spc_command[k].tim2;
226 else
227 m += spc_command[k].tim2 * spc_command2->p3;
228 }
229 } else {
230 if (spc_command2->cmd < 0xe0)
231 m++;
232 if (spc_command2->flag & 1) {
233 j += m * spc_command[i].b1;
234 m = 0;
235 }
236 }
237 spc_command2->tim = j;
238 spc_command2->tim2 = m;
239 spc_command2->flag |= 4;
240
241 if (i == num)
242 break;
243
244 i = spc_command2->prev;
245 }
246
247 ss_lasttime = n;
248 return spc_command[num].tim + prevtime * spc_command[num].tim2;
249}
250
261short Tracker::LoadSpcCommand(Rom& rom, unsigned short addr, short bank,
262 int t) {
263 int b = 0;
264 int c = 0;
265 int d = 0;
266 int e = 0;
267 int f = 0;
268 int g = 0;
269 int h = 0;
270 int i = 0;
271 int l = 0;
272 int m = 0;
273 int n = 0;
274 int o = 0;
275
276 unsigned char j = 0;
277 unsigned char k = 0;
278
279 unsigned char* a = nullptr;
280
281 SongRange* sr;
282 SpcCommand* spc_command = current_spc_command_;
283 SpcCommand* spc_command2;
284 if (!addr)
285 return -1;
286
287 a = GetSpcAddr(rom, addr, bank);
288 d = spcbank;
289 if (!a) {
290 printf("Address not found when loading track");
291 return -1;
292 }
293 sr = song_range_;
294 e = srnum;
295 f = 0x10000;
296
297 for (c = 0; c < e; c++) {
298 if (sr[c].bank == d) {
299 if (sr[c].start > addr) {
300 if (sr[c].start < f)
301 f = sr[c].start;
302 n = c;
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;
310 lastsr = c;
311 return f;
312 }
313 if (spc_command[f].flag & 1)
314 k = spc_command[f].b1;
315 if (spc_command[f].cmd < 0xca) {
316 if (k) {
317 m -= k;
318 } else {
319 o--;
320 }
321 }
322 }
323 printf("Misaligned music pointer");
324 return -1;
325 }
326 }
327 }
328
329 c = n;
330 i = h = m_free;
331 a -= addr;
332 m = 0;
333 k = 0;
334 o = 0;
335
336 for (g = addr; g < f;) {
337 spc_command2 = spc_command + i;
338 if (spc_command2->next == -1) {
339 l = m_size;
340 spc_command = current_spc_command_ = (SpcCommand*)realloc(
341 spc_command, sizeof(SpcCommand) * (m_size += 1024));
342 spc_command2 = spc_command + i;
343 n = l + 1023;
344 while (l < n)
345 spc_command[l].next = l + 1, l++;
346 spc_command[l].next = -1;
347 n -= 1023;
348 while (l > n)
349 spc_command[l].prev = l - 1, l--;
350 spc_command[l].prev = i;
351 spc_command2->next = l;
352 }
353 spc_command2->addr = g;
354 b = a[g];
355 if (!b)
356 break;
357 if (m >= t && b != 0xf9)
358 break;
359 g++;
360 j = 0;
361 if (b < 128) {
362 j = 1;
363 k = spc_command2->b1 = b;
364 b = a[g++];
365 if (b < 128)
366 j = 3, spc_command2->b2 = b, b = a[g++];
367 }
368 if (b < 0xe0) {
369 if (k) {
370 m += k;
371 } else {
372 o++;
373 }
374 }
375 spc_command2->cmd = b;
376 spc_command2->flag = j;
377 if (b >= 0xe0) {
378 b -= 0xe0;
379 if (op_len[b])
380 spc_command2->p1 = a[g++];
381 if (op_len[b] > 1)
382 spc_command2->p2 = a[g++];
383 if (op_len[b] > 2)
384 spc_command2->p3 = a[g++];
385 if (b == 15) {
386 m_free = spc_command2->next;
387 spc_command[spc_command2->next].prev = -1;
388 l = LoadSpcCommand(rom, *(short*)(&(spc_command2->p1)), bank, t - m);
389 spc_command = current_spc_command_;
390 spc_command2 = spc_command + i;
391 *(short*)(&(spc_command2->p1)) = l;
392 spc_command2->next = m_free;
393 spc_command[spc_command2->next].prev = i;
394 GetBlockTime(rom, l, 0);
395 if (spc_command[l].flag & 4)
396 m +=
397 (spc_command[l].tim + spc_command[l].tim2 * k) * spc_command2->p3;
398 else {
399 i = spc_command2->next;
400 break;
401 }
402 if (song_range_[lastsr].endtime)
404 }
405 }
406 i = spc_command2->next;
407 }
408
409 spc_command[h].tim = m;
410 spc_command[h].tim2 = o;
411 spc_command[h].flag |= 4;
412
413 if (f == g && m < t) {
414 l = spc_command[i].prev;
415 lastsr = c;
416 spc_command[sr[lastsr].first].prev = l;
417 l = spc_command[l].next = sr[lastsr].first;
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;
421 sr[lastsr].first = h;
422 sr[lastsr].start = addr;
423 sr[lastsr].inst++;
424 } else {
425 if (srsize == srnum)
427 (SongRange*)realloc(song_range_, (srsize += 16) * sizeof(SongRange));
428
429 lastsr = srnum;
430 sr = song_range_ + (srnum++);
431 sr->start = addr;
432 sr->end = g;
433 sr->first = h;
434 sr->endtime = k;
435 sr->inst = 1;
436 sr->editor = 0;
437 sr->bank = d;
438 spc_command[spc_command[i].prev].next = -1;
439 }
440
441 spc_command[i].prev = -1;
442 m_free = i;
443
444 return h;
445}
446
455 // unsigned char *b;
456 // unsigned char *c;
457 // unsigned char *d;
458 // short *e;
459
460 // Song song;
461 // Song song2;
462 // SongPart *sp;
463 // SpcCommand *spc_command;
464 // ZeldaWave *zelda_wave;
465
466 // int i;
467 // int j;
468 // int k;
469 // int l = 0;
470 // int m;
471 // int n;
472 // int o;
473 // int p;
474 // int q;
475 // int r;
476 // int t;
477 // int u;
478 // int range;
479 // int filter;
480
481 // spc_command = current_spc_command_ =
482 // (SpcCommand *)malloc(1024 * sizeof(SpcCommand));
483 // m_free = 0;
484 // m_size = 1024;
485 // srnum = 0;
486 // srsize = 0;
487 // song_range_ = 0;
488 // sp_mark = 0;
489 // b = rom.mutable_data();
490
491 // sbank_ofs[1] = (b[0x91c] << 15) + ((b[0x918] & 127) << 8) + b[0x914];
492 // sbank_ofs[3] = (b[0x93a] << 15) + ((b[0x936] & 127) << 8) + b[0x932];
493
494 // for (i = 0; i < 1024; i++) {
495 // spc_command[i].next = i + 1;
496 // spc_command[i].prev = i - 1;
497 // }
498
499 // // Init blank songs.
500 // for (i = 0; i < 128; i++) {
501 // Song new_song;
502 // songs.emplace_back(new_song);
503 // }
504
505 // spc_command[1023].next = -1;
506 // for (i = 0; i < 3; i++) {
507 // // Extract the song banks.
508 // b = GetSpcAddr(rom, 0xd000, i);
509 // for (j = 0;; j++) {
510 // if ((r = ((unsigned short *)b)[j]) >= 0xd000) {
511 // r = (r - 0xd000) >> 1;
512 // break;
513 // }
514 // }
515
516 // numsong[i] = r;
517 // for (j = 0; j < r; j++) {
518 // k = ((unsigned short *)b)[j];
519 // if (!k)
520 // songs[l].in_use = false;
521 // else {
522 // c = GetSpcAddr(rom, k, i);
523
524 // // Init the bank index we are current loading.
525 // if (!spcbank)
526 // m = 0;
527 // else
528 // m = l - j;
529
530 // for (; m < l; m++)
531 // if (songs[m].in_use && songs[m].addr == k) {
532 // (songs[l] = songs[m]).inst++;
533
534 // break;
535 // }
536
537 // if (m == l) {
538 // // create a new song (Song *)malloc(sizeof(Song));
539 // songs[l] = song;
540 // song.inst = 1;
541 // song.addr = k;
542 // song.flag = !spcbank;
543
544 // for (m = 0;; m++)
545 // if ((n = ((unsigned short *)c)[m]) < 256) break;
546
547 // if (n > 0) {
548 // song.flag |= 2;
549 // song.lopst = (((unsigned short *)c)[m + 1] - k) >> 1;
550 // }
551
552 // song.numparts = m;
553 // song.tbl = (SongPart **)malloc(4 * m);
554
555 // for (m = 0; m < song.numparts; m++) {
556 // k = ((unsigned short *)c)[m];
557 // d = GetSpcAddr(rom, k, i);
558 // if (!spcbank)
559 // n = 0;
560 // else
561 // n = l - j;
562
563 // for (; n < l; n++) {
564 // song2 = songs[n];
565 // if (song2.in_use)
566 // for (o = 0; o < song2.numparts; o++)
567 // if (song2.tbl[o]->addr == k) {
568 // (song.tbl[m] = song2.tbl[o])->inst++;
569 // goto foundpart;
570 // }
571 // }
572
573 // for (o = 0; o < m; o++)
574 // if (song.tbl[o]->addr == k) {
575 // (song.tbl[m] = song.tbl[o])->inst++;
576 // goto foundpart;
577 // }
578
579 // sp = song.tbl[m] = (SongPart *)malloc(sizeof(SongPart));
580 // sp->flag = !spcbank;
581 // sp->inst = 1;
582 // sp->addr = k;
583 // p = 50000;
584 // for (o = 0; o < 8; o++) {
585 // q = sp->tbl[o] =
586 // LoadSpcCommand(rom, ((unsigned short *)d)[o], i, p);
587 // spc_command = current_spc_command_ + q;
588 // if ((spc_command->flag & 4) && spc_command->tim < p)
589 // p = spc_command->tim;
590 // }
591 // foundpart:;
592 // }
593 // }
594 // }
595 // l++;
596 // }
597 // }
598
599 // b = GetSpcAddr(rom, 0x800, 0);
600 // snddat1 = (char *)malloc(spclen);
601 // sndlen1 = spclen;
602 // memcpy(snddat1, b, spclen);
603
604 // b = GetSpcAddr(rom, 0x17c0, 0);
605 // snddat2 = (char *)malloc(spclen);
606 // sndlen2 = spclen;
607 // memcpy(snddat2, b, spclen);
608
609 // b = GetSpcAddr(rom, 0x3d00, 0);
610 // insts = (ZeldaInstrument *)malloc(spclen);
611 // memcpy(insts, b, spclen);
612 // numinst = spclen / 6;
613
614 // b = GetSpcAddr(rom, 0x3e00, 0);
615 // m_ofs = b - rom.mutable_data() + spclen;
616 // sndinsts = (ZeldaSfxInstrument *)malloc(spclen);
617 // memcpy(sndinsts, b, spclen);
618 // numsndinst = spclen / 9;
619
620 // b = GetSpcAddr(rom, 0x3c00, 0);
621 // zelda_wave = waves = (ZeldaWave *)malloc(sizeof(ZeldaWave) * (spclen >>
622 // 2)); p = spclen >> 1;
623
624 // for (i = 0; i < p; i += 2) {
625 // j = ((unsigned short *)b)[i];
626
627 // if (j == 65535) break;
628
629 // for (k = 0; k < i; k += 2) {
630 // if (((unsigned short *)b)[k] == j) {
631 // zelda_wave->copy = (short)(k >> 1);
632 // goto foundwave;
633 // }
634 // }
635
636 // zelda_wave->copy = -1;
637
638 // foundwave:
639
640 // d = GetSpcAddr(rom, j, 0);
641 // e = (short *)malloc(2048);
642
643 // k = 0;
644 // l = 1024;
645 // u = t = 0;
646
647 // for (;;) {
648 // m = *(d++);
649
650 // range = (m >> 4) + 8;
651 // filter = (m & 12) >> 2;
652
653 // for (n = 0; n < 8; n++) {
654 // o = (*d) >> 4;
655
656 // if (o > 7) o -= 16;
657
658 // o <<= range;
659
660 // if (filter)
661 // o += (t * fil1[filter] >> fil2[filter]) -
662 // ((u & -256) * fil3[filter] >> 4);
663
664 // if (o > 0x7fffff) o = 0x7fffff;
665
666 // if (o < -0x800000) o = -0x800000;
667
668 // u = o;
669
670 // // \code if(t>0x7fffff) t=0x7fffff;
671 // // \code if(t < -0x800000) t=-0x800000;
672
673 // e[k++] = o >> 8;
674
675 // o = *(d++) & 15;
676
677 // if (o > 7) o -= 16;
678
679 // o <<= range;
680
681 // if (filter)
682 // o += (u * fil1[filter] >> fil2[filter]) -
683 // ((t & -256) * fil3[filter] >> 4);
684
685 // if (o > 0x7fffff) o = 0x7fffff;
686
687 // if (o < -0x800000) o = -0x800000;
688
689 // t = o;
690 // // \code if(u>0x7fffff) u=0x7fffff;
691 // // \code if(u < -0x800000) u= -0x800000;
692 // e[k++] = o >> 8;
693 // }
694
695 // if (m & 1) {
696 // zelda_wave->lflag = (m & 2) >> 1;
697 // break;
698 // }
699 // if (k == l) {
700 // l += 1024;
701 // e = (short *)realloc(e, l << 1);
702 // }
703 // }
704
705 // e = zelda_wave->buf = (short *)realloc(e, (k + 1) << 1);
706
707 // zelda_wave->lopst = (((unsigned short *)b)[i + 1] - j) * 16 / 9;
708
709 // if (zelda_wave->lflag)
710 // e[k] = e[zelda_wave->lopst];
711 // else
712 // e[k] = 0;
713
714 // zelda_wave->end = k;
715
716 // zelda_wave++;
717 // }
718
719 // numwave = i >> 1;
720 // m_loaded = 1;
721 // w_modf = 0;
722}
723
734short Tracker::SaveSpcCommand(Rom& rom, short num, short songtime,
735 short endtr) {
736 SpcCommand* spc_command = current_spc_command_;
737 SpcCommand* spc_command2;
739 SongSpcBlock* sbl;
740
741 text_buf_ty buf;
742
743 unsigned char* b;
744 int i = num;
745 int j = 0;
746 int k = 0;
747 int l = 0;
748 int m = 0;
749 int n = 0;
750 int o = 0;
751 int p = 0;
752
753 if (i == -1)
754 return 0;
755
756 if (i >= m_size) {
757 printf("Error.\n");
758 m_modf = 1;
759 return 0;
760 }
761
762 if (spc_command[i].flag & 8)
763 return spc_command[i].addr;
764
765 for (;;) {
766 j = spc_command[i].prev;
767 if (j == -1)
768 break;
769 i = j;
770 }
771
772 for (j = 0; j < srnum; j++) {
773 if (sr[j].first == i) {
774 l = GetBlockTime(rom, i, 0);
775 m = i;
776 for (;;) {
777 if (m == -1)
778 break;
779 k++;
780 spc_command2 = spc_command + m;
781 if (spc_command2->flag & 1)
782 k++, n = spc_command2->b1;
783 if (spc_command2->flag & 2)
784 k++;
785 if (spc_command2->cmd >= 0xe0)
786 k += op_len[spc_command2->cmd - 0xe0];
787 m = spc_command2->next;
788 }
789 songtime -= l;
790
791 if (songtime > 0) {
792 l = (songtime + 126) / 127;
793 if (songtime % l)
794 l += 2;
795 l++;
796 if (n && !songtime % n) {
797 p = songtime / n;
798 if (p < l)
799 l = p;
800 } else
801 p = -1;
802 k += l;
803 }
804 k++;
805 sbl = AllocSpcBlock(k, sr[j].bank | ((!endtr) << 3) | 16);
806 b = sbl->buf;
807
808 for (;;) {
809 if (i == -1)
810 break;
811 spc_command2 = spc_command + i;
812 spc_command2->addr = b - sbl->buf + sbl->start;
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) {
820 o = op_len[spc_command2->cmd - 0xe0];
821 if (spc_command2->cmd == 0xef) {
822 *(short*)b =
823 SaveSpcCommand(rom, *(short*)&(spc_command2->p1), 0, 1);
824 if (b)
825 AddSpcReloc(sbl, b - sbl->buf);
826 b[2] = spc_command2->p3;
827 b += 3;
828 } else {
829 if (o)
830 *(b++) = spc_command2->p1;
831 if (o > 1)
832 *(b++) = spc_command2->p2;
833 if (o > 2)
834 *(b++) = spc_command2->p3;
835 }
836 }
837 i = spc_command2->next;
838 }
839
840 if (songtime > 0) {
841 if (l != p) {
842 l = (songtime + 126) / 127;
843 if (songtime % l)
844 n = 127;
845 else
846 n = songtime / l;
847 *(b++) = n;
848 }
849
850 for (; songtime >= n; songtime -= n)
851 *(b++) = 0xc9;
852
853 if (songtime) {
854 *(b++) = (uint8_t)songtime;
855 *(b++) = 0xc9;
856 }
857 }
858 *(b++) = 0;
859 return spc_command[num].addr;
860 }
861 }
862
863 printf("Address %04X not found", num);
864
865 printf("Error");
866
867 m_modf = 1;
868
869 return 0;
870}
871
884int Tracker::WriteSpcData(Rom& rom, void* buf, int len, int addr, int spc,
885 int limit) {
886 unsigned char* rom_data = rom.mutable_data();
887
888 if (!len)
889 return addr;
890
891 auto report_space_error = [&]() -> int {
892 printf("Not enough space for sound data");
893 m_modf = 1;
894 return 0xc8000;
895 };
896
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;
902 addr += 5;
903 }
904
905 if (addr + len + 4 > limit)
906 return report_space_error();
907
908 *(short*)(rom_data + addr) = len;
909 *(short*)(rom_data + addr + 2) = spc;
910
911 memcpy(rom_data + addr + 4, buf, len);
912
913 return addr + len + 4;
914}
915
925 // int i;
926 // int j;
927 // int k;
928 // int l = 0;
929 // int m;
930 // int n;
931 // int o;
932 // int p;
933 // int q;
934 // int r;
935 // int t;
936 // int u;
937 // int v;
938 // int w;
939 // int a;
940 // int e;
941 // int f;
942 // int g;
943 // unsigned short bank_next[4];
944 // unsigned short bank_lwr[4];
945 // short *c;
946 // short *d;
947 // unsigned char *rom_data;
948 // unsigned char *b;
949
950 // Song song;
951
952 // SpcCommand *spc_command;
953
954 // SongPart *sp;
955
956 // SongSpcBlock *stbl;
957 // SongSpcBlock *sptbl;
958 // SongSpcBlock *trtbl;
959 // SongSpcBlock *pstbl;
960
961 // ZeldaWave *zelda_wave;
962 // ZeldaWave *zelda_wave2;
963
964 // ZeldaInstrument *zi;
965
966 // SampleEdit *sed = nullptr;
967
968 // short wtbl[128];
969 // short x[16];
970 // short y[18];
971 // unsigned char z[64];
972
973 // ss_num = 0;
974 // ss_size = 512;
975 // ss_next = 0;
976
977 // // if the music has not been modified, return.
978 // if (!(m_modf)) return;
979
980 // ssblt = (SongSpcBlock **)malloc(512 * sizeof(SongSpcBlock));
981
982 // // set it so the music has not been modified. (reset the status)
983 // m_modf = 0;
984 // rom_data = rom.mutable_data();
985
986 // // SetCursor(wait_cursor);
987
988 // for (i = 0; i < 3; i++) {
989 // k = numsong[i];
990
991 // for (j = 0; j < k; j++) {
992 // song = songs[l++];
993
994 // if (!song.in_use) continue;
995
996 // song.flag &= -5;
997
998 // for (m = 0; m < song.numparts; m++) {
999 // sp = song.tbl[m];
1000 // sp->flag &= -3;
1001 // }
1002 // }
1003 // }
1004
1005 // j = m_size;
1006 // spc_command = current_spc_command_;
1007
1008 // for (i = 0; i < j; i++) {
1009 // spc_command->flag &= -13;
1010 // spc_command++;
1011 // }
1012
1013 // l = 0;
1014
1015 // for (i = 0; i < 3; i++) {
1016 // k = numsong[i];
1017 // stbl = AllocSpcBlock(k << 1, i + 1);
1018
1019 // for (j = 0; j < k; j++) {
1020 // song = songs[l++];
1021
1022 // if (!song.in_use) {
1023 // ((short *)(stbl->buf))[j] = 0;
1024
1025 // continue;
1026 // }
1027
1028 // if (song.flag & 4) goto alreadysaved;
1029
1030 // sptbl = AllocSpcBlock(((song.numparts + 1) << 1) + (song.flag & 2),
1031 // (song.flag & 1) ? 0 : (i + 1));
1032
1033 // for (m = 0; m < song.numparts; m++) {
1034 // sp = song.tbl[m];
1035
1036 // if (sp->flag & 2) goto spsaved;
1037
1038 // trtbl = AllocSpcBlock(16, (sp->flag & 1) ? 0 : (i + 1));
1039
1040 // p = 0;
1041
1042 // for (n = 0; n < 8; n++) {
1043 // o = GetBlockTime(rom, sp->tbl[n], 0);
1044
1045 // if (o > p) p = o;
1046 // }
1047
1048 // q = 1;
1049
1050 // for (n = 0; n < 8; n++) {
1051 // stle16b_i(trtbl->buf, n, SaveSpcCommand(rom, sp->tbl[n], p, q));
1052
1053 // if (ldle16b_i(trtbl->buf, n)) AddSpcReloc(trtbl, n << 1), q = 0;
1054 // }
1055
1056 // sp->addr = trtbl->start;
1057 // sp->flag |= 2;
1058 // spsaved:
1059 // ((short *)(sptbl->buf))[m] = sp->addr;
1060
1061 // AddSpcReloc(sptbl, m << 1);
1062 // }
1063
1064 // if (song.flag & 2) {
1065 // ((short *)(sptbl->buf))[m++] = 255;
1066 // ((short *)(sptbl->buf))[m] = sptbl->start + (song.lopst << 1);
1067
1068 // AddSpcReloc(sptbl, m << 1);
1069 // } else
1070 // ((short *)(sptbl->buf))[m++] = 0;
1071
1072 // song.addr = sptbl->start;
1073 // song.flag |= 4;
1074 // alreadysaved:
1075 // ((short *)(stbl->buf))[j] = song.addr;
1076
1077 // AddSpcReloc(stbl, j << 1);
1078 // }
1079 // }
1080
1081 // if (w_modf) {
1082 // b = (uint8_t *)malloc(0xc000);
1083 // j = 0;
1084
1085 // zelda_wave = waves;
1086
1087 // // if (mbanks[3])
1088 // // sed = (SampleEdit *)GetWindowLongPtr(mbanks[3], GWLP_USERDATA);
1089 // // else
1090 // // sed = 0;
1091
1092 // for (i = 0; i < numwave; i++, zelda_wave++) {
1093 // if (zelda_wave->copy != -1) continue;
1094
1095 // wtbl[i << 1] = j + 0x4000;
1096
1097 // if (zelda_wave->lflag) {
1098 // l = zelda_wave->end - zelda_wave->lopst;
1099
1100 // if (l & 15) {
1101 // k = (l << 15) / ((l + 15) & -16);
1102 // p = (zelda_wave->end << 15) / k;
1103 // c = (short *)malloc(p << 1);
1104 // n = 0;
1105 // d = zelda_wave->buf;
1106
1107 // for (m = 0;;) {
1108 // c[n++] = (d[m >> 15] * ((m & 32767) ^ 32767) +
1109 // d[(m >> 15) + 1] * (m & 32767)) /
1110 // 32767;
1111
1112 // m += k;
1113
1114 // if (n >= p) break;
1115 // }
1116
1117 // zelda_wave->lopst = (zelda_wave->lopst << 15) / k;
1118 // zelda_wave->end = p;
1119 // zelda_wave->buf =
1120 // (short *)realloc(zelda_wave->buf, (zelda_wave->end + 1) << 1);
1121 // memcpy(zelda_wave->buf, c, zelda_wave->end << 1);
1122 // free(c);
1123 // zelda_wave->buf[zelda_wave->end] =
1124 // zelda_wave->buf[zelda_wave->lopst]; zelda_wave2 = waves;
1125
1126 // for (m = 0; m < numwave; m++, zelda_wave2++)
1127 // if (zelda_wave2->copy == i)
1128 // zelda_wave2->lopst = zelda_wave2->lopst << 15 / k;
1129
1130 // zi = insts;
1131
1132 // for (m = 0; m < numinst; m++) {
1133 // n = zi->samp;
1134
1135 // if (n >= numwave) continue;
1136
1137 // if (n == i || waves[n].copy == i) {
1138 // o = (zi->multhi << 8) + zi->multlo;
1139 // o = (o << 15) / k;
1140 // zi->multlo = o;
1141 // zi->multhi = o >> 8;
1142
1143 // // if (sed && sed->editinst == m) {
1144 // // sed->init = 1;
1145 // // // SetDlgItemInt(sed->dlg, 3014, o, 0);
1146 // // sed->init = 0;
1147 // // }
1148 // }
1149
1150 // zi++;
1151 // }
1152
1153 // // Modifywaves(rom, i);
1154 // }
1155 // }
1156
1157 // k = (-zelda_wave->end) & 15;
1158 // d = zelda_wave->buf;
1159 // n = 0;
1160 // wtbl[(i << 1) + 1] = ((zelda_wave->lopst + k) >> 4) * 9 + wtbl[i << 1];
1161 // y[0] = y[1] = 0;
1162 // u = 4;
1163
1164 // for (;;) {
1165 // for (o = 0; o < 16; o++) {
1166 // if (k)
1167 // k--, x[o] = 0;
1168 // else
1169 // x[o] = d[n++];
1170 // }
1171 // p = 0x7fffffff;
1172 // a = 0;
1173
1174 // for (t = 0; t < 4; t++) {
1175 // r = 0;
1176 // for (o = 0; o < 16; o++) {
1177 // l = x[o];
1178 // y[o + 2] = l;
1179 // l += (y[o] * fil3[t] >> 4) - (y[o + 1] * fil1[t] >> fil2[t]);
1180 // if (l > r)
1181 // r = l;
1182 // else if (-l > r)
1183 // r = -l;
1184 // }
1185 // r <<= 1;
1186 // if (t)
1187 // m = 14;
1188 // else
1189 // m = 15;
1190 // for (q = 0; q < 12; q++, m += m)
1191 // if (m >= r) break;
1192 // tryagain:
1193 // if (q && (q < 12 || m == r))
1194 // v = (1 << (q - 1)) - 1;
1195 // else
1196 // v = 0;
1197 // m = 0;
1198 // for (o = 0; o < 16; o++) {
1199 // l = (y[o + 1] * fil1[t] >> fil2[t]) - (y[o] * fil3[t] >> 4);
1200 // w = x[o];
1201 // r = (w - l + v) >> q;
1202 // if ((r + 8) & 0xfff0) {
1203 // q++;
1204 // a -= o;
1205 // goto tryagain;
1206 // }
1207 // z[a++] = r;
1208 // l = (r << q) + l;
1209 // y[o + 2] = l;
1210 // l -= w;
1211 // m += l * l;
1212 // }
1213 // if (u == 4) {
1214 // u = 0, e = q, f = y[16], g = y[17];
1215 // break;
1216 // }
1217 // if (m < p) p = m, u = t, e = q, f = y[16], g = y[17];
1218 // }
1219 // m = (e << 4) | (u << 2);
1220 // if (n == zelda_wave->end) m |= 1;
1221 // if (zelda_wave->lflag) m |= 2;
1222 // b[j++] = m;
1223 // m = 0;
1224 // a = u << 4;
1225 // for (o = 0; o < 16; o++) {
1226 // m |= z[a++] & 15;
1227 // if (o & 1)
1228 // b[j++] = m, m = 0;
1229 // else
1230 // m <<= 4;
1231 // }
1232 // if (n == zelda_wave->end) break;
1233 // y[0] = f;
1234 // y[1] = g;
1235 // }
1236 // }
1237
1238 // // if (sed) {
1239 // // SetDlgItemInt(sed->dlg, ID_Samp_SampleLengthEdit,
1240 // sed->zelda_wave->end,
1241 // // 0); SetDlgItemInt(sed->dlg, ID_Samp_LoopPointEdit,
1242 // // sed->zelda_wave->lopst, 0);
1243
1244 // // InvalidateRect(GetDlgItem(sed->dlg, ID_Samp_Display), 0, 1);
1245 // // }
1246
1247 // zelda_wave = waves;
1248
1249 // for (i = 0; i < numwave; i++, zelda_wave++) {
1250 // if (zelda_wave->copy != -1) {
1251 // wtbl[i << 1] = wtbl[zelda_wave->copy << 1];
1252 // wtbl[(i << 1) + 1] = (zelda_wave->lopst >> 4) * 9 + wtbl[i << 1];
1253 // }
1254 // }
1255
1256 // m = WriteSpcData(rom, wtbl, numwave << 2, 0xc8000, 0x3c00, 0xd74fc);
1257 // m = WriteSpcData(rom, b, j, m, 0x4000, 0xd74fc);
1258
1259 // free(b);
1260 // m = WriteSpcData(rom, insts, numinst * 6, m, 0x3d00, 0xd74fc);
1261 // m = WriteSpcData(rom, snddat1, sndlen1, m, 0x800, 0xd74fc);
1262 // m = WriteSpcData(rom, snddat2, sndlen2, m, 0x17c0, 0xd74fc);
1263 // m = WriteSpcData(rom, sndinsts, numsndinst * 9, m, 0x3e00, 0xd74fc);
1264 // m_ofs = m;
1265 // } else {
1266 // m = m_ofs;
1267 // }
1268
1269 // bank_next[0] = 0x2880;
1270 // bank_next[1] = 0xd000;
1271 // bank_next[2] = 0xd000;
1272 // bank_next[3] = 0xd000;
1273 // bank_lwr[0] = 0x2880;
1274
1275 // for (k = 0; k < 4; k++) {
1276 // pstbl = 0;
1277 // for (i = 0; i < ss_num; i++) {
1278 // stbl = ssblt[i];
1279 // if (stbl->bank != k) continue;
1280 // j = bank_next[k];
1281 // if (j + stbl->len > 0xffc0) {
1282 // if (k == 3)
1283 // j = 0x2880;
1284 // else
1285 // j = bank_next[0];
1286 // bank_lwr[k] = j;
1287 // pstbl = 0;
1288 // }
1289 // if (j + stbl->len > 0x3c00 && j < 0xd000) {
1290 // printf("Not enough space for music bank %d", k);
1291 // m_modf = 1;
1292 // return;
1293 // }
1294 // if (pstbl && (pstbl->flag & 1) && (stbl->flag & 2)) j--, pstbl->len--;
1295 // stbl->addr = j;
1296 // pstbl = stbl;
1297 // bank_next[k] = j + stbl->len;
1298 // }
1299 // }
1300 // for (i = 0; i < ss_num; i++) {
1301 // stbl = ssblt[i];
1302 // for (j = stbl->relnum - 1; j >= 0; j--) {
1303 // k = *(unsigned short *)(stbl->buf + stbl->relocs[j]);
1304 // for (l = 0; l < ss_num; l++) {
1305 // sptbl = ssblt[l];
1306 // if (sptbl->start <= k && sptbl->len > k - sptbl->start) goto noerror;
1307 // }
1308 // printf("Internal error");
1309 // m_modf = 1;
1310 // return;
1311 // noerror:
1312
1313 // if (((!sptbl->bank) && stbl->bank < 3) || (sptbl->bank == stbl->bank))
1314 // {
1315 // *(unsigned short *)(stbl->buf + stbl->relocs[j]) =
1316 // sptbl->addr + k - sptbl->start;
1317 // } else {
1318 // printf("An address outside the bank was referenced.\n");
1319 // m_modf = 1;
1320 // return;
1321 // }
1322 // }
1323 // }
1324 // l = m;
1325 // for (k = 0; k < 4; k++) {
1326 // switch (k) {
1327 // case 1:
1328 // rom[0x914] = l;
1329 // rom[0x918] = (l >> 8) | 128;
1330 // rom[0x91c] = l >> 15;
1331 // break;
1332 // case 2:
1333 // l = 0xd8000;
1334 // break;
1335 // case 3:
1336 // l = m;
1337 // rom[0x932] = l;
1338 // rom[0x936] = (l >> 8) | 128;
1339 // rom[0x93a] = l >> 15;
1340 // break;
1341 // }
1342 // for (o = 0; o < 2; o++) {
1343 // n = l + 4;
1344 // for (i = 0; i < ss_num; i++) {
1345 // stbl = ssblt[i];
1346 // if (!stbl) continue;
1347 // if ((stbl->addr < 0xd000) ^ o) continue;
1348 // if (stbl->bank != k) continue;
1349 // if (n + stbl->len > ((k == 2) ? 0xdb7fc : 0xd74fc)) {
1350 // printf("Not enough space for music");
1351 // m_modf = 1;
1352 // return;
1353 // }
1354 // memcpy(rom.mutable_data() + n, stbl->buf, stbl->len);
1355 // n += stbl->len;
1356 // free(stbl->relocs);
1357 // free(stbl->buf);
1358 // free(stbl);
1359 // ssblt[i] = 0;
1360 // }
1361 // if (n > l + 4) {
1362 // *(short *)(rom.mutable_data() + l) = n - l - 4;
1363 // *(short *)(rom.mutable_data() + l + 2) = o ? bank_lwr[k] : 0xd000;
1364 // l = n;
1365 // }
1366 // }
1367 // *(short *)(rom.mutable_data() + l) = 0;
1368 // *(short *)(rom.mutable_data() + l + 2) = 0x800;
1369 // if (k == 1) m = l + 4;
1370 // }
1371 // free(ssblt);
1372}
1373
1380void Tracker::EditTrack(Rom& rom, short i) {
1381 int j, k, l;
1382 SongRange* sr = song_range_;
1383 SpcCommand* spc_command;
1384
1385 text_buf_ty buf;
1386
1387 // -----------------------------
1388
1389 k = srnum;
1390
1391 spc_command = current_spc_command_;
1392
1393 if (i == -1)
1394 return;
1395
1396 if (i >= m_size) {
1397 printf("Invalid address: %04X", i);
1398 printf("Error");
1399 return;
1400 }
1401
1402 for (;;) {
1403 if ((j = spc_command[i].prev) != -1)
1404 i = j;
1405 else
1406 break;
1407 }
1408
1409 for (l = 0; l < k; l++)
1410 if (sr->first == i)
1411 break;
1412 else
1413 sr++;
1414
1415 if (l == k) {
1416 printf("Not found: %04X", i);
1417 printf("Error");
1418 return;
1419 }
1420
1421 // if (sr->editor)
1422 // HM_MDI_ActivateChild(clientwnd, sr->editor);
1423 // else
1424 // Editwin(rom, "TRACKEDIT", "Song editor", l + (i << 16),
1425 // sizeof(TRACKEDIT));
1426}
1427
1428// CRITICAL_SECTION cs_song;
1429// =============================================================================
1430
1437void Tracker::NewSR(Rom& rom, int bank) {
1438 SpcCommand* spc_command;
1439 SongRange* sr;
1440
1441 if (srnum == srsize) {
1442 srsize += 16;
1443 song_range_ = (SongRange*)realloc(song_range_, srsize * sizeof(SongRange));
1444 }
1445
1446 sr = song_range_ + srnum;
1447 srnum++;
1448 sr->first = AllocSpcCommand();
1449 sr->bank = bank;
1450 sr->editor = 0;
1451 spc_command = current_spc_command_ + sr->first;
1452 spc_command->prev = -1;
1453 spc_command->next = -1;
1454 spc_command->cmd = 128;
1455 spc_command->flag = 0;
1456 EditTrack(rom, sr->first);
1457}
1458
1459} // namespace music
1460} // namespace zelda3
1461} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:28
auto mutable_data()
Definition rom.h:140
void EditTrack(Rom &rom, short i)
Opens an editor window for a specific track. (Legacy UI-related function)
Definition tracker.cc:1380
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....
Definition tracker.cc:75
short AllocSpcCommand()
Allocates a new SpcCommand from a pre-allocated pool. This uses a classic free-list implementation fo...
Definition tracker.cc:118
SongSpcBlock * AllocSpcBlock(int len, int bank)
Allocates a new SongSpcBlock for holding generated SPC data. These blocks are the building blocks for...
Definition tracker.cc:42
void SaveSongs(Rom &rom)
High-level function to save all modified song data back to the ROM. (Currently commented out,...
Definition tracker.cc:924
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 ...
Definition tracker.cc:261
short GetBlockTime(Rom &rom, short num, short prevtime)
Calculates the total time (duration) of a block of SpcCommands. This is essential for synchronization...
Definition tracker.cc:154
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 ...
Definition tracker.cc:884
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,...
Definition tracker.cc:734
void NewSR(Rom &rom, int bank)
Creates a new, empty song range (SongRange) and opens it for editing. (Legacy UI-related function)
Definition tracker.cc:1437
SpcCommand * current_spc_command_
Definition tracker.h:268
void LoadSongs(Rom &rom)
High-level function to load all song data from the ROM. (Currently commented out, but this would be t...
Definition tracker.cc:454
SongSpcBlock ** ssblt
Definition tracker.h:274
void AddSpcReloc(music::SongSpcBlock *sbl, short addr)
Definition tracker.cc:24
char[512] text_buf_ty
Definition tracker.h:38
A metadata structure to keep track of parsed sections of the song data. Used to avoid re-parsing the ...
Definition tracker.h:64
Represents a block of binary data destined for the APU (SPC700) RAM. This is the intermediate format ...
Definition tracker.h:45
The core data structure representing a single command in a music track. A song track is a doubly-link...
Definition tracker.h:176