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