SPC Codec: Ensure no crash occurs on load failure which could cause emulation to...
[kugel-rb.git] / apps / codecs / spc / spc_codec.h
bloba18aece645622a5f8aa9679560ceb848dc07c2af
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007-2008 Michael Sevakis (jhMikeS)
11 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
12 * Copyright (C) 2004-2007 Shay Green (blargg)
13 * Copyright (C) 2002 Brad Martin
15 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 /* lovingly ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
24 /* DSP Based on Brad Martin's OpenSPC DSP emulator */
25 /* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */
27 #ifndef _SPC_CODEC_H_
28 #define _SPC_CODEC_H_
30 /* rather than comment out asserts, just define NDEBUG */
31 #define NDEBUG
32 #include <assert.h>
34 /** Basic configuration options **/
36 #define SPC_DUAL_CORE 1
38 #if !defined(SPC_DUAL_CORE) || NUM_CORES == 1
39 #undef SPC_DUAL_CORE
40 #define SPC_DUAL_CORE 0
41 #endif
43 /* TGB is the only target fast enough for gaussian and realtime BRR decode */
44 /* echo is almost fast enough but not quite */
45 #if defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR)
46 /* Don't cache BRR waves */
47 #define SPC_BRRCACHE 0
49 /* Allow gaussian interpolation */
50 #define SPC_NOINTERP 0
52 /* Allow echo processing */
53 #define SPC_NOECHO 0
54 #elif defined(CPU_COLDFIRE)
55 /* Cache BRR waves */
56 #define SPC_BRRCACHE 1
58 /* Disable gaussian interpolation */
59 #define SPC_NOINTERP 1
61 /* Allow echo processing */
62 #define SPC_NOECHO 0
63 #elif defined (CPU_PP) && SPC_DUAL_CORE
64 /* Cache BRR waves */
65 #define SPC_BRRCACHE 1
67 /* Disable gaussian interpolation */
68 #define SPC_NOINTERP 1
70 /* Allow echo processing */
71 #define SPC_NOECHO 0
72 #else
73 /* Cache BRR waves */
74 #define SPC_BRRCACHE 1
76 /* Disable gaussian interpolation */
77 #define SPC_NOINTERP 1
79 /* Disable echo processing */
80 #define SPC_NOECHO 1
81 #endif
83 #ifdef CPU_ARM
85 #if CONFIG_CPU != PP5002
86 #undef ICODE_ATTR
87 #define ICODE_ATTR
89 #undef IDATA_ATTR
90 #define IDATA_ATTR
92 #undef ICONST_ATTR
93 #define ICONST_ATTR
95 #undef IBSS_ATTR
96 #define IBSS_ATTR
97 #endif
99 #if SPC_DUAL_CORE
100 #undef NOCACHEBSS_ATTR
101 #define NOCACHEBSS_ATTR __attribute__ ((section(".ibss")))
102 #undef NOCACHEDATA_ATTR
103 #define NOCACHEDATA_ATTR __attribute__((section(".idata")))
104 #endif
105 #endif
107 /* Samples per channel per iteration */
108 #if defined(CPU_PP) && NUM_CORES == 1
109 #define WAV_CHUNK_SIZE 2048
110 #else
111 #define WAV_CHUNK_SIZE 1024
112 #endif
114 /**************** Little-endian handling ****************/
116 static inline unsigned get_le16( void const* p )
118 return ((unsigned char const*) p) [1] * 0x100u +
119 ((unsigned char const*) p) [0];
122 static inline int get_le16s( void const* p )
124 return ((signed char const*) p) [1] * 0x100 +
125 ((unsigned char const*) p) [0];
128 static inline void set_le16( void* p, unsigned n )
130 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
131 ((unsigned char*) p) [0] = (unsigned char) n;
134 #define GET_LE16( addr ) get_le16( addr )
135 #define SET_LE16( addr, data ) set_le16( addr, data )
136 #define INT16A( addr ) (*(uint16_t*) (addr))
137 #define INT16SA( addr ) (*(int16_t*) (addr))
139 #ifdef ROCKBOX_LITTLE_ENDIAN
140 #define GET_LE16A( addr ) (*(uint16_t*) (addr))
141 #define GET_LE16SA( addr ) (*( int16_t*) (addr))
142 #define SET_LE16A( addr, data ) (void) (*(uint16_t*) (addr) = (data))
143 #else
144 #define GET_LE16A( addr ) get_le16 ( addr )
145 #define GET_LE16SA( addr ) get_le16s( addr )
146 #define SET_LE16A( addr, data ) set_le16 ( addr, data )
147 #endif
149 struct Spc_Emu;
150 #define THIS struct Spc_Emu* const this
152 /* The CPU portion (shock!) */
154 struct cpu_regs_t
156 long pc; /* more than 16 bits to allow overflow detection */
157 uint8_t a;
158 uint8_t x;
159 uint8_t y;
160 uint8_t status;
161 uint8_t sp;
164 struct cpu_ram_t
166 union {
167 uint8_t padding1 [0x100];
168 uint16_t align;
169 } padding1 [1];
170 uint8_t ram [0x10000];
171 uint8_t padding2 [0x100];
174 #undef RAM
175 #define RAM ram.ram
176 extern struct cpu_ram_t ram;
178 long CPU_run( THIS, long start_time ) ICODE_ATTR;
179 void CPU_Init( THIS );
181 /* The DSP portion (awe!) */
182 enum { VOICE_COUNT = 8 };
183 enum { REGISTER_COUNT = 128 };
185 struct raw_voice_t
187 int8_t volume [2];
188 uint8_t rate [2];
189 uint8_t waveform;
190 uint8_t adsr [2]; /* envelope rates for attack, decay, and sustain */
191 uint8_t gain; /* envelope gain (if not using ADSR) */
192 int8_t envx; /* current envelope level */
193 int8_t outx; /* current sample */
194 int8_t unused [6];
197 struct globals_t
199 int8_t unused1 [12];
200 int8_t volume_0; /* 0C Main Volume Left (-.7) */
201 int8_t echo_feedback; /* 0D Echo Feedback (-.7) */
202 int8_t unused2 [14];
203 int8_t volume_1; /* 1C Main Volume Right (-.7) */
204 int8_t unused3 [15];
205 int8_t echo_volume_0; /* 2C Echo Volume Left (-.7) */
206 uint8_t pitch_mods; /* 2D Pitch Modulation on/off for each voice */
207 int8_t unused4 [14];
208 int8_t echo_volume_1; /* 3C Echo Volume Right (-.7) */
209 uint8_t noise_enables; /* 3D Noise output on/off for each voice */
210 int8_t unused5 [14];
211 uint8_t key_ons; /* 4C Key On for each voice */
212 uint8_t echo_ons; /* 4D Echo on/off for each voice */
213 int8_t unused6 [14];
214 uint8_t key_offs; /* 5C key off for each voice
215 (instantiates release mode) */
216 uint8_t wave_page; /* 5D source directory (wave table offsets) */
217 int8_t unused7 [14];
218 uint8_t flags; /* 6C flags and noise freq */
219 uint8_t echo_page; /* 6D */
220 int8_t unused8 [14];
221 uint8_t wave_ended; /* 7C */
222 uint8_t echo_delay; /* 7D ms >> 4 */
223 char unused9 [2];
226 enum state_t
227 { /* -1, 0, +1 allows more efficient if statements */
228 state_decay = -1,
229 state_sustain = 0,
230 state_attack = +1,
231 state_release = 2
234 struct cache_entry_t
236 int16_t const* samples;
237 unsigned end; /* past-the-end position */
238 unsigned loop; /* number of samples in loop */
239 unsigned start_addr;
242 enum { BRR_BLOCK_SIZE = 16 };
243 enum { BRR_CACHE_SIZE = 0x20000 + 32} ;
245 struct voice_t
247 #if SPC_BRRCACHE
248 int16_t const* samples;
249 long wave_end;
250 int wave_loop;
251 #else
252 int16_t samples [3 + BRR_BLOCK_SIZE + 1];
253 int block_header; /* header byte from current block */
254 #endif
255 uint8_t const* addr;
256 short volume [2];
257 long position;/* position in samples buffer, with 12-bit fraction */
258 short envx;
259 short env_mode;
260 short env_timer;
261 short key_on_delay;
264 #if SPC_BRRCACHE
265 /* a little extra for samples that go past end */
266 extern int16_t BRRcache [BRR_CACHE_SIZE];
267 #endif
269 enum { FIR_BUF_HALF = 8 };
271 #if defined(CPU_COLDFIRE)
272 /* global because of the large aligment requirement for hardware masking -
273 * L-R interleaved 16-bit samples for easy loading and mac.w use.
275 enum
277 FIR_BUF_CNT = FIR_BUF_HALF,
278 FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ),
279 FIR_BUF_ALIGN = FIR_BUF_SIZE * 2,
280 FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) - 1))
282 #elif defined (CPU_ARM)
283 enum
285 FIR_BUF_CNT = FIR_BUF_HALF * 2 * 2,
286 FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ),
287 FIR_BUF_ALIGN = FIR_BUF_SIZE,
288 FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) * 2 - 1))
290 #endif /* CPU_* */
292 struct Spc_Dsp
294 union
296 struct raw_voice_t voice [VOICE_COUNT];
297 uint8_t reg [REGISTER_COUNT];
298 struct globals_t g;
299 int16_t align;
300 } r;
302 unsigned echo_pos;
303 int keys_down;
304 int noise_count;
305 uint16_t noise; /* also read as int16_t */
307 #if defined(CPU_COLDFIRE)
308 /* circularly hardware masked address */
309 int32_t *fir_ptr;
310 /* wrapped address just behind current position -
311 allows mac.w to increment and mask fir_ptr */
312 int32_t *last_fir_ptr;
313 /* copy of echo FIR constants as int16_t for use with mac.w */
314 int16_t fir_coeff [VOICE_COUNT];
315 #elif defined (CPU_ARM)
316 /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */
317 int32_t *fir_ptr;
318 /* copy of echo FIR constants as int32_t, for faster access */
319 int32_t fir_coeff [VOICE_COUNT];
320 #else
321 /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */
322 int fir_pos; /* (0 to 7) */
323 int fir_buf [FIR_BUF_HALF * 2] [2];
324 /* copy of echo FIR constants as int, for faster access */
325 int fir_coeff [VOICE_COUNT];
326 #endif
328 struct voice_t voice_state [VOICE_COUNT];
330 #if SPC_BRRCACHE
331 uint8_t oldsize;
332 struct cache_entry_t wave_entry [256];
333 struct cache_entry_t wave_entry_old [256];
334 #endif
337 struct src_dir
339 char start [2];
340 char loop [2];
343 void DSP_run_( struct Spc_Dsp* this, long count, int32_t* out_buf ) ICODE_ATTR;
344 void DSP_reset( struct Spc_Dsp* this );
346 static inline void DSP_run( struct Spc_Dsp* this, long count, int32_t* out )
348 /* Should we just fill the buffer with silence? Flags won't be cleared */
349 /* during this run so it seems it should keep resetting every sample. */
350 if ( this->r.g.flags & 0x80 )
351 DSP_reset( this );
353 DSP_run_( this, count, out );
356 /**************** SPC emulator ****************/
357 /* 1.024 MHz clock / 32000 samples per second */
358 enum { CLOCKS_PER_SAMPLE = 32 };
360 enum { EXTRA_CLOCKS = CLOCKS_PER_SAMPLE / 2 };
362 /* using this disables timer (since this will always be in the future) */
363 enum { TIMER_DISABLED_TIME = 127 };
365 enum { ROM_SIZE = 64 };
366 enum { ROM_ADDR = 0xFFC0 };
368 enum { TIMER_COUNT = 3 };
370 struct Timer
372 long next_tick;
373 int period;
374 int count;
375 int shift;
376 int enabled;
377 int counter;
380 void Timer_run_( struct Timer* t, long time ) ICODE_ATTR;
382 static inline void Timer_run( struct Timer* t, long time )
384 if ( time >= t->next_tick )
385 Timer_run_( t, time );
388 struct Spc_Emu
390 uint8_t cycle_table [0x100];
391 struct cpu_regs_t r;
393 int32_t* sample_buf;
394 long next_dsp;
395 int rom_enabled;
396 int extra_cycles;
398 struct Timer timer [TIMER_COUNT];
400 /* large objects at end */
401 struct Spc_Dsp dsp;
402 uint8_t extra_ram [ROM_SIZE];
403 uint8_t boot_rom [ROM_SIZE];
406 enum { SPC_FILE_SIZE = 0x10180 };
408 struct spc_file_t
410 char signature [27];
411 char unused [10];
412 uint8_t pc [2];
413 uint8_t a;
414 uint8_t x;
415 uint8_t y;
416 uint8_t status;
417 uint8_t sp;
418 char unused2 [212];
419 uint8_t ram [0x10000];
420 uint8_t dsp [128];
421 uint8_t ipl_rom [128];
424 void SPC_Init( THIS );
426 int SPC_load_spc( THIS, const void* data, long size );
428 /**************** DSP interaction ****************/
429 void DSP_write( struct Spc_Dsp* this, int i, int data ) ICODE_ATTR;
431 static inline int DSP_read( struct Spc_Dsp* this, int i )
433 assert( (unsigned) i < REGISTER_COUNT );
434 return this->r.reg [i];
437 void SPC_run_dsp_( THIS, long time ) ICODE_ATTR;
439 static inline void SPC_run_dsp( THIS, long time )
441 if ( time >= this->next_dsp )
442 SPC_run_dsp_( this, time );
445 int SPC_read( THIS, unsigned addr, long const time ) ICODE_ATTR;
446 void SPC_write( THIS, unsigned addr, int data, long const time ) ICODE_ATTR;
448 /**************** Sample generation ****************/
449 int SPC_play( THIS, long count, int32_t* out ) ICODE_ATTR;
451 #endif /* _SPC_CODEC_H_ */