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