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