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