1 /*  Copyright 2013 Theo Berkau
2 
3     This file is part of YabauseUT
4 
5     YabauseUT is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     YabauseUT is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with YabauseUT; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include <iapetus.h>
21 #include "tests.h"
22 #include "scsp.h"
23 #include "main.h"
24 #include <stdio.h>
25 
26 #define SCSPREG_TIMERA  (*(volatile u16 *)0x25B00418)
27 #define SCSPREG_TIMERB  (*(volatile u16 *)0x25B0041A)
28 #define SCSPREG_TIMERC  (*(volatile u16 *)0x25B0041C)
29 
30 #define SCSPREG_SCIEB   (*(volatile u16 *)0x25B0041E)
31 #define SCSPREG_SCIPD   (*(volatile u16 *)0x25B00420)
32 #define SCSPREG_SCIRE   (*(volatile u16 *)0x25B00422)
33 
34 #define SCSPREG_MCIEB   (*(volatile u16 *)0x25B0042A)
35 #define SCSPREG_MCIPD   (*(volatile u16 *)0x25B0042C)
36 #define SCSPREG_MCIRE   (*(volatile u16 *)0x25B0042E)
37 
38 struct SlotRegs
39 {
40    u8 kx;
41    u8 kb;
42    u8 sbctl;
43    u8 ssctl;
44    u8 lpctl;
45    u8 pcm8b;
46    u32 sa;
47    u16 lsa;
48    u16 lea;
49    u8 d2r;
50    u8 d1r;
51    u8 hold;
52    u8 ar;
53    u8 ls;
54    u8 krs;
55    u8 dl;
56    u8 rr;
57    u8 si;
58    u8 sd;
59    u16 tl;
60    u8 mdl;
61    u8 mdxsl;
62    u8 mdysl;
63    u8 oct;
64    u16 fns;
65    u8 re;
66    u8 lfof;
67    u8 plfows;
68    u8 plfos;
69    u8 alfows;
70    u8 alfos;
71    u8 isel;
72    u8 imxl;
73    u8 disdl;
74    u8 dipan;
75    u8 efsdl;
76    u8 efpan;
77 };
78 
79 volatile u32 hblank_counter=0;
80 
81 int tinc=0;
82 
83 void scsp_interactive_test();
84 
85 void vdp1_setup(u32 vdp1_tile_address);
86 void vdp1_print_str(int x, int y, int palette, u32 vdp1_tile_address, char* str);
87 void load_font_8x8_to_vram_1bpp_to_4bpp(u32 tile_start_address, u32 ram_pointer);
88 extern u8 sine_tbl[];
89 
90 //////////////////////////////////////////////////////////////////////////////
91 
scsp_test()92 void scsp_test()
93 {
94    int choice;
95 
96    menu_item_struct vdp1_menu[] = {
97 //   { "Individual slots(Mute sound first)" , &scspslottest, },
98    { "SCSP timing" , &scsp_timing_test, },
99    { "Misc" , &scsp_misc_test, },
100 //   { "Interactive" , &scspinteractivetest, },
101    { "\0", NULL }
102    };
103 
104    for (;;)
105    {
106       choice = gui_do_menu(vdp1_menu, &test_disp_font, 0, 0, "SCSP Tests", MTYPE_CENTER, -1);
107       if (choice == -1)
108          break;
109    }
110 }
111 
112 //////////////////////////////////////////////////////////////////////////////
113 
scsp_minimal_init()114 void scsp_minimal_init()
115 {
116    // Put system in minimalized state
117    interrupt_set_level_mask(0xF);
118 
119    init_iapetus(RES_320x224);
120    vdp_rbg0_init(&test_disp_settings);
121    vdp_set_default_palette();
122 
123    // Turn off sound cpu
124    smpc_issue_command(0x07);
125 
126    // Display On
127    vdp_disp_on();
128 }
129 
130 //////////////////////////////////////////////////////////////////////////////
131 
scsp_minimal_slot_init(int slotnum)132 void scsp_minimal_slot_init(int slotnum)
133 {
134 /*
135    void *slot=(void *)(0x25B00000 + (slotnum << 5));
136 
137    // Setup slot
138    *(volatile u32 *)(slot+0x00) = 0x10300000 | (info->ssctl << 23) | 0; // key off, normal loop, start address
139    *(volatile u16 *)(slot+0x04) = 0x0000; // LSA
140    *(volatile u16 *)(slot+0x06) = 0x00FF; // LEA
141    *(volatile u16 *)(slot+0x08) = (info->d2r << 11) | (info->d1r << 6) | (info->eghold << 5) | info->ar; // Normal D2R, D1R, EGHOLD, AR
142    *(volatile u16 *)(slot+0x0A) = (info->lpslnk << 14) | (info->krs << 10) | (info->dl << 5) | info->rr; // Normal LPSLNK, KRS, DL, RR
143    *(volatile u16 *)(slot+0x0C) = (info->stwinh << 9) | (info->sdir << 8) | info->tl; // stwinh, sdir, tl
144    *(volatile u16 *)(slot+0x0E) = (info->mdl << 12) | (info->mdxsl << 6) | info->mdysl; // modulation stuff
145    *(volatile u16 *)(slot+0x10) = (info->oct << 11) | info->fns; // oct/fns
146    *(volatile u16 *)(slot+0x12) = (info->lfof << 10) | (info->plfows << 8) | (info->plfos << 5) | (info->alfows << 3) | info->alfos; // lfo
147    *(volatile u16 *)(slot+0x14) = (info->isel << 3) | info->imxl; // isel/imxl
148    *(volatile u16 *)(slot+0x16) = (info->disdl << 13) | (info->dipan << 8) | (info->efsdl << 5) | info->efpan; //
149 
150    // Time to key on
151    *(volatile u8 *)(slot+0x00) = 0x18 | (info->ssctl >> 1);
152 */
153 }
154 
155 //////////////////////////////////////////////////////////////////////////////
156 
scsp_slot_test()157 void scsp_slot_test()
158 {
159    scsp_minimal_init();
160    unregister_all_tests();
161    register_test(&scu_interrupt_test, "Key On/Off");
162    register_test(&scsp_timer_a_test, "8/16-bit/Noise samples");
163    register_test(&scsp_timer_a_test, "Source bit");
164    register_test(&scsp_timer_a_test, "Looping");
165    register_test(&scsp_timer_a_test, "Octaves"); // not sure I can easily test this
166    register_test(&scsp_timer_a_test, "Attack rate"); // not sure I can easily test this
167    register_test(&scsp_timer_a_test, "Decay rate"); // not sure I can easily test this
168    register_test(&scsp_timer_a_test, "Decay level"); // not sure I can easily test this
169    register_test(&scsp_timer_a_test, "Release rate"); // not sure I can easily test this
170    register_test(&scsp_timer_a_test, "Total level");
171    // modulation test here
172    // LFO tests here
173    // direct pan/sdl tests here
174    do_tests("SCSP Timer tests", 0, 0);
175 }
176 
177 //////////////////////////////////////////////////////////////////////////////
178 
scsp_timing_test()179 void scsp_timing_test()
180 {
181    scsp_minimal_init();
182    unregister_all_tests();
183    register_test(&scu_interrupt_test, "Sound Request Interrupt");
184    register_test(&scsp_timer_a_test, "Timer A");
185    register_test(&scsp_timer_b_test, "Timer B");
186    register_test(&scsp_timer_c_test, "Timer C");
187 /*
188    register_test(&ScspTimerTimingTest0, "Timer timing w/1 sample inc");
189    register_test(&ScspTimerTimingTest1, "Timer timing w/2 sample inc");
190    register_test(&ScspTimerTimingTest2, "Timer timing w/4 sample inc");
191    register_test(&ScspTimerTimingTest3, "Timer timing w/8 sample inc");
192    register_test(&ScspTimerTimingTest4, "Timer timing w/16 sample inc");
193    register_test(&ScspTimerTimingTest5, "Timer timing w/32 sample inc");
194    register_test(&ScspTimerTimingTest6, "Timer timing w/64 sample inc");
195    register_test(&ScspTimerTimingTest7, "Timer timing w/128 sample inc");
196 */
197    do_tests("SCSP Timer tests", 0, 0);
198 }
199 
200 //////////////////////////////////////////////////////////////////////////////
201 
scsp_misc_test()202 void scsp_misc_test()
203 {
204    scsp_minimal_init();
205    unregister_all_tests();
206    register_test(&scsp_int_on_timer_enable_test, "Int on Timer enable behaviour");
207    register_test(&scsp_int_on_timer_reset_test, "Int on Timer reset behaviour");
208    register_test(&scsp_int_dup_test, "No second Int after Timer done");
209 //   register_test(&scsp_mcipd_test, "MCIPD bit cleared after Timer Int");
210    register_test(&scsp_scipd_test, "Timers start after SCIRE write");
211    register_test(&scsp_scipd_test, "Timers start after MCIRE write");
212 
213    // DMA tests here
214 
215    // MSLC/CA tests here
216 
217    do_tests("SCSP Interrupt tests", 0, 0);
218 }
219 
220 //////////////////////////////////////////////////////////////////////////////
221 
222 int scsp_counter;
223 
scsp_interrupt()224 void scsp_interrupt()
225 {
226    scsp_counter++;
227 }
228 
229 //////////////////////////////////////////////////////////////////////////////
230 
scsp_interactive_test()231 void scsp_interactive_test()
232 {
233    u16 scieb=0;
234    u16 mcieb=0;
235 
236    scsp_minimal_init();
237 
238    test_disp_font.transparent = 0;
239    scsp_counter=0;
240    SCSPREG_SCIEB = mcieb;
241    SCSPREG_MCIEB = scieb;
242 
243    // Mask SCSP interrupt temporarily
244    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40);
245 
246    // Set SCSP interrupt function
247    bios_set_scu_interrupt(0x46, scsp_interrupt);
248 
249    // Unmask SCSP interrupt
250    bios_change_scu_interrupt_mask(~0x40, 0);
251 
252    for (;;)
253    {
254       u16 scipd;
255       u16 mcipd;
256 
257       vdp_vsync();
258 
259 #define Refresh(line) \
260       scipd = SCSPREG_SCIPD; \
261       mcipd = SCSPREG_MCIPD; \
262       \
263       vdp_printf(&test_disp_font, 2 * 8, line * 8, 0xF, "SCIEB = %04X", scieb); \
264       vdp_printf(&test_disp_font, 2 * 8, (line+1) * 8, 0xF, "MCIEB = %04X", mcieb); \
265       vdp_printf(&test_disp_font, 2 * 8, (line+2) * 8, 0xF, "SCIPD = %04X", scipd); \
266       vdp_printf(&test_disp_font, 2 * 8, (line+3) * 8, 0xF, "MCIPD = %04X", mcipd); \
267       vdp_printf(&test_disp_font, 2 * 8, (line+4)* 8, 0xF, "int counter = %d", scsp_counter);
268 
269       Refresh(17);
270 
271       if (per[0].but_push_once & PAD_A)
272       {
273          SCSPREG_TIMERA = 0x700;
274          Refresh(23);
275       }
276       else if (per[0].but_push_once & PAD_B)
277       {
278          SCSPREG_TIMERA = 0x07FF;
279          Refresh(23);
280       }
281       else if (per[0].but_push_once & PAD_C)
282       {
283          SCSPREG_SCIRE = 0x40;
284          Refresh(23);
285       }
286       else if (per[0].but_push_once & PAD_X)
287       {
288          mcieb ^= 0x40;
289          SCSPREG_MCIEB = mcieb;
290          Refresh(23);
291       }
292       else if (per[0].but_push_once & PAD_Y)
293       {
294          SCSPREG_MCIRE = 0x40;
295          Refresh(23);
296       }
297       else if (per[0].but_push_once & PAD_L)
298       {
299          mcieb ^= 0x20;
300          SCSPREG_MCIEB = mcieb;
301          Refresh(23);
302       }
303       else if (per[0].but_push_once & PAD_R)
304       {
305          if (SCSPREG_MCIPD & 0x20)
306             SCSPREG_MCIRE = 0x20;
307          else
308             SCSPREG_MCIPD = 0x20;
309          Refresh(23);
310       }
311    }
312 }
313 
314 //////////////////////////////////////////////////////////////////////////////
315 
scsp_int_test_func()316 void scsp_int_test_func()
317 {
318    stage_status = STAGESTAT_DONE;
319 
320    // Mask SCSP interrupts
321    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40);
322 }
323 
324 //////////////////////////////////////////////////////////////////////////////
325 
scu_interrupt_test()326 void scu_interrupt_test()
327 {
328    // Disable everything temporarily
329    SCSPREG_SCIEB = 0;
330    SCSPREG_MCIEB = 0;
331 
332    // Mask SCSP interrupt temporarily
333    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40);
334 
335    // Set SCSP interrupt function
336    bios_set_scu_interrupt(0x46, scsp_int_test_func);
337 
338    // Unmask SCSP interrupt
339    bios_change_scu_interrupt_mask(~0x40, 0);
340 
341    // Enable all SCSP Main cpu interrupts
342    SCSPREG_MCIEB = 0x7FF;
343    SCSPREG_MCIRE = 0x7FF;
344 }
345 
346 //////////////////////////////////////////////////////////////////////////////
347 
scsp_timer_pending_test(int timer_mask,int main_cpu)348 void scsp_timer_pending_test(int timer_mask, int main_cpu)
349 {
350    // Disable everything
351    SCSPREG_SCIEB = 0;
352    SCSPREG_MCIEB = 0;
353 
354    if (main_cpu)
355    {
356       // Clear any pending interrupts
357       SCSPREG_SCIRE = timer_mask;
358 
359       // Make sure it isn't set prematurely
360       if (SCSPREG_SCIPD & timer_mask)
361       {
362          stage_status = STAGESTAT_BADTIMING;
363          return;
364       }
365 
366       // Wait a bit while testing SCIPD
367       wait_test(SCSPREG_SCIPD & timer_mask, 80000, STAGESTAT_BADINTERRUPT)
368    }
369    else
370    {
371       // Clear any pending interrupts
372       SCSPREG_MCIRE = timer_mask;
373 
374       // Make sure it isn't set prematurely
375       if (SCSPREG_MCIPD & timer_mask)
376       {
377          stage_status = STAGESTAT_BADTIMING;
378          return;
379       }
380 
381       // Wait a bit while testing SCIPD
382       wait_test(SCSPREG_MCIPD & timer_mask, 80000, STAGESTAT_BADINTERRUPT)
383    }
384 }
385 
386 //////////////////////////////////////////////////////////////////////////////
387 
scsp_scipd_test()388 void scsp_scipd_test()
389 {
390    int i;
391    u16 mask_list[] = { 0x0040, 0x0080, 0x0100 };
392 
393    for (i = 0; i < (sizeof(mask_list) / sizeof(u16)); i++)
394    {
395       scsp_timer_pending_test(mask_list[i], 0);
396       if (stage_status != STAGESTAT_DONE)
397          return;
398    }
399 }
400 
401 //////////////////////////////////////////////////////////////////////////////
402 
scsp_mcipd_test()403 void scsp_mcipd_test()
404 {
405    int i;
406    u16 mask_list[] = { 0x0040, 0x0080, 0x0100 };
407 
408    for (i = 0; i < (sizeof(mask_list) / sizeof(u16)); i++)
409    {
410       scsp_timer_pending_test(mask_list[i], 1);
411       if (stage_status != STAGESTAT_DONE)
412          return;
413    }
414 }
415 
416 //////////////////////////////////////////////////////////////////////////////
417 
scsp_timer_test(int timer_mask)418 void scsp_timer_test(int timer_mask)
419 {
420    // Disable everything temporarily
421    SCSPREG_SCIEB = 0;
422    SCSPREG_MCIEB = 0;
423 
424    // Mask SCSP interrupt temporarily
425    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40);
426 
427    // Set SCSP interrupt function
428    bios_set_scu_interrupt(0x46, scsp_int_test_func);
429 
430    // Unmask SCSP interrupt
431    bios_change_scu_interrupt_mask(~0x40, 0);
432 
433    stage_status = STAGESTAT_WAITINGFORINT;
434 
435    // Enable Timer interrupt
436    SCSPREG_MCIRE = timer_mask;
437    SCSPREG_MCIEB = timer_mask;
438 }
439 
440 //////////////////////////////////////////////////////////////////////////////
441 
scsp_timer_a_test()442 void scsp_timer_a_test()
443 {
444    scsp_timer_test(0x40);
445 }
446 
447 //////////////////////////////////////////////////////////////////////////////
448 
scsp_timer_b_test()449 void scsp_timer_b_test()
450 {
451    scsp_timer_test(0x80);
452 }
453 
454 //////////////////////////////////////////////////////////////////////////////
455 
scsp_timer_c_test()456 void scsp_timer_c_test()
457 {
458    scsp_timer_test(0x100);
459 }
460 
461 //////////////////////////////////////////////////////////////////////////////
462 
scsp_timing_func(void)463 void scsp_timing_func(void)
464 {
465    u32 hblank_temp;
466    hblank_temp = hblank_counter;
467 
468 //   vdp_printf(&test_disp_font, 1 * 8, 22 * 8, 0xF, "hblankcounter: %08X", hblanktemp);
469 
470    switch (tinc)
471    {
472       case 0:
473          if ((hblank_temp & 0xFF00) < 0x100) // fix me
474             stage_status = STAGESTAT_DONE;
475          else
476             stage_status = STAGESTAT_BADTIMING;
477          break;
478       case 1:
479          if ((hblank_temp & 0xFF00) < 0x100) // fix me
480             stage_status = STAGESTAT_DONE;
481          else
482             stage_status = STAGESTAT_BADTIMING;
483          break;
484       case 2:
485          if ((hblank_temp & 0xFF00) == 0x100) // fix me
486             stage_status = STAGESTAT_DONE;
487          else
488             stage_status = STAGESTAT_BADTIMING;
489          break;
490       case 3:
491          if ((hblank_temp & 0xFF00) == 0x200) // fix me
492             stage_status = STAGESTAT_DONE;
493          else
494             stage_status = STAGESTAT_BADTIMING;
495          break;
496       case 4:
497          if ((hblank_temp & 0xFF00) == 0x500) // fix me
498             stage_status = STAGESTAT_DONE;
499          else
500             stage_status = STAGESTAT_BADTIMING;
501          break;
502       case 5:
503          if ((hblank_temp & 0xFF00) == 0xB00) // fix me
504             stage_status = STAGESTAT_DONE;
505          else
506             stage_status = STAGESTAT_BADTIMING;
507          break;
508       case 6:
509          if ((hblank_temp & 0xFF00) == 0x1600) // fix me
510             stage_status = STAGESTAT_DONE;
511          else
512             stage_status = STAGESTAT_BADTIMING;
513          break;
514       case 7:
515          if ((hblank_temp & 0xFF00) == 0x2D00) // fix me
516             stage_status = STAGESTAT_DONE;
517          else
518             stage_status = STAGESTAT_BADTIMING;
519       default:
520          stage_status = STAGESTAT_DONE;
521          break;
522    }
523 }
524 
525 //////////////////////////////////////////////////////////////////////////////
526 
hblank_timing_func(void)527 void hblank_timing_func(void)
528 {
529    hblank_counter++;
530 }
531 
532 //////////////////////////////////////////////////////////////////////////////
533 
scsp_timer_timing_test(u16 timer_setting)534 void scsp_timer_timing_test(u16 timer_setting)
535 {
536    // Disable everything temporarily
537    SCSPREG_SCIEB = 0;
538    SCSPREG_MCIEB = 0;
539 
540    tinc = timer_setting >> 8;
541 
542    interrupt_set_level_mask(0xF);
543 
544    // Mask SCSP/H-blank interrupts temporarily
545    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40 | 0x4);
546 
547    // Set SCSP interrupt function
548    bios_set_scu_interrupt(0x46, scsp_timing_func);
549 
550    // Set Hblank-in interrupt function
551    bios_set_scu_interrupt(0x42, hblank_timing_func);
552 
553    // Unmask SCSP/H-blank interrupts
554    bios_change_scu_interrupt_mask(~(0x40 | 0x4), 0);
555 
556    hblank_counter = 0;
557    vdp_vsync();
558 
559 //   switch (timermask)
560 //   {
561 //      case 0x40:
562          SCSPREG_TIMERA = timer_setting;
563 //         break;
564 //      case 0x80:
565 //         SCSPREG_TIMERB = timersetting;
566 //         break;
567 //      case 0x100:
568 //         SCSPREG_TIMERC = timersetting;
569 //         break;
570 //      default: break;
571 //   }
572    interrupt_set_level_mask(0x8);
573 
574    stage_status = STAGESTAT_WAITINGFORINT;
575 
576    // Enable Timer interrupt
577    SCSPREG_MCIRE = 0x0040;
578    SCSPREG_MCIEB = 0x0040;
579 }
580 
581 //////////////////////////////////////////////////////////////////////////////
582 
scsp_timer_timing_test0()583 void scsp_timer_timing_test0()
584 {
585    scsp_timer_timing_test(0x0000);
586 }
587 
588 //////////////////////////////////////////////////////////////////////////////
589 
scsp_timer_timing_test1()590 void scsp_timer_timing_test1()
591 {
592    scsp_timer_timing_test(0x0100);
593 }
594 
595 //////////////////////////////////////////////////////////////////////////////
596 
scsp_timer_timing_test2()597 void scsp_timer_timing_test2()
598 {
599    scsp_timer_timing_test(0x0200);
600 }
601 
602 //////////////////////////////////////////////////////////////////////////////
603 
scsp_timer_timing_test3()604 void scsp_timer_timing_test3()
605 {
606    scsp_timer_timing_test(0x0300);
607 }
608 
609 //////////////////////////////////////////////////////////////////////////////
610 
scsp_timer_timing_test4()611 void scsp_timer_timing_test4()
612 {
613    scsp_timer_timing_test(0x0400);
614 }
615 
616 //////////////////////////////////////////////////////////////////////////////
617 
scsp_timer_timing_test5()618 void scsp_timer_timing_test5()
619 {
620    scsp_timer_timing_test(0x0500);
621 }
622 
623 //////////////////////////////////////////////////////////////////////////////
624 
scsp_timer_timing_test6()625 void scsp_timer_timing_test6()
626 {
627    scsp_timer_timing_test(0x0600);
628 }
629 
630 //////////////////////////////////////////////////////////////////////////////
631 
scsp_timer_timing_test7()632 void scsp_timer_timing_test7()
633 {
634    scsp_timer_timing_test(0x0700);
635 }
636 
637 //////////////////////////////////////////////////////////////////////////////
638 
int_on_timer_enable_test_func(void)639 void int_on_timer_enable_test_func(void)
640 {
641 //   u32 hblanktemp;
642 //   hblanktemp = hblankcounter;
643 
644    if (hblank_counter == 0)
645       stage_status = STAGESTAT_DONE;
646    else
647       stage_status = STAGESTAT_BADTIMING;
648 
649 //   vdp_printf(&test_disp_font, 1 * 8, 23 * 8, 0xF, "hblankcounter: %08X", hblanktemp);
650 }
651 
652 //////////////////////////////////////////////////////////////////////////////
653 
scsp_int_on_timer_enable_test()654 void scsp_int_on_timer_enable_test()
655 {
656    // Disable everything temporarily
657    SCSPREG_SCIEB = 0;
658    SCSPREG_MCIEB = 0;
659 
660    // Mask SCSP/H-blank interrupts temporarily
661    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40 | 0x4);
662 
663    // Set SCSP interrupt function
664    bios_set_scu_interrupt(0x46, int_on_timer_enable_test_func);
665 
666    // Set Hblank-in interrupt function
667    bios_set_scu_interrupt(0x42, hblank_timing_func);
668 
669    // Unmask SCSP/H-blank interrupts
670    bios_change_scu_interrupt_mask(~(0x40 | 0x4), 0);
671 
672    // Clear timer
673    SCSPREG_TIMERA = 0x0700;
674    SCSPREG_MCIRE = 0x40;
675 
676    // Wait until MCIPD is showing an interrupt pending
677    while (!(SCSPREG_MCIPD & 0x40)) {}
678 
679    stage_status = STAGESTAT_WAITINGFORINT;
680 
681    // Enable Timer interrupt
682    hblank_counter = 0;
683    SCSPREG_MCIEB = 0x40;
684 }
685 
686 //////////////////////////////////////////////////////////////////////////////
687 
scsp_int_on_timer_reset_test()688 void scsp_int_on_timer_reset_test()
689 {
690    // Disable everything temporarily
691    SCSPREG_SCIEB = 0;
692    SCSPREG_MCIEB = 0;
693 
694    // Mask SCSP interrupt temporarily
695    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40);
696 
697    // Set SCSP interrupt function
698    bios_set_scu_interrupt(0x46, 0);
699 
700    // Unmask SCSP interrupt
701    bios_change_scu_interrupt_mask(~0x40, 0);
702 
703    // Enable timer
704    SCSPREG_TIMERA = 0x0700;
705    SCSPREG_MCIRE = 0x40;
706    SCSPREG_MCIEB = 0x40;
707 
708    // Wait until MCIPD is showing an interrupt pending
709    while (!(SCSPREG_MCIPD & 0x40)) {}
710 
711    // Set SCSP interrupt function
712    bios_set_scu_interrupt(0x46, scsp_int_test_func);
713 
714    stage_status = STAGESTAT_WAITINGFORINT;
715 
716    // Reset Timer
717    hblank_counter = 0;
718    SCSPREG_MCIRE = 0x40;
719 }
720 
721 //////////////////////////////////////////////////////////////////////////////
722 
scsp_int_dup_test()723 void scsp_int_dup_test()
724 {
725    // Disable everything temporarily
726    SCSPREG_SCIEB = 0;
727    SCSPREG_MCIEB = 0;
728 
729    // Mask SCSP/H-blank interrupts temporarily
730    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40 | 0x4);
731 
732    // Set SCSP interrupt function
733    bios_set_scu_interrupt(0x46, 0);
734 
735    // Set Hblank-in interrupt function
736    bios_set_scu_interrupt(0x42, hblank_timing_func);
737 
738    // Unmask SCSP/H-blank interrupts
739    bios_change_scu_interrupt_mask(~(0x40 | 0x4), 0);
740 
741    // Enable timer
742    SCSPREG_TIMERA = 0;
743    SCSPREG_MCIRE = 0x40;
744    SCSPREG_MCIEB = 0x40;
745 
746    // Wait until MCIPD is showing an interrupt pending
747    while (!(SCSPREG_MCIPD & 0x40)) {}
748 
749    // Set SCSP interrupt function
750    bios_set_scu_interrupt(0x46, scsp_int_test_func);
751 
752    // Wait around 0x2000 hblanks to make sure nothing else triggers the interrupt
753    hblank_counter = 0;
754 
755    while (hblank_counter < 0x2000) {}
756 
757    if (stage_status == STAGESTAT_DONE)
758       stage_status = STAGESTAT_BADINTERRUPT;
759    else
760       stage_status = STAGESTAT_DONE;
761 }
762 
763 //////////////////////////////////////////////////////////////////////////////
764 
765 u16 scsp_dsp_reg_test_pattern[8] = { 0xdead ,0xbeef,0xcafe ,0xbabe,0xba5e ,0xba11,0xf01d,0xab1e };
766 
scsp_dsp_do_reg_write(volatile u16 * ptr,int length)767 void scsp_dsp_do_reg_write(volatile u16* ptr, int length)
768 {
769    int i;
770    for (i = 0; i < length; i++)
771    {
772       ptr[i] = scsp_dsp_reg_test_pattern[i&7];
773    }
774 }
775 
776 //////////////////////////////////////////////////////////////////////////////
777 
scsp_dsp_check_reg(volatile u16 * ptr,int length,int mask,char * name,int pos)778 int scsp_dsp_check_reg(volatile u16* ptr, int length, int mask, char* name, int pos)
779 {
780    int i;
781    for (i = 0; i < length; i++)
782    {
783       u16 ptr_val = ptr[i];
784       u16 correct_val = scsp_dsp_reg_test_pattern[i & 7] & mask;
785       if (ptr_val != correct_val)
786       {
787          char str[64] = { 0 };
788          sprintf(str, "%d %s %04X != %04X", i, name, ptr_val, correct_val);
789          vdp_printf(&test_disp_font, 0 * 8, pos * 8, 40, str);
790          return 1;
791       }
792    }
793    return 0;
794 }
795 
796 //////////////////////////////////////////////////////////////////////////////
797 
scsp_dsp_register_write_test()798 void scsp_dsp_register_write_test()
799 {
800    volatile u16* coef_ptr = (volatile u16 *)0x25B00700;
801    volatile u16* madrs_ptr = (volatile u16 *)0x25B00780;
802    volatile u16* mpro_ptr = (volatile u16 *)0x25B00800;
803    int failure = 0;
804    int coef_length = 64;
805    int madrs_length = 32;
806    int mpro_length = 128;
807 
808    scsp_dsp_do_reg_write(coef_ptr, coef_length);
809    scsp_dsp_do_reg_write(madrs_ptr, madrs_length);
810    scsp_dsp_do_reg_write(mpro_ptr, mpro_length);
811 
812    int i;
813    for (i = 0; i < 28; i++)
814    {
815       vdp_printf(&test_disp_font, 0 * 8, i * 8, 0xF, "coef: %04X", coef_ptr[i]);
816       vdp_printf(&test_disp_font, 12 * 8, i * 8, 0xF, "madrs: %04X", madrs_ptr[i]);
817       vdp_printf(&test_disp_font, 24 * 8, i * 8, 0xF, "mpro: %04X", mpro_ptr[i]);
818    }
819 
820    if (scsp_dsp_check_reg(coef_ptr, coef_length, 0xfff8, "COEF", 0))
821       failure = 1;
822    if (scsp_dsp_check_reg(madrs_ptr, madrs_length, 0xffff, "MADRS", 1))
823       failure = 1;
824    if (scsp_dsp_check_reg(mpro_ptr, mpro_length, 0xffff, "MPRO", 2))
825       failure = 1;
826 
827 #ifndef BUILD_AUTOMATED_TESTING
828    for (;;)
829    {
830       vdp_vsync();
831 
832       //start to advance to the next test
833       if (per[0].but_push_once & PAD_START)
834       {
835          int q;
836          u32* dest = (u32 *)VDP2_RAM;
837 
838          //clear framebuffer
839          for (q = 0; q < 0x10000; q++)
840          {
841             dest[q] = 0;
842          }
843          break;
844       }
845    }
846 #endif
847 
848    if (!failure)
849    {
850       stage_status = STAGESTAT_DONE;
851    }
852    else
853    {
854       stage_status = STAGESTAT_BADDATA;
855    }
856 }
857 
858 //////////////////////////////////////////////////////////////////////////////
859 
scsp_dsp_write_mpro(u16 instr0,u16 instr1,u16 instr2,u16 instr3,u32 addr)860 void scsp_dsp_write_mpro(u16 instr0, u16 instr1, u16 instr2, u16 instr3, u32 addr)
861 {
862    volatile u16* mpro_ptr = (u16 *)0x25b00800;
863    addr *= 4;
864    mpro_ptr[addr+0] = instr0;
865    mpro_ptr[addr+1] = instr1;
866    mpro_ptr[addr+2] = instr2;
867    mpro_ptr[addr+3] = instr3;
868 }
869 
870 //////////////////////////////////////////////////////////////////////////////
871 
scsp_dsp_clear_instr(u16 * instr0,u16 * instr1,u16 * instr2,u16 * instr3)872 void scsp_dsp_clear_instr(u16 *instr0, u16 *instr1, u16 *instr2, u16 *instr3)
873 {
874    *instr0 = 0;
875    *instr1 = 0;
876    *instr2 = 0;
877    *instr3 = 0;
878 }
879 
880 //////////////////////////////////////////////////////////////////////////////
881 
scsp_dsp_erase_mpro()882 void scsp_dsp_erase_mpro()
883 {
884    volatile u16* mpro_ptr = (u16 *)0x25b00800;
885    int i;
886 
887    for (i = 0; i < 128 * 4; i++)
888    {
889       mpro_ptr[i] = 0;
890    }
891 }
892 
893 //////////////////////////////////////////////////////////////////////////////
894 
scsp_dsp_clear()895 void scsp_dsp_clear()
896 {
897    volatile u16* sound_ram_ptr = (u16 *)0x25a00000;
898    volatile u16* coef_ptr = (u16 *)0x25b00700;
899    volatile u16* madrs_ptr = (u16 *)0x25b00780;
900    volatile u16* temp_ptr = (u16 *)0x25b00C00;
901    volatile u16* mems_ptr = (u16 *)0x25b00E00;
902 
903    int i;
904 
905    scsp_dsp_erase_mpro();
906 
907    for (i = 0; i < 0xffff; i++)
908       sound_ram_ptr[i] = 0;
909 
910    for (i = 0; i < 64; i++)
911       mems_ptr[i] = 0;
912 
913    for (i = 0; i < 64; i++)
914       coef_ptr[i] = 0;
915 
916    for (i = 0; i < 64; i++)
917       madrs_ptr[i] = 0;
918 
919    for (i = 0; i < 256; i++)
920       temp_ptr[i] = 0;
921 }
922 
923 //////////////////////////////////////////////////////////////////////////////
924 
scsp_dsp_start_test(u16 a_val,u16 b_val,int * yval)925 void scsp_dsp_start_test(u16 a_val, u16 b_val, int*yval)
926 {
927 
928    volatile u16* sound_ram_ptr = (u16 *)0x25a00000;
929    volatile u16* coef_ptr = (u16 *)0x25b00700;
930    volatile u16* start_dsp = (u16 *)0x25b00BF0;
931 
932    u16 instr0 = 0;
933    u16 instr1 = 0;
934    u16 instr2 = 0;
935    u16 instr3 = 0;
936 
937    scsp_dsp_clear();
938 
939    coef_ptr[0] = a_val;
940 
941    sound_ram_ptr[0] = b_val;
942 
943    //nop
944    scsp_dsp_write_mpro(0, 0, 0, 0, 0);
945 
946    //set memval
947    instr2 = 1 << 13;//set mrd
948    instr2 |= 1 << 15;// set table
949    instr3 = 1 << 15; //set nofl
950 
951    scsp_dsp_write_mpro(0, 0, instr2, instr3, 1);
952 
953    scsp_dsp_clear_instr(&instr0, &instr1, &instr2, &instr3);
954 
955    //load memval to inputs
956    instr1 = 1 << 5;//set iwt
957    //ira and iwa will be 0 and equal to each other
958 
959    scsp_dsp_write_mpro(0, instr1, 0, 0, 2);
960 
961    scsp_dsp_clear_instr(&instr0, &instr1, &instr2, &instr3);
962 
963    scsp_dsp_write_mpro(0, 0, 0, 0, 3);//nop
964 
965    //load inputs to x, load coef to y, set B to zero
966    instr1 = 1 << 15;//set xsel
967    instr1 |= 1 << 13;//set ysel to 1
968    //coef == 0
969    instr2 = 1 << 1;//zero
970 
971    scsp_dsp_write_mpro(0, instr1, instr2, 0, 4);
972 
973    scsp_dsp_clear_instr(&instr0, &instr1, &instr2, &instr3);
974 
975    //needs to be on an odd instruction
976    instr2 |= 1 << 14;//set mwt
977    instr3 |= 1;//set nxadr
978    instr2 |= 1 << 15; //set table
979    instr3 |= 1 << 15; //set nofl
980 
981    scsp_dsp_write_mpro(instr0, instr1, instr2, instr3, 5);
982 
983    //start the dsp
984    start_dsp[0] = 1;
985 
986    //wait a frame
987    vdp_vsync();
988 
989    vdp_printf(&test_disp_font, 0 * 8, *yval * 8, 0xF, "a: 0x%04x * b: 0x%04x = 0x%04x", a_val,b_val, sound_ram_ptr[1]);
990    *yval = *yval + 1;
991 }
992 
993 //convert float in ring buffer to 24 bit int and store it in mems
scsp_dsp_float_to_int_test(u16 test_val,int * yval)994 void scsp_dsp_float_to_int_test(u16 test_val, int*yval)
995 {
996    volatile u16* sound_ram_ptr = (u16 *)0x25a00000;//ring buffer
997    volatile u16* start_dsp = (u16 *)0x25b00BF0;
998 
999    u16 instr1 = 0;
1000    u16 instr2 = 0;
1001    u16 instr3 = 0;
1002 
1003    scsp_dsp_clear();
1004 
1005    start_dsp[0] = 0;
1006 
1007    int i;
1008    for (i = 0; i < 0xffff; i++)
1009       sound_ram_ptr[i] = test_val;
1010 
1011    int instr_pos = 0;
1012 
1013    scsp_dsp_write_mpro(0, 0, 0, 0, instr_pos++);//nop
1014 
1015    //convert ring buffer value to float
1016    //and put it in memval
1017    instr2 = 1 << 13;//set mrd
1018    instr2 |= 1 << 15;// set table
1019    instr3 = 1 << 15; //set nofl
1020 
1021    scsp_dsp_write_mpro(0, 0, instr2, instr3, instr_pos++);
1022 
1023    scsp_dsp_write_mpro(0, 0, 0, 0, instr_pos++);//nop
1024 
1025    scsp_dsp_write_mpro(0, 1 << 5 | 1, 1 << 13, 0, instr_pos++);//iwa = 1, iwt, mrd
1026 
1027    //store memval in mems[0]
1028    instr1 = 1 << 5;//set iwt
1029 
1030    scsp_dsp_write_mpro(0, instr1, 0, 0, instr_pos++);
1031 
1032    //start the dsp
1033    start_dsp[0] = 1;
1034 
1035    int q;
1036 
1037    for(q = 0; q < 10; q++)
1038       vdp_wait_hblankout();
1039 
1040    vdp_printf(&test_disp_font, 0 * 8, *yval * 8, 0, "NNNNNNNNNNNNNN");
1041 
1042    volatile u16* mems_ptr = (u16 *)0x25b00E00;
1043 
1044    u32 test_result = mems_ptr[2] | mems_ptr[3] << 8;
1045 
1046    vdp_printf(&test_disp_font, 0 * 8, *yval * 8, 0xF, "0x%04x 0x%08x", test_val, test_result);
1047    *yval = *yval + 1;
1048 
1049 }
1050 
1051 //////////////////////////////////////////////////////////////////////////////
1052 
scsp_dsp_multiply_test()1053 void scsp_dsp_multiply_test()
1054 {
1055    int i, j;
1056    int yval = 0;
1057    u16 test_vals[] = { 0x0100,0x0200,0x0400,0x0800,0x1000};
1058 
1059    for (i = 0; i < 5; i++)
1060    {
1061       for (j = 0; j < 5; j++)
1062       {
1063          scsp_dsp_start_test(test_vals[i], test_vals[j], &yval);
1064       }
1065    }
1066 
1067    for (;;)
1068    {
1069       vdp_vsync();
1070 
1071       if (per[0].but_push_once & PAD_START)
1072       {
1073          reset_system();
1074       }
1075    }
1076 }
1077 
1078 //convert all possible 16 bit floats and store them in vdp1 ram
scsp_dsp_generate_float_to_int_table()1079 void scsp_dsp_generate_float_to_int_table()
1080 {
1081    int i;
1082    int yval = 0;
1083    u16 test_val = 0;
1084 
1085    volatile u16* control_ptr = (u16 *)0x25b00400;
1086 
1087    control_ptr[1] = 0 << 7 | 0;
1088 
1089    int write_results = 1;
1090 
1091    if (write_results)//write results to vdp1 ram
1092    {
1093       volatile u32* dest = (u32 *)VDP1_RAM;
1094       int i;
1095 
1096       int pos = 1;
1097 
1098       dest[0] = 0xdeadbeef;//for verifying byte order
1099 
1100       //int increment = 1;
1101 
1102       int start = 0;
1103       int stop = 0xffff;
1104 
1105       for (i = start; i < stop; i++)
1106       {
1107          yval = 0;
1108          scsp_dsp_float_to_int_test(i, &yval);
1109          volatile u16* mems_ptr = (u16 *)0x25b00E00;
1110          u32 test_result = mems_ptr[2] | mems_ptr[3] << 8;
1111          dest[pos++] = test_result;
1112       }
1113 
1114       dest[pos] = 0xdeadbeef;//end of list
1115 
1116       vdp_printf(&test_disp_font, 24 * 8, 0 * 8, 0xF, "finished");
1117 
1118       for (;;)
1119       {
1120          while (!(VDP2_REG_TVSTAT & 8))
1121          {
1122             ud_check(0);
1123          }
1124 
1125          if (per[0].but_push_once & PAD_START)
1126          {
1127             reset_system();
1128          }
1129       }
1130    }
1131 
1132    for (;;)
1133    {
1134       vdp_vsync();
1135 
1136       if (per[0].but_push_once & PAD_A)
1137       {
1138          u32* dest = (u32 *)VDP2_RAM;
1139 
1140          int q;
1141          for (q = 0; q < 0x10000; q++)
1142             dest[q] = 0;
1143 
1144          scsp_dsp_float_to_int_test(test_val, &yval);
1145          test_val += 0x1111;
1146 
1147          volatile u16* mems_ptr = (u16 *)0x25b00E00;
1148 
1149          volatile u16* sound_ram_ptr = (u16 *)0x25a00000;
1150 
1151          for (i = 0; i < 28; i++)
1152             vdp_printf(&test_disp_font, 8 * 8, i * 8, 0xF, "0x%04x", sound_ram_ptr[i]);
1153 
1154          for (i = 0; i < 28; i++)
1155             vdp_printf(&test_disp_font, 16 * 8, i * 8, 0xF, "0x%04x", mems_ptr[i]);
1156 
1157          u32 test_result = mems_ptr[2] | mems_ptr[3] << 8;
1158 
1159          vdp_printf(&test_disp_font, 24 * 8, 0 * 8, 0xF, "0x%08x", test_result);
1160       }
1161 
1162       if (per[0].but_push_once & PAD_START)
1163       {
1164          reset_system();
1165       }
1166    }
1167 }
1168 
1169 
1170 //////////////////////////////////////////////////////////////////////////////
1171 
scsp_dsp_test()1172 void scsp_dsp_test()
1173 {
1174    scsp_minimal_init();
1175    unregister_all_tests();
1176    register_test(&scsp_dsp_register_write_test, "Register Read/Write Test");
1177    do_tests("SCSP DSP tests", 0, 0);
1178 }
1179 
1180 //////////////////////////////////////////////////////////////////////////////
1181 
1182 u16 square_table[] =
1183 {
1184    0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000, 0xc000,
1185    0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000
1186 };
1187 
1188 u16 square_table8[] =
1189 {
1190    0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
1191    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
1192 };
1193 
1194 #define KEYONEX 0x10000000
1195 #define KEYONB 0x08000000
1196 
1197 u16 fns_table[] = {
1198    0x0,0x3d,0x7d,0xc2,0x10a,0x157,0x1a8,0x1fe,0x25a,0x2ba,0x321,0x38d
1199 };
1200 
1201 //////////////////////////////////////////////////////////////////////////////
1202 
write_note(u8 which_slot,u32 sa,u16 lsa,u16 lea,u8 oct,u16 fns,u8 pcm8b,u8 loop,u8 plfows,u8 plfos,u8 lfof,u8 ar)1203 void write_note(u8 which_slot, u32 sa, u16 lsa, u16 lea, u8 oct, u16 fns, u8 pcm8b, u8 loop, u8 plfows, u8 plfos,u8 lfof, u8 ar)
1204 {
1205    volatile u16* slot_ptr = (u16 *)0x25b00000;
1206    volatile u32* slot_ptr_l = (u32 *)0x25b00000;
1207 
1208    int offset = which_slot * 0x10;
1209 
1210    //force a note off
1211    slot_ptr_l[which_slot * 0x8] = KEYONEX;
1212 
1213    slot_ptr_l[which_slot*0x8] = KEYONEX | KEYONB | sa | (pcm8b << 20) | (loop << 21);
1214    slot_ptr[offset + 2] = lsa;//lsa
1215    slot_ptr[offset + 3] = lea;//lea
1216    slot_ptr[offset + 4] = 0x0000 | ar;//d2r,d1r,ho,ar
1217    slot_ptr[offset + 5] = 0x001f;//ls,krs,dl,rr
1218    slot_ptr[offset + 6] = 0x0000;//si,sd,tl
1219    slot_ptr[offset + 7] = 0x0000;//mdl,mdxsl,mdysl
1220    slot_ptr[offset + 8] = (oct << 11) | fns;//oct,fns
1221    slot_ptr[offset + 9] = (lfof << 10) | (plfows << 8) | (plfos << 5) | (0 << 3) | 0;//re,lfof,plfows,plfos,alfows,alfos
1222    slot_ptr[offset + 10] = 0x0000;//isel,imxl
1223    slot_ptr[offset + 11] = 0xE000;//disdl,dipan,efsdl,efpan
1224 }
1225 
write_note_struct(u8 which_slot,struct SlotRegs * regs)1226 void write_note_struct(u8 which_slot, struct SlotRegs * regs)
1227 {
1228    volatile u16* slot_ptr = (u16 *)0x25b00000;
1229    volatile u32* slot_ptr_l = (u32 *)0x25b00000;
1230 
1231    int offset = which_slot * 0x10;
1232 
1233    //force a note off
1234    slot_ptr_l[which_slot * 0x8] = KEYONEX;
1235 
1236    slot_ptr_l[which_slot * 0x8] =
1237       KEYONEX |
1238       KEYONB |
1239       (regs->sbctl << 25) |
1240       (regs->ssctl << 23) |
1241       (regs->lpctl << 21) |
1242       (regs->pcm8b << 20) |
1243       regs->sa;
1244 
1245    slot_ptr[offset + 2] = regs->lsa;//lsa
1246    slot_ptr[offset + 3] = regs->lea;//lea
1247    slot_ptr[offset + 4] =
1248       (regs->d2r << 11) |
1249       (regs->d1r << 6) |
1250       (regs->hold << 5) |
1251       regs->ar;//d2r,d1r,ho,ar
1252    slot_ptr[offset + 5] = (regs->ls << 14) | (regs->krs << 10) | (regs->dl << 5) | regs->rr;//ls,krs,dl,rr
1253    slot_ptr[offset + 6] = (regs->si << 9) | (regs->sd << 8) | regs->tl;//si,sd,tl
1254    slot_ptr[offset + 7] = (regs->mdl << 12) | (regs->mdxsl << 6) | regs->mdysl;//mdl,mdxsl,mdysl
1255    slot_ptr[offset + 8] = (regs->oct << 11) | regs->fns;//oct,fns
1256    slot_ptr[offset + 9] = (regs->re << 15) | (regs->lfof << 10) | (regs->plfows << 8) | (regs->plfos << 5) | (regs->alfows << 3) | regs->alfos;//re,lfof,plfows,plfos,alfows,alfos
1257    slot_ptr[offset + 10] = 0x0000;//isel,imxl
1258    slot_ptr[offset + 11] = (regs->disdl << 13);//disdl,dipan,efsdl,efpan
1259 }
1260 
all_note_off()1261 void all_note_off()
1262 {
1263    volatile u32* slot_ptr_l = (u32 *)0x25b00000;
1264 
1265    int which_slot = 0;
1266    for(which_slot = 0; which_slot < 32; which_slot++)
1267       slot_ptr_l[which_slot * 0x8] = KEYONEX; //force a note off
1268 }
1269 
1270 //////////////////////////////////////////////////////////////////////////////
1271 
scsp_setup(u32 base_addr)1272 void scsp_setup(u32 base_addr)
1273 {
1274    int i;
1275 
1276    volatile u16* erase = (u16 *)(0x25a00000);
1277 
1278    for (i = 0; i < 0x20000; i++)
1279    {
1280       erase[i] = 0;
1281    }
1282 
1283    volatile u16* sound_ram_ptr_16 = (u16 *)(0x25a00000 + base_addr);
1284 
1285    for (i = 0; i < 16; i++)
1286    {
1287       sound_ram_ptr_16[i] = square_table[i];
1288    }
1289    int offset = 128;
1290 
1291    volatile u8* su8 = (u8 *)(0x25a00000 + offset + base_addr);
1292 
1293    for (i = 0; i < 16; i++)
1294    {
1295       su8[i] = square_table8[i];
1296    }
1297 
1298    volatile u16* control = (u16 *)0x25b00400;
1299    control[0] = 7;//master vol
1300 
1301    //write a long sample
1302    volatile u16* sound_ram_ptr_16a = (u16 *)(0x25a00000 + base_addr + 256);
1303 
1304    for (i = 0; i < 0xfff0; i++)
1305    {
1306       sound_ram_ptr_16a[i] = square_table[i&0xf];
1307    }
1308 }
1309 
vdp1_setup(u32 vdp1_tile_address)1310 void vdp1_setup(u32 vdp1_tile_address)
1311 {
1312    load_font_8x8_to_vram_1bpp_to_4bpp(vdp1_tile_address, VDP1_RAM);
1313    VDP1_REG_PTMR = 0x02;//draw automatically with frame change
1314    VDP2_REG_PRISA = 7 | (6 << 8);
1315    VDP2_REG_PRISB = 5 | (4 << 8);
1316    VDP2_REG_PRISC = 3 | (2 << 8);
1317    VDP2_REG_PRISD = 1 | (0 << 8);
1318    VDP2_REG_SPCTL = (0 << 12) | (0 << 8) | (0 << 5) | 7;
1319 }
1320 
scsp_test_note_on()1321 void scsp_test_note_on()
1322 {
1323    volatile u32* slot_ptr_l = (u32 *)0x25b00000;
1324 
1325    int oct = 0xd;
1326    int which_note = 0;
1327    int major_scale[] = { 0,2,4,5,7,9,11 };
1328 
1329    scsp_setup(0);
1330 
1331    write_note(0, 0, 0, 0x10 - 1, oct, 0x0, 0, 1,0,0,0,0x1f);
1332 
1333    int oct_test = 0xd;
1334 
1335    int lfof = 7;
1336    int plfows = 2;
1337    int plfos = 5;
1338 
1339    int is_8_bit = 0;
1340 
1341    if (!is_8_bit)
1342       write_note(0, 0, 0, 0x10 - 1, oct_test & 0xf, 0, 0, 1, plfows, plfos, lfof,0x8);
1343    else
1344       write_note(0, 128, 0, 15, oct_test & 0xf, 0, 1, 1, plfows, plfos, lfof, 0x8);
1345 
1346    for (;;)
1347    {
1348       vdp_vsync();
1349 
1350       int scale_note = major_scale[which_note];
1351       int fns = fns_table[scale_note];
1352 
1353       //key on
1354       if (per[0].but_push_once & PAD_A)
1355       {
1356          write_note(0, 0, 0, 0x10 - 1, oct, fns, 0, 1, 0, 0, 0, 0x1f);
1357          which_note++;
1358          if (which_note > 6)
1359             which_note = 0;
1360       }
1361 
1362       if (per[0].but_push_once & PAD_X)
1363       {
1364          write_note(1, 0, 0, 0x10 - 1, oct, fns, 0, 1, 0, 0, 0, 0x1f);
1365          which_note++;
1366          if (which_note > 6)
1367             which_note = 0;
1368       }
1369 
1370       //key off
1371       if (per[0].but_push_once & PAD_B)
1372       {
1373          slot_ptr_l[0] = KEYONB;
1374       }
1375 
1376       if (per[0].but_push_once & PAD_Z)
1377       {
1378          oct_test++;
1379          write_note(0, 0, 0, 0x10 - 1, oct_test & 0xf, fns, 0, 1, 0, 0, 0, 0x1f);
1380 
1381       }
1382 
1383       if (per[0].but_push_once & PAD_C)
1384       {
1385          oct_test--;
1386          write_note(0, 0, 0, 0x10 - 1, oct_test & 0xf, fns, 0, 1, 0, 0, 0, 0x1f);
1387       }
1388 
1389       if (per[0].but_push_once & PAD_L)
1390       {
1391          plfows++;
1392 
1393          if (plfows > 3)
1394             plfows = 0;
1395          write_note(0, 0, 0, 0x10 - 1, oct_test & 0xf, fns, 0, 1, plfows, plfos, lfof, 0x1f);
1396       }
1397 
1398       if (per[0].but_push_once & PAD_R)
1399       {
1400          lfof++;
1401 
1402          if (lfof > 31)
1403             lfof = 0;
1404          write_note(0, 0, 0, 0x10 - 1, oct_test & 0xf, fns, 0, 1, plfows, plfos, lfof, 0x1f);
1405       }
1406 
1407       if (per[0].but_push_once & PAD_Y)
1408       {
1409          plfos++;
1410 
1411          if (plfos > 7)
1412             plfos = 0;
1413          write_note(0, 0, 0, 0x10 - 1, oct_test & 0xf, fns, 0, 1, plfows, plfos, lfof, 0x1f);
1414       }
1415 
1416 
1417       if (per[0].but_push_once & PAD_START)
1418       {
1419          reset_system();
1420       }
1421    }
1422 }
1423 
1424 //play note from different starting addresses
scsp_test_addrs()1425 void scsp_test_addrs()
1426 {
1427    u32 addr = 0;
1428 
1429    scsp_setup(addr);
1430 
1431    write_note(0, addr + 128, 0, 0x10 - 1, 0xd, 0, 1, 1, 0, 0, 0, 0x1f);
1432 
1433    for (;;)
1434    {
1435       vdp_vsync();
1436       if (per[0].but_push_once & PAD_A)
1437       {
1438 
1439          addr += 0x100;
1440          addr &= 0xfffff;
1441 
1442          scsp_setup(addr);
1443 
1444          write_note(0, addr + 128, 0, 0x10 - 1, 0xd & 0xf, 0, 1, 1, 0, 0, 0, 0x1f);
1445       }
1446 
1447       if (per[0].but_push_once & PAD_START)
1448       {
1449          reset_system();
1450       }
1451    }
1452 }
1453 
1454 //write key on to each channel
scsp_test_all_channels()1455 void scsp_test_all_channels()
1456 {
1457    u32 addr = 0;
1458 
1459    scsp_setup(addr);
1460 
1461    write_note(0, addr + 128, 0, 0x10 - 1, 0xd, 0, 1, 1, 0, 0, 0, 0x1f);
1462 
1463    int channel = 0;
1464 
1465    for (;;)
1466    {
1467       vdp_vsync();
1468       if (per[0].but_push_once & PAD_A)
1469       {
1470          channel++;
1471 
1472          all_note_off();
1473 
1474          write_note(channel, addr + 128, 0, 0x10 - 1, 0xd & 0xf, 0, 1, 1, 0, 0, 0, 0x1f);
1475       }
1476 
1477       if (per[0].but_push_once & PAD_START)
1478       {
1479          reset_system();
1480       }
1481    }
1482 }
1483 
vdp1_boilerplate()1484 void vdp1_boilerplate()
1485 {
1486    vdp_start_draw_list();
1487    sprite_struct quad = { 0 };
1488 
1489    //system clipping
1490    quad.x = 320;
1491    quad.y = 224;
1492 
1493    vdp_system_clipping(&quad);
1494 
1495    //user clipping
1496    quad.x = 0;
1497    quad.y = 0;
1498    quad.x2 = 320;
1499    quad.y2 = 224;
1500 
1501    vdp_user_clipping(&quad);
1502 
1503    quad.x = 0;
1504    quad.y = 0;
1505 
1506    vdp_local_coordinate(&quad);
1507 }
1508 
print_regs(u32 which_slot,u32 vdp1_tile_address,u8 is_word)1509 void print_regs(u32 which_slot, u32 vdp1_tile_address, u8 is_word)
1510 {
1511    char str[128] = { 0 };
1512 
1513    int i;
1514 
1515    if (is_word)
1516    {
1517       volatile u16* slot_ptr = (u16 *)0x25b00000;
1518 
1519       int offset = which_slot * 0x10;
1520 
1521       for (i = 0; i < 16; i++)
1522       {
1523          u16 val = slot_ptr[offset + i];
1524          sprintf(str, "%04x", val);
1525          vdp1_print_str(0, i * 8, 4, vdp1_tile_address, str);
1526       }
1527    }
1528    else
1529    {
1530       volatile u8* slot_ptr = (u8 *)0x25b00000;
1531 
1532       int offset = which_slot * 0x20;
1533 
1534       int j = 0;
1535       for (i = 0; i < 32; i+=2)
1536       {
1537          u8 val = slot_ptr[offset + i];
1538          sprintf(str, "%02x", val);
1539          vdp1_print_str(0, j * 8, 4, vdp1_tile_address, str);
1540          val = slot_ptr[offset + i + 1];
1541          sprintf(str, "%02x", val);
1542          vdp1_print_str(16, j * 8, 4, vdp1_tile_address, str);
1543          j++;
1544       }
1545    }
1546 }
1547 
do_word_write(int which_slot,u16 value,u32 vdp1_tile_address)1548 void do_word_write(int which_slot, u16 value, u32 vdp1_tile_address)
1549 {
1550    int i;
1551 
1552    for (i = 0; i < 16; i++)
1553    {
1554       volatile u16* slot_ptr = (u16 *)0x25b00000;
1555       int offset = which_slot * 0x10;
1556 
1557       slot_ptr[i + offset] = value;
1558    }
1559    print_regs(which_slot, vdp1_tile_address, 1);
1560 }
1561 
do_byte_write(int which_slot,u8 value,u32 vdp1_tile_address)1562 void do_byte_write(int which_slot, u8 value, u32 vdp1_tile_address)
1563 {
1564    int i;
1565 
1566    for (i = 0; i < 32; i++)
1567    {
1568       volatile u8* slot_ptr = (u8 *)0x25b00000;
1569       int offset = which_slot * 0x20;
1570 
1571       slot_ptr[i + offset] = value;
1572    }
1573    print_regs(which_slot, vdp1_tile_address, 0);
1574 }
1575 
1576 //write and read all the slot registers
scsp_slot_reg_write_read()1577 void scsp_slot_reg_write_read()
1578 {
1579    const u32 vdp1_tile_address = 0x10000;
1580 
1581    vdp1_setup(vdp1_tile_address);
1582 
1583    int which_slot = 0;
1584 
1585    u8 val = 0;
1586 
1587    for (;;)
1588    {
1589       vdp_vsync();
1590 
1591       u16 write_val = val << 12 | val << 8 | val << 4 | val;
1592 
1593       if (per[0].but_push_once & PAD_A)
1594       {
1595          do_word_write(which_slot, write_val, vdp1_tile_address);
1596          val++;
1597       }
1598       if (per[0].but_push_once & PAD_B)
1599       {
1600          do_byte_write(which_slot, write_val, vdp1_tile_address);
1601          val++;
1602       }
1603 
1604       if (per[0].but_push_once & PAD_C)
1605       {
1606          which_slot++;
1607       }
1608       if (per[0].but_push_once & PAD_START)
1609       {
1610          reset_system();
1611       }
1612    }
1613 }
1614 
display_registers(int slot,u32 vdp1_tile_address)1615 void display_registers(int slot, u32 vdp1_tile_address)
1616 {
1617    char str[128] = { 0 };
1618    int i;
1619    volatile u16* control = (u16 *)(0x25b00400);
1620 
1621    int x_coord = 5;
1622 
1623    print_regs(slot, vdp1_tile_address, 1);
1624 
1625    for (i = 0; i < 30; i++)
1626    {
1627       u16 var = control[i];
1628       sprintf(str, "%04x ", var);
1629       vdp1_print_str(x_coord * 8, i * 8, 4, vdp1_tile_address, str);
1630    }
1631 
1632    x_coord += 5;
1633 
1634    for (i = 0; i < 32; i++)
1635    {
1636       volatile u16* stack = (u16 *)0x25b00600;
1637       sprintf(str, "%04x", stack[0 + i]);
1638       vdp1_print_str(x_coord * 8, i * 8, 4, vdp1_tile_address, str);
1639       sprintf(str, "%04x", stack[32 + i]);
1640       vdp1_print_str((x_coord+5) * 8, i * 8, 4, vdp1_tile_address, str);
1641    }
1642 }
1643 
1644 //record envelope deltas
scsp_envelope_edit()1645 void scsp_envelope_edit()
1646 {
1647    u32 addr = 0;
1648 
1649    const u32 vdp1_tile_address = 0x10000;
1650 
1651    vdp1_setup(vdp1_tile_address);
1652 
1653    scsp_setup(addr);
1654 
1655    int i;
1656 
1657    u32 max_snd_addr = 512;
1658 
1659    volatile u16* max_snd_ptr = (u16 *)(0x25a00000 + max_snd_addr);
1660 
1661    for (i = 0; i < 128; i++)
1662       max_snd_ptr[i] = 0x7fff;
1663 
1664    volatile u16* control = (u16 *)(0x25b00400);
1665 
1666    int monitor = 0;
1667 
1668    int menu_cursor = 0;
1669 
1670    int values[8] = { 0 };
1671 
1672    int initial_setting = 2;
1673 
1674    if (initial_setting == 0)
1675    {
1676       values[0] = 0x1;//ar
1677       values[5] = 0xf;//krs
1678    }
1679    else if (initial_setting == 1)
1680    {
1681       values[0] = 0xf;//ar
1682       values[1] = 0xf;//d1r
1683       values[2] = 0x0;//d2r
1684       values[3] = 0x0;//rr
1685       values[4] = 0x4;//dl
1686       values[5] = 0xf;//krs
1687    }
1688    else if (initial_setting == 2)
1689    {
1690       values[0] = 0xf;//ar
1691       values[1] = 0xf;//d1r
1692       values[2] = 0xe;//d2r
1693       values[3] = 0x0;//rr
1694       values[4] = 0x4;//dl
1695       values[5] = 0xf;//krs
1696    }
1697 
1698    char* value_names[] =
1699    {
1700       "ar",
1701       "d1r",
1702       "d2r",
1703       "rr",
1704       "dl",
1705       "krs",
1706       "ho"
1707    };
1708 
1709    struct ResultRecord
1710    {
1711       int frame;
1712       int env_value;
1713       int env_state;
1714    };
1715 
1716    struct ResultRecord results[512] = { { 0 } };
1717    int result_record_pos = 0;
1718 
1719    int test_active = 0;
1720    int test_frame = 0;
1721 
1722    int write_keyoff = 0;
1723    int keyoff_timer = 0;
1724    int keyoff_limit = 0;
1725 
1726    int record_all = 0;
1727 
1728    for (;;)
1729    {
1730       char str[128] = { 0 };
1731 
1732       vdp_vsync();
1733 
1734       if (write_keyoff)
1735       {
1736          if (keyoff_timer == keyoff_limit)
1737          {
1738             write_keyoff = 0;
1739             keyoff_timer = 0;
1740             volatile u8* slot_ptr = (u8 *)0x25b00000;
1741             //execute keyoff
1742             slot_ptr[0] = (1 << 4);
1743          }
1744          else
1745              keyoff_timer++;
1746       }
1747 
1748       if (test_active)
1749       {
1750          u32 val1 = (control[4] & 0x1f) << 5;//upper 5 bits of internal eg value
1751          u32 val2 = (control[4] >> 5) & 3;//current envelope state
1752 
1753          if (record_all)
1754          {
1755             result_record_pos++;
1756             results[result_record_pos].frame = test_frame;
1757             results[result_record_pos].env_value = val1;
1758             results[result_record_pos].env_state = val2;
1759          }
1760          else
1761          {
1762             //just record the differences
1763             if (results[result_record_pos].env_value != val1 ||
1764                results[result_record_pos].env_state != val2)
1765             {
1766                result_record_pos++;
1767                results[result_record_pos].frame = test_frame;
1768                results[result_record_pos].env_value = val1;
1769                results[result_record_pos].env_state = val2;
1770             }
1771          }
1772 
1773          if (result_record_pos > 28 || test_frame > (60*5))
1774          {
1775             test_active = 0;
1776 
1777             int j;
1778 
1779             //zero unused results
1780             for (j = result_record_pos + 1; j < 28; j++)
1781             {
1782                results[j].frame = 0;
1783                results[j].env_value = 0;
1784                results[j].env_state = 0;
1785             }
1786          }
1787 
1788          test_frame++;
1789       }
1790 
1791       control[4] = monitor << 11;
1792 
1793       vdp1_boilerplate();
1794 
1795       display_registers(monitor, vdp1_tile_address);
1796 
1797       vdp1_print_str(20 * 8, menu_cursor * 8, 4, vdp1_tile_address, ">");
1798 
1799       for (i = 0; i < 6; i++)
1800       {
1801          sprintf(str, "%s: %02x", value_names[i], values[i]);
1802          vdp1_print_str(21 * 8, i * 8, 4, vdp1_tile_address, str);
1803       }
1804 
1805       u16 val1 = (control[4] & 0x1f) << 5;//upper 5 bits of internal eg value
1806       u16 val2 = (control[4] >> 5) & 3;//current envelope state
1807       sprintf(str, "%04x  %01x", val1, val2);
1808       vdp1_print_str(21 * 8, 27 * 8, 4, vdp1_tile_address, str);
1809 
1810       for (i = 0; i < 28; i++)
1811       {
1812          sprintf(str, "%02x %03x %01x", results[i].frame, results[i].env_value, results[i].env_state);
1813          vdp1_print_str(30 * 8, i * 8, 4, vdp1_tile_address, str);
1814       }
1815 
1816       vdp_end_draw_list();
1817 
1818       if (
1819          per[0].but_push_once & PAD_A ||
1820          per[0].but_push_once & PAD_B ||
1821          per[0].but_push_once & PAD_C)
1822       {
1823          struct SlotRegs slot = { 0 };
1824 
1825          slot.sa = addr;
1826          slot.lsa = 0;
1827          slot.lea = 15;
1828 
1829          slot.lpctl = 1;
1830          slot.oct = 0xb;
1831          slot.fns = 0;
1832          slot.disdl = 7;
1833 
1834          slot.ar = values[0];
1835          slot.d1r = values[1];
1836          slot.d2r = values[2];
1837          slot.rr = values[3];
1838          slot.dl = values[4];
1839          slot.krs = values[5];
1840          slot.hold = values[6];
1841 
1842          all_note_off();
1843 
1844          test_active = 1;
1845          test_frame = 0;
1846          result_record_pos = 0;
1847 
1848          write_note_struct(0, &slot);
1849 
1850          if(per[0].but_push_once & PAD_B)
1851          {
1852             write_keyoff = 1;
1853             keyoff_timer = 0;
1854             keyoff_limit = 10;
1855          }
1856 
1857          if (per[0].but_push_once & PAD_C)
1858          {
1859             write_keyoff = 1;
1860             keyoff_timer = 0;
1861             keyoff_limit = 2;
1862          }
1863       }
1864 
1865       if (per[0].but_push_once & PAD_UP)
1866       {
1867          menu_cursor--;
1868 
1869          if (menu_cursor < 0)
1870             menu_cursor = 0;
1871       }
1872 
1873       if (per[0].but_push_once & PAD_DOWN)
1874       {
1875          menu_cursor++;
1876       }
1877 
1878       if (per[0].but_push_once & PAD_LEFT)
1879       {
1880          values[menu_cursor]--;
1881       }
1882 
1883       if (per[0].but_push_once & PAD_RIGHT)
1884       {
1885          values[menu_cursor]++;
1886       }
1887 
1888       if (per[0].but_push_once & PAD_START)
1889       {
1890          reset_system();
1891       }
1892    }
1893 }
1894 
1895 //sweep entire pitch spectrum
scsp_full_sweep()1896 void scsp_full_sweep()
1897 {
1898    const u32 vdp1_tile_address = 0x10000;
1899 
1900    vdp1_setup(vdp1_tile_address);
1901 
1902    int addr = 0;
1903 
1904    scsp_setup(addr);
1905 
1906    int monitor = 0;
1907 
1908    int oct = 10;
1909    int fns = 0;
1910 
1911    for (;;)
1912    {
1913       vdp_vsync();
1914 
1915       fns += 10;
1916 
1917       if (fns >= 0x3FF)
1918          fns = 0;
1919 
1920       volatile u16* slot_ptr = (u16 *)0x25b00000;
1921 
1922       int offset = 0 * 0x10;
1923 
1924       slot_ptr[offset + 8] = (oct << 11) | fns;//oct,fns
1925 
1926       vdp1_boilerplate();
1927 
1928       display_registers(monitor, vdp1_tile_address);
1929 
1930       vdp_end_draw_list();
1931 
1932       if (per[0].but_push_once & PAD_UP)
1933       {
1934          oct++;
1935 
1936          if (oct > 0xf)
1937             oct = 0xf;
1938       }
1939 
1940       if (per[0].but_push_once & PAD_DOWN)
1941       {
1942          oct--;
1943 
1944          if (oct < 0)
1945             oct = 0;
1946       }
1947 
1948       if (per[0].but_push_once & PAD_A)
1949       {
1950          struct SlotRegs slot = { 0 };
1951 
1952          slot.sa = addr;
1953          slot.lsa = 0;
1954          slot.lea = 15;
1955 
1956          slot.lpctl = 1;
1957          slot.disdl = 7;
1958 
1959          slot.ar = 0x1f;
1960 
1961          all_note_off();
1962 
1963          write_note_struct(0, &slot);
1964       }
1965 
1966       if (per[0].but_push_once & PAD_START)
1967       {
1968          reset_system();
1969       }
1970    }
1971 }
1972 
1973 //test different starting addresses
scsp_address_decode()1974 void scsp_address_decode()
1975 {
1976    const u32 vdp1_tile_address = 0x10000;
1977 
1978    vdp1_setup(vdp1_tile_address);
1979 
1980    int addr = 0;
1981 
1982    scsp_setup(addr);
1983 
1984    int monitor = 0;
1985 
1986    int oct = 10;
1987    int fns = 0;
1988 
1989    char str[128] = { 0 };
1990 
1991    for (;;)
1992    {
1993       vdp_vsync();
1994 
1995       volatile u16* slot_ptr = (u16 *)0x25b00000;
1996 
1997       int offset = 0 * 0x10;
1998 
1999       slot_ptr[offset + 8] = (oct << 11) | fns;//oct,fns
2000 
2001       vdp1_boilerplate();
2002 
2003       display_registers(monitor, vdp1_tile_address);
2004 
2005       sprintf(str, "%04x", addr);
2006       vdp1_print_str(21 * 8, 27 * 8, 4, vdp1_tile_address, str);
2007 
2008       vdp_end_draw_list();
2009 
2010       if (per[0].but_push_once & PAD_UP)
2011       {
2012          oct++;
2013 
2014          if (oct > 0xf)
2015             oct = 0xf;
2016       }
2017 
2018       if (per[0].but_push_once & PAD_DOWN)
2019       {
2020          oct--;
2021 
2022          if (oct < 0)
2023             oct = 0;
2024       }
2025 
2026       if (per[0].but_push_once & PAD_A ||
2027          per[0].but_push_once & PAD_B ||
2028          per[0].but_push_once & PAD_C ||
2029          per[0].but_push_once & PAD_X ||
2030          per[0].but_push_once & PAD_Y ||
2031          per[0].but_push_once & PAD_Z)
2032       {
2033          struct SlotRegs slot = { 0 };
2034 
2035 
2036          if (per[0].but_push_once & PAD_A)
2037             addr -= 0x10;
2038 
2039          if (per[0].but_push_once & PAD_X)
2040             addr += 0x10;
2041 
2042          if (per[0].but_push_once & PAD_B)
2043             addr -= 0x100;
2044 
2045          if (per[0].but_push_once & PAD_Y)
2046             addr += 0x100;
2047 
2048          if (per[0].but_push_once & PAD_C)
2049             addr -= 0x1000;
2050 
2051          if (per[0].but_push_once & PAD_Z)
2052             addr += 0x1000;
2053 
2054          if (addr < 0)
2055             addr = 0;
2056 
2057          slot.sa = addr;
2058          slot.lsa = 0;
2059          slot.lea = 15;
2060 
2061          slot.lpctl = 1;
2062          slot.disdl = 7;
2063 
2064          slot.ar = 0x1f;
2065 
2066          all_note_off();
2067 
2068          write_note_struct(0, &slot);
2069       }
2070 
2071       if (per[0].but_push_once & PAD_START)
2072       {
2073          reset_system();
2074       }
2075    }
2076 }
2077 
scsp_fm_slot_connection()2078 void scsp_fm_slot_connection()
2079 {
2080    u32 addr = 0;
2081 
2082    const u32 vdp1_tile_address = 0x10000;
2083 
2084    vdp1_setup(vdp1_tile_address);
2085 
2086    scsp_setup(addr);
2087 
2088    struct SlotRegs slot = { 0 };
2089 
2090    slot.sa = addr;
2091    slot.lpctl = 1;
2092    slot.oct = 0xf;
2093    slot.fns = 0;
2094    slot.disdl = 7;
2095    slot.lsa = 0;
2096    slot.lea = 15;
2097    slot.ar = 0x1f;
2098 
2099    write_note_struct(0, &slot);
2100 
2101    int mdxsl = 0x20;
2102    int mdl = 0xa;
2103 
2104    char str[128] = { 0 };
2105 
2106    int i;
2107 
2108    u32 sound_len = 1024*3;
2109 
2110    volatile u16* sound_ram_ptr_16 = (u16 *)(0x25a00000);
2111 
2112    for (i = 0; i < sound_len; i++)
2113    {
2114       sound_ram_ptr_16[i] = sine_tbl[i & 0xff] << 8;
2115    }
2116 
2117    volatile u16* control = (u16 *)(0x25b00400);
2118 
2119    int monitor = 0xa;
2120 
2121    int capture = 0;
2122 
2123    for (;;)
2124    {
2125       vdp_vsync();
2126 
2127       control[4] = monitor << 11;
2128 
2129       vdp1_boilerplate();
2130 
2131       display_registers(monitor, vdp1_tile_address);
2132 
2133       if (per[0].but_push_once & PAD_UP)
2134       {
2135          mdxsl++;
2136       }
2137       if (per[0].but_push_once & PAD_DOWN)
2138       {
2139          mdxsl--;
2140 
2141          if (mdxsl < 0)
2142             mdxsl = 0;
2143       }
2144       if (per[0].but_push_once & PAD_LEFT)
2145       {
2146          mdl--;
2147       }
2148       if (per[0].but_push_once & PAD_RIGHT)
2149       {
2150          mdl++;
2151 
2152          if (mdl > 0xf)
2153             mdl = 0xf;
2154       }
2155 
2156       if (per[0].but_push_once & PAD_L)
2157       {
2158          monitor--;
2159 
2160          if (monitor < 0)
2161             monitor = 0;
2162       }
2163 
2164       if (per[0].but_push_once & PAD_R)
2165       {
2166          monitor++;
2167       }
2168 
2169       sprintf(str, "mdxsl: %02x mdl: %02x", mdxsl, mdl);
2170       vdp1_print_str(20 * 8, 0 * 8, 4, vdp1_tile_address, str);
2171 
2172       u16 ca = (control[4] >> 7) & 0xf;
2173       sprintf(str, "ca: %04x mon: %04x %04x", ca, monitor, capture);
2174       vdp1_print_str(20 * 8, 16 * 8, 4, vdp1_tile_address, str);
2175 
2176       vdp_end_draw_list();
2177 
2178       //one modulator both slots
2179       if (per[0].but_push_once & PAD_X)
2180       {
2181          slot.krs = 0xf;
2182          slot.sd = 1;
2183          slot.tl = 0;
2184          slot.sa = 1024;
2185          slot.lsa = 0;
2186          slot.lea = 1023;
2187 
2188          slot.ar = 0x1f;
2189          slot.hold = 0;
2190          slot.d1r = 0;
2191          slot.d2r = 0;
2192          slot.rr = 0;
2193          slot.dl = 0;
2194          slot.disdl = 7;
2195 
2196          slot.mdl = mdl;
2197          slot.mdxsl = mdxsl;
2198          slot.mdysl = mdxsl;
2199 
2200          all_note_off();
2201 
2202          write_note_struct(monitor + 0, &slot);
2203 
2204          slot.sa = 1024;
2205          slot.lsa = 0;
2206          slot.lea = 1023;
2207 
2208          slot.ar = 0x1f;
2209          slot.hold = 0;
2210          slot.d1r = 0;
2211          slot.d2r = 0;
2212          slot.rr = 0;
2213          slot.dl = 0;
2214 
2215          slot.disdl = 0;
2216 
2217          slot.mdl = 0;
2218          slot.mdxsl = 0;
2219          slot.mdysl = 0;
2220 
2221          write_note_struct(monitor + 1, &slot);
2222       }
2223 
2224       if (per[0].but_push_once & PAD_START)
2225       {
2226          reset_system();
2227       }
2228    }
2229 }
2230 
2231 //////////////////////////////////////////////////////////////////////////////
2232 
2233 /*
2234 void mcipd_test_func()
2235 {
2236    u16 mcipd_temp=SCSPREG_MCIPD;
2237 
2238    vdp_printf(&test_disp_font, 1 * 8, 22 * 8, 0xF, "MCIPD: %04X", mcipd_temp);
2239 }
2240 
2241 //////////////////////////////////////////////////////////////////////////////
2242 
2243 void scsp_mcipd_test()
2244 {
2245    // Disable everything temporarily
2246    SCSPREG_SCIEB = 0;
2247    SCSPREG_MCIEB = 0;
2248 
2249    // Mask SCSP/H-blank interrupts temporarily
2250    bios_change_scu_interrupt_mask(0xFFFFFFFF, 0x40);
2251 
2252    // Set SCSP interrupt function
2253    bios_set_scu_interrupt(0x46, mcipd_test_func);
2254 
2255    // Unmask SCSP/H-blank interrupts
2256    bios_change_scu_interrupt_mask(~0x40, 0);
2257 
2258    stagestatus = STAGESTAT_WAITINGFORINT;
2259 
2260    // Enable timer
2261    SCSPREG_TIMERA = 0x0700;
2262    SCSPREG_MCIRE = 0x40;
2263    SCSPREG_MCIEB = 0x40;
2264 }
2265 
2266 //////////////////////////////////////////////////////////////////////////////
2267 
2268 */
2269