1 /*  src/scsp2.c: New, threadable SCSP implementation for Yabause
2     Copyright 2004 Stephane Dallongeville
3     Copyright 2004-2007 Theo Berkau
4     Copyright 2006 Guillaume Duhamel
5     Copyright 2010 Andrew Church
6 
7     This file is part of Yabause.
8 
9     Yabause is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13 
14     Yabause is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with Yabause; if not, write to the Free Software
21     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
22 */
23 
24 #include "core.h"
25 #include "debug.h"
26 #include "error.h"
27 #include "m68kcore.h"
28 #include "memory.h"
29 #include "scsp.h"
30 #include "threads.h"
31 #include "yabause.h"
32 
33 #include <math.h>
34 #include <stdlib.h>
35 
36 #undef round  // In case math.h defines it
37 #define round(x)  ((int) (floor((x) + 0.5)))
38 
39 #undef ScspInit  // Disable compatibility alias
40 
41 extern SoundInterface_struct *SNDCoreList[];  // Defined by each port
42 
43 ///////////////////////////////////////////////////////////////////////////
44 
45 // This SCSP implementation is designed to be runnable as an independent
46 // thread, encompassing the SCSP emulation itself as well as the MC68EC000
47 // sound processor and the actual generation of PCM audio data.
48 //
49 // When running in multithreaded mode, the actual SCSP and M68K emulation
50 // is performed via ScspThread().  This function is started as a subthread
51 // (YAB_THREAD_SCSP), and loops over ScspDoExec() until scsp_thread_running
52 // goes to zero, which is used as a signal for the thread to stop.
53 // Synchronization is performed via the scsp_clock_target variable; the SCSP
54 // thread sleeps until clock_target != clock, then calls ScspDoExec() for
55 // (clock - clock_target) cycles.  The main thread wakes up the subthread
56 // both when clock_target is updated and when register writes, discussed
57 // below, are submitted.
58 //
59 // Additionally, any register writes from outside the SCSP/M68K will be
60 // processed synchronously in multithreaded mode, by passing the write
61 // through a shared buffer (scsp_write_buffer_* variables).  When the
62 // thread loop detects scsp_write_buffer_size nonzero, it processes the
63 // write before its next ScspDoExec() iteration and clears ..._size; the
64 // main thread then waits for ..._size to return to zero before returning
65 // from the write operation.  (This will typically be no more expensive
66 // than a pair of context switches, and it seems that SCSP register writes
67 // from the SH-2 are uncommon.)
68 //
69 // The "PSP_*" macros scattered throughout the file are to support the
70 // execution of the SCSP thread on the Media Engine CPU (ME) in the PSP.
71 // The ME lacks cache coherence with the main CPU (SC), so special care
72 // needs to be taken to avoid bugs arising from inconsistent cache states;
73 // see the technical notes in README.PSP for details.  These macros are all
74 // no-ops on other platforms.
75 
76 //-------------------------------------------------------------------------
77 // PSP cache management macros
78 
79 #ifdef PSP
80 
81 # include "psp/common.h"
82 # include "psp/me.h"
83 # include "psp/me-utility.h"
84 # include "psp/misc.h"  // psp_writeback_cache_for_scsp() declaration
85 
86 // Data section management (to avoid cache line collisions between CPUs)
87 # define PSP_SECTION(name) \
88    __attribute__((section(".meshared.scsp." #name)))
89 # define PSP_SECTION_START(name) \
90    __attribute__((section(".meshared.scsp." #name), aligned(64))) \
91    extern volatile char __scsp_sectstart_##name[64];
92 # define PSP_SECTION_END(name) \
93    __attribute__((section(".meshared.scsp." #name))) \
94    extern volatile char __scsp_sectend_##name;
95 
96 // Cache control
97 # define PSP_WRITEBACK_CACHE(ptr,len) \
98    sceKernelDcacheWritebackRange((ptr), (len))
99 # define PSP_WRITEBACK_ALL() \
100    sceKernelDcacheWritebackAll()
101 # define PSP_FLUSH_ALL() \
102    sceKernelDcacheWritebackInvalidateAll()
103 
104 // Uncached pointer access
105 # define PSP_UCPTR(ptr) ((typeof(&*ptr))((uint32_t)(ptr) | 0x40000000))
106 // Uncached variable access (either read or write)
107 # define PSP_UC(var) (*((typeof(&var))((uint32_t)(&var) | 0x40000000)))
108 
109 #else  // !PSP
110 
111 # define PSP_SECTION(name)              /*nothing*/
112 # define PSP_SECTION_START(name)        /*nothing*/
113 # define PSP_SECTION_END(name)          /*nothing*/
114 # define PSP_WRITEBACK_CACHE(ptr,len)   /*nothing*/
115 # define PSP_WRITEBACK_ALL()            /*nothing*/
116 # define PSP_FLUSH_ALL()                /*nothing*/
117 # define PSP_UCPTR(ptr)                 ptr
118 # define PSP_UC(var)                    var
119 
120 #endif
121 
122 //-------------------------------------------------------------------------
123 // SCSP constants
124 
125 // SCSP hardware version (4 bits)
126 #define SCSP_VERSION            0
127 
128 // SCSP clock frequency (11.2896 MHz, or exactly 44100*256)
129 #define SCSP_CLOCK_FREQ         (44100 * 256)
130 
131 // SCSP output frequency
132 #define SCSP_OUTPUT_FREQ        (SCSP_CLOCK_FREQ / 256)
133 
134 // SCSP clock increment per 1/10 scanline
135 #define SCSP_CLOCK_INC_NTSC     (((u64)SCSP_CLOCK_FREQ<<20) * 1001 / 60000 / 263 / 10)
136 #define SCSP_CLOCK_INC_PAL      (((u64)SCSP_CLOCK_FREQ<<20) / 50 / 313 / 10)
137 
138 // Limit on execution time for a single thread loop (in SCSP clock cycles);
139 // if the thread's delay exceeds this value, we stop in the main loop to
140 // let the SCSP catch up
141 #define SCSP_CLOCK_MAX_EXEC     (SCSP_CLOCK_FREQ / 1000)
142 
143 // Sound RAM size
144 #define SCSP_RAM_SIZE           0x80000
145 #define SCSP_RAM_MASK           (SCSP_RAM_SIZE - 1)
146 
147 // Envelope phases
148 #define SCSP_ENV_RELEASE        0
149 #define SCSP_ENV_SUSTAIN        1
150 #define SCSP_ENV_DECAY          2
151 #define SCSP_ENV_ATTACK         3
152 
153 // LFO waveform types (equal to ALFOWS/PLFOWS values)
154 #define SCSP_LFO_SAWTOOTH       0
155 #define SCSP_LFO_SQUARE         1
156 #define SCSP_LFO_TRIANGLE       2
157 #define SCSP_LFO_NOISE          3
158 
159 // Bit sizes of fixed-point counters
160 
161 // Fractional part of frequency counter (determines accuracy of audio
162 // playback frequency)
163 #define SCSP_FREQ_LOW_BITS      10
164 // Integer part of envelope counter (determines resolution of attack/decay
165 // envelope); also used to define envelope value range
166 #define SCSP_ENV_HIGH_BITS      10
167 // Fractional part of envelope counter (determines accuracy of envelope timing)
168 #define SCSP_ENV_LOW_BITS       10
169 // Integer part of LFO counter (determines resolution of LFO waveform);
170 // also used to define LFO value range
171 #define SCSP_LFO_HIGH_BITS      10
172 // Fractional part of LFO counter (determines accuracy of LFO frequency)
173 #define SCSP_LFO_LOW_BITS       10
174 // Fractional part of TL attenuation lookup table (determines resolution of
175 // per-voice volume control)
176 #define SCSP_TL_BITS            10
177 
178 // Envelope/waveform table data sizes and corresponding masks
179 #define SCSP_ENV_LEN            (1 << SCSP_ENV_HIGH_BITS)
180 #define SCSP_ENV_MASK           (SCSP_ENV_LEN - 1)
181 #define SCSP_LFO_LEN            (1 << SCSP_LFO_HIGH_BITS)
182 #define SCSP_LFO_MASK           (SCSP_LFO_LEN - 1)
183 
184 // Envelope attack/decay points (counter values)
185 #define SCSP_ENV_ATTACK_START   0
186 #define SCSP_ENV_DECAY_START    (SCSP_ENV_LEN << SCSP_ENV_LOW_BITS)
187 #define SCSP_ENV_ATTACK_END     (SCSP_ENV_DECAY_START - 1)
188 #define SCSP_ENV_DECAY_END      (((2 * SCSP_ENV_LEN) << SCSP_ENV_LOW_BITS) - 1)
189 
190 // Envelope attack/decay base times
191 #define SCSP_ATTACK_TIME        ((u32) (8 * SCSP_OUTPUT_FREQ))
192 #define SCSP_DECAY_TIME         ((u32) (12 * SCSP_ATTACK_TIME))
193 
194 // Interrupt bit numbers
195 #define SCSP_INTERRUPT_MIDI_IN  3       // Data available in MIDI input buffer
196 #define SCSP_INTERRUPT_DMA      4       // DMA complete
197 #define SCSP_INTERRUPT_MANUAL   5       // 1 written to bit 5 of [MS]CIPD
198 #define SCSP_INTERRUPT_TIMER_A  6       // Timer A reached 0xFF
199 #define SCSP_INTERRUPT_TIMER_B  7       // Timer B reached 0xFF
200 #define SCSP_INTERRUPT_TIMER_C  8       // Timer C reached 0xFF
201 #define SCSP_INTERRUPT_MIDI_OUT 9       // MIDI output buffer became empty
202 #define SCSP_INTERRUPT_SAMPLE   10      // Raised once per output sample
203 
204 // Interrupt target flags
205 #define SCSP_INTTARGET_MAIN     (1 << 0)  // Interrupt to main CPU (SCU)
206 #define SCSP_INTTARGET_SOUND    (1 << 1)  // Interrupt to sound CPU
207 #define SCSP_INTTARGET_BOTH     (SCSP_INTTARGET_MAIN | SCSP_INTTARGET_SOUND)
208 
209 // PCM output buffer size parameters
210 #define SCSP_SOUND_LEN_NTSC     (SCSP_OUTPUT_FREQ / 60)  // Samples per frame
211 #define SCSP_SOUND_LEN_PAL      (SCSP_OUTPUT_FREQ / 50)
212 // Reserve 10x the maximum samples per frame
213 #define SCSP_SOUND_BUFSIZE      (10 * SCSP_SOUND_LEN_PAL)
214 
215 // CDDA data buffer size in sectors (must be at least 3)
216 #define CDDA_NUM_BUFFERS        3
217 
218 // CDDA playback start delay in samples (see cdda_delay comments)
219 #define CDDA_DELAY_SAMPLES      100
220 
221 //-------------------------------------------------------------------------
222 // Internal state data structures
223 
224 // Per-slot data structure
225 
226 typedef struct SlotState_struct
227 {
228    ////////////
229    // Register fields
230 
231    // ISR $00
232                         // [12] Write 1 to execute KEY state change
233    u8   key;            // [11] KEY state (on/off)
234    u8   sbctl;          // [10:9] Source bit control
235    u8   ssctl;          // [8:7] Sound source control
236    u8   lpctl;          // [6:5] Loop control
237    u8   pcm8b;          // [4] PCM sound format
238                         // [3:0] Start address (in bytes), high bits (19:16)
239 
240    // ISR $02
241    u32  sa;             // [15:0] Start address (in bytes), low bits (15:0)
242 
243    // ISR $04
244    u16  lsa;            // [15:0] Loop start address (in samples)
245 
246    // ISR $06
247    u16  lea;            // [15:0] Loop end address (in samples)
248 
249    // ISR $08
250    u8   sr;             // [15:11] Sustain rate
251    u8   dr;             // [10:6] Decay rate
252    u8   eghold;         // [5] Envelope hold (attack rate 0) flag
253    u8   ar;             // [4:0] Attack rate
254 
255    // ISR $0A
256    u8   lpslnk;         // [14] Loop start link (start decay on reaching LSA)
257    u8   krs;            // [13:10] Key rate scale
258    u8   sl;             // [9:5] Sustain level
259    u8   rr;             // [4:0] Release rate
260 
261    // ISR $0C
262    u8   stwinh;         // [9] Stack write inhibit flag
263    u8   sdir;           // [8] Sound direct output flag
264    u8   tl;             // [7:0] Total level
265 
266    // ISR $0E
267    u8   mdl;            // [15:12] Modulation level
268    u8   mdx;            // [11:6] Modulation source X
269    u8   mdy;            // [5:0] Modulation source Y
270 
271    // ISR $10
272    u8   oct;            // [14:11] Octave (treated as signed -8..7)
273    u16  fns;            // [9:0] Frequency number switch
274 
275    // ISR $12
276    u8   lfore;          // [15] LFO reset flag (1 = reset, 0 = count)
277    u8   lfof;           // [14:10] LFO frequency index
278    u8   plfows;         // [9:8] Pitch LFO waveform select
279    u8   plfos;          // [7:5] Pitch LFO sensitivity
280    u8   alfows;         // [4:3] Amplitude LFO waveform select
281    u8   alfos;          // [2:0] Amplitude LFO sensitivity
282 
283    // ISR $14
284    u8   isel;           // [6:3] Input selector
285    u8   imxl;           // [2:0] Input mix level
286 
287    // ISR $16
288    u8   disdl;          // [15:13] Direct data send level
289    u8   dipan;          // [12:8] Direct data pan position
290    u8   efsdl;          // [7:5] Effect data send level
291    u8   efpan;          // [2:0] Effect data pan position
292 
293    ////////////
294    // Internal state
295 
296    // Audio generation routine (selected based on slot parameters)
297    void (* FASTCALL audiogen)(struct SlotState_struct *slot, u32 len);
298 
299    const void *buf;     // Pointer to sample data in sound RAM
300 
301    u32  addr_counter;   // Address (playback) counter
302    u32  addr_step;      // Address counter increment
303    u8   octave_shift;   // Octave shift amount (0..15)
304    u32  lsa_shifted;    // lsa << SCSP_FREQ_LOW_BITS (for addr_counter)
305    u32  lea_shifted;    // lea << SCSP_FREQ_LOW_BITS (for addr_counter)
306    u32  looplen_shifted;// (lea - lsa + 1) << SCSP_FREQ_LOW_BITS
307 
308    u32  env_phase;      // Current envelope phase (attack/decay/...)
309    s32  env_counter;    // Envelope counter
310    s32  env_step;       // Envelope counter increment for current phase
311    s32  env_target;     // Envelope target value for advancing to next phase
312    s32  env_step_a;     // Envelope counter increment for attack phase
313    s32  env_step_d;     // Envelope counter increment for decay phase
314    s32  env_step_s;     // Envelope counter increment for sustain phase
315    s32  env_step_r;     // Envelope counter increment for release phase
316    s32  last_env;       // Last calculated envelope multiplier
317    u8   krs_shift;      // Shift count corresponding to KRS
318    s32  sl_target;      // Compare value corresponding to SL
319    s32  tl_mult;        // Envelope volume multiplier corresponding to TL
320 
321    u32  lfo_counter;    // LFO counter (fixed point index into LFO waveforms)
322    s32  lfo_step;       // LFO counter increment, or -1 if in reset mode
323    s32  *lfo_fm_wave;   // LFO frequency modulation waveform pointer
324    s32  *lfo_am_wave;   // LFO amplitude modulation waveform pointer
325    s8   lfo_fm_shift;   // LFO frequency modulation strength, -1 if disabled
326    s8   lfo_am_shift;   // LFO amplitude modulation strength, -1 if disabled
327 
328    u8   outshift_l;     // Output shift for left channel (down to 16 bits)
329    u8   outshift_r;     // Output shift for right channel (down to 16 bits)
330 
331    u8   imxl_shift;     // Shift count for IMXL
332 
333 } SlotState;
334 
335 //------------------------------------
336 
337 // Overall SCSP data structure
338 
339 typedef struct ScspState_struct {
340 
341    ////////////
342    // Register fields
343 
344    // $400
345    u8   mem4mb;         // [9] Sound RAM memory size flag (4Mbit vs. 2Mbit)
346    u8   dac18b;         // [8] DAC 18-bit output flag (ignored)
347    u8   ver;            // [7:4] Hardware version (fixed at 0)
348    u8   mvol;           // [3:0] Master volume
349 
350    // $402
351    u8   rbl;            // [8:7] Ring buffer length (8192<<RBL words)
352    u32  rbp;            // [6:0] Ring buffer pointer 19:13 (low bits are zero)
353 
354    // $404
355    u8   mofull;         // [12] MIDI output FIFO full flag
356    u8   moemp;          // [11] MIDI output FIFO empty flag
357    u8   miovf;          // [10] MIDI input FIFO overflow flag
358    u8   mifull;         // [9] MIDI input FIFO full flag
359    u8   miemp;          // [8] MIDI input FIFO empty flag
360    u8   mibuf;          // [7:0] MIDI input data buffer
361 
362    // $406
363    u8   mobuf;          // [7:0] MIDI output data buffer
364 
365    // $408
366    u8   mslc;           // [15:11] Monitor slot
367    u8   ca;             // [10:7] Call address
368    u8   sgc;            // [6:5] Envelope phase
369    u8   eg;             // [4:0] Envelope volume
370 
371    // $40A..$410 unused (possibly used in the model 2 SCSP?)
372 
373    // $412              // [15:1] DMA transfer start address 15:1
374    u32  dmea;
375 
376    // $414
377                         // [15:12] DMA transfer start address 19:16
378    u16  drga;           // [11:1] DMA register address 11:1
379 
380    // $416
381    u8   dgate;          // [14] DMA gate (1 = zero-clear target)
382    u8   ddir;           // [13] DMA direction (0 = from, 1 = to sound RAM)
383    u8   dexe;           // [12] DMA execute (write 1 to start; returns to 0 when done)
384    u16  dtlg;           // [11:1] DMA transfer length 11:1
385 
386    // $418
387    u8   tactl;          // [10:8] Timer A step divisor (step every 1<<tactl output samples)
388    u16  tima;           // [7:0] Timer A counter (sends an IRQ at 0xFF), as 8.8 fixed point
389 
390    // $41A
391    u8   tbctl;          // [10:8] Timer B step divisor
392    u16  timb;           // [7:0] Timer B counter, as 8.8 fixed point
393 
394    // $41C
395    u8   tcctl;          // [10:8] Timer C step divisor
396    u16  timc;           // [7:0] Timer C counter, as 8.8 fixed point
397 
398    // $41E
399    u16  scieb;          // [10:0] Sound CPU interrupt enable
400 
401    // $420
402    u16  scipd;          // [10:0] Sound CPU interrupt pending
403 
404    // $422
405    //   scire;          // [10:0] Sound CPU interrupt reset (not readable)
406 
407    // $424
408    u8   scilv0;         // [7:0] Sound CPU interrupt levels, bit 0
409 
410    // $426
411    u8   scilv1;         // [7:0] Sound CPU interrupt levels, bit 1
412 
413    // $428
414    u8   scilv2;         // [7:0] Sound CPU interrupt levels, bit 2
415 
416    // $42A
417    u16  mcieb;          // [10:0] Main CPU interrupt enable
418 
419    // $42C
420    u16  mcipd;          // [10:0] Main CPU interrupt pending
421 
422    // $42E
423    //   mcire;          // [10:0] Main CPU interrupt reset (not readable)
424 
425    ////////////
426    // Internal state
427 
428    s32  stack[32*2];    // 2 generations of sound output data ($600..$67E)
429 
430    SlotState slot[32];  // Data for each slot
431 
432    u32  sample_timer;   // Sample output timer (in SCSP clocks, 256 = 1 sample)
433 
434    u32  sound_ram_mask; // Sound RAM address mask (tracks mem4mb)
435 
436    u8   midi_in_buf[4]; // MIDI in buffer
437    u8   midi_out_buf[4];// MIDI out buffer
438    u8   midi_in_cnt;    // MIDI in data count
439    u8   midi_out_cnt;   // MIDI out data count
440 
441 } ScspState;
442 
443 //-------------------------------------------------------------------------
444 // Exported data
445 
446 u8 *SoundRam;
447 
448 //-------------------------------------------------------------------------
449 // Lookup tables
450 
451 // Attack/decay envelope lookup table
452 static s32 scsp_env_table[SCSP_ENV_LEN*2];
453 
454 // LFO waveforms for amplitude modulation
455 static s32 scsp_lfo_wave_amp[4][SCSP_LFO_LEN];
456 // LFO waveforms for frequency modulation
457 static s32 scsp_lfo_wave_freq[4][SCSP_LFO_LEN];
458 // LFO counter step values for each LFOF index
459 static s32 scsp_lfo_step[32];
460 
461 // Envelope increments for each attack/decay rate (AR, DR, etc.)
462 static s32 scsp_attack_rate[62+16];
463 static s32 scsp_decay_rate[62+16];
464 
465 // Table of volume multipliers for TL (total level) register
466 static s32 scsp_tl_table[256];
467 
468 //-------------------------------------------------------------------------
469 // Other local data
470 
471 //-------- Data written by main thread only --------//
472 
473 // Cached fraction of a clock cycle (12.20 fixed point)
474 static u32 scsp_clock_frac;
475 // scsp_clock_frac increment per ScspExec(1) call
476 static u32 scsp_clock_inc;
477 
478 // Selected sound output module
479 static SoundInterface_struct *SNDCore;
480 
481 // Main CPU (SCU) interrupt function pointer
482 static void (*scsp_interrupt_handler)(void);
483 
484 // Flag: Generate sound with frame-accurate timing?
485 static u8 scsp_frame_accurate;
486 
487 //-------- Data used for inter-thread communication --------//
488 
489 PSP_SECTION_START(sc_write)
490 PSP_SECTION_START(me_write)
491 
492 // Core 11.2896MHz clock (continually counts up)
493 PSP_SECTION(me_write)
494    static volatile u32 scsp_clock;
495 // Target clock value for execution (execute until clock == clock_target)
496 PSP_SECTION(sc_write)
497    static volatile u32 scsp_clock_target;
498 
499 // Flag: Is a subthread currently running?  (Also used to signal the
500 // subthread to stop.)
501 PSP_SECTION(sc_write)
502    static volatile u8 scsp_thread_running;
503 
504 // Flag: Has an interrupt request been generated for the main processor?
505 // (Set by the subthread, cleared by the main thread.)
506 PSP_SECTION(both_write)
507    static volatile u8 scsp_main_interrupt_pending;
508 
509 // Buffer for external (SH-2) SCSP writes (only _size is written by both
510 // CPUs, but we keep all three in the same section for cache safety)
511 PSP_SECTION(both_write)
512    static volatile u8 scsp_write_buffer_size;  // 0 = nothing buffered
513 PSP_SECTION(both_write)
514    static volatile u16 scsp_write_buffer_address;
515 PSP_SECTION(both_write)
516    static volatile u32 scsp_write_buffer_data;
517 
518 // SCSP register value cache (caching handled separately)
519 #ifdef PSP
520 __attribute__((aligned(64)))
521 #endif
522 static u16 scsp_regcache[0x1000/2];
523 
524 // CDDA input buffer and read/write pointers
525 PSP_SECTION(sc_write)
526 static union {
527    u8 sectors[CDDA_NUM_BUFFERS][2352];
528    u8 data[CDDA_NUM_BUFFERS*2352];
529 } cdda_buf;
530 PSP_SECTION(sc_write)
531    static volatile u32 cdda_next_in;  // Offset of next _sector_ to store
532 PSP_SECTION(me_write)
533    static volatile u32 cdda_next_out; // Offset of next _byte_ to read out
534 
535 PSP_SECTION_END(sc_write)
536 PSP_SECTION_END(me_write)
537 
538 //--- Data written by SCSP thread only (except when thread is stopped) ---//
539 
540 // Current SCSP state
541 static ScspState scsp;
542 
543 // PCM output buffers and related data
544 static s32 scsp_buffer_L[SCSP_SOUND_BUFSIZE];
545 static s32 scsp_buffer_R[SCSP_SOUND_BUFSIZE];
546 static u32 scsp_sound_genpos;     // Offset of next sample to generate
547 static u32 scsp_sound_left;       // Samples not yet sent to host driver
548 
549 // Parameters for audio data generation (these are file-scope to reduce
550 // parameter passing overhead)
551 static s32 *scsp_bufL;            // Base pointer for left channel
552 static s32 *scsp_bufR;            // Base pointer for right channel
553 
554 // CDDA playback delay in samples (used to avoid audio popping when the
555 // SCSP emulation gets a few samples ahead of the CDDA input)
556 static u32 cdda_delay;
557 
558 // M68K-related data
559 static u8 m68k_running;            // Nonzero if M68K execution is enabled
560 static s32 FASTCALL (*m68k_execf)(s32 cycles);  // M68K->Exec or M68KExecBP
561 static s32 m68k_saved_cycles;      // Requested minus actual cycles executed
562 static M68KBreakpointInfo m68k_breakpoint[M68K_MAX_BREAKPOINTS];
563 static int m68k_num_breakpoints;
564 static void (*M68KBreakpointCallback)(u32);
565 static u8 m68k_in_breakpoint;
566 
567 //-------------------------------------------------------------------------
568 // Local function declarations
569 
570 static void ScspThread(void *arg);
571 static void ScspDoExec(u32 cycles);
572 static u32 ScspTimerCyclesLeft(u16 timer, u8 timer_scale);
573 static void ScspUpdateTimer(u32 samples, u16 *timer_ptr, u8 timer_scale,
574                             int interrupt);
575 static void ScspGenerateAudio(s32 *bufL, s32 *bufR, u32 samples);
576 static void ScspGenerateAudioForSlot(SlotState *slot, u32 samples);
577 static void ScspGenerateAudioForCDDA(s32 *bufL, s32 *bufR, u32 samples);
578 
579 static u8 FASTCALL ScspReadByteDirect(u32 address);
580 static u16 FASTCALL ScspReadWordDirect(u32 address);
581 static void FASTCALL ScspWriteByteDirect(u32 address, u8 data);
582 static void FASTCALL ScspWriteWordDirect(u32 address, u16 data);
583 static u16 ScspReadMonitor(void);
584 static void ScspDoKeyOnOff(void);
585 static void ScspKeyOn(SlotState *slot);
586 static void ScspKeyOff(SlotState *slot);
587 static void ScspUpdateSlotAddress(SlotState *slot);
588 static void ScspUpdateSlotEnv(SlotState *slot);
589 static void ScspUpdateSlotFunc(SlotState *slot);
590 static u16 ScspMidiIn(void);
591 static void ScspMidiOut(u8 data);
592 static void ScspDoDMA(void);
593 
594 static void ScspSyncThread(void);
595 static void ScspRaiseInterrupt(int which, int target);
596 static void ScspCheckInterrupts(u16 mask, int target);
597 static void ScspClearInterrupts(u16 mask, int target);
598 static void ScspRunM68K(u32 cycles);
599 static s32 FASTCALL M68KExecBP(s32 cycles);
600 
601 static int scsp_mute_flags = 0;
602 static int scsp_volume = 100;
603 
604 ///////////////////////////////////////////////////////////////////////////
605 // Single-slot audio generation routines and corresponding table.  The
606 // table is indexed by:
607 //    scsp_audiogen_func_table[F][A][S][L][R]
608 //                             ^  ^  ^  ^  ^-- Right channel on/off (on = 1)
609 //                             |  |  |  `-- Left channel on/off (on = 1)
610 //                             |  |  `-- Sample size 16/8 bit (16 bit = 1)
611 //                             |  `-- Amplitude modulation on/off (on = 1)
612 //                             `-- Frequency modulation on/off (on = 1)
613 ///////////////////////////////////////////////////////////////////////////
614 
615 // For convenience, we use a single, parameterized macro to define every
616 // function, with 0 or 1 in each of the F/A/S/L/R parameters; the compiler
617 // will optimize out the disabled branches.
618 
619 // A couple of handy sub-macros:
620 #define ADDRESS      (addr_counter >> SCSP_FREQ_LOW_BITS)
621 #ifdef WORDS_BIGENDIAN
622 #define ADDRESS_8BIT (ADDRESS)
623 #else
624 #define ADDRESS_8BIT (ADDRESS ^ 1)
625 #endif
626 #define ENV_POS      (env_counter >> SCSP_ENV_LOW_BITS)
627 #define LFO_POS      ((slot->lfo_counter >> SCSP_LFO_LOW_BITS) & SCSP_LFO_MASK)
628 
629 #define DEFINE_AUDIOGEN(tag,F,A,S,L,R)                                      \
630 static void FASTCALL audiogen_##tag(SlotState *slot, u32 len)               \
631 {                                                                           \
632    /* Load these first to avoid having to reload them every iteration */    \
633          u32 addr_counter = slot->addr_counter;                             \
634    const u32 addr_step    = slot->addr_step;                                \
635          u32 env_counter  = slot->env_counter;                              \
636          u32 env_step     = slot->env_step;                                 \
637                                                                             \
638    u32 pos;                                                                 \
639    for (pos = 0; pos < len; pos++)                                          \
640    {                                                                        \
641       if (L || R)  /* Don't bother with calculations if it's all silent */  \
642       {                                                                     \
643          /* Compute envelope/TL multiplier for waveform data */             \
644          s32 env = scsp_env_table[ENV_POS] * slot->tl_mult >> SCSP_TL_BITS; \
645          if (A)                                                             \
646             env -= slot->lfo_am_wave[LFO_POS] >> slot->lfo_am_shift;        \
647          slot->last_env = env;                                              \
648                                                                             \
649          /* Apply envelope / channel volume to waveform data and output */  \
650          if (LIKELY(env > 0))                                               \
651          {                                                                  \
652             s32 out;                                                        \
653             if (S)                                                          \
654                out = (s32) ((const s16 *)slot->buf)[ADDRESS];               \
655             else                                                            \
656                out = (s32) ((const s8 *)slot->buf)[ADDRESS_8BIT] << 8;      \
657             out *= env;                                                     \
658             if (L)                                                          \
659                scsp_bufL[pos] += out >> slot->outshift_l;                   \
660             if (R)                                                          \
661                scsp_bufR[pos] += out >> slot->outshift_r;                   \
662          }                                                                  \
663       }                                                                     \
664                                                                             \
665       /* Update address counter, exiting if we reach the end of the data */ \
666       if (F)                                                                \
667       {                                                                     \
668          /* FIXME: need to handle the case where LFO data range != 1<<FREQ_LOW_BITS */ \
669          addr_counter += slot->lfo_fm_wave[LFO_POS]                         \
670                          << slot->lfo_fm_shift                              \
671                          >> slot->octave_shift;                             \
672       }                                                                     \
673       addr_counter += addr_step;                                            \
674       if (UNLIKELY(addr_counter > slot->lea_shifted))                       \
675       {                                                                     \
676          /* FIXME: reverse/alternating loops not implemented */             \
677          if (slot->lpctl)                                                   \
678          {                                                                  \
679             addr_counter = slot->lsa_shifted                                \
680                          + ((addr_counter - slot->lsa_shifted)              \
681                             % slot->looplen_shifted);                       \
682          }                                                                  \
683          else                                                               \
684          {                                                                  \
685             env_counter = SCSP_ENV_DECAY_END;                               \
686             goto done;                                                      \
687          }                                                                  \
688       }                                                                     \
689                                                                             \
690       /* Update envelope counter, advancing the envelope phase as needed */ \
691       env_counter += env_step;                                              \
692       if (UNLIKELY(env_counter >= slot->env_target))                        \
693       {                                                                     \
694          switch (slot->env_phase)                                           \
695          {                                                                  \
696             case SCSP_ENV_ATTACK:                                           \
697                env_counter = SCSP_ENV_DECAY_START;                          \
698                env_step = slot->env_step = slot->env_step_d;                \
699                slot->env_target = slot->sl_target;                          \
700                slot->env_phase = SCSP_ENV_DECAY;                            \
701                break;                                                       \
702             case SCSP_ENV_DECAY:                                            \
703                env_counter = slot->sl_target;                               \
704                env_step = slot->env_step = slot->env_step_s;                \
705                slot->env_target = SCSP_ENV_DECAY_END;                       \
706                slot->env_phase = SCSP_ENV_SUSTAIN;                          \
707                break;                                                       \
708             default:                                                        \
709                env_counter = SCSP_ENV_DECAY_END;                            \
710                env_step = slot->env_step = 0;                               \
711                slot->env_target = SCSP_ENV_DECAY_END + 1;                   \
712                goto done;                                                   \
713          }                                                                  \
714       }                                                                     \
715                                                                             \
716       /* Update the LFO counter if either LFO waveform is in use            \
717        * (technically, we should update whenever slot->lfore == 0, but      \
718        * we skip the update on non-modulated channels to save time) */      \
719       if (F || A)                                                           \
720          slot->lfo_counter += slot->lfo_step;                               \
721    }                                                                        \
722                                                                             \
723   done:                                                                     \
724    slot->addr_counter = addr_counter;                                       \
725    slot->env_counter = env_counter;                                         \
726 }
727 
728 //-------------------------------------------------------------------------
729 
730 // Define the actual audio generation functions.  For simplicity, we name
731 // each function using the state of its parameter flags, with uppercase for
732 // an enabled flag and lowercase for a disabled flag.  We also use the null
733 // output function for all cases where L and R are zero, to avoid
734 // unnecessary code bloat.
735 
736 DEFINE_AUDIOGEN(null,  0,0,0,0,0)
737 
738 DEFINE_AUDIOGEN(faslR, 0,0,0,0,1)
739 DEFINE_AUDIOGEN(fasLr, 0,0,0,1,0)
740 DEFINE_AUDIOGEN(fasLR, 0,0,0,1,1)
741 DEFINE_AUDIOGEN(faSlR, 0,0,1,0,1)
742 DEFINE_AUDIOGEN(faSLr, 0,0,1,1,0)
743 DEFINE_AUDIOGEN(faSLR, 0,0,1,1,1)
744 
745 DEFINE_AUDIOGEN(fAslR, 0,1,0,0,1)
746 DEFINE_AUDIOGEN(fAsLr, 0,1,0,1,0)
747 DEFINE_AUDIOGEN(fAsLR, 0,1,0,1,1)
748 DEFINE_AUDIOGEN(fASlR, 0,1,1,0,1)
749 DEFINE_AUDIOGEN(fASLr, 0,1,1,1,0)
750 DEFINE_AUDIOGEN(fASLR, 0,1,1,1,1)
751 
752 DEFINE_AUDIOGEN(FaslR, 1,0,0,0,1)
753 DEFINE_AUDIOGEN(FasLr, 1,0,0,1,0)
754 DEFINE_AUDIOGEN(FasLR, 1,0,0,1,1)
755 DEFINE_AUDIOGEN(FaSlR, 1,0,1,0,1)
756 DEFINE_AUDIOGEN(FaSLr, 1,0,1,1,0)
757 DEFINE_AUDIOGEN(FaSLR, 1,0,1,1,1)
758 
759 DEFINE_AUDIOGEN(FAslR, 1,1,0,0,1)
760 DEFINE_AUDIOGEN(FAsLr, 1,1,0,1,0)
761 DEFINE_AUDIOGEN(FAsLR, 1,1,0,1,1)
762 DEFINE_AUDIOGEN(FASlR, 1,1,1,0,1)
763 DEFINE_AUDIOGEN(FASLr, 1,1,1,1,0)
764 DEFINE_AUDIOGEN(FASLR, 1,1,1,1,1)
765 
766 // We don't need these anymore, so get rid of them
767 #undef ADDRESS
768 #undef ADDRESS_8BIT
769 #undef ENV_POS
770 #undef LFO_POS
771 #undef DEFINE_AUDIOGEN
772 
773 //-------------------------------------------------------------------------
774 
775 // Define the function lookup table.
776 
777 static void (* FASTCALL scsp_audiogen_func_table[2][2][2][2][2])(SlotState *slot, u32 len) =
778 {
779    {  // F==0
780       {  // A==0
781          {{audiogen_null, audiogen_faslR}, {audiogen_fasLr, audiogen_fasLR}},
782          {{audiogen_null, audiogen_faSlR}, {audiogen_faSLr, audiogen_faSLR}}
783       },
784       {  // A==1
785          {{audiogen_null, audiogen_fAslR}, {audiogen_fAsLr, audiogen_fAsLR}},
786          {{audiogen_null, audiogen_fASlR}, {audiogen_fASLr, audiogen_fASLR}}
787       }
788    },
789    {  // F==1
790       {  // A==0
791          {{audiogen_null, audiogen_FaslR}, {audiogen_FasLr, audiogen_FasLR}},
792          {{audiogen_null, audiogen_FaSlR}, {audiogen_FaSLr, audiogen_FaSLR}}
793       },
794       {  // A==1
795          {{audiogen_null, audiogen_FAslR}, {audiogen_FAsLr, audiogen_FAsLR}},
796          {{audiogen_null, audiogen_FASlR}, {audiogen_FASLr, audiogen_FASLR}}
797       }
798    }
799 };
800 
801 ///////////////////////////////////////////////////////////////////////////
802 // Initialization, configuration, and cleanup routines
803 ///////////////////////////////////////////////////////////////////////////
804 
805 // ScspInit:  Initialize the SCSP emulation.  interrupt_handler should
806 // specify a function to handle interrupts delivered to the SCU.
807 // Must be called after M68KInit(); returns 0 on success, -1 on failure.
808 
ScspInit(int coreid,void (* interrupt_handler)(void))809 int ScspInit(int coreid, void (*interrupt_handler)(void))
810 {
811    int i, j;
812    double x;
813 
814    if ((SoundRam = T2MemoryInit(0x80000)) == NULL)
815       return -1;
816 
817    // Fill in lookup tables
818 
819    for (i = 0; i < SCSP_ENV_LEN; i++)
820    {
821       // Attack Curve (x^4 ?)
822       x = pow(((double) (SCSP_ENV_MASK - i) / SCSP_ENV_LEN), 4);
823       x *= (double) SCSP_ENV_LEN;
824       scsp_env_table[i] = SCSP_ENV_MASK - (s32) floor(x);
825 
826       // Decay curve (x = linear)
827       scsp_env_table[i + SCSP_ENV_LEN] = SCSP_ENV_MASK - i;
828    }
829 
830    for (i = 0, j = 0; i < 32; i++)
831    {
832       double lfo_frequency, lfo_step;
833       // Frequency divider follows the pattern 1,2,3,4, 6,8,10,12, 16,...
834       j += 1 << (i >> 2);
835       // Base LFO frequency is 44100/256 or ~172.3 Hz
836       lfo_frequency = (44100.0 / 256.0) / j;
837       // Calculate LFO address step per output sample; we use a literal
838       // 44100 above but OUTPUT_FREQ here in case anyone wants to try
839       // upsampling the audio output someday
840       lfo_step = (lfo_frequency / SCSP_OUTPUT_FREQ) * SCSP_LFO_LEN;
841       scsp_lfo_step[31 - i] = round(lfo_step * (1 << SCSP_LFO_LOW_BITS));
842    }
843 
844    for (i = 0; i < SCSP_LFO_LEN; i++)
845    {
846       // Amplitude modulation uses unsigned values which are subtracted
847       // from the base envelope value
848       scsp_lfo_wave_amp[SCSP_LFO_SAWTOOTH][i] = i;
849       if (i < SCSP_LFO_LEN / 2)
850          scsp_lfo_wave_amp[SCSP_LFO_SQUARE][i] = 0;
851       else
852          scsp_lfo_wave_amp[SCSP_LFO_SQUARE][i] = SCSP_LFO_MASK;
853       if (i < SCSP_LFO_LEN / 2)
854          scsp_lfo_wave_amp[SCSP_LFO_TRIANGLE][i] = i*2;
855       else
856          scsp_lfo_wave_amp[SCSP_LFO_TRIANGLE][i] = SCSP_LFO_MASK - ((i - SCSP_LFO_LEN/2) * 2);
857       scsp_lfo_wave_amp[SCSP_LFO_NOISE][i] = rand() & SCSP_LFO_MASK;
858       // FIXME: note that the noise generator output should be independent
859       // of LFORE/LFOF
860 
861       // Frequency modulation uses signed values which are added to the
862       // address counter
863       if (i < SCSP_LFO_LEN / 2)
864          scsp_lfo_wave_freq[SCSP_LFO_SAWTOOTH][i] = i;
865       else
866          scsp_lfo_wave_freq[SCSP_LFO_SAWTOOTH][i] = i - SCSP_LFO_LEN;
867       if (i < SCSP_LFO_LEN / 2)
868          scsp_lfo_wave_freq[SCSP_LFO_SQUARE][i] = SCSP_LFO_MASK - SCSP_LFO_LEN/2;
869       else
870          scsp_lfo_wave_freq[SCSP_LFO_SQUARE][i] = 0 - SCSP_LFO_LEN/2;
871       if (i < SCSP_LFO_LEN / 4)
872          scsp_lfo_wave_freq[SCSP_LFO_TRIANGLE][i] = i*2;
873       else if (i < SCSP_LFO_LEN * 3 / 4)
874          scsp_lfo_wave_freq[SCSP_LFO_TRIANGLE][i] = SCSP_LFO_MASK - i*2;
875       else
876          scsp_lfo_wave_freq[SCSP_LFO_TRIANGLE][i] = i*2 - SCSP_LFO_LEN*2;
877       scsp_lfo_wave_freq[SCSP_LFO_NOISE][i] = scsp_lfo_wave_amp[SCSP_LFO_NOISE][i] - SCSP_LFO_LEN/2;
878    }
879 
880    for (i = 0; i < 4; i++)
881    {
882       scsp_attack_rate[i] = 0;
883       scsp_decay_rate[i] = 0;
884    }
885    for (i = 0; i < 60; i++)
886    {
887       x = 1.0 + ((i & 3) * 0.25);  // Bits 0-1: x1.00, x1.25, x1.50, x1.75
888       x *= 1 << (i >> 2);          // Bits 2-5: shift bits (x2^0 - x2^15)
889       x *= SCSP_ENV_LEN << SCSP_ENV_LOW_BITS; // Adjust for envelope table size
890 
891       scsp_attack_rate[i + 4] = round(x / SCSP_ATTACK_TIME);
892       if (scsp_attack_rate[i + 4] == 0)
893          scsp_attack_rate[i + 4] = 1;
894       scsp_decay_rate[i + 4] = round(x / SCSP_DECAY_TIME);
895       if (scsp_decay_rate[i + 4] == 0)
896          scsp_decay_rate[i + 4] = 1;
897    }
898    scsp_attack_rate[63] = SCSP_ENV_ATTACK_END;
899    scsp_decay_rate[61] = scsp_decay_rate[60];
900    scsp_decay_rate[62] = scsp_decay_rate[60];
901    scsp_decay_rate[63] = scsp_decay_rate[60];
902    for (i = 64; i < 78; i++)
903    {
904       scsp_attack_rate[i] = scsp_attack_rate[63];
905       scsp_decay_rate[i] = scsp_decay_rate[63];
906    }
907 
908    for (i = 0; i < 256; i++)
909       scsp_tl_table[i] = round(pow(2.0, -(i/16.0)) * (1 << SCSP_TL_BITS));
910 
911    // Initialize the SCSP state
912 
913    scsp_interrupt_handler = interrupt_handler;
914    scsp_clock_inc = yabsys.IsPal ? SCSP_CLOCK_INC_PAL : SCSP_CLOCK_INC_NTSC;
915 
916    ScspReset();
917 
918    // Note that we NEVER reset the clock counter after initialization,
919    // because in multithreaded mode, that would cause a race condition in
920    // which the SCSP thread runs between the two assignments and detects
921    // clock != clock_target, causing it to execute a huge number of cycles.
922    // (We do, however, reset the accumulated fraction of a cycle inside
923    // ScspReset().)
924    scsp_clock = 0;
925    scsp_clock_target = 0;
926 
927    // Initialize the M68K state
928 
929    if (M68K->Init() != 0)
930       return -1;
931 
932    M68K->SetReadB(M68KReadByte);
933    M68K->SetReadW(M68KReadWord);
934    M68K->SetWriteB(M68KWriteByte);
935    M68K->SetWriteW(M68KWriteWord);
936 
937    M68K->SetFetch(0x000000, 0x040000, (pointer)SoundRam);
938    M68K->SetFetch(0x040000, 0x080000, (pointer)SoundRam);
939    M68K->SetFetch(0x080000, 0x0C0000, (pointer)SoundRam);
940    M68K->SetFetch(0x0C0000, 0x100000, (pointer)SoundRam);
941 
942    m68k_running = 0;
943    m68k_execf = M68K->Exec;
944    m68k_saved_cycles = 0;
945    for (i = 0; i < MAX_BREAKPOINTS; i++)
946       m68k_breakpoint[i].addr = 0xFFFFFFFF;
947    m68k_num_breakpoints = 0;
948    M68KBreakpointCallback = NULL;
949    m68k_in_breakpoint = 0;
950 
951    // Set up sound output
952 
953    scsp_sound_genpos = 0;
954    scsp_sound_left = 0;
955 
956    if (ScspChangeSoundCore(coreid) < 0)
957       return -1;
958 
959    // Start a subthread if requested
960 
961    scsp_thread_running = 0;
962    if (yabsys.UseThreads)
963    {
964       scsp_thread_running = 1;  // Set now so the thread doesn't quit instantly
965       PSP_FLUSH_ALL();
966       if (YabThreadStart(YAB_THREAD_SCSP, ScspThread, NULL) < 0)
967       {
968          SCSPLOG("Failed to start SCSP thread\n");
969          scsp_thread_running = 0;
970       }
971    }
972 
973    // Successfully initialized!
974 
975    return 0;
976 }
977 
978 //-------------------------------------------------------------------------
979 
980 // ScspReset:  Reset the SCSP to its power-on state, also stopping the M68K
981 // processor.
982 
ScspReset(void)983 void ScspReset(void)
984 {
985    int slotnum;
986 
987    if (scsp_thread_running)
988       ScspSyncThread();
989 
990    scsp.mem4mb  = 0;
991    scsp.dac18b  = 0;
992    scsp.ver     = 0;
993    scsp.mvol    = 0;
994 
995    scsp.rbl     = 0;
996    scsp.rbp     = 0;
997 
998    scsp.mofull  = 0;
999    scsp.moemp   = 1;
1000    scsp.miovf   = 0;
1001    scsp.mifull  = 0;
1002    scsp.miemp   = 1;
1003    scsp.mibuf   = 0;
1004    scsp.mobuf   = 0;
1005 
1006    scsp.mslc    = 0;
1007    scsp.ca      = 0;
1008 
1009    scsp.dmea    = 0;
1010    scsp.drga    = 0;
1011    scsp.dgate   = 0;
1012    scsp.ddir    = 0;
1013    scsp.dexe    = 0;
1014    scsp.dtlg    = 0;
1015 
1016    scsp.tactl   = 0;
1017    scsp.tima    = 0xFF00;
1018    scsp.tbctl   = 0;
1019    scsp.timb    = 0xFF00;
1020    scsp.tcctl   = 0;
1021    scsp.timc    = 0xFF00;
1022 
1023    scsp.mcieb   = 0;
1024    scsp.mcipd   = 0;
1025    scsp.scilv0  = 0;
1026    scsp.scilv1  = 0;
1027    scsp.scilv2  = 0;
1028    scsp.scieb   = 0;
1029    scsp.scipd   = 0;
1030 
1031    memset(scsp_regcache, 0, sizeof(scsp_regcache));
1032    scsp_regcache[0x400>>1] = SCSP_VERSION << 4;
1033 
1034    memset(scsp.stack, 0, sizeof(scsp.stack));
1035 
1036    for (slotnum = 0; slotnum < 32; slotnum++)
1037    {
1038       memset(&scsp.slot[slotnum], 0, sizeof(scsp.slot[slotnum]));
1039       scsp.slot[slotnum].env_counter = SCSP_ENV_DECAY_END;  // Slot off
1040       scsp.slot[slotnum].outshift_l = 31;                   // Output off
1041       scsp.slot[slotnum].outshift_r = 31;
1042       scsp.slot[slotnum].audiogen = audiogen_null;
1043    }
1044 
1045    scsp.sound_ram_mask = 0x3FFFF;
1046    scsp_clock_frac = 0;
1047    scsp.sample_timer = 0;
1048 
1049    scsp_main_interrupt_pending = 0;
1050    scsp_write_buffer_size = 0;
1051 
1052    cdda_next_in = 0;
1053    cdda_next_out = 0;
1054    cdda_delay = CDDA_DELAY_SAMPLES;
1055 
1056    m68k_running = 0;
1057 
1058    if (scsp_thread_running)
1059       PSP_FLUSH_ALL();
1060 }
1061 
1062 //-------------------------------------------------------------------------
1063 
1064 // ScspChangeSoundCore:  Change the module used for sound output.  Returns
1065 // 0 on success, -1 on error.
1066 
ScspChangeSoundCore(int coreid)1067 int ScspChangeSoundCore(int coreid)
1068 {
1069    int i;
1070 
1071    // Make sure the old core is freed
1072    if (SNDCore)
1073       SNDCore->DeInit();
1074 
1075    // If the default was requested, use the first core in the list
1076    if (coreid == SNDCORE_DEFAULT)
1077       SNDCore = SNDCoreList[0];
1078    else
1079    {
1080       // Otherwise, go through core list and find the id
1081       for (i = 0; SNDCoreList[i] != NULL; i++)
1082       {
1083          if (SNDCoreList[i]->id == coreid)
1084          {
1085             // Set to current core
1086             SNDCore = SNDCoreList[i];
1087             break;
1088          }
1089       }
1090    }
1091 
1092    if (SNDCore == NULL)
1093    {
1094       SNDCore = &SNDDummy;
1095       return -1;
1096    }
1097 
1098    if (SNDCore->Init() == -1)
1099    {
1100       // Since it failed, instead of it being fatal, we'll just use the dummy
1101       // core instead
1102 
1103       // This might be helpful though.
1104       YabSetError(YAB_ERR_CANNOTINIT, (void *)SNDCore->Name);
1105 
1106       SNDCore = &SNDDummy;
1107    }
1108 
1109    if (SNDCore)
1110    {
1111       if (scsp_mute_flags) SNDCore->MuteAudio();
1112       else SNDCore->UnMuteAudio();
1113       SNDCore->SetVolume(scsp_volume);
1114    }
1115 
1116    return 0;
1117 }
1118 
1119 //-------------------------------------------------------------------------
1120 
1121 // ScspChangeVideoFormat:  Update SCSP parameters for a change in video
1122 // format.  type is nonzero for PAL (50Hz), zero for NTSC (59.94Hz) video.
1123 // Always returns 0 for success.
1124 
ScspChangeVideoFormat(int type)1125 int ScspChangeVideoFormat(int type)
1126 {
1127    scsp_clock_inc = yabsys.IsPal ? SCSP_CLOCK_INC_PAL : SCSP_CLOCK_INC_NTSC;
1128 
1129    SNDCore->ChangeVideoFormat(type ? 50 : 60);
1130 
1131    return 0;
1132 }
1133 
1134 
1135 //-------------------------------------------------------------------------
1136 
1137 // ScspSetFrameAccurate:  Set whether sound should be generated with
1138 // frame-accurate timing.
1139 
ScspSetFrameAccurate(int on)1140 void ScspSetFrameAccurate(int on)
1141 {
1142    scsp_frame_accurate = (on != 0);
1143 }
1144 
1145 //-------------------------------------------------------------------------
1146 
1147 // ScspMuteAudio, ScspUnMuteAudio:  Mute or unmute the sound output.  Does
1148 // not affect actual SCSP processing.
1149 
ScspMuteAudio(int flags)1150 void ScspMuteAudio(int flags)
1151 {
1152    scsp_mute_flags |= flags;
1153    if (SNDCore && scsp_mute_flags)
1154       SNDCore->MuteAudio();
1155 }
1156 
ScspUnMuteAudio(int flags)1157 void ScspUnMuteAudio(int flags)
1158 {
1159    scsp_mute_flags &= ~flags;
1160    if (SNDCore && (scsp_mute_flags == 0))
1161       SNDCore->UnMuteAudio();
1162 }
1163 
1164 //-------------------------------------------------------------------------
1165 
1166 // ScspSetVolume:  Set the sound output volume.  Does not affect actual
1167 // SCSP processing.
1168 
ScspSetVolume(int volume)1169 void ScspSetVolume(int volume)
1170 {
1171    scsp_volume = volume;
1172    if (SNDCore)
1173       SNDCore->SetVolume(volume);
1174 }
1175 
1176 //-------------------------------------------------------------------------
1177 
1178 // ScspDeInit:  Free all resources used by the SCSP emulation.
1179 
ScspDeInit(void)1180 void ScspDeInit(void)
1181 {
1182    if (scsp_thread_running)
1183    {
1184       scsp_thread_running = 0;  // Tell the subthread to stop
1185       YabThreadWake(YAB_THREAD_SCSP);
1186       YabThreadWait(YAB_THREAD_SCSP);
1187    }
1188 
1189    if (SNDCore)
1190       SNDCore->DeInit();
1191    SNDCore = NULL;
1192 
1193    if (SoundRam)
1194       T2MemoryDeInit(SoundRam);
1195    SoundRam = NULL;
1196 }
1197 
1198 ///////////////////////////////////////////////////////////////////////////
1199 // Main SCSP processing routine and internal helpers
1200 ///////////////////////////////////////////////////////////////////////////
1201 
1202 // ScspExec:  Main SCSP processing routine.  Executes (decilines/10.0)
1203 // scanlines worth of SCSP emulation; in multithreaded mode, bumps the
1204 // clock target by the same amount of time.
1205 
ScspExec(int decilines)1206 void ScspExec(int decilines)
1207 {
1208    u32 new_target;
1209 
1210    scsp_clock_frac += scsp_clock_inc * decilines;
1211    new_target = scsp_clock_target + (scsp_clock_frac >> 20);
1212    scsp_clock_target = new_target;
1213    scsp_clock_frac &= 0xFFFFF;
1214 
1215    if (scsp_thread_running)
1216    {
1217 #ifdef PSP
1218       if (!psp_writeback_cache_for_scsp())
1219           PSP_UC(scsp_clock_target) = new_target; // Push just this one through
1220 #endif
1221       while (new_target - PSP_UC(scsp_clock) > SCSP_CLOCK_MAX_EXEC)
1222       {
1223          YabThreadWake(YAB_THREAD_SCSP);
1224          YabThreadYield();
1225       }
1226       if (PSP_UC(scsp_main_interrupt_pending))
1227       {
1228           (*scsp_interrupt_handler)();
1229           PSP_UC(scsp_main_interrupt_pending) = 0;
1230       }
1231    }
1232    else
1233       ScspDoExec(new_target - scsp_clock);
1234 }
1235 
1236 ///////////////////////////////////////////////////////////////////////////
1237 
1238 // ScspThread:  Control routine for SCSP thread.  Loops over ScspDoExec()
1239 // and SCSP write buffer processing until told to stop.
1240 
ScspThread(void * arg)1241 static void ScspThread(void *arg)
1242 {
1243    while (PSP_UC(scsp_thread_running))
1244    {
1245       const u8 write_size = PSP_UC(scsp_write_buffer_size);
1246       u32 clock_cycles;
1247 
1248       if (write_size != 0)
1249       {
1250          const u32 address = PSP_UC(scsp_write_buffer_address);
1251          const u32 data = PSP_UC(scsp_write_buffer_data);
1252          if (write_size == 1)
1253             ScspWriteByteDirect(address, data);
1254          else if (write_size == 2)
1255             ScspWriteWordDirect(address, data);
1256          else
1257          {
1258             ScspWriteWordDirect(address, data >> 16);
1259             ScspWriteWordDirect(address+2, data & 0xFFFF);
1260          }
1261          PSP_UC(scsp_write_buffer_size) = 0;
1262       }
1263 
1264       clock_cycles = PSP_UC(scsp_clock_target) - scsp_clock;
1265       if (clock_cycles > SCSP_CLOCK_MAX_EXEC)
1266          clock_cycles = SCSP_CLOCK_MAX_EXEC;
1267       if (clock_cycles > 0)
1268       {
1269          ScspDoExec(clock_cycles);
1270          YabThreadYield();
1271       }
1272       else
1273          YabThreadSleep();
1274    }
1275 }
1276 
1277 ///////////////////////////////////////////////////////////////////////////
1278 
1279 // ScspDoExec:  Main SCSP processing routine implementation.  Runs M68K
1280 // code, updates timers, and generates samples for the given number of
1281 // SCSP clock cycles.
1282 
ScspDoExec(u32 cycles)1283 static void ScspDoExec(u32 cycles)
1284 {
1285 #if 0
1286    s16 stereodata16[(44100 / 60) * 16]; //11760
1287 #endif
1288    u32 cycles_left;
1289    u32 sample_count;
1290    u32 audio_free;
1291 
1292 
1293    // If any of the timer interrupts are enabled, give the M68K a chance
1294    // to respond to them immediately, so that music doesn't slow down if
1295    // the SCSP thread gets behind and executes a lot of cycles at once.
1296    sample_count = 0;
1297    cycles_left = cycles;
1298    while (cycles_left > 0)
1299    {
1300       u32 this_samples = 0;
1301       u32 this_cycles = cycles_left;
1302       if (scsp.scieb & (1 << SCSP_INTERRUPT_TIMER_A))
1303          this_cycles = MIN(this_cycles, ScspTimerCyclesLeft(scsp.tima, scsp.tactl));
1304       if (scsp.scieb & (1 << SCSP_INTERRUPT_TIMER_B))
1305          this_cycles = MIN(this_cycles, ScspTimerCyclesLeft(scsp.timb, scsp.tbctl));
1306       if (scsp.scieb & (1 << SCSP_INTERRUPT_TIMER_C))
1307          this_cycles = MIN(this_cycles, ScspTimerCyclesLeft(scsp.timc, scsp.tcctl));
1308 
1309       scsp.sample_timer += this_cycles;
1310       this_samples = scsp.sample_timer >> 8;
1311       scsp.sample_timer &= 0xFF;
1312       cycles_left -= this_cycles;
1313       sample_count += this_samples;
1314 
1315       ScspRunM68K(this_cycles);
1316 
1317       ScspUpdateTimer(this_samples, &scsp.tima, scsp.tactl,
1318                       SCSP_INTERRUPT_TIMER_A);
1319       ScspUpdateTimer(this_samples, &scsp.timb, scsp.tbctl,
1320                       SCSP_INTERRUPT_TIMER_B);
1321       ScspUpdateTimer(this_samples, &scsp.timc, scsp.tcctl,
1322                       SCSP_INTERRUPT_TIMER_C);
1323    }
1324 
1325    if (scsp_frame_accurate)
1326    {
1327       s32 *bufL, *bufR;
1328 
1329       // Update sound buffers
1330       if (scsp_sound_left + sample_count > SCSP_SOUND_BUFSIZE)
1331       {
1332          u32 overrun = (scsp_sound_left + sample_count) - SCSP_SOUND_BUFSIZE;
1333          SCSPLOG("WARNING: Sound buffer overrun, %u samples\n", (int)overrun);
1334          scsp_sound_left -= overrun;
1335       }
1336       while (sample_count > 0)
1337       {
1338          u32 this_count = sample_count;
1339          if (scsp_sound_genpos >= SCSP_SOUND_BUFSIZE)
1340             scsp_sound_genpos = 0;
1341          if (this_count > SCSP_SOUND_BUFSIZE - scsp_sound_genpos)
1342             this_count = SCSP_SOUND_BUFSIZE - scsp_sound_genpos;
1343          bufL = &scsp_buffer_L[scsp_sound_genpos];
1344          bufR = &scsp_buffer_R[scsp_sound_genpos];
1345          ScspGenerateAudio(bufL, bufR, this_count);
1346          scsp_sound_genpos += this_count;
1347          scsp_sound_left += this_count;
1348          sample_count -= this_count;
1349       }
1350 
1351       // Send audio to the output device if possible
1352       while (scsp_sound_left > 0 && (audio_free = SNDCore->GetAudioSpace()) > 0)
1353       {
1354          s32 out_start = (s32)scsp_sound_genpos - (s32)scsp_sound_left;
1355          if (out_start < 0)
1356             out_start += SCSP_SOUND_BUFSIZE;
1357          if (audio_free > scsp_sound_left)
1358             audio_free = scsp_sound_left;
1359          if (audio_free > SCSP_SOUND_BUFSIZE - out_start)
1360             audio_free = SCSP_SOUND_BUFSIZE - out_start;
1361          SNDCore->UpdateAudio((u32 *)&scsp_buffer_L[out_start],
1362                               (u32 *)&scsp_buffer_R[out_start], audio_free);
1363          scsp_sound_left -= audio_free;
1364 #if 0
1365          ScspConvert32uto16s(&scsp_buffer_L[out_start], &scsp_buffer_R[out_start], (s16 *)stereodata16, audio_free);
1366          DRV_AviSoundUpdate(stereodata16, audio_free);
1367 #endif
1368       }
1369    }
1370    else  // !scsp_frame_accurate
1371    {
1372       if ((audio_free = SNDCore->GetAudioSpace()))
1373       {
1374          if (audio_free > SCSP_SOUND_BUFSIZE)
1375             audio_free = SCSP_SOUND_BUFSIZE;
1376          ScspGenerateAudio(scsp_buffer_L, scsp_buffer_R, audio_free);
1377          SNDCore->UpdateAudio((u32 *)scsp_buffer_L,
1378                               (u32 *)scsp_buffer_R, audio_free);
1379 #if 0
1380          ScspConvert32uto16s((s32 *)scsp_buffer_L, (s32 *)scsp_buffer_R, (s16 *)stereodata16, audio_free);
1381          DRV_AviSoundUpdate(stereodata16, audio_free);
1382 #endif
1383       }
1384    }  // if (scsp_frame_accurate)
1385 
1386    // Update scsp_clock last, so the main thread can use it as a signal
1387    // that we've finished processing to this point
1388    scsp_clock += cycles;
1389 }
1390 
1391 //-------------------------------------------------------------------------
1392 
1393 // ScspTimerCyclesLeft:  Return the approximate number of SCSP clock cycles
1394 // before an SCSP timer (A, B, or C) triggers an interrupt.
1395 
ScspTimerCyclesLeft(u16 timer,u8 timer_scale)1396 static u32 ScspTimerCyclesLeft(u16 timer, u8 timer_scale)
1397 {
1398    return (0xFF00 - timer) << timer_scale;
1399 }
1400 
1401 //----------------------------------//
1402 
1403 // ScspUpdateTimer:  Update an SCSP timer (A, B, or C) by the given number
1404 // of output samples, and raise an interrupt if the timer reaches 0xFF.
1405 
ScspUpdateTimer(u32 samples,u16 * timer_ptr,u8 timer_scale,int interrupt)1406 static void ScspUpdateTimer(u32 samples, u16 *timer_ptr, u8 timer_scale,
1407                             int interrupt)
1408 {
1409    u32 timer_new = *timer_ptr + (samples << (8 - timer_scale));
1410    if (UNLIKELY(timer_new >= 0xFF00))
1411    {
1412       ScspRaiseInterrupt(interrupt, SCSP_INTTARGET_BOTH);
1413       timer_new -= 0xFF00;  // We won't pass 0xFF00 multiple times at once
1414    }
1415    *timer_ptr = timer_new;
1416 }
1417 
1418 //-------------------------------------------------------------------------
1419 
1420 // ScspGenerateAudio:  Generate the given number of audio samples based on
1421 // the current SCSP state, and update the sound slot counters.
1422 
ScspGenerateAudio(s32 * bufL,s32 * bufR,u32 samples)1423 static void ScspGenerateAudio(s32 *bufL, s32 *bufR, u32 samples)
1424 {
1425    int slotnum;
1426 
1427    u32 i;
1428    for (i = 0; i < samples; i++)
1429       bufL[i] = bufR[i] = 0;
1430 
1431    scsp_bufL = bufL;
1432    scsp_bufR = bufR;
1433    for (slotnum = 0; slotnum < 32; slotnum++)
1434       ScspGenerateAudioForSlot(&scsp.slot[slotnum], samples);
1435 
1436    if (cdda_next_out != PSP_UC(cdda_next_in) * 2352)
1437    {
1438       if (cdda_delay > 0)
1439       {
1440          if (samples > cdda_delay)
1441          {
1442             samples -= cdda_delay;
1443             cdda_delay = 0;
1444          }
1445          else
1446          {
1447             cdda_delay -= samples;
1448             samples = 0;
1449          }
1450       }
1451       if (cdda_delay == 0)
1452          ScspGenerateAudioForCDDA(bufL, bufR, samples);
1453    }
1454    if (cdda_next_out == PSP_UC(cdda_next_in) * 2352)
1455       cdda_delay = CDDA_DELAY_SAMPLES;  // No data buffered, so reset delay
1456 }
1457 
1458 //----------------------------------//
1459 
1460 // ScspGenerateAudioForSlot:  Generate audio samples and update counters for
1461 // a single slot.  scsp_bufL and scsp_bufR are assumed to be set properly.
1462 
ScspGenerateAudioForSlot(SlotState * slot,u32 samples)1463 static void ScspGenerateAudioForSlot(SlotState *slot, u32 samples)
1464 {
1465    if (slot->env_counter >= SCSP_ENV_DECAY_END)
1466       return;  // No sound is currently playing
1467 
1468    (*slot->audiogen)(slot, samples);
1469 }
1470 
1471 //----------------------------------//
1472 
1473 // ScspGenerateAudioForCDDA:  Generate audio samples for buffered CDDA data.
1474 
ScspGenerateAudioForCDDA(s32 * bufL,s32 * bufR,u32 samples)1475 static void ScspGenerateAudioForCDDA(s32 *bufL, s32 *bufR, u32 samples)
1476 {
1477    // May need to wrap around the buffer, so use nested loops
1478    while (samples > 0)
1479    {
1480       const u32 next_out = cdda_next_out;  // Save volatile value locally
1481       const s32 temp = (PSP_UC(cdda_next_in) * 2352) - next_out;
1482       const u32 out_left = (temp < 0) ? sizeof(cdda_buf) - next_out : temp;
1483       const u32 this_len = (samples > out_left/4) ? out_left/4 : samples;
1484       const u8 *buf = &cdda_buf.data[next_out];
1485       const u8 *top = buf + this_len*4;
1486 
1487       if (this_len == 0)
1488          break;  // We ran out of buffered data
1489 
1490       for (; buf < top; buf += 4, bufL++, bufR++)
1491       {
1492          *bufL += (s32)(s16)((buf[1] << 8) | buf[0]);
1493          *bufR += (s32)(s16)((buf[3] << 8) | buf[2]);
1494       }
1495 
1496       if (next_out + this_len*4 >= sizeof(cdda_buf))
1497          cdda_next_out = 0;
1498       else
1499          cdda_next_out = next_out + this_len*4;
1500       samples -= this_len;
1501    }
1502 }
1503 
1504 ///////////////////////////////////////////////////////////////////////////
1505 // SCSP register/memory access and I/O interface routines
1506 ///////////////////////////////////////////////////////////////////////////
1507 
1508 // SoundRam{Read,Write}{Byte,Word,Long}:  Read or write sound RAM.
1509 // Intended for calling from external sources.
1510 
SoundRamReadByte(u32 address)1511 u8 FASTCALL SoundRamReadByte(u32 address)
1512 {
1513    address &= scsp.sound_ram_mask;
1514    return T2ReadByte(SoundRam, address);
1515 }
1516 
SoundRamReadWord(u32 address)1517 u16 FASTCALL SoundRamReadWord(u32 address)
1518 {
1519    address &= scsp.sound_ram_mask;
1520    return T2ReadWord(SoundRam, address);
1521 }
1522 
SoundRamReadLong(u32 address)1523 u32 FASTCALL SoundRamReadLong(u32 address)
1524 {
1525    address &= scsp.sound_ram_mask;
1526    return T2ReadLong(SoundRam, address);
1527 }
1528 
1529 //----------------------------------//
1530 
SoundRamWriteByte(u32 address,u8 data)1531 void FASTCALL SoundRamWriteByte(u32 address, u8 data)
1532 {
1533    address &= scsp.sound_ram_mask;
1534    T2WriteByte(SoundRam, address, data);
1535    M68K->WriteNotify(address, 1);
1536 }
1537 
SoundRamWriteWord(u32 address,u16 data)1538 void FASTCALL SoundRamWriteWord(u32 address, u16 data)
1539 {
1540    address &= scsp.sound_ram_mask;
1541    T2WriteWord(SoundRam, address, data);
1542    M68K->WriteNotify(address, 2);
1543 }
1544 
SoundRamWriteLong(u32 address,u32 data)1545 void FASTCALL SoundRamWriteLong(u32 address, u32 data)
1546 {
1547    address &= scsp.sound_ram_mask;
1548    T2WriteLong(SoundRam, address, data);
1549    M68K->WriteNotify(address, 4);
1550 }
1551 
1552 //-------------------------------------------------------------------------
1553 
1554 // Scsp{Read,Write}{Byte,Word,Long}:  Read or write SCSP registers.
1555 // Intended for calling from external sources.
1556 
ScspReadByte(u32 address)1557 u8 FASTCALL ScspReadByte(u32 address)
1558 {
1559    const u16 data = ScspReadWord(address & ~1);
1560    if (address & 1)
1561       return data & 0xFF;
1562    else
1563       return data >> 8;
1564 }
1565 
ScspReadWord(u32 address)1566 u16 FASTCALL ScspReadWord(u32 address)
1567 {
1568 #ifdef PSP  // Special handling for PSP cache management
1569    switch (address)
1570    {
1571       case 0x404:  // MIDI in
1572          return 0xFF;  // Not even supported, so don't bother trying
1573       case 0x408:  // CA/SGC/EG
1574          return ScspReadMonitor();
1575       default:
1576          return PSP_UC(scsp_regcache[address >> 1]);
1577    }
1578 #else
1579    return ScspReadWordDirect(address & 0xFFF);
1580 #endif
1581 }
1582 
ScspReadLong(u32 address)1583 u32 FASTCALL ScspReadLong(u32 address)
1584 {
1585    return (u32)ScspReadWord(address) << 16 | ScspReadWord(address+2);
1586 }
1587 
1588 //----------------------------------//
1589 
ScspWriteByte(u32 address,u8 data)1590 void FASTCALL ScspWriteByte(u32 address, u8 data)
1591 {
1592    if (scsp_thread_running)
1593    {
1594       PSP_UC(scsp_write_buffer_address) = address & 0xFFF;
1595       PSP_UC(scsp_write_buffer_data) = data;
1596       PSP_UC(scsp_write_buffer_size) = 1;
1597       while (PSP_UC(scsp_write_buffer_size) != 0)
1598       {
1599          YabThreadWake(YAB_THREAD_SCSP);
1600          YabThreadYield();
1601       }
1602       return;
1603    }
1604 
1605    ScspWriteByteDirect(address & 0xFFF, data);
1606 }
1607 
ScspWriteWord(u32 address,u16 data)1608 void FASTCALL ScspWriteWord(u32 address, u16 data)
1609 {
1610    if (scsp_thread_running)
1611    {
1612       PSP_UC(scsp_write_buffer_address) = address & 0xFFF;
1613       PSP_UC(scsp_write_buffer_data) = data;
1614       PSP_UC(scsp_write_buffer_size) = 2;
1615       while (PSP_UC(scsp_write_buffer_size) != 0)
1616       {
1617          YabThreadWake(YAB_THREAD_SCSP);
1618          YabThreadYield();
1619       }
1620       return;
1621    }
1622 
1623    ScspWriteWordDirect(address & 0xFFF, data);
1624 }
1625 
ScspWriteLong(u32 address,u32 data)1626 void FASTCALL ScspWriteLong(u32 address, u32 data)
1627 {
1628    if (scsp_thread_running)
1629    {
1630       PSP_UC(scsp_write_buffer_address) = address & 0xFFF;
1631       PSP_UC(scsp_write_buffer_data) = data;
1632       PSP_UC(scsp_write_buffer_size) = 4;
1633       while (PSP_UC(scsp_write_buffer_size) != 0)
1634       {
1635          YabThreadWake(YAB_THREAD_SCSP);
1636          YabThreadYield();
1637       }
1638       return;
1639    }
1640 
1641    ScspWriteWordDirect(address & 0xFFF, data >> 16);
1642    ScspWriteWordDirect((address+2) & 0xFFF, data & 0xFFFF);
1643 }
1644 
1645 //-------------------------------------------------------------------------
1646 
1647 // ScspReceiveCDDA:  Receive and buffer a sector (2352 bytes) of CDDA audio
1648 // data.  Intended to be called by the CD driver when an audio sector has
1649 // been read in for playback.
1650 
ScspReceiveCDDA(const u8 * sector)1651 void ScspReceiveCDDA(const u8 *sector)
1652 {
1653    const u32 next_in = cdda_next_in;  // Save volatile value locally
1654    const u32 next_next_in =
1655       (next_in + 1) % (sizeof(cdda_buf.sectors) / sizeof(cdda_buf.sectors[0]));
1656 
1657    // Make sure we have room for the new sector first
1658    const u32 next_out = PSP_UC(cdda_next_out);
1659    if (next_out > next_in * 2352 && next_out <= (next_in+1) * 2352)
1660    {
1661       SCSPLOG("WARNING: CDDA buffer overflow, discarding sector\n");
1662       return;
1663    }
1664 
1665    memcpy(cdda_buf.sectors[next_in], sector, 2352);
1666    PSP_WRITEBACK_CACHE(cdda_buf.sectors[next_in], 2352);
1667    cdda_next_in = next_next_in;
1668 }
1669 
1670 ///////////////////////////////////////////////////////////////////////////
1671 // Miscellaneous SCSP interface routines
1672 ///////////////////////////////////////////////////////////////////////////
1673 
1674 // SoundSaveState:  Save the current SCSP state to the given file.
1675 
SoundSaveState(FILE * fp)1676 int SoundSaveState(FILE *fp)
1677 {
1678    int i;
1679    u32 temp;
1680    u8 temp8;
1681    int offset;
1682    IOCheck_struct check = { 0, 0 };
1683 
1684    if (scsp_thread_running)
1685       ScspSyncThread();
1686 
1687    offset = StateWriteHeader(fp, "SCSP", 2);
1688 
1689    // Save 68k registers first
1690    ywrite(&check, (void *)&m68k_running, 1, 1, fp);
1691    for (i = 0; i < 8; i++)
1692    {
1693       temp = M68K->GetDReg(i);
1694       ywrite(&check, (void *)&temp, 4, 1, fp);
1695    }
1696    for (i = 0; i < 8; i++)
1697    {
1698       temp = M68K->GetAReg(i);
1699       ywrite(&check, (void *)&temp, 4, 1, fp);
1700    }
1701    temp = M68K->GetSR();
1702    ywrite(&check, (void *)&temp, 4, 1, fp);
1703    temp = M68K->GetPC();
1704    ywrite(&check, (void *)&temp, 4, 1, fp);
1705 
1706    // Now for the SCSP registers
1707    ywrite(&check, (void *)scsp_regcache, 0x1000, 1, fp);
1708 
1709    // Sound RAM is important
1710    ywrite(&check, (void *)SoundRam, 0x80000, 1, fp);
1711 
1712    // Write slot internal variables
1713    for (i = 0; i < 32; i++)
1714    {
1715       ywrite(&check, (void *)&scsp.slot[i].key, 1, 1, fp);
1716       ywrite(&check, (void *)&scsp.slot[i].addr_counter, 4, 1, fp);
1717       ywrite(&check, (void *)&scsp.slot[i].env_counter, 4, 1, fp);
1718       ywrite(&check, (void *)&scsp.slot[i].env_step, 4, 1, fp);
1719       ywrite(&check, (void *)&scsp.slot[i].env_target, 4, 1, fp);
1720       ywrite(&check, (void *)&scsp.slot[i].env_phase, 4, 1, fp);
1721 
1722       // Was enxt in scsp1; we don't use it, so just derive the proper
1723       // value from env_phase
1724       if (scsp.slot[i].env_phase == SCSP_ENV_RELEASE)
1725          temp8 = 1;
1726       else if (scsp.slot[i].env_phase == SCSP_ENV_SUSTAIN)
1727          temp8 = 2;
1728       else if (scsp.slot[i].env_phase == SCSP_ENV_DECAY)
1729          temp8 = 3;
1730       else if (scsp.slot[i].env_phase == SCSP_ENV_ATTACK)
1731          temp8 = 4;
1732       else  // impossible, but avoid "undefined value" warnings
1733          temp8 = 0;
1734       ywrite(&check, (void *)&temp8, 1, 1, fp);
1735 
1736       ywrite(&check, (void *)&scsp.slot[i].lfo_counter, 4, 1, fp);
1737       ywrite(&check, (void *)&scsp.slot[i].lfo_step, 4, 1, fp);
1738    }
1739 
1740    // Write main internal variables
1741    // FIXME/SCSP1: need to write a lot of these from temporary variables
1742    // to maintain save state compatibility
1743    temp = scsp.mem4mb;
1744    ywrite(&check, (void *)&temp, 4, 1, fp);
1745    temp = scsp.mvol;
1746    ywrite(&check, (void *)&temp, 4, 1, fp);
1747 
1748    temp = scsp.rbl;
1749    ywrite(&check, (void *)&temp, 4, 1, fp);
1750    ywrite(&check, (void *)&scsp.rbp, 4, 1, fp);
1751 
1752    temp = scsp.mslc;
1753    ywrite(&check, (void *)&temp, 4, 1, fp);
1754 
1755    ywrite(&check, (void *)&scsp.dmea, 4, 1, fp);
1756    temp = scsp.drga;
1757    ywrite(&check, (void *)&temp, 4, 1, fp);
1758    temp = scsp.dgate<<6 | scsp.ddir<<5 | scsp.dexe<<4;
1759    ywrite(&check, (void *)&temp, 4, 1, fp);
1760    temp = scsp.dtlg;
1761    ywrite(&check, (void *)&temp, 4, 1, fp);
1762 
1763    ywrite(&check, (void *)scsp.midi_in_buf, 1, 4, fp);
1764    ywrite(&check, (void *)scsp.midi_out_buf, 1, 4, fp);
1765    ywrite(&check, (void *)&scsp.midi_in_cnt, 1, 1, fp);
1766    ywrite(&check, (void *)&scsp.midi_out_cnt, 1, 1, fp);
1767    temp8 = scsp.mofull<<4 | scsp.moemp<<3
1768          | scsp.miovf<<2 | scsp.mifull<<1 | scsp.miemp<<0;
1769    ywrite(&check, (void *)&temp8, 1, 1, fp);
1770 
1771    temp = scsp.tima;
1772    ywrite(&check, (void *)&temp, 4, 1, fp);
1773    temp = scsp.tactl;
1774    ywrite(&check, (void *)&temp, 4, 1, fp);
1775    temp = scsp.timb;
1776    ywrite(&check, (void *)&temp, 4, 1, fp);
1777    temp = scsp.tbctl;
1778    ywrite(&check, (void *)&temp, 4, 1, fp);
1779    temp = scsp.timc;
1780    ywrite(&check, (void *)&temp, 4, 1, fp);
1781    temp = scsp.tcctl;
1782    ywrite(&check, (void *)&temp, 4, 1, fp);
1783 
1784    temp = scsp.scieb;
1785    ywrite(&check, (void *)&temp, 4, 1, fp);
1786    temp = scsp.scipd;
1787    ywrite(&check, (void *)&temp, 4, 1, fp);
1788    temp = scsp.scilv0;
1789    ywrite(&check, (void *)&temp, 4, 1, fp);
1790    temp = scsp.scilv1;
1791    ywrite(&check, (void *)&temp, 4, 1, fp);
1792    temp = scsp.scilv2;
1793    ywrite(&check, (void *)&temp, 4, 1, fp);
1794    temp = scsp.mcieb;
1795    ywrite(&check, (void *)&temp, 4, 1, fp);
1796    temp = scsp.mcipd;
1797    ywrite(&check, (void *)&temp, 4, 1, fp);
1798 
1799    ywrite(&check, (void *)scsp.stack, 4, 32 * 2, fp);
1800 
1801    return StateFinishHeader(fp, offset);
1802 }
1803 
1804 //-------------------------------------------------------------------------
1805 
1806 // SoundLoadState:  Load the current SCSP state from the given file.
1807 
SoundLoadState(FILE * fp,int version,int size)1808 int SoundLoadState(FILE *fp, int version, int size)
1809 {
1810    int i, i2;
1811    u32 temp;
1812    u8 temp8;
1813    IOCheck_struct check = { 0, 0 };
1814 
1815    if (scsp_thread_running)
1816       ScspSyncThread();
1817 
1818    // Read 68k registers first
1819    yread(&check, (void *)&m68k_running, 1, 1, fp);
1820    for (i = 0; i < 8; i++)
1821    {
1822       yread(&check, (void *)&temp, 4, 1, fp);
1823       M68K->SetDReg(i, temp);
1824    }
1825    for (i = 0; i < 8; i++)
1826    {
1827       yread(&check, (void *)&temp, 4, 1, fp);
1828       M68K->SetAReg(i, temp);
1829    }
1830    yread(&check, (void *)&temp, 4, 1, fp);
1831    M68K->SetSR(temp);
1832    yread(&check, (void *)&temp, 4, 1, fp);
1833    M68K->SetPC(temp);
1834 
1835    // Now for the SCSP registers
1836    yread(&check, (void *)scsp_regcache, 0x1000, 1, fp);
1837 
1838    // And sound RAM
1839    yread(&check, (void *)SoundRam, 0x80000, 1, fp);
1840 
1841    // Break out slot registers into their respective fields
1842    for (i = 0; i < 32; i++)
1843    {
1844       for (i2 = 0; i2 < 0x18; i2 += 2)
1845          ScspWriteWordDirect(i<<5 | i2, scsp_regcache[(i<<5 | i2) >> 1]);
1846       // These are also called during writes, so they're not technically
1847       // necessary, but call them again anyway just to ensure everything's
1848       // up to date
1849       ScspUpdateSlotAddress(&scsp.slot[i]);
1850       ScspUpdateSlotFunc(&scsp.slot[i]);
1851    }
1852 
1853    if (version > 1)
1854    {
1855       // Read slot internal variables
1856       for (i = 0; i < 32; i++)
1857       {
1858          yread(&check, (void *)&scsp.slot[i].key, 1, 1, fp);
1859          yread(&check, (void *)&scsp.slot[i].addr_counter, 4, 1, fp);
1860          yread(&check, (void *)&scsp.slot[i].env_counter, 4, 1, fp);
1861          yread(&check, (void *)&scsp.slot[i].env_step, 4, 1, fp);
1862          yread(&check, (void *)&scsp.slot[i].env_target, 4, 1, fp);
1863          yread(&check, (void *)&scsp.slot[i].env_phase, 4, 1, fp);
1864 
1865          // Was enxt in scsp1; we don't use it, so just read and ignore
1866          yread(&check, (void *)&temp8, 1, 1, fp);
1867 
1868          yread(&check, (void *)&scsp.slot[i].lfo_counter, 4, 1, fp);
1869          yread(&check, (void *)&scsp.slot[i].lfo_step, 4, 1, fp);
1870       }
1871 
1872       // Read main internal variables
1873       yread(&check, (void *)&temp, 4, 1, fp);
1874       scsp.mem4mb = temp;
1875       // This one isn't saved in the state file (though it's not used anyway)
1876       scsp.dac18b = (scsp_regcache[0x400>>1] >> 8) & 1;
1877       yread(&check, (void *)&temp, 4, 1, fp);
1878       scsp.mvol = temp;
1879 
1880       yread(&check, (void *)&temp, 4, 1, fp);
1881       scsp.rbl = temp;
1882       yread(&check, (void *)&scsp.rbp, 4, 1, fp);
1883 
1884       yread(&check, (void *)&temp, 4, 1, fp);
1885       scsp.mslc = temp;
1886 
1887       yread(&check, (void *)&scsp.dmea, 4, 1, fp);
1888       yread(&check, (void *)&temp, 4, 1, fp);
1889       scsp.drga = temp;
1890       yread(&check, (void *)&temp, 4, 1, fp);
1891       scsp.dgate = temp>>6 & 1;
1892       scsp.ddir  = temp>>5 & 1;
1893       scsp.dexe  = temp>>4 & 1;
1894       yread(&check, (void *)&temp, 4, 1, fp);
1895       scsp.dtlg = temp;
1896 
1897       yread(&check, (void *)scsp.midi_in_buf, 1, 4, fp);
1898       yread(&check, (void *)scsp.midi_out_buf, 1, 4, fp);
1899       yread(&check, (void *)&scsp.midi_in_cnt, 1, 1, fp);
1900       yread(&check, (void *)&scsp.midi_out_cnt, 1, 1, fp);
1901       yread(&check, (void *)&temp8, 1, 1, fp);
1902       scsp.mofull = temp8>>4 & 1;
1903       scsp.moemp  = temp8>>3 & 1;
1904       scsp.miovf  = temp8>>2 & 1;
1905       scsp.mifull = temp8>>1 & 1;
1906       scsp.miemp  = temp8>>0 & 1;
1907 
1908       yread(&check, (void *)&temp, 4, 1, fp);
1909       scsp.tima = temp;
1910       yread(&check, (void *)&temp, 4, 1, fp);
1911       scsp.tactl = temp;
1912       yread(&check, (void *)&temp, 4, 1, fp);
1913       scsp.timb = temp;
1914       yread(&check, (void *)&temp, 4, 1, fp);
1915       scsp.tbctl = temp;
1916       yread(&check, (void *)&temp, 4, 1, fp);
1917       scsp.timc = temp;
1918       yread(&check, (void *)&temp, 4, 1, fp);
1919       scsp.tcctl = temp;
1920 
1921       yread(&check, (void *)&temp, 4, 1, fp);
1922       scsp.scieb = temp;
1923       yread(&check, (void *)&temp, 4, 1, fp);
1924       scsp.scipd = temp;
1925       yread(&check, (void *)&temp, 4, 1, fp);
1926       scsp.scilv0 = temp;
1927       yread(&check, (void *)&temp, 4, 1, fp);
1928       scsp.scilv1 = temp;
1929       yread(&check, (void *)&temp, 4, 1, fp);
1930       scsp.scilv2 = temp;
1931       yread(&check, (void *)&temp, 4, 1, fp);
1932       scsp.mcieb = temp;
1933       yread(&check, (void *)&temp, 4, 1, fp);
1934       scsp.mcipd = temp;
1935 
1936       yread(&check, (void *)scsp.stack, 4, 32 * 2, fp);
1937    }
1938 
1939    if (scsp_thread_running)
1940       PSP_FLUSH_ALL();
1941 
1942    return size;
1943 }
1944 
1945 //-------------------------------------------------------------------------
1946 
1947 // ScspSlotDebugStats:  Generate a string describing the given slot's state
1948 // and store it in the passed-in buffer (which is assumed to be large enough
1949 // to hold the result).
1950 
1951 // Helper functions (defined below)
1952 static char *AddSoundLFO(char *outstring, const char *string, u16 level, u16 waveform);
1953 static char *AddSoundPan(char *outstring, u16 pan);
1954 static char *AddSoundLevel(char *outstring, u16 level);
1955 
ScspSlotDebugStats(u8 slotnum,char * outstring)1956 void ScspSlotDebugStats(u8 slotnum, char *outstring)
1957 {
1958    AddString(outstring, "Sound Source = ");
1959    switch (scsp.slot[slotnum].ssctl)
1960    {
1961       case 0:
1962       {
1963          AddString(outstring, "External DRAM data\r\n");
1964          break;
1965       }
1966       case 1:
1967       {
1968          AddString(outstring, "Internal(Noise)\r\n");
1969          break;
1970       }
1971       case 2:
1972       {
1973          AddString(outstring, "Internal(0's)\r\n");
1974          break;
1975       }
1976       default:
1977       {
1978          AddString(outstring, "Invalid setting\r\n");
1979          break;
1980       }
1981    }
1982    AddString(outstring, "Source bit = ");
1983    switch (scsp.slot[slotnum].sbctl)
1984    {
1985       case 0:
1986       {
1987          AddString(outstring, "No bit reversal\r\n");
1988          break;
1989       }
1990       case 1:
1991       {
1992          AddString(outstring, "Reverse other bits\r\n");
1993          break;
1994       }
1995       case 2:
1996       {
1997          AddString(outstring, "Reverse sign bit\r\n");
1998          break;
1999       }
2000       case 3:
2001       {
2002          AddString(outstring, "Reverse sign and other bits\r\n");
2003          break;
2004       }
2005    }
2006 
2007    // Loop Control
2008    AddString(outstring, "Loop Mode = ");
2009    switch (scsp.slot[slotnum].lpctl)
2010    {
2011       case 0:
2012       {
2013          AddString(outstring, "Off\r\n");
2014          break;
2015       }
2016       case 1:
2017       {
2018          AddString(outstring, "Normal\r\n");
2019          break;
2020       }
2021       case 2:
2022       {
2023          AddString(outstring, "Reverse\r\n");
2024          break;
2025       }
2026       case 3:
2027       {
2028          AddString(outstring, "Alternating\r\n");
2029          break;
2030       }
2031    }
2032    // PCM8B
2033    if (scsp.slot[slotnum].pcm8b)
2034    {
2035       AddString(outstring, "8-bit samples\r\n");
2036    }
2037    else
2038    {
2039       AddString(outstring, "16-bit samples\r\n");
2040    }
2041 
2042    AddString(outstring, "Start Address = %05lX\r\n", (unsigned long)scsp.slot[slotnum].sa);
2043    AddString(outstring, "Loop Start Address = %04X\r\n", scsp.slot[slotnum].lsa);
2044    AddString(outstring, "Loop End Address = %04X\r\n", scsp.slot[slotnum].lea);
2045    AddString(outstring, "Decay 1 Rate = %d\r\n", scsp.slot[slotnum].dr);
2046    AddString(outstring, "Decay 2 Rate = %d\r\n", scsp.slot[slotnum].sr);
2047    if (scsp.slot[slotnum].eghold)
2048    {
2049       AddString(outstring, "EG Hold Enabled\r\n");
2050    }
2051    AddString(outstring, "Attack Rate = %d\r\n", scsp.slot[slotnum].ar);
2052 
2053    if (scsp.slot[slotnum].lpslnk)
2054    {
2055       AddString(outstring, "Loop Start Link Enabled\r\n");
2056    }
2057 
2058    if (scsp.slot[slotnum].krs != 0)
2059    {
2060       AddString(outstring, "Key rate scaling = %d\r\n", scsp.slot[slotnum].krs);
2061    }
2062 
2063    AddString(outstring, "Decay Level = %d\r\n", scsp.slot[slotnum].sl);
2064    AddString(outstring, "Release Rate = %d\r\n", scsp.slot[slotnum].rr);
2065 
2066    if (scsp.slot[slotnum].stwinh)
2067    {
2068       AddString(outstring, "Stack Write Inhibited\r\n");
2069    }
2070 
2071    if (scsp.slot[slotnum].sdir)
2072    {
2073       AddString(outstring, "Sound Direct Enabled\r\n");
2074    }
2075 
2076    AddString(outstring, "Total Level = %d\r\n", scsp.slot[slotnum].tl);
2077 
2078    AddString(outstring, "Modulation Level = %d\r\n", scsp.slot[slotnum].mdl);
2079    AddString(outstring, "Modulation Input X = %d\r\n", scsp.slot[slotnum].mdx);
2080    AddString(outstring, "Modulation Input Y = %d\r\n", scsp.slot[slotnum].mdy);
2081 
2082    AddString(outstring, "Octave = %d\r\n", scsp.slot[slotnum].oct);
2083    AddString(outstring, "Frequency Number Switch = %d\r\n", scsp.slot[slotnum].fns);
2084 
2085    AddString(outstring, "LFO Reset = %s\r\n", scsp.slot[slotnum].lfore ? "TRUE" : "FALSE");
2086    AddString(outstring, "LFO Frequency = %d\r\n", scsp.slot[slotnum].lfof);
2087    outstring = AddSoundLFO(outstring, "LFO Frequency modulation waveform =",
2088                            scsp.slot[slotnum].plfos, scsp.slot[slotnum].plfows);
2089    AddString(outstring, "LFO Frequency modulation level = %d\r\n", scsp.slot[slotnum].plfos);
2090    outstring = AddSoundLFO(outstring, "LFO Amplitude modulation waveform =",
2091                            scsp.slot[slotnum].alfos, scsp.slot[slotnum].alfows);
2092    AddString(outstring, "LFO Amplitude modulation level = %d\r\n", scsp.slot[slotnum].alfos);
2093 
2094    AddString(outstring, "Input mix level = ");
2095    outstring = AddSoundLevel(outstring, scsp.slot[slotnum].imxl);
2096    AddString(outstring, "Input Select = %d\r\n", scsp.slot[slotnum].isel);
2097 
2098    AddString(outstring, "Direct data send level = ");
2099    outstring = AddSoundLevel(outstring, scsp.slot[slotnum].disdl);
2100    AddString(outstring, "Direct data panpot = ");
2101    outstring = AddSoundPan(outstring, scsp.slot[slotnum].dipan);
2102 
2103    AddString(outstring, "Effect data send level = ");
2104    outstring = AddSoundLevel(outstring, scsp.slot[slotnum].efsdl);
2105    AddString(outstring, "Effect data panpot = ");
2106    outstring = AddSoundPan(outstring, scsp.slot[slotnum].efpan);
2107 }
2108 
2109 //----------------------------------//
2110 
AddSoundLFO(char * outstring,const char * string,u16 level,u16 waveform)2111 static char *AddSoundLFO(char *outstring, const char *string, u16 level, u16 waveform)
2112 {
2113    if (level > 0)
2114    {
2115       switch (waveform)
2116       {
2117          case 0:
2118             AddString(outstring, "%s Sawtooth\r\n", string);
2119             break;
2120          case 1:
2121             AddString(outstring, "%s Square\r\n", string);
2122             break;
2123          case 2:
2124             AddString(outstring, "%s Triangle\r\n", string);
2125             break;
2126          case 3:
2127             AddString(outstring, "%s Noise\r\n", string);
2128             break;
2129       }
2130    }
2131 
2132    return outstring;
2133 }
2134 
2135 //----------------------------------//
2136 
AddSoundPan(char * outstring,u16 pan)2137 static char *AddSoundPan(char *outstring, u16 pan)
2138 {
2139    if (pan == 0x0F)
2140    {
2141       AddString(outstring, "Left = -MAX dB, Right = -0 dB\r\n");
2142    }
2143    else if (pan == 0x1F)
2144    {
2145       AddString(outstring, "Left = -0 dB, Right = -MAX dB\r\n");
2146    }
2147    else
2148    {
2149       AddString(outstring, "Left = -%d dB, Right = -%d dB\r\n", (pan & 0xF) * 3, (pan >> 4) * 3);
2150    }
2151 
2152    return outstring;
2153 }
2154 
2155 //----------------------------------//
2156 
AddSoundLevel(char * outstring,u16 level)2157 static char *AddSoundLevel(char *outstring, u16 level)
2158 {
2159    if (level == 0)
2160    {
2161       AddString(outstring, "-MAX dB\r\n");
2162    }
2163    else
2164    {
2165       AddString(outstring, "-%d dB\r\n", (7-level) *  6);
2166    }
2167 
2168    return outstring;
2169 }
2170 
2171 //-------------------------------------------------------------------------
2172 
2173 // ScspCommonControlRegisterDebugStats:  Generate a string describing the
2174 // SCSP common state registers and store it in the passed-in buffer (which
2175 // is assumed to be large enough to hold the result).
2176 
ScspCommonControlRegisterDebugStats(char * outstring)2177 void ScspCommonControlRegisterDebugStats(char *outstring)
2178 {
2179    AddString(outstring, "Memory: %s\r\n", scsp.mem4mb ? "4 Mbit" : "2 Mbit");
2180    AddString(outstring, "Master volume: %d\r\n", scsp.mvol);
2181    AddString(outstring, "Ring buffer length: %d\r\n", scsp.rbl);
2182    AddString(outstring, "Ring buffer address: %08lX\r\n", (unsigned long)scsp.rbp);
2183    AddString(outstring, "\r\n");
2184 
2185    AddString(outstring, "Slot Status Registers\r\n");
2186    AddString(outstring, "-----------------\r\n");
2187    AddString(outstring, "Monitor slot: %d\r\n", scsp.mslc);
2188    AddString(outstring, "Call address: %d\r\n", (ScspReadWordDirect(0x408) >> 7) & 0xF);
2189    AddString(outstring, "\r\n");
2190 
2191    AddString(outstring, "DMA Registers\r\n");
2192    AddString(outstring, "-----------------\r\n");
2193    AddString(outstring, "DMA memory address start: %08lX\r\n", (unsigned long)scsp.dmea);
2194    AddString(outstring, "DMA register address start: %03X\r\n", scsp.drga);
2195    AddString(outstring, "DMA Flags: %02X (%cDGATE %cDDIR %cDEXE)\r\n",
2196              scsp.dgate<<6 | scsp.ddir<<5 | scsp.dexe<<4,
2197              scsp.dgate ? '+' : '-', scsp.ddir ? '+' : '-',
2198              scsp.dexe ? '+' : '-');
2199    AddString(outstring, "\r\n");
2200 
2201    AddString(outstring, "Timer Registers\r\n");
2202    AddString(outstring, "-----------------\r\n");
2203    AddString(outstring, "Timer A counter: %02X\r\n", scsp.tima >> 8);
2204    AddString(outstring, "Timer A increment: Every %d sample(s)\r\n", 1 << scsp.tactl);
2205    AddString(outstring, "Timer B counter: %02X\r\n", scsp.timb >> 8);
2206    AddString(outstring, "Timer B increment: Every %d sample(s)\r\n", 1 << scsp.tbctl);
2207    AddString(outstring, "Timer C counter: %02X\r\n", scsp.timc >> 8);
2208    AddString(outstring, "Timer C increment: Every %d sample(s)\r\n", 1 << scsp.tcctl);
2209    AddString(outstring, "\r\n");
2210 
2211    AddString(outstring, "Interrupt Registers\r\n");
2212    AddString(outstring, "-----------------\r\n");
2213    AddString(outstring, "Sound cpu interrupt pending: %04X\r\n", scsp.scipd);
2214    AddString(outstring, "Sound cpu interrupt enable: %04X\r\n", scsp.scieb);
2215    AddString(outstring, "Sound cpu interrupt level 0: %04X\r\n", scsp.scilv0);
2216    AddString(outstring, "Sound cpu interrupt level 1: %04X\r\n", scsp.scilv1);
2217    AddString(outstring, "Sound cpu interrupt level 2: %04X\r\n", scsp.scilv2);
2218    AddString(outstring, "Main cpu interrupt pending: %04X\r\n", scsp.mcipd);
2219    AddString(outstring, "Main cpu interrupt enable: %04X\r\n", scsp.mcieb);
2220    AddString(outstring, "\r\n");
2221 }
2222 
2223 //-------------------------------------------------------------------------
2224 
2225 // ScspSlotDebugSaveRegisters:  Write the values of a single slot's
2226 // registers to a file.
2227 
ScspSlotDebugSaveRegisters(u8 slotnum,const char * filename)2228 int ScspSlotDebugSaveRegisters(u8 slotnum, const char *filename)
2229 {
2230    FILE *fp;
2231    int i;
2232    IOCheck_struct check = { 0, 0 };
2233 
2234    if ((fp = fopen(filename, "wb")) == NULL)
2235       return -1;
2236 
2237    for (i = (slotnum * 0x20); i < ((slotnum+1) * 0x20); i += 2)
2238    {
2239 #ifdef WORDS_BIGENDIAN
2240       ywrite(&check, (void *)&scsp_regcache[i], 1, 2, fp);
2241 #else
2242       ywrite(&check, (void *)&scsp_regcache[i+1], 1, 1, fp);
2243       ywrite(&check, (void *)&scsp_regcache[i], 1, 1, fp);
2244 #endif
2245    }
2246 
2247    fclose(fp);
2248    return 0;
2249 }
2250 
2251 //-------------------------------------------------------------------------
2252 
2253 // ScspSlotDebugAudioSaveWav:  Generate audio for a single slot and save it
2254 // to a WAV file.
2255 
2256 // Helper function to generate audio (defined below)
2257 static u32 ScspSlotDebugAudio(SlotState *slot, s32 *workbuf, s16 *buf, u32 len);
2258 
ScspSlotDebugAudioSaveWav(u8 slotnum,const char * filename)2259 int ScspSlotDebugAudioSaveWav(u8 slotnum, const char *filename)
2260 {
2261    typedef struct {
2262       char id[4];
2263       u32 size;
2264    } chunk_struct;
2265 
2266    typedef struct {
2267       chunk_struct riff;
2268       char rifftype[4];
2269    } waveheader_struct;
2270 
2271    typedef struct {
2272       chunk_struct chunk;
2273       u16 compress;
2274       u16 numchan;
2275       u32 rate;
2276       u32 bytespersec;
2277       u16 blockalign;
2278       u16 bitspersample;
2279    } fmt_struct;
2280 
2281    s32 workbuf[512*2*2];
2282    s16 buf[512*2];
2283    SlotState slot;
2284    FILE *fp;
2285    u32 counter = 0;
2286    waveheader_struct waveheader;
2287    fmt_struct fmt;
2288    chunk_struct data;
2289    long length;
2290    IOCheck_struct check = { 0, 0 };
2291 
2292    if (scsp.slot[slotnum].lea == 0)
2293       return 0;
2294 
2295    if ((fp = fopen(filename, "wb")) == NULL)
2296       return -1;
2297 
2298    // Do wave header
2299    memcpy(waveheader.riff.id, "RIFF", 4);
2300    waveheader.riff.size = 0; // we'll fix this after the file is closed
2301    memcpy(waveheader.rifftype, "WAVE", 4);
2302    ywrite(&check, (void *)&waveheader, 1, sizeof(waveheader_struct), fp);
2303 
2304    // fmt chunk
2305    memcpy(fmt.chunk.id, "fmt ", 4);
2306    fmt.chunk.size = 16; // we'll fix this at the end
2307    fmt.compress = 1; // PCM
2308    fmt.numchan = 2; // Stereo
2309    fmt.rate = 44100;
2310    fmt.bitspersample = 16;
2311    fmt.blockalign = fmt.bitspersample / 8 * fmt.numchan;
2312    fmt.bytespersec = fmt.rate * fmt.blockalign;
2313    ywrite(&check, (void *)&fmt, 1, sizeof(fmt_struct), fp);
2314 
2315    // data chunk
2316    memcpy(data.id, "data", 4);
2317    data.size = 0; // we'll fix this at the end
2318    ywrite(&check, (void *)&data, 1, sizeof(chunk_struct), fp);
2319 
2320    memcpy(&slot, &scsp.slot[slotnum], sizeof(slot));
2321 
2322    // Clear out the phase counter, etc.
2323    slot.addr_counter = 0;
2324    slot.env_counter = SCSP_ENV_ATTACK_START;
2325    slot.env_step = slot.env_step_a;
2326    slot.env_target = SCSP_ENV_ATTACK_END;
2327    slot.env_phase = SCSP_ENV_ATTACK;
2328 
2329    // Mix the audio, and then write it to the file
2330    for(;;)
2331    {
2332       if (ScspSlotDebugAudio(&slot, workbuf, buf, 512) == 0)
2333          break;
2334 
2335       counter += 512;
2336       ywrite(&check, (void *)buf, 2, 512 * 2, fp);
2337       if (slot.lpctl != 0 && counter >= (44100 * 2 * 5))
2338          break;
2339    }
2340 
2341    length = ftell(fp);
2342 
2343    // Let's fix the riff chunk size and the data chunk size
2344    fseek(fp, sizeof(waveheader_struct)-0x8, SEEK_SET);
2345    length -= 0x4;
2346    ywrite(&check, (void *)&length, 1, 4, fp);
2347 
2348    fseek(fp, sizeof(waveheader_struct)+sizeof(fmt_struct)+0x4, SEEK_SET);
2349    length -= sizeof(waveheader_struct)+sizeof(fmt_struct);
2350    ywrite(&check, (void *)&length, 1, 4, fp);
2351    fclose(fp);
2352    return 0;
2353 }
2354 
2355 //----------------------------------//
2356 
ScspSlotDebugAudio(SlotState * slot,s32 * workbuf,s16 * buf,u32 len)2357 static u32 ScspSlotDebugAudio(SlotState *slot, s32 *workbuf, s16 *buf, u32 len)
2358 {
2359    s32 *bufL, *bufR;
2360 
2361    bufL = workbuf;
2362    bufR = workbuf+len;
2363    scsp_bufL = bufL;
2364    scsp_bufR = bufR;
2365 
2366    if (slot->env_counter >= SCSP_ENV_DECAY_END)
2367       return 0;  // Not playing
2368 
2369    if (slot->ssctl)
2370       return 0; // not yet supported!
2371 
2372    memset(bufL, 0, sizeof(u32) * len);
2373    memset(bufR, 0, sizeof(u32) * len);
2374    ScspGenerateAudioForSlot(slot, len);
2375    ScspConvert32uto16s(bufL, bufR, buf, len);
2376    return len;
2377 }
2378 
2379 //-------------------------------------------------------------------------
2380 
2381 // ScspConvert32uto16s:  Saturate two 32-bit input sample buffers to 16-bit
2382 // and interleave them into a single output buffer.
2383 
ScspConvert32uto16s(s32 * srcL,s32 * srcR,s16 * dest,u32 len)2384 void ScspConvert32uto16s(s32 *srcL, s32 *srcR, s16 *dest, u32 len)
2385 {
2386    u32 i;
2387 
2388    for (i = 0; i < len; i++, srcL++, srcR++, dest += 2)
2389    {
2390       // Left channel
2391       if (*srcL > 0x7FFF)
2392          dest[0] = 0x7FFF;
2393       else if (*srcL < -0x8000)
2394          dest[0] = -0x8000;
2395       else
2396          dest[0] = *srcL;
2397       // Right channel
2398       if (*srcR > 0x7FFF)
2399          dest[1] = 0x7FFF;
2400       else if (*srcR < -0x8000)
2401          dest[1] = -0x8000;
2402       else
2403          dest[1] = *srcR;
2404    }
2405 }
2406 
2407 ///////////////////////////////////////////////////////////////////////////
2408 // SCSP register read/write routines and internal helpers
2409 ///////////////////////////////////////////////////////////////////////////
2410 
2411 // Scsp{Read,Write}{Byte,Word}Direct:  Perform an SCSP register read or
2412 // write.  These are internal routines that implement the actual register
2413 // read/write logic.  The address must be in the range [0,0xFFF].
2414 
ScspReadByteDirect(u32 address)2415 static u8 FASTCALL ScspReadByteDirect(u32 address)
2416 {
2417    const u16 data = ScspReadWordDirect(address & ~1);
2418    if (address & 1)
2419       return data & 0xFF;
2420    else
2421       return data >> 8;
2422 }
2423 
2424 //----------------------------------//
2425 
ScspReadMonitor(void)2426 static u16 ScspReadMonitor(void)
2427 {
2428    u8 ca, sgc, eg;
2429 
2430    ca = (scsp.slot[scsp.mslc].addr_counter >> (SCSP_FREQ_LOW_BITS + 12)) & 0xF;
2431 
2432    switch (scsp.slot[scsp.mslc].env_phase) {
2433       case SCSP_ENV_ATTACK:
2434          sgc = 0;
2435          break;
2436       case SCSP_ENV_DECAY:
2437          sgc = 1;
2438          break;
2439       case SCSP_ENV_SUSTAIN:
2440          sgc = 2;
2441          break;
2442       case SCSP_ENV_RELEASE:
2443          sgc = 3;
2444          break;
2445    }
2446 
2447    eg = 0x1f - (scsp.slot[scsp.mslc].last_env >> 27);
2448 
2449    return (ca << 7) | (sgc << 5) | eg;
2450 }
2451 
ScspReadWordDirect(u32 address)2452 static u16 FASTCALL ScspReadWordDirect(u32 address)
2453 {
2454    switch (address)
2455    {
2456       case 0x404:  // MIDI in
2457          return ScspMidiIn();
2458       case 0x408:  // CA/SGC/EG
2459          return ScspReadMonitor();
2460       default:
2461          return PSP_UC(scsp_regcache[address >> 1]);
2462    }
2463 }
2464 
2465 //----------------------------------//
2466 
ScspWriteByteDirect(u32 address,u8 data)2467 static void FASTCALL ScspWriteByteDirect(u32 address, u8 data)
2468 {
2469    switch (address >> 8)
2470    {
2471       case 0x0:
2472       case 0x1:
2473       case 0x2:
2474       case 0x3:
2475       write_as_word:
2476       {
2477          // These can be treated as word writes, borrowing the missing
2478          // 8 bits from the register cache
2479          u16 word_data;
2480          if (address & 1)
2481             word_data = (PSP_UC(scsp_regcache[address >> 1]) & 0xFF00) | data;
2482          else
2483             word_data = (PSP_UC(scsp_regcache[address >> 1]) & 0x00FF) | (data << 8);
2484          ScspWriteWordDirect(address & ~1, word_data);
2485          return;
2486       }
2487 
2488       case 0x4:
2489          switch (address & 0xFF)
2490          {
2491             // FIXME: if interrupts are only triggered on 0->1 changes in
2492             // [SM]CIEB, we can skip 0x1E/0x1F/0x26/0x27 (see FIXME in
2493             // ScspWriteWordDirect())
2494 
2495             case 0x1E:
2496                data &= 0x07;
2497                scsp.scieb = (data << 8) | (scsp.scieb & 0x00FF);
2498                ScspCheckInterrupts(0x700, SCSP_INTTARGET_SOUND);
2499                break;
2500 
2501             case 0x1F:
2502                scsp.scieb = (scsp.scieb & 0xFF00) | data;
2503                ScspCheckInterrupts(0x700, SCSP_INTTARGET_SOUND);
2504                break;
2505 
2506             case 0x20:
2507                return;  // Not writable
2508 
2509             case 0x21:
2510                if (data & (1<<5))
2511                   ScspRaiseInterrupt(5, SCSP_INTTARGET_SOUND);
2512                return;  // Not writable
2513 
2514             case 0x2A:
2515                data &= 0x07;
2516                scsp.mcieb = (data << 8) | (scsp.mcieb & 0x00FF);
2517                ScspCheckInterrupts(0x700, SCSP_INTTARGET_MAIN);
2518                break;
2519 
2520             case 0x2B:
2521                scsp.mcieb = (scsp.mcieb & 0xFF00) | data;
2522                ScspCheckInterrupts(0x700, SCSP_INTTARGET_MAIN);
2523                break;
2524 
2525             case 0x2C:
2526                return;  // Not writable
2527 
2528             case 0x2D:
2529                if (data & (1<<5))
2530                   ScspRaiseInterrupt(5, SCSP_INTTARGET_MAIN);
2531                return;  // Not writable
2532 
2533             case 0x00:
2534             case 0x01:
2535             case 0x02:
2536             case 0x03:
2537             case 0x04:
2538             case 0x05:
2539             case 0x06:
2540             case 0x07:
2541             case 0x08:
2542             case 0x09:
2543             case 0x12:
2544             case 0x13:
2545             case 0x14:
2546             case 0x15:
2547             case 0x16:
2548             case 0x17:
2549             case 0x18:
2550             case 0x19:
2551             case 0x1A:
2552             case 0x1B:
2553             case 0x1C:
2554             case 0x1D:
2555             case 0x22:
2556             case 0x23:
2557             case 0x24:
2558             case 0x25:
2559             case 0x26:
2560             case 0x27:
2561             case 0x28:
2562             case 0x29:
2563             case 0x2E:
2564             case 0x2F:
2565                goto write_as_word;
2566 
2567             default:
2568                goto unhandled_write;
2569          }
2570          break;
2571 
2572       default:
2573       unhandled_write:
2574          SCSPLOG("ScspWriteByteDirect(): unhandled write %02X to 0x%03X\n",
2575                  data, address);
2576          break;
2577    }
2578 
2579    if (address & 1)
2580    {
2581       PSP_UC(scsp_regcache[address >> 1]) &= 0xFF00;
2582       PSP_UC(scsp_regcache[address >> 1]) |= data;
2583    }
2584    else
2585    {
2586       PSP_UC(scsp_regcache[address >> 1]) &= 0x00FF;
2587       PSP_UC(scsp_regcache[address >> 1]) |= data << 8;
2588    }
2589 }
2590 
2591 //----------------------------------//
2592 
ScspWriteWordDirect(u32 address,u16 data)2593 static void FASTCALL ScspWriteWordDirect(u32 address, u16 data)
2594 {
2595    switch (address >> 8)
2596    {
2597       case 0x0:
2598       case 0x1:
2599       case 0x2:
2600       case 0x3:
2601       {
2602          const int slotnum = (address & 0x3E0) >> 5;
2603          SlotState *slot = &scsp.slot[slotnum];
2604          switch (address & 0x1F)
2605          {
2606             case 0x00:
2607                slot->key    = (data >> 11) & 0x1;
2608                slot->sbctl  = (data >>  9) & 0x3;
2609                slot->ssctl  = (data >>  7) & 0x3;
2610                slot->lpctl  = (data >>  5) & 0x3;
2611                slot->pcm8b  = (data >>  4) & 0x1;
2612                slot->sa     =((data >>  0) & 0xF) << 16 | (slot->sa & 0xFFFF);
2613 
2614                ScspUpdateSlotFunc(slot);
2615                if (slot->env_counter < SCSP_ENV_DECAY_END)
2616                   ScspUpdateSlotAddress(slot);
2617 
2618                if (data & (1<<12))
2619                   ScspDoKeyOnOff();
2620 
2621                data &= 0x0FFF;  // Don't save KYONEX
2622                break;
2623 
2624             case 0x02:
2625                slot->sa     = (slot->sa & 0xF0000) | data;
2626                if (slot->env_counter < SCSP_ENV_DECAY_END)
2627                   ScspUpdateSlotAddress(slot);
2628                break;
2629 
2630             case 0x04:
2631                slot->lsa    = data;
2632                if (slot->env_counter < SCSP_ENV_DECAY_END)
2633                   ScspUpdateSlotAddress(slot);
2634                break;
2635 
2636             case 0x06:
2637                slot->lea    = data;
2638                if (slot->env_counter < SCSP_ENV_DECAY_END)
2639                   ScspUpdateSlotAddress(slot);
2640                break;
2641 
2642             case 0x08:
2643                slot->sr     = (data >> 11) & 0x1F;
2644                slot->dr     = (data >>  6) & 0x1F;
2645                slot->eghold = (data >>  5) & 0x1;
2646                slot->ar     = (data >>  0) & 0x1F;
2647                ScspUpdateSlotEnv(slot);
2648                break;
2649 
2650             case 0x0A:
2651                data &= 0x7FFF;
2652                slot->lpslnk = (data >> 14) & 0x1;
2653                slot->krs    = (data >> 10) & 0xF;
2654                slot->sl     = (data >>  5) & 0x1F;
2655                slot->rr     = (data >>  0) & 0x1F;
2656 
2657                if (slot->krs == 0xF)
2658                   slot->krs_shift = 4;
2659                else
2660                   slot->krs_shift = slot->krs >> 2;
2661 
2662                ScspUpdateSlotEnv(slot);
2663 
2664                slot->sl_target = (slot->sl << (5 + SCSP_ENV_LOW_BITS))
2665                                  + SCSP_ENV_DECAY_START;
2666 
2667                break;
2668 
2669             case 0x0C:
2670                data &= 0x03FF;
2671                slot->stwinh = (data >>  9) & 0x1;
2672                slot->sdir   = (data >>  8) & 0x1;
2673                slot->tl     = (data >>  0) & 0xFF;
2674 
2675                slot->tl_mult = scsp_tl_table[slot->tl];
2676 
2677                break;
2678 
2679             case 0x0E:
2680                slot->mdl    = (data >> 12) & 0xF;
2681                slot->mdx    = (data >>  6) & 0x3F;
2682                slot->mdy    = (data >>  0) & 0x3F;
2683                break;
2684 
2685             case 0x10:
2686                data &= 0x7BFF;
2687                slot->oct    = (data >> 11) & 0xF;
2688                slot->fns    = (data >>  0) & 0x3FF;
2689 
2690                if (slot->oct & 8)
2691                   slot->octave_shift = 23 - slot->oct;
2692                else
2693                   slot->octave_shift = 7 - slot->oct;
2694                slot->addr_step = ((0x400 + slot->fns) << 7) >> slot->octave_shift;
2695 
2696                ScspUpdateSlotEnv(slot);
2697 
2698                break;
2699 
2700             case 0x12:
2701                slot->lfore  = (data >> 15) & 0x1;
2702                slot->lfof   = (data >> 10) & 0x1F;
2703                slot->plfows = (data >>  8) & 0x3;
2704                slot->plfos  = (data >>  5) & 0x7;
2705                slot->alfows = (data >>  3) & 0x3;
2706                slot->alfos  = (data >>  0) & 0x7;
2707 
2708                if (slot->lfore)
2709                {
2710                   slot->lfo_step = -1;
2711                   slot->lfo_counter = 0;
2712                   slot->lfo_fm_shift = -1;
2713                   slot->lfo_am_shift = -1;
2714                }
2715                else
2716                {
2717                   slot->lfo_step = scsp_lfo_step[slot->lfof];
2718                   if (slot->plfos)
2719                      slot->lfo_fm_shift = slot->plfos - 1;
2720                   else
2721                      slot->lfo_fm_shift = -1;
2722                   if (slot->alfos)
2723                      slot->lfo_am_shift = 11 - slot->alfos;
2724                   else
2725                      slot->lfo_am_shift = -1;
2726                }
2727                slot->lfo_fm_wave = scsp_lfo_wave_freq[slot->plfows];
2728                slot->lfo_am_wave = scsp_lfo_wave_amp[slot->alfows];
2729 
2730                ScspUpdateSlotFunc(slot);
2731 
2732                break;
2733 
2734             case 0x14:
2735                data &= 0x007F;
2736                slot->isel   = (data >>  3) & 0xF;
2737                slot->imxl   = (data >>  0) & 0x7;
2738 
2739                if (slot->imxl)
2740                   slot->imxl_shift = (7 - slot->imxl) + SCSP_ENV_HIGH_BITS;
2741                else
2742                   slot->imxl_shift = 31;
2743 
2744                break;
2745 
2746             case 0x16:
2747                slot->disdl  = (data >> 13) & 0x7;
2748                slot->dipan  = (data >>  8) & 0x1F;
2749                slot->efsdl  = (data >>  5) & 0x7;
2750                slot->efpan  = (data >>  0) & 0x1F;
2751 
2752                // Compute the output shift counts for the left and right
2753                // channels.  If the direct sound output is muted, we assume
2754                // the data is being passed through the DSP (which we don't
2755                // currently implement) and take the effect output level
2756                // instead.  Note that we lose 1 bit of resolution from the
2757                // panning parameter because we adjust the output level by
2758                // shifting (powers of two), while DIPAN/EFPAN have a
2759                // resolution of sqrt(2).
2760 
2761                if (slot->disdl)
2762                {
2763                   slot->outshift_l = slot->outshift_r = (7 - slot->disdl)
2764                                                         + SCSP_ENV_HIGH_BITS;
2765                   if (slot->dipan & 0x10)  // Pan left
2766                   {
2767                      if (slot->dipan == 0x1F)
2768                         slot->outshift_r = 31;
2769                      else
2770                         slot->outshift_r += (slot->dipan >> 1) & 7;
2771                   }
2772                   else  // Pan right
2773                   {
2774                      if (slot->dipan == 0xF)
2775                         slot->outshift_l = 31;
2776                      else
2777                         slot->outshift_l += (slot->dipan >> 1) & 7;
2778                   }
2779                }
2780                else if (slot->efsdl)
2781                {
2782                   slot->outshift_l = slot->outshift_r = (7 - slot->efsdl)
2783                                                         + SCSP_ENV_HIGH_BITS;
2784                   if (slot->efpan & 0x10)  // Pan left
2785                   {
2786                      if (slot->efpan == 0x1F)
2787                         slot->outshift_r = 31;
2788                      else
2789                         slot->outshift_r += (slot->efpan >> 1) & 7;
2790                   }
2791                   else  // Pan right
2792                   {
2793                      if (slot->efpan == 0xF)
2794                         slot->outshift_l = 31;
2795                      else
2796                         slot->outshift_l += (slot->efpan >> 1) & 7;
2797                   }
2798                }
2799                else
2800                   slot->outshift_l = slot->outshift_r = 31;  // Muted
2801 
2802                ScspUpdateSlotFunc(slot);
2803 
2804                break;
2805 
2806             default:
2807                goto unhandled_write;
2808          }
2809          break;
2810       }
2811 
2812       case 0x4:
2813          switch (address & 0xFF)
2814          {
2815             case 0x00:
2816                data &= 0x030F;  // VER is hardwired
2817                data |= SCSP_VERSION << 4;
2818                scsp.mem4mb = (data >>  9) & 0x1;
2819                scsp.dac18b = (data >>  8) & 0x1;
2820                scsp.mvol   = (data >>  0) & 0xF;
2821 
2822                if (scsp.mem4mb)
2823                   M68K->SetFetch(0x000000, 0x080000, (pointer)SoundRam);
2824                else
2825                {
2826                   M68K->SetFetch(0x000000, 0x040000, (pointer)SoundRam);
2827                   M68K->SetFetch(0x040000, 0x080000, (pointer)SoundRam);
2828                   M68K->SetFetch(0x080000, 0x0C0000, (pointer)SoundRam);
2829                   M68K->SetFetch(0x0C0000, 0x100000, (pointer)SoundRam);
2830                }
2831                scsp.sound_ram_mask = scsp.mem4mb ? 0x7FFFF : 0x3FFFF;
2832 
2833                break;
2834 
2835             case 0x02:
2836                data &= 0x01FF;
2837                scsp.rbl    = (data >>  7) & 0x3;
2838                scsp.rbp    =((data >>  0) & 0x7F) << 13;
2839                break;
2840 
2841             case 0x04:
2842                return;  // Not writable
2843 
2844             case 0x06:
2845                data &= 0x00FF;
2846                ScspMidiOut(data);
2847                break;
2848 
2849             case 0x08:
2850                data &= 0x7800;  // CA/SGC/EG are not writable
2851                scsp.mslc   = (data >> 11) & 0x1F;
2852                break;
2853 
2854             case 0x12:
2855                data &= 0xFFFE;
2856                scsp.dmea   = (scsp.dmea & 0xF0000) | data;
2857                break;
2858 
2859             case 0x14:
2860                data &= 0xFFFE;
2861                scsp.dmea   =((data >> 12) & 0xF) << 16 | (scsp.dmea & 0xFFFF);
2862                scsp.drga   = (data >>  0) & 0xFFF;
2863                break;
2864 
2865             case 0x16:
2866                data &= 0x7FFE;
2867                scsp.dgate  = (data >> 14) & 0x1;
2868                scsp.ddir   = (data >> 13) & 0x1;
2869                scsp.dexe  |= (data >> 12) & 0x1;  // Writing 0 not allowed
2870                scsp.dtlg   = (data >>  0) & 0xFFF;
2871                if (data & (1<<12))
2872                   ScspDoDMA();
2873                break;
2874 
2875             case 0x18:
2876                data &= 0x07FF;
2877                scsp.tactl  = (data >>  8) & 0x7;
2878                scsp.tima   =((data >>  0) & 0xFF) << 8;
2879                break;
2880 
2881             case 0x1A:
2882                data &= 0x07FF;
2883                scsp.tbctl  = (data >>  8) & 0x7;
2884                scsp.timb   =((data >>  0) & 0xFF) << 8;
2885                break;
2886 
2887             case 0x1C:
2888                data &= 0x07FF;
2889                scsp.tcctl  = (data >>  8) & 0x7;
2890                scsp.timc   =((data >>  0) & 0xFF) << 8;
2891                break;
2892 
2893             case 0x1E:
2894                data &= 0x07FF;
2895                scsp.scieb = data;
2896                // FIXME: If a bit is already 1 in both SCIEB and SCIPD,
2897                // does writing another 1 here (no change) trigger another
2898                // interrupt or not?
2899                ScspCheckInterrupts(0x7FF, SCSP_INTTARGET_SOUND);
2900                break;
2901 
2902             case 0x20:
2903                if (data & (1<<5))
2904                   ScspRaiseInterrupt(5, SCSP_INTTARGET_SOUND);
2905                return;  // Not writable
2906 
2907             case 0x22:
2908                ScspClearInterrupts(data, SCSP_INTTARGET_SOUND);
2909                return;  // Not writable
2910 
2911             case 0x24:
2912                data &= 0x00FF;
2913                scsp.scilv0 = data;
2914                break;
2915 
2916             case 0x26:
2917                data &= 0x00FF;
2918                scsp.scilv1 = data;
2919                break;
2920 
2921             case 0x28:
2922                data &= 0x00FF;
2923                scsp.scilv2 = data;
2924                break;
2925 
2926             case 0x2A:
2927                data &= 0x07FF;
2928                scsp.mcieb = data;
2929                // FIXME: as above (SCIEB)
2930                ScspCheckInterrupts(0x7FF, SCSP_INTTARGET_MAIN);
2931                break;
2932 
2933             case 0x2C:
2934                if (data & (1<<5))
2935                   ScspRaiseInterrupt(5, SCSP_INTTARGET_MAIN);
2936                return;  // Not writable
2937 
2938             case 0x2E:
2939                ScspClearInterrupts(data, SCSP_INTTARGET_MAIN);
2940                return;  // Not writable
2941 
2942             default:
2943                goto unhandled_write;
2944          }
2945          break;
2946 
2947       default:
2948       unhandled_write:
2949          SCSPLOG("ScspWriteWordDirect(): unhandled write %04X to 0x%03X\n",
2950                  data, address);
2951          break;
2952    }
2953 
2954    PSP_UC(scsp_regcache[address >> 1]) = data;
2955 }
2956 
2957 //-------------------------------------------------------------------------
2958 
2959 // ScspDoKeyOnOff:  Apply the key-on/key-off setting for all slots.
2960 // Implements the KYONEX trigger.
2961 
ScspDoKeyOnOff(void)2962 static void ScspDoKeyOnOff(void)
2963 {
2964    int slotnum;
2965    for (slotnum = 0; slotnum < 32; slotnum++)
2966    {
2967       if (scsp.slot[slotnum].key)
2968          ScspKeyOn(&scsp.slot[slotnum]);
2969       else
2970          ScspKeyOff(&scsp.slot[slotnum]);
2971    }
2972 }
2973 
2974 //----------------------------------//
2975 
2976 // ScspKeyOn:  Execute a key-on event for a single slot.
2977 
ScspKeyOn(SlotState * slot)2978 static void ScspKeyOn(SlotState *slot)
2979 {
2980    if (slot->env_phase != SCSP_ENV_RELEASE)
2981       return;  // Can't key a sound that's already playing
2982 
2983    ScspUpdateSlotAddress(slot);
2984 
2985    slot->addr_counter = 0;
2986    slot->env_phase = SCSP_ENV_ATTACK;
2987    slot->env_counter = SCSP_ENV_ATTACK_START;  // FIXME: should this start at the current value if the old sound is still decaying?
2988    slot->env_step = slot->env_step_a;
2989    slot->env_target = SCSP_ENV_ATTACK_END;
2990 }
2991 
2992 //----------------------------------//
2993 
2994 // ScspKeyOff:  Execute a key-off event for a single slot.
2995 
ScspKeyOff(SlotState * slot)2996 static void ScspKeyOff(SlotState *slot)
2997 {
2998    if (slot->env_phase == SCSP_ENV_RELEASE)
2999       return;  // Can't release a sound that's already released
3000 
3001    // If we still are in attack phase at release time, convert attack to decay
3002    if (slot->env_phase == SCSP_ENV_ATTACK)
3003       slot->env_counter = SCSP_ENV_DECAY_END - slot->env_counter;
3004 
3005    slot->env_phase = SCSP_ENV_RELEASE;
3006    slot->env_step = slot->env_step_r;
3007    slot->env_target = SCSP_ENV_DECAY_END;
3008 }
3009 
3010 //-------------------------------------------------------------------------
3011 
3012 // ScspUpdateSlotAddress:  Update the sample data pointer for the given
3013 // slot, bound slot->lea to the end of sound RAM, and cache the shifted
3014 // values of slot->lsa and slot->lea in slot->{lea,lsa}_shifted.
3015 
ScspUpdateSlotAddress(SlotState * slot)3016 static void ScspUpdateSlotAddress(SlotState *slot)
3017 {
3018    u32 max_samples;
3019 
3020    if (slot->pcm8b)
3021       slot->sa &= ~1;
3022    slot->sa &= scsp.sound_ram_mask;
3023    slot->buf = &SoundRam[slot->sa];
3024    max_samples = scsp.sound_ram_mask - slot->sa;
3025    if (slot->pcm8b)
3026       max_samples >>= 1;
3027 
3028    if (slot->lsa > max_samples)
3029       slot->lsa = max_samples;
3030    slot->lsa_shifted = slot->lsa << SCSP_FREQ_LOW_BITS;
3031 
3032    if (slot->lea > max_samples)
3033       slot->lea = max_samples;
3034    slot->lea_shifted = ((slot->lea + 1) << SCSP_FREQ_LOW_BITS) - 1;
3035 
3036    slot->looplen_shifted = slot->lea_shifted - slot->lsa_shifted + 1;
3037 }
3038 
3039 //----------------------------------//
3040 
3041 // ScspUpdateSlotEnv:  Update the envelope step values from the SR/DR/AR/RR
3042 // slot registers.  slot->krs_shift and slot->octave_shift are assumed to
3043 // be up to date with respect to the KRS and OCT registers.
3044 
ScspUpdateSlotEnv(SlotState * slot)3045 static void ScspUpdateSlotEnv(SlotState *slot)
3046 {
3047    if (slot->sr)
3048    {
3049       const s32 *rate_table = &scsp_decay_rate[slot->sr << 1];
3050       slot->env_step_s = rate_table[(15 - slot->octave_shift)
3051                                     >> slot->krs_shift];
3052    }
3053    else
3054       slot->env_step_s = 0;
3055 
3056    if (slot->dr)
3057    {
3058       const s32 *rate_table = &scsp_decay_rate[slot->dr << 1];
3059       slot->env_step_d = rate_table[(15 - slot->octave_shift)
3060                                     >> slot->krs_shift];
3061    }
3062    else
3063       slot->env_step_d = 0;
3064 
3065    if (slot->ar)
3066    {
3067       const s32 *rate_table = &scsp_attack_rate[slot->ar << 1];
3068       slot->env_step_a = rate_table[(15 - slot->octave_shift)
3069                                     >> slot->krs_shift];
3070    }
3071    else
3072       slot->env_step_a = 0;
3073 
3074    if (slot->rr)
3075    {
3076       const s32 *rate_table = &scsp_decay_rate[slot->rr << 1];
3077       slot->env_step_r = rate_table[(15 - slot->octave_shift)
3078                                     >> slot->krs_shift];
3079    }
3080    else
3081       slot->env_step_r = 0;
3082 }
3083 
3084 //----------------------------------//
3085 
3086 // ScspUpdateSlotFunc:  Update the audio generation function for the given
3087 // slot based on the slot's parameters.
3088 
ScspUpdateSlotFunc(SlotState * slot)3089 static void ScspUpdateSlotFunc(SlotState *slot)
3090 {
3091    if (slot->ssctl)
3092       // FIXME: noise (ssctl==1) not implemented
3093       slot->audiogen = scsp_audiogen_func_table[0][0][0][0][0];
3094    else
3095       slot->audiogen = scsp_audiogen_func_table[slot->lfo_fm_shift >= 0]
3096                                                [slot->lfo_am_shift >= 0]
3097                                                [slot->pcm8b == 0]
3098                                                [slot->outshift_l != 31]
3099                                                [slot->outshift_r != 31];
3100 }
3101 
3102 //-------------------------------------------------------------------------
3103 
3104 // ScspMidiIn:  Handle a read from the MIDI input register ($404).  Since
3105 // there is no facility for sending MIDI data (the Saturn does not have a
3106 // MIDI I/O port), most of this is essentially a giant no-op, but the logic
3107 // is included for reference.
3108 
ScspMidiIn(void)3109 static u16 ScspMidiIn(void)
3110 {
3111    scsp.miovf = 0;
3112    scsp.mifull = 0;
3113    if (scsp.midi_in_cnt > 0)
3114    {
3115       scsp.mibuf = scsp.midi_in_buf[0];
3116       scsp.midi_in_buf[0] = scsp.midi_in_buf[1];
3117       scsp.midi_in_buf[1] = scsp.midi_in_buf[2];
3118       scsp.midi_in_buf[2] = scsp.midi_in_buf[3];
3119       scsp.midi_in_cnt--;
3120       scsp.miemp = (scsp.midi_in_cnt == 0);
3121       if (!scsp.miemp)
3122          ScspRaiseInterrupt(SCSP_INTERRUPT_MIDI_IN, SCSP_INTTARGET_BOTH);
3123    }
3124    else  // scsp.midi_in_cnt == 0
3125       scsp.mibuf = 0xFF;
3126 
3127    return scsp.mofull << 12
3128         | scsp.moemp  << 11
3129         | scsp.miovf  << 10
3130         | scsp.mifull <<  9
3131         | scsp.miemp  <<  8
3132         | scsp.mibuf  <<  0;
3133 }
3134 
3135 //----------------------------------//
3136 
3137 // ScspMidiOut:  Handle a write to the MIDI output register ($406).
3138 
ScspMidiOut(u8 data)3139 static void ScspMidiOut(u8 data)
3140 {
3141    scsp.moemp = 0;
3142    if (scsp.midi_out_cnt < 4)
3143       scsp.midi_out_buf[scsp.midi_out_cnt++] = data;
3144    scsp.mofull = (scsp.midi_out_cnt >= 4);
3145 }
3146 
3147 //-------------------------------------------------------------------------
3148 
3149 // ScspDoDMA:  Handle a DMA request (when 1 is written to DEXE).  DMA is
3150 // processed instantaneously regardless of transfer size.
3151 
ScspDoDMA(void)3152 static void ScspDoDMA(void)
3153 {
3154    const u32 dmea = scsp.dmea & scsp.sound_ram_mask;
3155 
3156    if (scsp.ddir)  // {RAM,zero} -> registers
3157    {
3158       SCSPLOG("DMA %s RAM[$%05X] -> registers[$%03X]\n",
3159               scsp.dgate ? "clear" : "copy", dmea, scsp.drga);
3160       if (scsp.dgate)
3161       {
3162          u32 i;
3163          for (i = 0; i < scsp.dtlg; i += 2)
3164             ScspWriteWordDirect(scsp.drga + i, 0);
3165       }
3166       else
3167       {
3168          u32 i;
3169          for (i = 0; i < scsp.dtlg; i += 2)
3170             ScspWriteWordDirect(scsp.drga + i, T2ReadWord(SoundRam, dmea + i));
3171       }
3172    }
3173    else  // !scsp.ddir, i.e. registers -> RAM
3174    {
3175       SCSPLOG("DMA %s registers[$%03X] -> RAM[$%05X]\n",
3176               scsp.dgate ? "clear" : "copy", scsp.drga, dmea);
3177       if (scsp.dgate)
3178          memset(&SoundRam[dmea], 0, scsp.dtlg);
3179       else
3180       {
3181          u32 i;
3182          for (i = 0; i < scsp.dtlg; i += 2)
3183             T2WriteWord(SoundRam, dmea + i, ScspReadWordDirect(scsp.drga + i));
3184       }
3185       M68K->WriteNotify(dmea, scsp.dtlg);
3186    }
3187 
3188    scsp.dexe = 0;
3189    PSP_UC(scsp_regcache[0x416>>1]) &= ~(1<<12);
3190    ScspRaiseInterrupt(SCSP_INTERRUPT_DMA, SCSP_INTTARGET_BOTH);
3191 }
3192 
3193 ///////////////////////////////////////////////////////////////////////////
3194 // Other SCSP internal helper routines
3195 ///////////////////////////////////////////////////////////////////////////
3196 
3197 // ScspSyncThread:  Wait for the SCSP subthread to finish executing all
3198 // pending cycles.  Do not call if the subthread is not running.
3199 
ScspSyncThread(void)3200 static void ScspSyncThread(void)
3201 {
3202    PSP_FLUSH_ALL();
3203    while (PSP_UC(scsp_clock) != scsp_clock_target)
3204    {
3205       YabThreadWake(YAB_THREAD_SCSP);
3206       YabThreadYield();
3207    }
3208 }
3209 
3210 //-------------------------------------------------------------------------
3211 
3212 // ScspRaiseInterrupt:  Raise an interrupt for the main and/or sound CPU.
3213 
ScspRaiseInterrupt(int which,int target)3214 static void ScspRaiseInterrupt(int which, int target)
3215 {
3216    if (target & SCSP_INTTARGET_MAIN)
3217    {
3218       scsp.mcipd |= 1 << which;
3219       PSP_UC(scsp_regcache[0x42C >> 1]) = scsp.mcipd;
3220       if (scsp.mcieb & (1 << which))
3221       {
3222          if (scsp_thread_running)
3223             PSP_UC(scsp_main_interrupt_pending) = 1;
3224          else
3225             (*scsp_interrupt_handler)();
3226       }
3227    }
3228 
3229    if (target & SCSP_INTTARGET_SOUND)
3230    {
3231       scsp.scipd |= 1 << which;
3232       PSP_UC(scsp_regcache[0x420 >> 1]) = scsp.scipd;
3233       if (scsp.scieb & (1 << which))
3234       {
3235          const int level_shift = (which > 7) ? 7 : which;
3236          const int level = ((scsp.scilv0 >> level_shift) & 1) << 0
3237                          | ((scsp.scilv1 >> level_shift) & 1) << 1
3238                          | ((scsp.scilv2 >> level_shift) & 1) << 2;
3239          M68K->SetIRQ(level);
3240       }
3241    }
3242 }
3243 
3244 //----------------------------------//
3245 
3246 // ScspCheckInterrupts:  Check pending interrupts for the main or sound CPU
3247 // against the interrupt enable flags, and raise any interrupts which are
3248 // both enabled and pending.  The mask parameter indicates which interrupts
3249 // should be checked.  Implements writes to SCIEB and MCIEB.
3250 
ScspCheckInterrupts(u16 mask,int target)3251 static void ScspCheckInterrupts(u16 mask, int target)
3252 {
3253    int i;
3254 
3255    for (i = 0; i < 11; i++)
3256    {
3257       if ((1<<i) & mask & scsp.mcieb && scsp.mcipd)
3258          ScspRaiseInterrupt(i, SCSP_INTTARGET_MAIN & target);
3259       if ((1<<i) & mask & scsp.scieb && scsp.scipd)
3260          ScspRaiseInterrupt(i, SCSP_INTTARGET_SOUND & target);
3261    }
3262 }
3263 
3264 //----------------------------------//
3265 
3266 // ScspClearInterrupts:  Clear all pending interrupts specified by the mask
3267 // parameter for the main or sound CPU.  Implements writes to SCIRE and MCIRE.
3268 
ScspClearInterrupts(u16 mask,int target)3269 static void ScspClearInterrupts(u16 mask, int target)
3270 {
3271    if (target & SCSP_INTTARGET_MAIN)
3272    {
3273       scsp.mcipd &= ~mask;
3274       PSP_UC(scsp_regcache[0x42C >> 1]) = scsp.mcipd;
3275    }
3276 
3277    if (target & SCSP_INTTARGET_SOUND)
3278    {
3279       scsp.scipd &= ~mask;
3280       PSP_UC(scsp_regcache[0x420 >> 1]) = scsp.scipd;
3281    }
3282 }
3283 
3284 //-------------------------------------------------------------------------
3285 
3286 // ScspRunM68K:  Run the M68K for the given number of cycles.
3287 
ScspRunM68K(u32 cycles)3288 static void ScspRunM68K(u32 cycles)
3289 {
3290    if (LIKELY(m68k_running))
3291    {
3292       s32 new_cycles = m68k_saved_cycles + cycles;
3293       if (LIKELY(new_cycles > 0))
3294          new_cycles -= (*m68k_execf)(new_cycles);
3295       m68k_saved_cycles = new_cycles;
3296    }
3297 }
3298 
3299 //----------------------------------//
3300 
3301 // M68KExecBP:  Wrapper for M68K->Exec() which checks for breakpoints and
3302 // calls the breakpoint callback when one is reached.  This logic is
3303 // extracted from M68KExec() to avoid unnecessary register spillage on the
3304 // fast (no-breakpoint) path.
3305 
M68KExecBP(s32 cycles)3306 static s32 FASTCALL M68KExecBP(s32 cycles)
3307 {
3308    s32 cycles_to_exec = cycles;
3309    s32 cycles_executed = 0;
3310    int i;
3311 
3312    while (cycles_executed < cycles_to_exec)
3313    {
3314       // Make sure it isn't one of our breakpoints
3315       for (i = 0; i < m68k_num_breakpoints; i++)
3316       {
3317          if ((M68K->GetPC() == m68k_breakpoint[i].addr) && !m68k_in_breakpoint)
3318          {
3319             m68k_in_breakpoint = 1;
3320             if (M68KBreakpointCallback)
3321                M68KBreakpointCallback(m68k_breakpoint[i].addr);
3322             m68k_in_breakpoint = 0;
3323          }
3324       }
3325 
3326       // Execute instructions individually
3327       cycles_executed += M68K->Exec(1);
3328    }
3329 
3330    return cycles_executed;
3331 }
3332 
3333 ///////////////////////////////////////////////////////////////////////////
3334 // M68K management routines
3335 ///////////////////////////////////////////////////////////////////////////
3336 
3337 // M68KStart:  Start the M68K processor running.
3338 
M68KStart(void)3339 void M68KStart(void)
3340 {
3341    if (scsp_thread_running)
3342       ScspSyncThread();
3343 
3344    M68K->Reset();
3345    m68k_saved_cycles = 0;
3346 
3347    m68k_running = 1;
3348 
3349    if (scsp_thread_running)
3350       PSP_FLUSH_ALL();
3351 }
3352 
3353 //-------------------------------------------------------------------------
3354 
3355 // M68KStop:  Halt the M68K processor.
3356 
M68KStop(void)3357 void M68KStop(void)
3358 {
3359    if (scsp_thread_running)
3360       ScspSyncThread();
3361 
3362    m68k_running = 0;
3363 
3364    if (scsp_thread_running)
3365       PSP_FLUSH_ALL();
3366 }
3367 
3368 //-------------------------------------------------------------------------
3369 
3370 // M68KStep:  Execute a single M68K instruction.
3371 
M68KStep(void)3372 void M68KStep(void)
3373 {
3374    M68K->Exec(1);
3375 }
3376 
3377 //-------------------------------------------------------------------------
3378 
3379 // M68KWriteNotify:  Notify the M68K emulator that a region of sound RAM
3380 // has been written to by an external agent.
3381 
M68KWriteNotify(u32 address,u32 size)3382 void M68KWriteNotify(u32 address, u32 size)
3383 {
3384    M68K->WriteNotify(address, size);
3385 }
3386 
3387 //-------------------------------------------------------------------------
3388 
3389 // M68KGetRegisters, M68KSetRegisters:  Get or set the current values of
3390 // the M68K registers.
3391 
M68KGetRegisters(M68KRegs * regs)3392 void M68KGetRegisters(M68KRegs *regs)
3393 {
3394    int i;
3395 
3396    if (regs != NULL)
3397    {
3398       for (i = 0; i < 8; i++)
3399       {
3400          regs->D[i] = M68K->GetDReg(i);
3401          regs->A[i] = M68K->GetAReg(i);
3402       }
3403       regs->SR = M68K->GetSR();
3404       regs->PC = M68K->GetPC();
3405    }
3406 }
3407 
M68KSetRegisters(const M68KRegs * regs)3408 void M68KSetRegisters(const M68KRegs *regs)
3409 {
3410    int i;
3411 
3412    if (regs != NULL)
3413    {
3414       for (i = 0; i < 8; i++)
3415       {
3416          M68K->SetDReg(i, regs->D[i]);
3417          M68K->SetAReg(i, regs->A[i]);
3418       }
3419       M68K->SetSR(regs->SR);
3420       M68K->SetPC(regs->PC);
3421    }
3422 }
3423 
3424 //-------------------------------------------------------------------------
3425 
3426 // M68KSetBreakpointCallback:  Set a function to be called whenever an M68K
3427 // breakpoint is reached.
3428 
M68KSetBreakpointCallBack(void (* func)(u32 address))3429 void M68KSetBreakpointCallBack(void (*func)(u32 address))
3430 {
3431    M68KBreakpointCallback = func;
3432 }
3433 
3434 //-------------------------------------------------------------------------
3435 
3436 // M68KAddCodeBreakpoint:  Add an M68K breakpoint on the given address.
3437 // Returns 0 on success, -1 if the breakpoint table is full or there is
3438 // already a breakpoint set on the address.
3439 
M68KAddCodeBreakpoint(u32 address)3440 int M68KAddCodeBreakpoint(u32 address)
3441 {
3442    int i;
3443 
3444    if (m68k_num_breakpoints >= MAX_BREAKPOINTS)
3445       return -1;
3446 
3447    // Make sure it isn't already on the list
3448    for (i = 0; i < m68k_num_breakpoints; i++)
3449    {
3450       if (m68k_breakpoint[i].addr == address)
3451          return -1;
3452    }
3453 
3454    m68k_breakpoint[m68k_num_breakpoints].addr = address;
3455    m68k_num_breakpoints++;
3456 
3457    // Switch to the slow exec routine so we can catch the breakpoint
3458    m68k_execf = M68KExecBP;
3459 
3460    return 0;
3461 }
3462 
3463 //-------------------------------------------------------------------------
3464 
3465 // M68KDelCodeBreakpoint:  Delete an M68K breakpoint on the given address.
3466 // Returns 0 on success, -1 if there was no breakpoint set on the address.
3467 
M68KDelCodeBreakpoint(u32 address)3468 int M68KDelCodeBreakpoint(u32 address)
3469 {
3470    int i;
3471 
3472    if (m68k_num_breakpoints > 0)
3473    {
3474       for (i = 0; i < m68k_num_breakpoints; i++)
3475       {
3476          if (m68k_breakpoint[i].addr == address)
3477          {
3478             // Swap with the last breakpoint in the table, so there are
3479             // no holes in the breakpoint list
3480             m68k_breakpoint[i].addr = m68k_breakpoint[m68k_num_breakpoints-1].addr;
3481             m68k_breakpoint[m68k_num_breakpoints-1].addr = 0xFFFFFFFF;
3482             m68k_num_breakpoints--;
3483 
3484             if (m68k_num_breakpoints == 0)
3485             {
3486                // Last breakpoint deleted, so go back to the fast exec routine
3487                m68k_execf = M68K->Exec;
3488             }
3489 
3490             return 0;
3491          }
3492       }
3493    }
3494 
3495    return -1;
3496 }
3497 
3498 //-------------------------------------------------------------------------
3499 
3500 // M68KGetBreakpointList:  Return the array of breakpoints currently set.
3501 // The array is M68K_MAX_BREAKPOINTS elements long, and an address of
3502 // 0xFFFFFFFF indicates that no breakpoint is set in that slot.
3503 
M68KGetBreakpointList(void)3504 const M68KBreakpointInfo *M68KGetBreakpointList(void)
3505 {
3506    return m68k_breakpoint;
3507 }
3508 
3509 //-------------------------------------------------------------------------
3510 
3511 // M68KClearCodeBreakpoints:  Clear all M68K breakpoints.
3512 
M68KClearCodeBreakpoints(void)3513 void M68KClearCodeBreakpoints(void)
3514 {
3515    int i;
3516    for (i = 0; i < MAX_BREAKPOINTS; i++)
3517       m68k_breakpoint[i].addr = 0xFFFFFFFF;
3518 
3519    m68k_num_breakpoints = 0;
3520    m68k_execf = M68K->Exec;
3521 }
3522 
3523 //-------------------------------------------------------------------------
3524 
3525 // M68K{Read,Write}{Byte,Word}:  Memory access routines for the M68K
3526 // emulation.  Exported for use in debugging.
3527 
M68KReadByte(u32 address)3528 u32 FASTCALL M68KReadByte(u32 address)
3529 {
3530    if (address < 0x100000)
3531       return T2ReadByte(SoundRam, address & scsp.sound_ram_mask);
3532    else
3533       return ScspReadByteDirect(address & 0xFFF);
3534 }
3535 
M68KReadWord(u32 address)3536 u32 FASTCALL M68KReadWord(u32 address)
3537 {
3538    if (address < 0x100000)
3539       return T2ReadWord(SoundRam, address & scsp.sound_ram_mask);
3540    else
3541       return ScspReadWordDirect(address & 0xFFF);
3542 }
3543 
M68KWriteByte(u32 address,u32 data)3544 void FASTCALL M68KWriteByte(u32 address, u32 data)
3545 {
3546    if (address < 0x100000)
3547       T2WriteByte(SoundRam, address & scsp.sound_ram_mask, data);
3548    else
3549       ScspWriteByteDirect(address & 0xFFF, data);
3550 }
3551 
M68KWriteWord(u32 address,u32 data)3552 void FASTCALL M68KWriteWord(u32 address, u32 data)
3553 {
3554    if (address < 0x100000)
3555       T2WriteWord(SoundRam, address & scsp.sound_ram_mask, data);
3556    else
3557       ScspWriteWordDirect(address & 0xFFF, data);
3558 }
3559 
3560 ///////////////////////////////////////////////////////////////////////////
3561