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