summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/Makefile45
-rw-r--r--apps/codecs/asap.c2
-rw-r--r--apps/codecs/libasap/CREDITS (renamed from apps/codecs/asap/CREDITS)0
-rw-r--r--apps/codecs/libasap/Makefile (renamed from apps/codecs/asap/Makefile)0
-rw-r--r--apps/codecs/libasap/README (renamed from apps/codecs/asap/README)0
-rw-r--r--apps/codecs/libasap/README.rockbox (renamed from apps/codecs/asap/README.rockbox)0
-rw-r--r--apps/codecs/libasap/SOURCES (renamed from apps/codecs/asap/SOURCES)0
-rw-r--r--apps/codecs/libasap/acpu.c (renamed from apps/codecs/asap/acpu.c)0
-rw-r--r--apps/codecs/libasap/apokeysnd.c (renamed from apps/codecs/asap/apokeysnd.c)0
-rw-r--r--apps/codecs/libasap/asap.c (renamed from apps/codecs/asap/asap.c)0
-rw-r--r--apps/codecs/libasap/asap.h (renamed from apps/codecs/asap/asap.h)0
-rw-r--r--apps/codecs/libasap/asap_internal.h (renamed from apps/codecs/asap/asap_internal.h)0
-rw-r--r--apps/codecs/libasap/players.h (renamed from apps/codecs/asap/players.h)0
-rw-r--r--apps/codecs/libtremor/CHANGELOG (renamed from apps/codecs/Tremor/CHANGELOG)0
-rw-r--r--apps/codecs/libtremor/COPYING (renamed from apps/codecs/Tremor/COPYING)0
-rw-r--r--apps/codecs/libtremor/Makefile (renamed from apps/codecs/Tremor/Makefile)4
-rw-r--r--apps/codecs/libtremor/README (renamed from apps/codecs/Tremor/README)0
-rw-r--r--apps/codecs/libtremor/README.rockbox (renamed from apps/codecs/Tremor/README.rockbox)0
-rw-r--r--apps/codecs/libtremor/SOURCES (renamed from apps/codecs/Tremor/SOURCES)0
-rw-r--r--apps/codecs/libtremor/asm_arm.h (renamed from apps/codecs/Tremor/asm_arm.h)0
-rw-r--r--apps/codecs/libtremor/asm_mcf5249.h (renamed from apps/codecs/Tremor/asm_mcf5249.h)0
-rw-r--r--apps/codecs/libtremor/backends.h (renamed from apps/codecs/Tremor/backends.h)0
-rw-r--r--apps/codecs/libtremor/bitwise.c (renamed from apps/codecs/Tremor/bitwise.c)0
-rw-r--r--apps/codecs/libtremor/block.c (renamed from apps/codecs/Tremor/block.c)0
-rw-r--r--apps/codecs/libtremor/codebook.c (renamed from apps/codecs/Tremor/codebook.c)0
-rw-r--r--apps/codecs/libtremor/codebook.h (renamed from apps/codecs/Tremor/codebook.h)0
-rw-r--r--apps/codecs/libtremor/codec_internal.h (renamed from apps/codecs/Tremor/codec_internal.h)0
-rw-r--r--apps/codecs/libtremor/config-tremor.h (renamed from apps/codecs/Tremor/config-tremor.h)0
-rw-r--r--apps/codecs/libtremor/config_types.h (renamed from apps/codecs/Tremor/config_types.h)0
-rw-r--r--apps/codecs/libtremor/ctype.c (renamed from apps/codecs/Tremor/ctype.c)0
-rw-r--r--apps/codecs/libtremor/floor0.c (renamed from apps/codecs/Tremor/floor0.c)0
-rw-r--r--apps/codecs/libtremor/floor1.c (renamed from apps/codecs/Tremor/floor1.c)0
-rw-r--r--apps/codecs/libtremor/framing.c (renamed from apps/codecs/Tremor/framing.c)0
-rw-r--r--apps/codecs/libtremor/info.c (renamed from apps/codecs/Tremor/info.c)0
-rw-r--r--apps/codecs/libtremor/ivorbiscodec.h (renamed from apps/codecs/Tremor/ivorbiscodec.h)0
-rw-r--r--apps/codecs/libtremor/ivorbisfile.h (renamed from apps/codecs/Tremor/ivorbisfile.h)0
-rw-r--r--apps/codecs/libtremor/lsp_lookup.h (renamed from apps/codecs/Tremor/lsp_lookup.h)0
-rw-r--r--apps/codecs/libtremor/mapping0.c (renamed from apps/codecs/Tremor/mapping0.c)0
-rw-r--r--apps/codecs/libtremor/misc.h (renamed from apps/codecs/Tremor/misc.h)0
-rw-r--r--apps/codecs/libtremor/ogg.h (renamed from apps/codecs/Tremor/ogg.h)0
-rw-r--r--apps/codecs/libtremor/oggmalloc.c (renamed from apps/codecs/Tremor/oggmalloc.c)0
-rw-r--r--apps/codecs/libtremor/os.h (renamed from apps/codecs/Tremor/os.h)0
-rw-r--r--apps/codecs/libtremor/os_types.h (renamed from apps/codecs/Tremor/os_types.h)0
-rw-r--r--apps/codecs/libtremor/registry.c (renamed from apps/codecs/Tremor/registry.c)0
-rw-r--r--apps/codecs/libtremor/registry.h (renamed from apps/codecs/Tremor/registry.h)0
-rw-r--r--apps/codecs/libtremor/res012.c (renamed from apps/codecs/Tremor/res012.c)0
-rw-r--r--apps/codecs/libtremor/sharedbook.c (renamed from apps/codecs/Tremor/sharedbook.c)0
-rw-r--r--apps/codecs/libtremor/synthesis.c (renamed from apps/codecs/Tremor/synthesis.c)0
-rw-r--r--apps/codecs/libtremor/vorbisfile.c (renamed from apps/codecs/Tremor/vorbisfile.c)0
-rw-r--r--apps/codecs/libtremor/window.c (renamed from apps/codecs/Tremor/window.c)0
-rw-r--r--apps/codecs/libtremor/window.h (renamed from apps/codecs/Tremor/window.h)0
-rw-r--r--apps/codecs/libtremor/window_lookup.h (renamed from apps/codecs/Tremor/window_lookup.h)0
-rw-r--r--apps/codecs/spc.c4
-rw-r--r--apps/codecs/spc/Makefile44
-rw-r--r--apps/codecs/spc/SOURCES4
-rw-r--r--apps/codecs/spc/spc_codec.h454
-rw-r--r--apps/codecs/spc/spc_cpu.c1050
-rw-r--r--apps/codecs/spc/spc_dsp.c1276
-rw-r--r--apps/codecs/spc/spc_emu.c384
-rw-r--r--apps/codecs/spc/spc_profiler.c66
-rw-r--r--apps/codecs/spc/spc_profiler.h72
-rw-r--r--apps/codecs/vorbis.c4
-rw-r--r--apps/plugins/Makefile2
63 files changed, 38 insertions, 3373 deletions
diff --git a/apps/codecs/Makefile b/apps/codecs/Makefile
index ffbccf4c27..6d3f1f683a 100644
--- a/apps/codecs/Makefile
+++ b/apps/codecs/Makefile
@@ -17,8 +17,8 @@ ifdef APPEXTRA
17endif 17endif
18 18
19ifdef SOFTWARECODECS 19ifdef SOFTWARECODECS
20 CODECLIBS = -lspc -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex -ldemac -lwma -lasap 20 CODECLIBS = -lspc -lmad -la52 -lffmpegFLAC -ltremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex -ldemac -lwma -lasap
21 OUTPUT = libspc libmad liba52 libffmpegFLAC libwma libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac libasap 21 OUTPUT = libspc libmad liba52 libffmpegFLAC libwma libtremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac libasap
22endif 22endif
23 23
24# we "borrow" the plugin LDS file 24# we "borrow" the plugin LDS file
@@ -41,7 +41,7 @@ DIRS = .
41CODECLIB := $(BUILDDIR)/libcodec.a 41CODECLIB := $(BUILDDIR)/libcodec.a
42CODECDEPS = $(LINKCODEC) $(CODECLIB) 42CODECDEPS = $(LINKCODEC) $(CODECLIB)
43 43
44.PHONY: libspc libmad liba52 libffmpegFLAC libTremor libspeex libwavpack libmusepack libalac libfaad libm4a libdemac libwma libasap 44.PHONY: libspc libmad liba52 libffmpegFLAC libtremor libspeex libwavpack libmusepack libalac libfaad libm4a libdemac libwma libasap
45 45
46all: $(LINKCODEC) $(ROCKS) 46all: $(LINKCODEC) $(ROCKS)
47 47
@@ -53,7 +53,7 @@ $(OBJDIR)/spc.elf : $(BUILDDIR)/libspc.a
53$(OBJDIR)/mpa.elf : $(BUILDDIR)/libmad.a 53$(OBJDIR)/mpa.elf : $(BUILDDIR)/libmad.a
54$(OBJDIR)/a52.elf : $(BUILDDIR)/liba52.a 54$(OBJDIR)/a52.elf : $(BUILDDIR)/liba52.a
55$(OBJDIR)/flac.elf : $(BUILDDIR)/libffmpegFLAC.a 55$(OBJDIR)/flac.elf : $(BUILDDIR)/libffmpegFLAC.a
56$(OBJDIR)/vorbis.elf : $(BUILDDIR)/libTremor.a 56$(OBJDIR)/vorbis.elf : $(BUILDDIR)/libtremor.a
57$(OBJDIR)/speex.elf : $(BUILDDIR)/libspeex.a 57$(OBJDIR)/speex.elf : $(BUILDDIR)/libspeex.a
58$(OBJDIR)/mpc.elf : $(BUILDDIR)/libmusepack.a 58$(OBJDIR)/mpc.elf : $(BUILDDIR)/libmusepack.a
59$(OBJDIR)/wavpack.elf : $(BUILDDIR)/libwavpack.a 59$(OBJDIR)/wavpack.elf : $(BUILDDIR)/libwavpack.a
@@ -139,8 +139,8 @@ $(LINKCODEC): $(LDS)
139$(BUILDDIR)/libspc.a: libspc 139$(BUILDDIR)/libspc.a: libspc
140 140
141libspc: 141libspc:
142 $(SILENT)mkdir -p $(OBJDIR)/spc 142 $(SILENT)mkdir -p $(OBJDIR)/libspc
143 $(call PRINTS,MAKE in spc)$(MAKE) -C spc OBJDIR=$(OBJDIR)/spc OUTPUT=$(BUILDDIR)/libspc.a 143 $(call PRINTS,MAKE in libspc)$(MAKE) -C libspc OBJDIR=$(OBJDIR)/libspc OUTPUT=$(BUILDDIR)/libspc.a
144 144
145$(BUILDDIR)/libmad.a: libmad 145$(BUILDDIR)/libmad.a: libmad
146 146
@@ -166,11 +166,11 @@ libffmpegFLAC:
166 $(SILENT)mkdir -p $(OBJDIR)/libffmpegFLAC 166 $(SILENT)mkdir -p $(OBJDIR)/libffmpegFLAC
167 $(call PRINTS,MAKE in libffmpegFLAC)$(MAKE) -C libffmpegFLAC OBJDIR=$(OBJDIR)/libffmpegFLAC OUTPUT=$(BUILDDIR)/libffmpegFLAC.a 167 $(call PRINTS,MAKE in libffmpegFLAC)$(MAKE) -C libffmpegFLAC OBJDIR=$(OBJDIR)/libffmpegFLAC OUTPUT=$(BUILDDIR)/libffmpegFLAC.a
168 168
169$(BUILDDIR)/libTremor.a: libTremor 169$(BUILDDIR)/libtremor.a: libtremor
170 170
171libTremor: 171libtremor:
172 $(SILENT)mkdir -p $(OBJDIR)/Tremor 172 $(SILENT)mkdir -p $(OBJDIR)/libtremor
173 $(call PRINTS,MAKE in Tremor)$(MAKE) -C Tremor OBJDIR=$(OBJDIR)/Tremor OUTPUT=$(BUILDDIR)/libTremor.a 173 $(call PRINTS,MAKE in libtremor)$(MAKE) -C libtremor OBJDIR=$(OBJDIR)/libtremor OUTPUT=$(BUILDDIR)/libtremor.a
174 174
175$(BUILDDIR)/libspeex.a: libspeex 175$(BUILDDIR)/libspeex.a: libspeex
176 176
@@ -217,15 +217,29 @@ libdemac:
217$(BUILDDIR)/libasap.a: libasap 217$(BUILDDIR)/libasap.a: libasap
218 218
219libasap: 219libasap:
220 $(SILENT)mkdir -p $(OBJDIR)/asap 220 $(SILENT)mkdir -p $(OBJDIR)/libasap
221 $(call PRINTS,MAKE in asap)$(MAKE) -C asap OBJDIR=$(OBJDIR)/asap OUTPUT=$(BUILDDIR)/libasap.a 221 $(call PRINTS,MAKE in libasap)$(MAKE) -C libasap OBJDIR=$(OBJDIR)/libasap OUTPUT=$(BUILDDIR)/libasap.a
222clean: 222clean:
223 $(call PRINTS,cleaning codecs)rm -fr $(OBJDIR)/spc $(BUILDDIR)/libspc.a $(OBJDIR)/libmad $(BUILDDIR)/libmad.a $(OBJDIR)/liba52 $(BUILDDIR)/liba52.a $(OBJDIR)/libffmpegFLAC $(BUILDDIR)/libffmpegFLAC.a $(OBJDIR)/Tremor $(BUILDDIR)/libTremor.a $(OBJDIR)/libspeex $(BUILDDIR)/libSpeex.a $(OBJDIR)/libwavpack $(BUILDDIR)/libwavpack.a $(OBJDIR)/libmusepack $(BUILDDIR)/libmusepack.a $(OBJDIR)/libalac $(BUILDDIR)/libalac.a $(OBJDIR)/libfaad $(BUILDDIR)/libfaad.a $(OBJDIR)/libm4a $(BUILDDIR)/libm4a.a $(OBJDIR)/libdemac $(BUILDDIR)/libdemac.a $(OBJDIR)/libwma $(BUILDDIR)/libwma.a 223 $(call PRINTS,cleaning codecs)rm -fr \
224 $(SILENT)$(MAKE) -C spc clean OBJDIR=$(OBJDIR)/spc 224 $(OBJDIR)/libspc $(BUILDDIR)/libspc.a \
225 $(OBJDIR)/libmad $(BUILDDIR)/libmad.a \
226 $(OBJDIR)/liba52 $(BUILDDIR)/liba52.a \
227 $(OBJDIR)/libffmpegFLAC $(BUILDDIR)/libffmpegFLAC.a \
228 $(OBJDIR)/libtremor $(BUILDDIR)/libtremor.a \
229 $(OBJDIR)/libspeex $(BUILDDIR)/libSpeex.a \
230 $(OBJDIR)/libwavpack $(BUILDDIR)/libwavpack.a \
231 $(OBJDIR)/libmusepack $(BUILDDIR)/libmusepack.a \
232 $(OBJDIR)/libalac $(BUILDDIR)/libalac.a \
233 $(OBJDIR)/libfaad $(BUILDDIR)/libfaad.a \
234 $(OBJDIR)/libm4a $(BUILDDIR)/libm4a.a \
235 $(OBJDIR)/libdemac $(BUILDDIR)/libdemac.a \
236 $(OBJDIR)/libwma $(BUILDDIR)/libwma.a
237 $(OBJDIR)/libasap $(BUILDDIR)/libasap.a
238 $(SILENT)$(MAKE) -C libspc clean OBJDIR=$(OBJDIR)/libspc
225 $(SILENT)$(MAKE) -C libmad clean OBJDIR=$(OBJDIR)/libmad 239 $(SILENT)$(MAKE) -C libmad clean OBJDIR=$(OBJDIR)/libmad
226 $(SILENT)$(MAKE) -C liba52 clean OBJDIR=$(OBJDIR)/liba52 240 $(SILENT)$(MAKE) -C liba52 clean OBJDIR=$(OBJDIR)/liba52
227 $(SILENT)$(MAKE) -C libffmpegFLAC clean OBJDIR=$(OBJDIR)/libffmpegFLAC 241 $(SILENT)$(MAKE) -C libffmpegFLAC clean OBJDIR=$(OBJDIR)/libffmpegFLAC
228 $(SILENT)$(MAKE) -C Tremor clean OBJDIR=$(OBJDIR)/Tremor 242 $(SILENT)$(MAKE) -C libtremor clean OBJDIR=$(OBJDIR)/libtremor
229 $(SILENT)$(MAKE) -C libspeex clean OBJDIR=$(OBJDIR)/libspeex 243 $(SILENT)$(MAKE) -C libspeex clean OBJDIR=$(OBJDIR)/libspeex
230 $(SILENT)$(MAKE) -C libwavpack clean OBJDIR=$(OBJDIR)/libwavpack 244 $(SILENT)$(MAKE) -C libwavpack clean OBJDIR=$(OBJDIR)/libwavpack
231 $(SILENT)$(MAKE) -C libmusepack clean OBJDIR=$(OBJDIR)/libmusepack 245 $(SILENT)$(MAKE) -C libmusepack clean OBJDIR=$(OBJDIR)/libmusepack
@@ -234,6 +248,7 @@ clean:
234 $(SILENT)$(MAKE) -C libm4a clean OBJDIR=$(OBJDIR)/libm4a 248 $(SILENT)$(MAKE) -C libm4a clean OBJDIR=$(OBJDIR)/libm4a
235 $(SILENT)$(MAKE) -C demac/libdemac clean OBJDIR=$(OBJDIR)/libdemac 249 $(SILENT)$(MAKE) -C demac/libdemac clean OBJDIR=$(OBJDIR)/libdemac
236 $(SILENT)$(MAKE) -C libwma clean OBJDIR=$(OBJDIR)/libwma 250 $(SILENT)$(MAKE) -C libwma clean OBJDIR=$(OBJDIR)/libwma
251 $(SILENT)$(MAKE) -C libasap clean OBJDIR=$(OBJDIR)/libasap
237 $(SILENT)$(MAKE) -C lib clean OBJDIR=$(OBJDIR)/lib 252 $(SILENT)$(MAKE) -C lib clean OBJDIR=$(OBJDIR)/lib
238 253
239ifneq ($(MAKECMDGOALS),clean) 254ifneq ($(MAKECMDGOALS),clean)
diff --git a/apps/codecs/asap.c b/apps/codecs/asap.c
index c36a02369d..9e2228bf84 100644
--- a/apps/codecs/asap.c
+++ b/apps/codecs/asap.c
@@ -20,7 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "codeclib.h" 22#include "codeclib.h"
23#include "asap/asap.h" 23#include "libasap/asap.h"
24 24
25CODEC_HEADER 25CODEC_HEADER
26 26
diff --git a/apps/codecs/asap/CREDITS b/apps/codecs/libasap/CREDITS
index 97d41067fe..97d41067fe 100644
--- a/apps/codecs/asap/CREDITS
+++ b/apps/codecs/libasap/CREDITS
diff --git a/apps/codecs/asap/Makefile b/apps/codecs/libasap/Makefile
index d20f2393e4..d20f2393e4 100644
--- a/apps/codecs/asap/Makefile
+++ b/apps/codecs/libasap/Makefile
diff --git a/apps/codecs/asap/README b/apps/codecs/libasap/README
index d43a872b25..d43a872b25 100644
--- a/apps/codecs/asap/README
+++ b/apps/codecs/libasap/README
diff --git a/apps/codecs/asap/README.rockbox b/apps/codecs/libasap/README.rockbox
index 322c130358..322c130358 100644
--- a/apps/codecs/asap/README.rockbox
+++ b/apps/codecs/libasap/README.rockbox
diff --git a/apps/codecs/asap/SOURCES b/apps/codecs/libasap/SOURCES
index 0d1f1f46fa..0d1f1f46fa 100644
--- a/apps/codecs/asap/SOURCES
+++ b/apps/codecs/libasap/SOURCES
diff --git a/apps/codecs/asap/acpu.c b/apps/codecs/libasap/acpu.c
index a4def24371..a4def24371 100644
--- a/apps/codecs/asap/acpu.c
+++ b/apps/codecs/libasap/acpu.c
diff --git a/apps/codecs/asap/apokeysnd.c b/apps/codecs/libasap/apokeysnd.c
index 1d48bc20d2..1d48bc20d2 100644
--- a/apps/codecs/asap/apokeysnd.c
+++ b/apps/codecs/libasap/apokeysnd.c
diff --git a/apps/codecs/asap/asap.c b/apps/codecs/libasap/asap.c
index 31de730d93..31de730d93 100644
--- a/apps/codecs/asap/asap.c
+++ b/apps/codecs/libasap/asap.c
diff --git a/apps/codecs/asap/asap.h b/apps/codecs/libasap/asap.h
index 783d628019..783d628019 100644
--- a/apps/codecs/asap/asap.h
+++ b/apps/codecs/libasap/asap.h
diff --git a/apps/codecs/asap/asap_internal.h b/apps/codecs/libasap/asap_internal.h
index 1385215f37..1385215f37 100644
--- a/apps/codecs/asap/asap_internal.h
+++ b/apps/codecs/libasap/asap_internal.h
diff --git a/apps/codecs/asap/players.h b/apps/codecs/libasap/players.h
index ac94f66d49..ac94f66d49 100644
--- a/apps/codecs/asap/players.h
+++ b/apps/codecs/libasap/players.h
diff --git a/apps/codecs/Tremor/CHANGELOG b/apps/codecs/libtremor/CHANGELOG
index 53f23351e2..53f23351e2 100644
--- a/apps/codecs/Tremor/CHANGELOG
+++ b/apps/codecs/libtremor/CHANGELOG
diff --git a/apps/codecs/Tremor/COPYING b/apps/codecs/libtremor/COPYING
index 6111c6c5a6..6111c6c5a6 100644
--- a/apps/codecs/Tremor/COPYING
+++ b/apps/codecs/libtremor/COPYING
diff --git a/apps/codecs/Tremor/Makefile b/apps/codecs/libtremor/Makefile
index 1c40e56a26..674d2ae64c 100644
--- a/apps/codecs/Tremor/Makefile
+++ b/apps/codecs/libtremor/Makefile
@@ -30,7 +30,7 @@ include $(TOOLSDIR)/makesrc.inc
30SOURCES = $(SRC) 30SOURCES = $(SRC)
31OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o) 31OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o)
32OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2)) 32OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2))
33DEPFILE = $(OBJDIR)/dep-Tremor 33DEPFILE = $(OBJDIR)/dep-libtremor
34DIRS = 34DIRS =
35 35
36all: $(OUTPUT) 36all: $(OUTPUT)
@@ -42,7 +42,7 @@ $(OUTPUT): $(OBJS)
42include $(TOOLSDIR)/make.inc 42include $(TOOLSDIR)/make.inc
43 43
44clean: 44clean:
45 $(call PRINTS,cleaning Tremor)rm -f $(OBJS) $(OUTPUT) $(DEPFILE) 45 $(call PRINTS,cleaning libtremor)rm -f $(OBJS) $(OUTPUT) $(DEPFILE)
46 46
47ifneq ($(MAKECMDGOALS),clean) 47ifneq ($(MAKECMDGOALS),clean)
48-include $(DEPFILE) 48-include $(DEPFILE)
diff --git a/apps/codecs/Tremor/README b/apps/codecs/libtremor/README
index 1321175322..1321175322 100644
--- a/apps/codecs/Tremor/README
+++ b/apps/codecs/libtremor/README
diff --git a/apps/codecs/Tremor/README.rockbox b/apps/codecs/libtremor/README.rockbox
index a4e141f6b3..a4e141f6b3 100644
--- a/apps/codecs/Tremor/README.rockbox
+++ b/apps/codecs/libtremor/README.rockbox
diff --git a/apps/codecs/Tremor/SOURCES b/apps/codecs/libtremor/SOURCES
index c622699599..c622699599 100644
--- a/apps/codecs/Tremor/SOURCES
+++ b/apps/codecs/libtremor/SOURCES
diff --git a/apps/codecs/Tremor/asm_arm.h b/apps/codecs/libtremor/asm_arm.h
index bc09ac5170..bc09ac5170 100644
--- a/apps/codecs/Tremor/asm_arm.h
+++ b/apps/codecs/libtremor/asm_arm.h
diff --git a/apps/codecs/Tremor/asm_mcf5249.h b/apps/codecs/libtremor/asm_mcf5249.h
index 64dfb1b785..64dfb1b785 100644
--- a/apps/codecs/Tremor/asm_mcf5249.h
+++ b/apps/codecs/libtremor/asm_mcf5249.h
diff --git a/apps/codecs/Tremor/backends.h b/apps/codecs/libtremor/backends.h
index 50c1c45cfd..50c1c45cfd 100644
--- a/apps/codecs/Tremor/backends.h
+++ b/apps/codecs/libtremor/backends.h
diff --git a/apps/codecs/Tremor/bitwise.c b/apps/codecs/libtremor/bitwise.c
index caa42f4277..caa42f4277 100644
--- a/apps/codecs/Tremor/bitwise.c
+++ b/apps/codecs/libtremor/bitwise.c
diff --git a/apps/codecs/Tremor/block.c b/apps/codecs/libtremor/block.c
index e609fc44f7..e609fc44f7 100644
--- a/apps/codecs/Tremor/block.c
+++ b/apps/codecs/libtremor/block.c
diff --git a/apps/codecs/Tremor/codebook.c b/apps/codecs/libtremor/codebook.c
index 8c319ab49e..8c319ab49e 100644
--- a/apps/codecs/Tremor/codebook.c
+++ b/apps/codecs/libtremor/codebook.c
diff --git a/apps/codecs/Tremor/codebook.h b/apps/codecs/libtremor/codebook.h
index 14f65382dd..14f65382dd 100644
--- a/apps/codecs/Tremor/codebook.h
+++ b/apps/codecs/libtremor/codebook.h
diff --git a/apps/codecs/Tremor/codec_internal.h b/apps/codecs/libtremor/codec_internal.h
index 3ca7f54724..3ca7f54724 100644
--- a/apps/codecs/Tremor/codec_internal.h
+++ b/apps/codecs/libtremor/codec_internal.h
diff --git a/apps/codecs/Tremor/config-tremor.h b/apps/codecs/libtremor/config-tremor.h
index e1ade700e5..e1ade700e5 100644
--- a/apps/codecs/Tremor/config-tremor.h
+++ b/apps/codecs/libtremor/config-tremor.h
diff --git a/apps/codecs/Tremor/config_types.h b/apps/codecs/libtremor/config_types.h
index 1fdcb27fe7..1fdcb27fe7 100644
--- a/apps/codecs/Tremor/config_types.h
+++ b/apps/codecs/libtremor/config_types.h
diff --git a/apps/codecs/Tremor/ctype.c b/apps/codecs/libtremor/ctype.c
index 9eb6eef80a..9eb6eef80a 100644
--- a/apps/codecs/Tremor/ctype.c
+++ b/apps/codecs/libtremor/ctype.c
diff --git a/apps/codecs/Tremor/floor0.c b/apps/codecs/libtremor/floor0.c
index 81587cad72..81587cad72 100644
--- a/apps/codecs/Tremor/floor0.c
+++ b/apps/codecs/libtremor/floor0.c
diff --git a/apps/codecs/Tremor/floor1.c b/apps/codecs/libtremor/floor1.c
index 4ee58c18ca..4ee58c18ca 100644
--- a/apps/codecs/Tremor/floor1.c
+++ b/apps/codecs/libtremor/floor1.c
diff --git a/apps/codecs/Tremor/framing.c b/apps/codecs/libtremor/framing.c
index fb26b02709..fb26b02709 100644
--- a/apps/codecs/Tremor/framing.c
+++ b/apps/codecs/libtremor/framing.c
diff --git a/apps/codecs/Tremor/info.c b/apps/codecs/libtremor/info.c
index c0bd0ae990..c0bd0ae990 100644
--- a/apps/codecs/Tremor/info.c
+++ b/apps/codecs/libtremor/info.c
diff --git a/apps/codecs/Tremor/ivorbiscodec.h b/apps/codecs/libtremor/ivorbiscodec.h
index 2574a11f2a..2574a11f2a 100644
--- a/apps/codecs/Tremor/ivorbiscodec.h
+++ b/apps/codecs/libtremor/ivorbiscodec.h
diff --git a/apps/codecs/Tremor/ivorbisfile.h b/apps/codecs/libtremor/ivorbisfile.h
index 9ff446ab10..9ff446ab10 100644
--- a/apps/codecs/Tremor/ivorbisfile.h
+++ b/apps/codecs/libtremor/ivorbisfile.h
diff --git a/apps/codecs/Tremor/lsp_lookup.h b/apps/codecs/libtremor/lsp_lookup.h
index 8609936542..8609936542 100644
--- a/apps/codecs/Tremor/lsp_lookup.h
+++ b/apps/codecs/libtremor/lsp_lookup.h
diff --git a/apps/codecs/Tremor/mapping0.c b/apps/codecs/libtremor/mapping0.c
index 6bcc717d86..6bcc717d86 100644
--- a/apps/codecs/Tremor/mapping0.c
+++ b/apps/codecs/libtremor/mapping0.c
diff --git a/apps/codecs/Tremor/misc.h b/apps/codecs/libtremor/misc.h
index 7d8b846381..7d8b846381 100644
--- a/apps/codecs/Tremor/misc.h
+++ b/apps/codecs/libtremor/misc.h
diff --git a/apps/codecs/Tremor/ogg.h b/apps/codecs/libtremor/ogg.h
index 7e2785f117..7e2785f117 100644
--- a/apps/codecs/Tremor/ogg.h
+++ b/apps/codecs/libtremor/ogg.h
diff --git a/apps/codecs/Tremor/oggmalloc.c b/apps/codecs/libtremor/oggmalloc.c
index b11eaa54f5..b11eaa54f5 100644
--- a/apps/codecs/Tremor/oggmalloc.c
+++ b/apps/codecs/libtremor/oggmalloc.c
diff --git a/apps/codecs/Tremor/os.h b/apps/codecs/libtremor/os.h
index bb4b867e3d..bb4b867e3d 100644
--- a/apps/codecs/Tremor/os.h
+++ b/apps/codecs/libtremor/os.h
diff --git a/apps/codecs/Tremor/os_types.h b/apps/codecs/libtremor/os_types.h
index 5738ef4911..5738ef4911 100644
--- a/apps/codecs/Tremor/os_types.h
+++ b/apps/codecs/libtremor/os_types.h
diff --git a/apps/codecs/Tremor/registry.c b/apps/codecs/libtremor/registry.c
index b1592628a1..b1592628a1 100644
--- a/apps/codecs/Tremor/registry.c
+++ b/apps/codecs/libtremor/registry.c
diff --git a/apps/codecs/Tremor/registry.h b/apps/codecs/libtremor/registry.h
index 2bc8068f69..2bc8068f69 100644
--- a/apps/codecs/Tremor/registry.h
+++ b/apps/codecs/libtremor/registry.h
diff --git a/apps/codecs/Tremor/res012.c b/apps/codecs/libtremor/res012.c
index 46b782def1..46b782def1 100644
--- a/apps/codecs/Tremor/res012.c
+++ b/apps/codecs/libtremor/res012.c
diff --git a/apps/codecs/Tremor/sharedbook.c b/apps/codecs/libtremor/sharedbook.c
index edabf3ccb3..edabf3ccb3 100644
--- a/apps/codecs/Tremor/sharedbook.c
+++ b/apps/codecs/libtremor/sharedbook.c
diff --git a/apps/codecs/Tremor/synthesis.c b/apps/codecs/libtremor/synthesis.c
index cef240e796..cef240e796 100644
--- a/apps/codecs/Tremor/synthesis.c
+++ b/apps/codecs/libtremor/synthesis.c
diff --git a/apps/codecs/Tremor/vorbisfile.c b/apps/codecs/libtremor/vorbisfile.c
index ca18ecb3f7..ca18ecb3f7 100644
--- a/apps/codecs/Tremor/vorbisfile.c
+++ b/apps/codecs/libtremor/vorbisfile.c
diff --git a/apps/codecs/Tremor/window.c b/apps/codecs/libtremor/window.c
index 14d97cf6ac..14d97cf6ac 100644
--- a/apps/codecs/Tremor/window.c
+++ b/apps/codecs/libtremor/window.c
diff --git a/apps/codecs/Tremor/window.h b/apps/codecs/libtremor/window.h
index 27647fe62e..27647fe62e 100644
--- a/apps/codecs/Tremor/window.h
+++ b/apps/codecs/libtremor/window.h
diff --git a/apps/codecs/Tremor/window_lookup.h b/apps/codecs/libtremor/window_lookup.h
index ccf316e227..ccf316e227 100644
--- a/apps/codecs/Tremor/window_lookup.h
+++ b/apps/codecs/libtremor/window_lookup.h
diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c
index a2b6fabf99..380cfbdb8b 100644
--- a/apps/codecs/spc.c
+++ b/apps/codecs/spc.c
@@ -26,8 +26,8 @@
26/* DSP Based on Brad Martin's OpenSPC DSP emulator */ 26/* DSP Based on Brad Martin's OpenSPC DSP emulator */
27/* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */ 27/* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */
28#include "codeclib.h" 28#include "codeclib.h"
29#include "spc/spc_codec.h" 29#include "libspc/spc_codec.h"
30#include "spc/spc_profiler.h" 30#include "libspc/spc_profiler.h"
31 31
32CODEC_HEADER 32CODEC_HEADER
33 33
diff --git a/apps/codecs/spc/Makefile b/apps/codecs/spc/Makefile
deleted file mode 100644
index 8929149ce2..0000000000
--- a/apps/codecs/spc/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10INCLUDES=-I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
11 -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(BUILDDIR)
12
13ifdef APPEXTRA
14 INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA)))
15endif
16
17SPCOPTS = -O -DROCKBOX
18
19CFLAGS = $(INCLUDES) $(GCCOPTS) $(TARGET_INC) $(SPCOPTS) $(TARGET) \
20$(EXTRA_DEFINES) -DMEM=${MEMORYSIZE} $(PROFILE_OPTS) -DCODEC=1
21
22# This sets up 'SRC' based on the files mentioned in SOURCES
23include $(TOOLSDIR)/makesrc.inc
24
25SOURCES = $(SRC)
26OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o)
27OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2))
28DEPFILE = $(OBJDIR)/dep-spc
29DIRS =
30
31all: $(OUTPUT)
32
33$(OUTPUT): $(OBJS)
34 $(call PRINTS,AR+RANLIB $(@F))$(AR) ruv $@ $+ >/dev/null 2>&1
35 $(SILENT)$(RANLIB) $@
36
37include $(TOOLSDIR)/make.inc
38
39clean:
40 $(call PRINTS,cleaning spc)rm -f $(OBJS) $(OUTPUT) $(DEPFILE)
41
42ifneq ($(MAKECMDGOALS),clean)
43-include $(DEPFILE)
44endif
diff --git a/apps/codecs/spc/SOURCES b/apps/codecs/spc/SOURCES
deleted file mode 100644
index 901232a6eb..0000000000
--- a/apps/codecs/spc/SOURCES
+++ /dev/null
@@ -1,4 +0,0 @@
1spc_cpu.c
2spc_dsp.c
3spc_emu.c
4spc_profiler.c
diff --git a/apps/codecs/spc/spc_codec.h b/apps/codecs/spc/spc_codec.h
deleted file mode 100644
index 33e566aea2..0000000000
--- a/apps/codecs/spc/spc_codec.h
+++ /dev/null
@@ -1,454 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
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
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25/* lovingly ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
26/* DSP Based on Brad Martin's OpenSPC DSP emulator */
27/* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */
28
29#ifndef _SPC_CODEC_H_
30#define _SPC_CODEC_H_
31
32/* rather than comment out asserts, just define NDEBUG */
33#define NDEBUG
34#include <assert.h>
35
36/** Basic configuration options **/
37
38#define SPC_DUAL_CORE 1
39
40#if !defined(SPC_DUAL_CORE) || NUM_CORES == 1
41#undef SPC_DUAL_CORE
42#define SPC_DUAL_CORE 0
43#endif
44
45/* TGB is the only target fast enough for gaussian and realtime BRR decode */
46/* echo is almost fast enough but not quite */
47#if defined(TOSHIBA_GIGABEAT_F) || defined(TOSHIBA_GIGABEAT_S) ||\
48 defined(SIMULATOR)
49 /* Don't cache BRR waves */
50 #define SPC_BRRCACHE 0
51
52 /* Allow gaussian interpolation */
53 #define SPC_NOINTERP 0
54
55 /* Allow echo processing */
56 #define SPC_NOECHO 0
57#elif defined(CPU_COLDFIRE)
58 /* Cache BRR waves */
59 #define SPC_BRRCACHE 1
60
61 /* Disable gaussian interpolation */
62 #define SPC_NOINTERP 1
63
64 /* Allow echo processing */
65 #define SPC_NOECHO 0
66#elif defined (CPU_PP) && SPC_DUAL_CORE
67 /* Cache BRR waves */
68 #define SPC_BRRCACHE 1
69
70 /* Disable gaussian interpolation */
71 #define SPC_NOINTERP 1
72
73 /* Allow echo processing */
74 #define SPC_NOECHO 0
75#else
76 /* Cache BRR waves */
77 #define SPC_BRRCACHE 1
78
79 /* Disable gaussian interpolation */
80 #define SPC_NOINTERP 1
81
82 /* Disable echo processing */
83 #define SPC_NOECHO 1
84#endif
85
86#ifdef CPU_ARM
87
88#if CONFIG_CPU != PP5002
89 #undef ICODE_ATTR
90 #define ICODE_ATTR
91
92 #undef IDATA_ATTR
93 #define IDATA_ATTR
94
95 #undef ICONST_ATTR
96 #define ICONST_ATTR
97
98 #undef IBSS_ATTR
99 #define IBSS_ATTR
100#endif
101
102#if SPC_DUAL_CORE
103 #undef SHAREDBSS_ATTR
104 #define SHAREDBSS_ATTR __attribute__ ((section(".ibss")))
105 #undef SHAREDDATA_ATTR
106 #define SHAREDDATA_ATTR __attribute__((section(".idata")))
107#endif
108#endif
109
110/* Samples per channel per iteration */
111#if defined(CPU_PP) && NUM_CORES == 1
112#define WAV_CHUNK_SIZE 2048
113#else
114#define WAV_CHUNK_SIZE 1024
115#endif
116
117/**************** Little-endian handling ****************/
118
119static inline unsigned get_le16( void const* p )
120{
121 return ((unsigned char const*) p) [1] * 0x100u +
122 ((unsigned char const*) p) [0];
123}
124
125static inline int get_le16s( void const* p )
126{
127 return ((signed char const*) p) [1] * 0x100 +
128 ((unsigned char const*) p) [0];
129}
130
131static inline void set_le16( void* p, unsigned n )
132{
133 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
134 ((unsigned char*) p) [0] = (unsigned char) n;
135}
136
137#define GET_LE16( addr ) get_le16( addr )
138#define SET_LE16( addr, data ) set_le16( addr, data )
139#define INT16A( addr ) (*(uint16_t*) (addr))
140#define INT16SA( addr ) (*(int16_t*) (addr))
141
142#ifdef ROCKBOX_LITTLE_ENDIAN
143 #define GET_LE16A( addr ) (*(uint16_t*) (addr))
144 #define GET_LE16SA( addr ) (*( int16_t*) (addr))
145 #define SET_LE16A( addr, data ) (void) (*(uint16_t*) (addr) = (data))
146#else
147 #define GET_LE16A( addr ) get_le16 ( addr )
148 #define GET_LE16SA( addr ) get_le16s( addr )
149 #define SET_LE16A( addr, data ) set_le16 ( addr, data )
150#endif
151
152struct Spc_Emu;
153#define THIS struct Spc_Emu* const this
154
155/* The CPU portion (shock!) */
156
157struct cpu_regs_t
158{
159 long pc; /* more than 16 bits to allow overflow detection */
160 uint8_t a;
161 uint8_t x;
162 uint8_t y;
163 uint8_t status;
164 uint8_t sp;
165};
166
167struct cpu_ram_t
168{
169 union {
170 uint8_t padding1 [0x100];
171 uint16_t align;
172 } padding1 [1];
173 uint8_t ram [0x10000];
174 uint8_t padding2 [0x100];
175};
176
177#undef RAM
178#define RAM ram.ram
179extern struct cpu_ram_t ram;
180
181long CPU_run( THIS, long start_time ) ICODE_ATTR;
182void CPU_Init( THIS );
183
184/* The DSP portion (awe!) */
185enum { VOICE_COUNT = 8 };
186enum { REGISTER_COUNT = 128 };
187
188struct raw_voice_t
189{
190 int8_t volume [2];
191 uint8_t rate [2];
192 uint8_t waveform;
193 uint8_t adsr [2]; /* envelope rates for attack, decay, and sustain */
194 uint8_t gain; /* envelope gain (if not using ADSR) */
195 int8_t envx; /* current envelope level */
196 int8_t outx; /* current sample */
197 int8_t unused [6];
198};
199
200struct globals_t
201{
202 int8_t unused1 [12];
203 int8_t volume_0; /* 0C Main Volume Left (-.7) */
204 int8_t echo_feedback; /* 0D Echo Feedback (-.7) */
205 int8_t unused2 [14];
206 int8_t volume_1; /* 1C Main Volume Right (-.7) */
207 int8_t unused3 [15];
208 int8_t echo_volume_0; /* 2C Echo Volume Left (-.7) */
209 uint8_t pitch_mods; /* 2D Pitch Modulation on/off for each voice */
210 int8_t unused4 [14];
211 int8_t echo_volume_1; /* 3C Echo Volume Right (-.7) */
212 uint8_t noise_enables; /* 3D Noise output on/off for each voice */
213 int8_t unused5 [14];
214 uint8_t key_ons; /* 4C Key On for each voice */
215 uint8_t echo_ons; /* 4D Echo on/off for each voice */
216 int8_t unused6 [14];
217 uint8_t key_offs; /* 5C key off for each voice
218 (instantiates release mode) */
219 uint8_t wave_page; /* 5D source directory (wave table offsets) */
220 int8_t unused7 [14];
221 uint8_t flags; /* 6C flags and noise freq */
222 uint8_t echo_page; /* 6D */
223 int8_t unused8 [14];
224 uint8_t wave_ended; /* 7C */
225 uint8_t echo_delay; /* 7D ms >> 4 */
226 char unused9 [2];
227};
228
229enum state_t
230{ /* -1, 0, +1 allows more efficient if statements */
231 state_decay = -1,
232 state_sustain = 0,
233 state_attack = +1,
234 state_release = 2
235};
236
237struct cache_entry_t
238{
239 int16_t const* samples;
240 unsigned end; /* past-the-end position */
241 unsigned loop; /* number of samples in loop */
242 unsigned start_addr;
243};
244
245enum { BRR_BLOCK_SIZE = 16 };
246enum { BRR_CACHE_SIZE = 0x20000 + 32} ;
247
248struct voice_t
249{
250#if SPC_BRRCACHE
251 int16_t const* samples;
252 long wave_end;
253 int wave_loop;
254#else
255 int16_t samples [3 + BRR_BLOCK_SIZE + 1];
256 int block_header; /* header byte from current block */
257#endif
258 uint8_t const* addr;
259 short volume [2];
260 long position;/* position in samples buffer, with 12-bit fraction */
261 short envx;
262 short env_mode;
263 short env_timer;
264 short key_on_delay;
265};
266
267#if SPC_BRRCACHE
268/* a little extra for samples that go past end */
269extern int16_t BRRcache [BRR_CACHE_SIZE];
270#endif
271
272enum { FIR_BUF_HALF = 8 };
273
274#if defined(CPU_COLDFIRE)
275/* global because of the large aligment requirement for hardware masking -
276 * L-R interleaved 16-bit samples for easy loading and mac.w use.
277 */
278enum
279{
280 FIR_BUF_CNT = FIR_BUF_HALF,
281 FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ),
282 FIR_BUF_ALIGN = FIR_BUF_SIZE * 2,
283 FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) - 1))
284};
285#elif defined (CPU_ARM)
286enum
287{
288 FIR_BUF_CNT = FIR_BUF_HALF * 2 * 2,
289 FIR_BUF_SIZE = FIR_BUF_CNT * sizeof ( int32_t ),
290 FIR_BUF_ALIGN = FIR_BUF_SIZE,
291 FIR_BUF_MASK = ~((FIR_BUF_ALIGN / 2) | (sizeof ( int32_t ) * 2 - 1))
292};
293#endif /* CPU_* */
294
295struct Spc_Dsp
296{
297 union
298 {
299 struct raw_voice_t voice [VOICE_COUNT];
300 uint8_t reg [REGISTER_COUNT];
301 struct globals_t g;
302 int16_t align;
303 } r;
304
305 unsigned echo_pos;
306 int keys_down;
307 int noise_count;
308 uint16_t noise; /* also read as int16_t */
309
310#if defined(CPU_COLDFIRE)
311 /* circularly hardware masked address */
312 int32_t *fir_ptr;
313 /* wrapped address just behind current position -
314 allows mac.w to increment and mask fir_ptr */
315 int32_t *last_fir_ptr;
316 /* copy of echo FIR constants as int16_t for use with mac.w */
317 int16_t fir_coeff [VOICE_COUNT];
318#elif defined (CPU_ARM)
319 /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */
320 int32_t *fir_ptr;
321 /* copy of echo FIR constants as int32_t, for faster access */
322 int32_t fir_coeff [VOICE_COUNT];
323#else
324 /* fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code */
325 int fir_pos; /* (0 to 7) */
326 int fir_buf [FIR_BUF_HALF * 2] [2];
327 /* copy of echo FIR constants as int, for faster access */
328 int fir_coeff [VOICE_COUNT];
329#endif
330
331 struct voice_t voice_state [VOICE_COUNT];
332
333#if SPC_BRRCACHE
334 uint8_t oldsize;
335 struct cache_entry_t wave_entry [256];
336 struct cache_entry_t wave_entry_old [256];
337#endif
338};
339
340struct src_dir
341{
342 char start [2];
343 char loop [2];
344};
345
346void DSP_run_( struct Spc_Dsp* this, long count, int32_t* out_buf ) ICODE_ATTR;
347void DSP_reset( struct Spc_Dsp* this );
348
349static inline void DSP_run( struct Spc_Dsp* this, long count, int32_t* out )
350{
351 /* Should we just fill the buffer with silence? Flags won't be cleared */
352 /* during this run so it seems it should keep resetting every sample. */
353 if ( this->r.g.flags & 0x80 )
354 DSP_reset( this );
355
356 DSP_run_( this, count, out );
357}
358
359/**************** SPC emulator ****************/
360/* 1.024 MHz clock / 32000 samples per second */
361enum { CLOCKS_PER_SAMPLE = 32 };
362
363enum { EXTRA_CLOCKS = CLOCKS_PER_SAMPLE / 2 };
364
365/* using this disables timer (since this will always be in the future) */
366enum { TIMER_DISABLED_TIME = 127 };
367
368enum { ROM_SIZE = 64 };
369enum { ROM_ADDR = 0xFFC0 };
370
371enum { TIMER_COUNT = 3 };
372
373struct Timer
374{
375 long next_tick;
376 int period;
377 int count;
378 int shift;
379 int enabled;
380 int counter;
381};
382
383void Timer_run_( struct Timer* t, long time ) ICODE_ATTR;
384
385static inline void Timer_run( struct Timer* t, long time )
386{
387 if ( time >= t->next_tick )
388 Timer_run_( t, time );
389}
390
391struct Spc_Emu
392{
393 uint8_t cycle_table [0x100];
394 struct cpu_regs_t r;
395
396 int32_t* sample_buf;
397 long next_dsp;
398 int rom_enabled;
399 int extra_cycles;
400
401 struct Timer timer [TIMER_COUNT];
402
403 /* large objects at end */
404 struct Spc_Dsp dsp;
405 uint8_t extra_ram [ROM_SIZE];
406 uint8_t boot_rom [ROM_SIZE];
407};
408
409enum { SPC_FILE_SIZE = 0x10180 };
410
411struct spc_file_t
412{
413 char signature [27];
414 char unused [10];
415 uint8_t pc [2];
416 uint8_t a;
417 uint8_t x;
418 uint8_t y;
419 uint8_t status;
420 uint8_t sp;
421 char unused2 [212];
422 uint8_t ram [0x10000];
423 uint8_t dsp [128];
424 uint8_t ipl_rom [128];
425};
426
427void SPC_Init( THIS );
428
429int SPC_load_spc( THIS, const void* data, long size );
430
431/**************** DSP interaction ****************/
432void DSP_write( struct Spc_Dsp* this, int i, int data ) ICODE_ATTR;
433
434static inline int DSP_read( struct Spc_Dsp* this, int i )
435{
436 assert( (unsigned) i < REGISTER_COUNT );
437 return this->r.reg [i];
438}
439
440void SPC_run_dsp_( THIS, long time ) ICODE_ATTR;
441
442static inline void SPC_run_dsp( THIS, long time )
443{
444 if ( time >= this->next_dsp )
445 SPC_run_dsp_( this, time );
446}
447
448int SPC_read( THIS, unsigned addr, long const time ) ICODE_ATTR;
449void SPC_write( THIS, unsigned addr, int data, long const time ) ICODE_ATTR;
450
451/**************** Sample generation ****************/
452int SPC_play( THIS, long count, int32_t* out ) ICODE_ATTR;
453
454#endif /* _SPC_CODEC_H_ */
diff --git a/apps/codecs/spc/spc_cpu.c b/apps/codecs/spc/spc_cpu.c
deleted file mode 100644
index 6aa9499d1e..0000000000
--- a/apps/codecs/spc/spc_cpu.c
+++ /dev/null
@@ -1,1050 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
11 * Copyright (C) 2004-2007 Shay Green (blargg)
12 * Copyright (C) 2002 Brad Martin
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24/* The CPU portion (shock!) */
25#include "codec.h"
26#include "codecs.h"
27#include "spc_codec.h"
28#include "spc_profiler.h"
29
30#undef check
31#define check assert
32
33#define READ( addr ) (SPC_read( this, addr, spc_time_ ))
34#define WRITE( addr, value ) (SPC_write( this, addr, value, spc_time_ ))
35
36#define READ_DP( addr ) READ( (addr) + dp )
37#define WRITE_DP( addr, value ) WRITE( (addr) + dp, value )
38
39#define READ_PROG16( addr ) GET_LE16( RAM + (addr) )
40
41#define READ_PC( pc ) (*(pc))
42#define READ_PC16( pc ) GET_LE16( pc )
43
44#define SET_PC( n ) (pc = RAM + (n))
45#define GET_PC() (pc - RAM)
46
47static unsigned char const cycle_table [0x100] = {
48 2,8,4,5,3,4,3,6,2,6,5,4,5,4,6,8, /* 0 */
49 2,8,4,5,4,5,5,6,5,5,6,5,2,2,4,6, /* 1 */
50 2,8,4,5,3,4,3,6,2,6,5,4,5,4,5,4, /* 2 */
51 2,8,4,5,4,5,5,6,5,5,6,5,2,2,3,8, /* 3 */
52 2,8,4,5,3,4,3,6,2,6,4,4,5,4,6,6, /* 4 */
53 2,8,4,5,4,5,5,6,5,5,4,5,2,2,4,3, /* 5 */
54 2,8,4,5,3,4,3,6,2,6,4,4,5,4,5,5, /* 6 */
55 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,6, /* 7 */
56 2,8,4,5,3,4,3,6,2,6,5,4,5,2,4,5, /* 8 */
57 2,8,4,5,4,5,5,6,5,5,5,5,2,2,12,5,/* 9 */
58 3,8,4,5,3,4,3,6,2,6,4,4,5,2,4,4, /* A */
59 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,4, /* B */
60 3,8,4,5,4,5,4,7,2,5,6,4,5,2,4,9, /* C */
61 2,8,4,5,5,6,6,7,4,5,4,5,2,2,6,3, /* D */
62 2,8,4,5,3,4,3,6,2,4,5,3,4,3,4,3, /* E */
63 2,8,4,5,4,5,5,6,3,4,5,4,2,2,4,3 /* F */
64};
65
66#define MEM_BIT() CPU_mem_bit( this, pc, spc_time_ )
67
68static unsigned CPU_mem_bit( THIS, uint8_t const* pc, long const spc_time_ )
69 ICODE_ATTR;
70
71static unsigned CPU_mem_bit( THIS, uint8_t const* pc, long const spc_time_ )
72{
73 unsigned addr = READ_PC16( pc );
74 unsigned t = READ( addr & 0x1FFF ) >> (addr >> 13);
75 return (t << 8) & 0x100;
76}
77
78/* status flags */
79enum { st_n = 0x80 };
80enum { st_v = 0x40 };
81enum { st_p = 0x20 };
82enum { st_b = 0x10 };
83enum { st_h = 0x08 };
84enum { st_i = 0x04 };
85enum { st_z = 0x02 };
86enum { st_c = 0x01 };
87
88#define IS_NEG (nz & 0x880)
89
90#define CALC_STATUS( out )\
91{\
92 out = status & ~(st_n | st_z | st_c);\
93 out |= (c >> 8) & st_c;\
94 out |= (dp >> 3) & st_p;\
95 if ( IS_NEG ) out |= st_n;\
96 if ( !(nz & 0xFF) ) out |= st_z;\
97}
98
99#define SET_STATUS( in )\
100{\
101 status = in & ~(st_n | st_z | st_c | st_p);\
102 c = in << 8;\
103 nz = ((in << 4) & 0x800) | (~in & st_z);\
104 dp = (in << 3) & 0x100;\
105}
106
107
108/* stack */
109#define PUSH( v ) (*--sp = (uint8_t) (v))
110#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
111#define POP() (*sp++)
112#define SET_SP( v ) (sp = RAM + 0x101 + (v))
113#define GET_SP() (sp - 0x101 - RAM)
114
115long CPU_run( THIS, long start_time )
116{
117#if 0
118 ENTER_TIMER(cpu);
119#endif
120
121 register long spc_time_ = start_time;
122
123#ifdef CPU_ARM
124 uint8_t* const ram_ = ram.ram;
125 #undef RAM
126 #define RAM ram_
127#endif
128
129 int a = this->r.a;
130 int x = this->r.x;
131 int y = this->r.y;
132
133 uint8_t const* pc;
134 SET_PC( this->r.pc );
135
136 uint8_t* sp;
137 SET_SP( this->r.sp );
138
139 int status;
140 int c;
141 int nz;
142 unsigned dp;
143 {
144 int temp = this->r.status;
145 SET_STATUS( temp );
146 }
147
148 goto loop;
149
150 /* main loop */
151cbranch_taken_loop:
152 pc += *(int8_t const*) pc;
153 spc_time_ += 2;
154inc_pc_loop:
155 pc++;
156loop:
157 check( (unsigned) GET_PC() < 0x10000 );
158 check( (unsigned) GET_SP() < 0x100 );
159 check( (unsigned) a < 0x100 );
160 check( (unsigned) x < 0x100 );
161 check( (unsigned) y < 0x100 );
162
163 unsigned opcode = *pc;
164 int cycles = this->cycle_table [opcode];
165 unsigned data = *++pc;
166 if ( (spc_time_ += cycles) > 0 )
167 goto out_of_time;
168 switch ( opcode )
169 {
170
171/* Common instructions */
172
173#define BRANCH( cond )\
174{\
175 pc++;\
176 int offset = (int8_t) data;\
177 if ( cond ) {\
178 pc += offset;\
179 spc_time_ += 2;\
180 }\
181 goto loop;\
182}
183
184 case 0xF0: /* BEQ (most common) */
185 BRANCH( !(uint8_t) nz )
186
187 case 0xD0: /* BNE */
188 BRANCH( (uint8_t) nz )
189
190 case 0x3F: /* CALL */
191 PUSH16( GET_PC() + 2 );
192 SET_PC( READ_PC16( pc ) );
193 goto loop;
194
195 case 0x6F: /* RET */
196 SET_PC( POP() );
197 pc += POP() * 0x100;
198 goto loop;
199
200#define CASE( n ) case n:
201
202/* Define common address modes based on opcode for immediate mode. Execution
203 ends with data set to the address of the operand. */
204#define ADDR_MODES( op )\
205 CASE( op - 0x02 ) /* (X) */\
206 data = x + dp;\
207 pc--;\
208 goto end_##op;\
209 CASE( op + 0x0F ) /* (dp)+Y */\
210 data = READ_PROG16( data + dp ) + y;\
211 goto end_##op;\
212 CASE( op - 0x01 ) /* (dp+X) */\
213 data = READ_PROG16( ((uint8_t) (data + x)) + dp );\
214 goto end_##op;\
215 CASE( op + 0x0E ) /* abs+Y */\
216 data += y;\
217 goto abs_##op;\
218 CASE( op + 0x0D ) /* abs+X */\
219 data += x;\
220 CASE( op - 0x03 ) /* abs */\
221 abs_##op:\
222 data += 0x100 * READ_PC( ++pc );\
223 goto end_##op;\
224 CASE( op + 0x0C ) /* dp+X */\
225 data = (uint8_t) (data + x);\
226 CASE( op - 0x04 ) /* dp */\
227 data += dp;\
228 end_##op:
229
230/* 1. 8-bit Data Transmission Commands. Group I */
231
232 ADDR_MODES( 0xE8 ) /* MOV A,addr */
233 /*case 0xE4:*/ /* MOV a,dp (most common) */
234 mov_a_addr:
235 a = nz = READ( data );
236 goto inc_pc_loop;
237 case 0xBF: /* MOV A,(X)+ */
238 data = x + dp;
239 x = (uint8_t) (x + 1);
240 pc--;
241 goto mov_a_addr;
242
243 case 0xE8: /* MOV A,imm */
244 a = data;
245 nz = data;
246 goto inc_pc_loop;
247
248 case 0xF9: /* MOV X,dp+Y */
249 data = (uint8_t) (data + y);
250 case 0xF8: /* MOV X,dp */
251 data += dp;
252 goto mov_x_addr;
253 case 0xE9: /* MOV X,abs */
254 data = READ_PC16( pc );
255 pc++;
256 mov_x_addr:
257 data = READ( data );
258 case 0xCD: /* MOV X,imm */
259 x = data;
260 nz = data;
261 goto inc_pc_loop;
262
263 case 0xFB: /* MOV Y,dp+X */
264 data = (uint8_t) (data + x);
265 case 0xEB: /* MOV Y,dp */
266 data += dp;
267 goto mov_y_addr;
268 case 0xEC: /* MOV Y,abs */
269 data = READ_PC16( pc );
270 pc++;
271 mov_y_addr:
272 data = READ( data );
273 case 0x8D: /* MOV Y,imm */
274 y = data;
275 nz = data;
276 goto inc_pc_loop;
277
278/* 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 */
279
280 ADDR_MODES( 0xC8 ) /* MOV addr,A */
281 WRITE( data, a );
282 goto inc_pc_loop;
283
284 {
285 int temp;
286 case 0xCC: /* MOV abs,Y */
287 temp = y;
288 goto mov_abs_temp;
289 case 0xC9: /* MOV abs,X */
290 temp = x;
291 mov_abs_temp:
292 WRITE( READ_PC16( pc ), temp );
293 pc += 2;
294 goto loop;
295 }
296
297 case 0xD9: /* MOV dp+Y,X */
298 data = (uint8_t) (data + y);
299 case 0xD8: /* MOV dp,X */
300 WRITE( data + dp, x );
301 goto inc_pc_loop;
302
303 case 0xDB: /* MOV dp+X,Y */
304 data = (uint8_t) (data + x);
305 case 0xCB: /* MOV dp,Y */
306 WRITE( data + dp, y );
307 goto inc_pc_loop;
308
309 case 0xFA: /* MOV dp,dp */
310 data = READ( data + dp );
311 case 0x8F: /* MOV dp,#imm */
312 WRITE_DP( READ_PC( ++pc ), data );
313 goto inc_pc_loop;
314
315/* 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. */
316
317 case 0x7D: /* MOV A,X */
318 a = x;
319 nz = x;
320 goto loop;
321
322 case 0xDD: /* MOV A,Y */
323 a = y;
324 nz = y;
325 goto loop;
326
327 case 0x5D: /* MOV X,A */
328 x = a;
329 nz = a;
330 goto loop;
331
332 case 0xFD: /* MOV Y,A */
333 y = a;
334 nz = a;
335 goto loop;
336
337 case 0x9D: /* MOV X,SP */
338 x = nz = GET_SP();
339 goto loop;
340
341 case 0xBD: /* MOV SP,X */
342 SET_SP( x );
343 goto loop;
344
345 /*case 0xC6:*/ /* MOV (X),A (handled by MOV addr,A in group 2) */
346
347 case 0xAF: /* MOV (X)+,A */
348 WRITE_DP( x, a );
349 x++;
350 goto loop;
351
352/* 5. 8-BIT LOGIC OPERATION COMMANDS */
353
354#define LOGICAL_OP( op, func )\
355 ADDR_MODES( op ) /* addr */\
356 data = READ( data );\
357 case op: /* imm */\
358 nz = a func##= data;\
359 goto inc_pc_loop;\
360 { unsigned addr;\
361 case op + 0x11: /* X,Y */\
362 data = READ_DP( y );\
363 addr = x + dp;\
364 pc--;\
365 goto addr_##op;\
366 case op + 0x01: /* dp,dp */\
367 data = READ_DP( data );\
368 case op + 0x10: /*dp,imm*/\
369 addr = READ_PC( ++pc ) + dp;\
370 addr_##op:\
371 nz = data func READ( addr );\
372 WRITE( addr, nz );\
373 goto inc_pc_loop;\
374 }
375
376 LOGICAL_OP( 0x28, & ); /* AND */
377
378 LOGICAL_OP( 0x08, | ); /* OR */
379
380 LOGICAL_OP( 0x48, ^ ); /* EOR */
381
382/* 4. 8-BIT ARITHMETIC OPERATION COMMANDS */
383
384 ADDR_MODES( 0x68 ) /* CMP addr */
385 data = READ( data );
386 case 0x68: /* CMP imm */
387 nz = a - data;
388 c = ~nz;
389 nz &= 0xFF;
390 goto inc_pc_loop;
391
392 case 0x79: /* CMP (X),(Y) */
393 data = READ_DP( x );
394 nz = data - READ_DP( y );
395 c = ~nz;
396 nz &= 0xFF;
397 goto loop;
398
399 case 0x69: /* CMP (dp),(dp) */
400 data = READ_DP( data );
401 case 0x78: /* CMP dp,imm */
402 nz = READ_DP( READ_PC( ++pc ) ) - data;
403 c = ~nz;
404 nz &= 0xFF;
405 goto inc_pc_loop;
406
407 case 0x3E: /* CMP X,dp */
408 data += dp;
409 goto cmp_x_addr;
410 case 0x1E: /* CMP X,abs */
411 data = READ_PC16( pc );
412 pc++;
413 cmp_x_addr:
414 data = READ( data );
415 case 0xC8: /* CMP X,imm */
416 nz = x - data;
417 c = ~nz;
418 nz &= 0xFF;
419 goto inc_pc_loop;
420
421 case 0x7E: /* CMP Y,dp */
422 data += dp;
423 goto cmp_y_addr;
424 case 0x5E: /* CMP Y,abs */
425 data = READ_PC16( pc );
426 pc++;
427 cmp_y_addr:
428 data = READ( data );
429 case 0xAD: /* CMP Y,imm */
430 nz = y - data;
431 c = ~nz;
432 nz &= 0xFF;
433 goto inc_pc_loop;
434
435 {
436 int addr;
437 case 0xB9: /* SBC (x),(y) */
438 case 0x99: /* ADC (x),(y) */
439 pc--; /* compensate for inc later */
440 data = READ_DP( x );
441 addr = y + dp;
442 goto adc_addr;
443 case 0xA9: /* SBC dp,dp */
444 case 0x89: /* ADC dp,dp */
445 data = READ_DP( data );
446 case 0xB8: /* SBC dp,imm */
447 case 0x98: /* ADC dp,imm */
448 addr = READ_PC( ++pc ) + dp;
449 adc_addr:
450 nz = READ( addr );
451 goto adc_data;
452
453/* catch ADC and SBC together, then decode later based on operand */
454#undef CASE
455#define CASE( n ) case n: case (n) + 0x20:
456 ADDR_MODES( 0x88 ) /* ADC/SBC addr */
457 data = READ( data );
458 case 0xA8: /* SBC imm */
459 case 0x88: /* ADC imm */
460 addr = -1; /* A */
461 nz = a;
462 adc_data: {
463 if ( opcode & 0x20 )
464 data ^= 0xFF; /* SBC */
465 int carry = (c >> 8) & 1;
466 int ov = (nz ^ 0x80) + carry + (int8_t) data; /* sign-extend */
467 int hc = (nz & 15) + carry;
468 c = nz += data + carry;
469 hc = (nz & 15) - hc;
470 status = (status & ~(st_v | st_h)) | ((ov >> 2) & st_v) |
471 ((hc >> 1) & st_h);
472 if ( addr < 0 ) {
473 a = (uint8_t) nz;
474 goto inc_pc_loop;
475 }
476 WRITE( addr, (uint8_t) nz );
477 goto inc_pc_loop;
478 }
479
480 }
481
482/* 6. ADDITION & SUBTRACTION COMMANDS */
483
484#define INC_DEC_REG( reg, n )\
485 nz = reg + n;\
486 reg = (uint8_t) nz;\
487 goto loop;
488
489 case 0xBC: INC_DEC_REG( a, 1 ) /* INC A */
490 case 0x3D: INC_DEC_REG( x, 1 ) /* INC X */
491 case 0xFC: INC_DEC_REG( y, 1 ) /* INC Y */
492
493 case 0x9C: INC_DEC_REG( a, -1 ) /* DEC A */
494 case 0x1D: INC_DEC_REG( x, -1 ) /* DEC X */
495 case 0xDC: INC_DEC_REG( y, -1 ) /* DEC Y */
496
497 case 0x9B: /* DEC dp+X */
498 case 0xBB: /* INC dp+X */
499 data = (uint8_t) (data + x);
500 case 0x8B: /* DEC dp */
501 case 0xAB: /* INC dp */
502 data += dp;
503 goto inc_abs;
504 case 0x8C: /* DEC abs */
505 case 0xAC: /* INC abs */
506 data = READ_PC16( pc );
507 pc++;
508 inc_abs:
509 nz = ((opcode >> 4) & 2) - 1;
510 nz += READ( data );
511 WRITE( data, (uint8_t) nz );
512 goto inc_pc_loop;
513
514/* 7. SHIFT, ROTATION COMMANDS */
515
516 case 0x5C: /* LSR A */
517 c = 0;
518 case 0x7C:{/* ROR A */
519 nz = ((c >> 1) & 0x80) | (a >> 1);
520 c = a << 8;
521 a = nz;
522 goto loop;
523 }
524
525 case 0x1C: /* ASL A */
526 c = 0;
527 case 0x3C:{/* ROL A */
528 int temp = (c >> 8) & 1;
529 c = a << 1;
530 nz = c | temp;
531 a = (uint8_t) nz;
532 goto loop;
533 }
534
535 case 0x0B: /* ASL dp */
536 c = 0;
537 data += dp;
538 goto rol_mem;
539 case 0x1B: /* ASL dp+X */
540 c = 0;
541 case 0x3B: /* ROL dp+X */
542 data = (uint8_t) (data + x);
543 case 0x2B: /* ROL dp */
544 data += dp;
545 goto rol_mem;
546 case 0x0C: /* ASL abs */
547 c = 0;
548 case 0x2C: /* ROL abs */
549 data = READ_PC16( pc );
550 pc++;
551 rol_mem:
552 nz = (c >> 8) & 1;
553 nz |= (c = READ( data ) << 1);
554 WRITE( data, (uint8_t) nz );
555 goto inc_pc_loop;
556
557 case 0x4B: /* LSR dp */
558 c = 0;
559 data += dp;
560 goto ror_mem;
561 case 0x5B: /* LSR dp+X */
562 c = 0;
563 case 0x7B: /* ROR dp+X */
564 data = (uint8_t) (data + x);
565 case 0x6B: /* ROR dp */
566 data += dp;
567 goto ror_mem;
568 case 0x4C: /* LSR abs */
569 c = 0;
570 case 0x6C: /* ROR abs */
571 data = READ_PC16( pc );
572 pc++;
573 ror_mem: {
574 int temp = READ( data );
575 nz = ((c >> 1) & 0x80) | (temp >> 1);
576 c = temp << 8;
577 WRITE( data, nz );
578 goto inc_pc_loop;
579 }
580
581 case 0x9F: /* XCN */
582 nz = a = (a >> 4) | (uint8_t) (a << 4);
583 goto loop;
584
585/* 8. 16-BIT TRANSMISION COMMANDS */
586
587 case 0xBA: /* MOVW YA,dp */
588 a = READ_DP( data );
589 nz = (a & 0x7F) | (a >> 1);
590 y = READ_DP( (uint8_t) (data + 1) );
591 nz |= y;
592 goto inc_pc_loop;
593
594 case 0xDA: /* MOVW dp,YA */
595 WRITE_DP( data, a );
596 WRITE_DP( (uint8_t) (data + 1), y );
597 goto inc_pc_loop;
598
599/* 9. 16-BIT OPERATION COMMANDS */
600
601 case 0x3A: /* INCW dp */
602 case 0x1A:{/* DECW dp */
603 data += dp;
604
605 /* low byte */
606 int temp = READ( data );
607 temp += ((opcode >> 4) & 2) - 1; /* +1 for INCW, -1 for DECW */
608 nz = ((temp >> 1) | temp) & 0x7F;
609 WRITE( data, (uint8_t) temp );
610
611 /* high byte */
612 data = ((uint8_t) (data + 1)) + dp;
613 temp >>= 8;
614 temp = (uint8_t) (temp + READ( data ));
615 nz |= temp;
616 WRITE( data, temp );
617
618 goto inc_pc_loop;
619 }
620
621 case 0x9A: /* SUBW YA,dp */
622 case 0x7A: /* ADDW YA,dp */
623 {
624 /* read 16-bit addend */
625 int temp = READ_DP( data );
626 int sign = READ_DP( (uint8_t) (data + 1) );
627 temp += 0x100 * sign;
628 status &= ~(st_v | st_h);
629
630 /* to do: fix half-carry for SUBW (it's probably wrong) */
631
632 /* for SUBW, negate and truncate to 16 bits */
633 if ( opcode & 0x80 ) {
634 temp = (temp ^ 0xFFFF) + 1;
635 sign = temp >> 8;
636 }
637
638 /* add low byte (A) */
639 temp += a;
640 a = (uint8_t) temp;
641 nz = (temp | (temp >> 1)) & 0x7F;
642
643 /* add high byte (Y) */
644 temp >>= 8;
645 c = y + temp;
646 nz = (nz | c) & 0xFF;
647
648 /* half-carry (temporary avoids CodeWarrior optimizer bug) */
649 unsigned hc = (c & 15) - (y & 15);
650 status |= (hc >> 4) & st_h;
651
652 /* overflow if sign of YA changed when previous sign
653 and addend sign were same */
654 status |= (((c ^ y) & ~(y ^ sign)) >> 1) & st_v;
655
656 y = (uint8_t) c;
657
658 goto inc_pc_loop;
659 }
660
661 case 0x5A: { /* CMPW YA,dp */
662 int temp = a - READ_DP( data );
663 nz = ((temp >> 1) | temp) & 0x7F;
664 temp = y + (temp >> 8);
665 temp -= READ_DP( (uint8_t) (data + 1) );
666 nz |= temp;
667 c = ~temp;
668 nz &= 0xFF;
669 goto inc_pc_loop;
670 }
671
672/* 10. MULTIPLICATION & DIVISON COMMANDS */
673
674 case 0xCF: { /* MUL YA */
675 unsigned temp = y * a;
676 a = (uint8_t) temp;
677 nz = ((temp >> 1) | temp) & 0x7F;
678 y = temp >> 8;
679 nz |= y;
680 goto loop;
681 }
682
683 case 0x9E: /* DIV YA,X */
684 {
685 /* behavior based on SPC CPU tests */
686
687 status &= ~(st_h | st_v);
688
689 if ( (y & 15) >= (x & 15) )
690 status |= st_h;
691
692 if ( y >= x )
693 status |= st_v;
694
695 unsigned ya = y * 0x100 + a;
696 if ( y < x * 2 )
697 {
698 a = ya / x;
699 y = ya - a * x;
700 }
701 else
702 {
703 a = 255 - (ya - x * 0x200) / (256 - x);
704 y = x + (ya - x * 0x200) % (256 - x);
705 }
706
707 nz = (uint8_t) a;
708 a = (uint8_t) a;
709
710 goto loop;
711 }
712
713/* 11. DECIMAL COMPENSATION COMMANDS */
714
715 /* seem unused */
716 /* case 0xDF: */ /* DAA */
717 /* case 0xBE: */ /* DAS */
718
719/* 12. BRANCHING COMMANDS */
720
721 case 0x2F: /* BRA rel */
722 pc += (int8_t) data;
723 goto inc_pc_loop;
724
725 case 0x30: /* BMI */
726 BRANCH( IS_NEG )
727
728 case 0x10: /* BPL */
729 BRANCH( !IS_NEG )
730
731 case 0xB0: /* BCS */
732 BRANCH( c & 0x100 )
733
734 case 0x90: /* BCC */
735 BRANCH( !(c & 0x100) )
736
737 case 0x70: /* BVS */
738 BRANCH( status & st_v )
739
740 case 0x50: /* BVC */
741 BRANCH( !(status & st_v) )
742
743 case 0x03: /* BBS dp.bit,rel */
744 case 0x23:
745 case 0x43:
746 case 0x63:
747 case 0x83:
748 case 0xA3:
749 case 0xC3:
750 case 0xE3:
751 pc++;
752 if ( (READ_DP( data ) >> (opcode >> 5)) & 1 )
753 goto cbranch_taken_loop;
754 goto inc_pc_loop;
755
756 case 0x13: /* BBC dp.bit,rel */
757 case 0x33:
758 case 0x53:
759 case 0x73:
760 case 0x93:
761 case 0xB3:
762 case 0xD3:
763 case 0xF3:
764 pc++;
765 if ( !((READ_DP( data ) >> (opcode >> 5)) & 1) )
766 goto cbranch_taken_loop;
767 goto inc_pc_loop;
768
769 case 0xDE: /* CBNE dp+X,rel */
770 data = (uint8_t) (data + x);
771 /* fall through */
772 case 0x2E: /* CBNE dp,rel */
773 pc++;
774 if ( READ_DP( data ) != a )
775 goto cbranch_taken_loop;
776 goto inc_pc_loop;
777
778 case 0xFE: /* DBNZ Y,rel */
779 y = (uint8_t) (y - 1);
780 BRANCH( y )
781
782 case 0x6E: { /* DBNZ dp,rel */
783 pc++;
784 unsigned temp = READ_DP( data ) - 1;
785 WRITE_DP( (uint8_t) data, (uint8_t) temp );
786 if ( temp )
787 goto cbranch_taken_loop;
788 goto inc_pc_loop;
789 }
790
791 case 0x1F: /* JMP (abs+X) */
792 SET_PC( READ_PC16( pc ) + x );
793 /* fall through */
794 case 0x5F: /* JMP abs */
795 SET_PC( READ_PC16( pc ) );
796 goto loop;
797
798/* 13. SUB-ROUTINE CALL RETURN COMMANDS */
799
800 case 0x0F:{/* BRK */
801 check( 0 ); /* untested */
802 PUSH16( GET_PC() + 1 );
803 SET_PC( READ_PROG16( 0xFFDE ) ); /* vector address verified */
804 int temp;
805 CALC_STATUS( temp );
806 PUSH( temp );
807 status = (status | st_b) & ~st_i;
808 goto loop;
809 }
810
811 case 0x4F: /* PCALL offset */
812 PUSH16( GET_PC() + 1 );
813 SET_PC( 0xFF00 + data );
814 goto loop;
815
816 case 0x01: /* TCALL n */
817 case 0x11:
818 case 0x21:
819 case 0x31:
820 case 0x41:
821 case 0x51:
822 case 0x61:
823 case 0x71:
824 case 0x81:
825 case 0x91:
826 case 0xA1:
827 case 0xB1:
828 case 0xC1:
829 case 0xD1:
830 case 0xE1:
831 case 0xF1:
832 PUSH16( GET_PC() );
833 SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) );
834 goto loop;
835
836/* 14. STACK OPERATION COMMANDS */
837
838 {
839 int temp;
840 case 0x7F: /* RET1 */
841 temp = POP();
842 SET_PC( POP() );
843 pc += POP() << 8;
844 goto set_status;
845 case 0x8E: /* POP PSW */
846 temp = POP();
847 set_status:
848 SET_STATUS( temp );
849 goto loop;
850 }
851
852 case 0x0D: { /* PUSH PSW */
853 int temp;
854 CALC_STATUS( temp );
855 PUSH( temp );
856 goto loop;
857 }
858
859 case 0x2D: /* PUSH A */
860 PUSH( a );
861 goto loop;
862
863 case 0x4D: /* PUSH X */
864 PUSH( x );
865 goto loop;
866
867 case 0x6D: /* PUSH Y */
868 PUSH( y );
869 goto loop;
870
871 case 0xAE: /* POP A */
872 a = POP();
873 goto loop;
874
875 case 0xCE: /* POP X */
876 x = POP();
877 goto loop;
878
879 case 0xEE: /* POP Y */
880 y = POP();
881 goto loop;
882
883/* 15. BIT OPERATION COMMANDS */
884
885 case 0x02: /* SET1 */
886 case 0x22:
887 case 0x42:
888 case 0x62:
889 case 0x82:
890 case 0xA2:
891 case 0xC2:
892 case 0xE2:
893 case 0x12: /* CLR1 */
894 case 0x32:
895 case 0x52:
896 case 0x72:
897 case 0x92:
898 case 0xB2:
899 case 0xD2:
900 case 0xF2: {
901 data += dp;
902 int bit = 1 << (opcode >> 5);
903 int mask = ~bit;
904 if ( opcode & 0x10 )
905 bit = 0;
906 WRITE( data, (READ( data ) & mask) | bit );
907 goto inc_pc_loop;
908 }
909
910 case 0x0E: /* TSET1 abs */
911 case 0x4E:{/* TCLR1 abs */
912 data = READ_PC16( pc );
913 pc += 2;
914 unsigned temp = READ( data );
915 nz = temp & a;
916 temp &= ~a;
917 if ( !(opcode & 0x40) )
918 temp |= a;
919 WRITE( data, temp );
920 goto loop;
921 }
922
923 case 0x4A: /* AND1 C,mem.bit */
924 c &= MEM_BIT();
925 pc += 2;
926 goto loop;
927
928 case 0x6A: /* AND1 C,/mem.bit */
929 check( 0 ); /* untested */
930 c &= ~MEM_BIT();
931 pc += 2;
932 goto loop;
933
934 case 0x0A: /* OR1 C,mem.bit */
935 check( 0 ); /* untested */
936 c |= MEM_BIT();
937 pc += 2;
938 goto loop;
939
940 case 0x2A: /* OR1 C,/mem.bit */
941 check( 0 ); /* untested */
942 c |= ~MEM_BIT();
943 pc += 2;
944 goto loop;
945
946 case 0x8A: /* EOR1 C,mem.bit */
947 c ^= MEM_BIT();
948 pc += 2;
949 goto loop;
950
951 case 0xEA: { /* NOT1 mem.bit */
952 data = READ_PC16( pc );
953 pc += 2;
954 unsigned temp = READ( data & 0x1FFF );
955 temp ^= 1 << (data >> 13);
956 WRITE( data & 0x1FFF, temp );
957 goto loop;
958 }
959
960 case 0xCA: { /* MOV1 mem.bit,C */
961 data = READ_PC16( pc );
962 pc += 2;
963 unsigned temp = READ( data & 0x1FFF );
964 unsigned bit = data >> 13;
965 temp = (temp & ~(1 << bit)) | (((c >> 8) & 1) << bit);
966 WRITE( data & 0x1FFF, temp );
967 goto loop;
968 }
969
970 case 0xAA: /* MOV1 C,mem.bit */
971 c = MEM_BIT();
972 pc += 2;
973 goto loop;
974
975/* 16. PROGRAM STATUS FLAG OPERATION COMMANDS */
976
977 case 0x60: /* CLRC */
978 c = 0;
979 goto loop;
980
981 case 0x80: /* SETC */
982 c = ~0;
983 goto loop;
984
985 case 0xED: /* NOTC */
986 c ^= 0x100;
987 goto loop;
988
989 case 0xE0: /* CLRV */
990 status &= ~(st_v | st_h);
991 goto loop;
992
993 case 0x20: /* CLRP */
994 dp = 0;
995 goto loop;
996
997 case 0x40: /* SETP */
998 dp = 0x100;
999 goto loop;
1000
1001 case 0xA0: /* EI */
1002 check( 0 ); /* untested */
1003 status |= st_i;
1004 goto loop;
1005
1006 case 0xC0: /* DI */
1007 check( 0 ); /* untested */
1008 status &= ~st_i;
1009 goto loop;
1010
1011/* 17. OTHER COMMANDS */
1012
1013 case 0x00: /* NOP */
1014 goto loop;
1015
1016 /*case 0xEF:*/ /* SLEEP */
1017 /*case 0xFF:*/ /* STOP */
1018 case 0xFF:
1019 c |= 1; /* force switch table to have 256 entries,
1020 hopefully helping optimizer */
1021 } /* switch */
1022
1023 /* unhandled instructions fall out of switch so emulator can catch them */
1024
1025out_of_time:
1026 /* undo partial execution of opcode */
1027 spc_time_ -= this->cycle_table [*--pc];
1028 {
1029 int temp;
1030 CALC_STATUS( temp );
1031 this->r.status = (uint8_t) temp;
1032 }
1033
1034 this->r.pc = GET_PC();
1035 this->r.sp = (uint8_t) GET_SP();
1036 this->r.a = (uint8_t) a;
1037 this->r.x = (uint8_t) x;
1038 this->r.y = (uint8_t) y;
1039
1040#if 0
1041 EXIT_TIMER(cpu);
1042#endif
1043 return spc_time_;
1044}
1045
1046void CPU_Init( THIS )
1047{
1048 ci->memcpy( this->cycle_table, cycle_table, sizeof cycle_table );
1049}
1050
diff --git a/apps/codecs/spc/spc_dsp.c b/apps/codecs/spc/spc_dsp.c
deleted file mode 100644
index 153950ca75..0000000000
--- a/apps/codecs/spc/spc_dsp.c
+++ /dev/null
@@ -1,1276 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
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
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25/* The DSP portion (awe!) */
26#include "codec.h"
27#include "codecs.h"
28#include "spc_codec.h"
29#include "spc_profiler.h"
30
31#if defined(CPU_COLDFIRE) || defined (CPU_ARM)
32int32_t fir_buf[FIR_BUF_CNT]
33 __attribute__ ((aligned (FIR_BUF_ALIGN*1))) IBSS_ATTR;
34#endif
35#if SPC_BRRCACHE
36/* a little extra for samples that go past end */
37int16_t BRRcache [BRR_CACHE_SIZE] CACHEALIGN_ATTR;
38#endif
39
40void DSP_write( struct Spc_Dsp* this, int i, int data )
41{
42 assert( (unsigned) i < REGISTER_COUNT );
43
44 this->r.reg [i] = data;
45 int high = i >> 4;
46 int low = i & 0x0F;
47 if ( low < 2 ) /* voice volumes */
48 {
49 int left = *(int8_t const*) &this->r.reg [i & ~1];
50 int right = *(int8_t const*) &this->r.reg [i | 1];
51 struct voice_t* v = this->voice_state + high;
52 v->volume [0] = left;
53 v->volume [1] = right;
54 }
55 else if ( low == 0x0F ) /* fir coefficients */
56 {
57 this->fir_coeff [7 - high] = (int8_t) data; /* sign-extend */
58 }
59}
60
61/* if ( n < -32768 ) out = -32768; */
62/* if ( n > 32767 ) out = 32767; */
63#define CLAMP16( n ) \
64({ \
65 if ( (int16_t) n != n ) \
66 n = 0x7FFF ^ (n >> 31); \
67 n; \
68})
69
70#if SPC_BRRCACHE
71static void decode_brr( struct Spc_Dsp* this, unsigned start_addr,
72 struct voice_t* voice,
73 struct raw_voice_t const* const raw_voice ) ICODE_ATTR;
74static void decode_brr( struct Spc_Dsp* this, unsigned start_addr,
75 struct voice_t* voice,
76 struct raw_voice_t const* const raw_voice )
77{
78 /* setup same variables as where decode_brr() is called from */
79 #undef RAM
80 #define RAM ram.ram
81 struct src_dir const* const sd =
82 (struct src_dir*) &RAM [this->r.g.wave_page * 0x100];
83 struct cache_entry_t* const wave_entry =
84 &this->wave_entry [raw_voice->waveform];
85
86 /* the following block can be put in place of the call to
87 decode_brr() below
88 */
89 {
90 DEBUGF( "decode at %08x (wave #%d)\n",
91 start_addr, raw_voice->waveform );
92
93 /* see if in cache */
94 int i;
95 for ( i = 0; i < this->oldsize; i++ )
96 {
97 struct cache_entry_t* e = &this->wave_entry_old [i];
98 if ( e->start_addr == start_addr )
99 {
100 DEBUGF( "found in wave_entry_old (oldsize=%d)\n",
101 this->oldsize );
102 *wave_entry = *e;
103 goto wave_in_cache;
104 }
105 }
106
107 wave_entry->start_addr = start_addr;
108
109 uint8_t const* const loop_ptr =
110 RAM + GET_LE16A( sd [raw_voice->waveform].loop );
111 short* loop_start = 0;
112
113 short* out = BRRcache + start_addr * 2;
114 wave_entry->samples = out;
115 *out++ = 0;
116 int smp1 = 0;
117 int smp2 = 0;
118
119 uint8_t const* addr = RAM + start_addr;
120 int block_header;
121 do
122 {
123 if ( addr == loop_ptr )
124 {
125 loop_start = out;
126 DEBUGF( "loop at %08lx (wave #%d)\n",
127 (unsigned long)(addr - RAM), raw_voice->waveform );
128 }
129
130 /* header */
131 block_header = *addr;
132 addr += 9;
133 voice->addr = addr;
134 int const filter = (block_header & 0x0C) - 0x08;
135
136 /* scaling
137 (invalid scaling gives -4096 for neg nybble, 0 for pos) */
138 static unsigned char const right_shifts [16] = {
139 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29,
140 };
141 static unsigned char const left_shifts [16] = {
142 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
143 };
144 int const scale = block_header >> 4;
145 int const right_shift = right_shifts [scale];
146 int const left_shift = left_shifts [scale];
147
148 /* output position */
149 out += BRR_BLOCK_SIZE;
150 int offset = -BRR_BLOCK_SIZE << 2;
151
152 do /* decode and filter 16 samples */
153 {
154 /* Get nybble, sign-extend, then scale
155 get byte, select which nybble, sign-extend, then shift based
156 on scaling. also handles invalid scaling values. */
157 int delta = (int) (int8_t) (addr [offset >> 3] << (offset & 4))
158 >> right_shift << left_shift;
159
160 out [offset >> 2] = smp2;
161
162 if ( filter == 0 ) /* mode 0x08 (30-90% of the time) */
163 {
164 delta -= smp2 >> 1;
165 delta += smp2 >> 5;
166 smp2 = smp1;
167 delta += smp1;
168 delta += (-smp1 - (smp1 >> 1)) >> 5;
169 }
170 else
171 {
172 if ( filter == -4 ) /* mode 0x04 */
173 {
174 delta += smp1 >> 1;
175 delta += (-smp1) >> 5;
176 }
177 else if ( filter > -4 ) /* mode 0x0C */
178 {
179 delta -= smp2 >> 1;
180 delta += (smp2 + (smp2 >> 1)) >> 4;
181 delta += smp1;
182 delta += (-smp1 * 13) >> 7;
183 }
184 smp2 = smp1;
185 }
186
187 delta = CLAMP16( delta );
188 smp1 = (int16_t) (delta * 2); /* sign-extend */
189 }
190 while ( (offset += 4) != 0 );
191
192 /* if next block has end flag set, this block ends early */
193 /* (verified) */
194 if ( (block_header & 3) != 3 && (*addr & 3) == 1 )
195 {
196 /* skip last 9 samples */
197 out -= 9;
198 goto early_end;
199 }
200 }
201 while ( !(block_header & 1) && addr < RAM + 0x10000 );
202
203 out [0] = smp2;
204 out [1] = smp1;
205
206 early_end:
207 wave_entry->end = (out - 1 - wave_entry->samples) << 12;
208
209 wave_entry->loop = 0;
210 if ( (block_header & 2) )
211 {
212 if ( loop_start )
213 {
214 int loop = out - loop_start;
215 wave_entry->loop = loop;
216 wave_entry->end += 0x3000;
217 out [2] = loop_start [2];
218 out [3] = loop_start [3];
219 out [4] = loop_start [4];
220 }
221 else
222 {
223 DEBUGF( "loop point outside initial wave\n" );
224 }
225 }
226
227 DEBUGF( "end at %08lx (wave #%d)\n",
228 (unsigned long)(addr - RAM), raw_voice->waveform );
229
230 /* add to cache */
231 this->wave_entry_old [this->oldsize++] = *wave_entry;
232wave_in_cache:;
233 }
234}
235#endif
236
237static void key_on(struct Spc_Dsp* const this, struct voice_t* const voice,
238 struct src_dir const* const sd,
239 struct raw_voice_t const* const raw_voice,
240 const int key_on_delay, const int vbit) ICODE_ATTR;
241static void key_on(struct Spc_Dsp* const this, struct voice_t* const voice,
242 struct src_dir const* const sd,
243 struct raw_voice_t const* const raw_voice,
244 const int key_on_delay, const int vbit) {
245 #undef RAM
246 #define RAM ram.ram
247 int const env_rate_init = 0x7800;
248 voice->key_on_delay = key_on_delay;
249 if ( key_on_delay == 0 )
250 {
251 this->keys_down |= vbit;
252 voice->envx = 0;
253 voice->env_mode = state_attack;
254 voice->env_timer = env_rate_init; /* TODO: inaccurate? */
255 unsigned start_addr = GET_LE16A(sd [raw_voice->waveform].start);
256 #if !SPC_BRRCACHE
257 {
258 voice->addr = RAM + start_addr;
259 /* BRR filter uses previous samples */
260 voice->samples [BRR_BLOCK_SIZE + 1] = 0;
261 voice->samples [BRR_BLOCK_SIZE + 2] = 0;
262 /* decode three samples immediately */
263 voice->position = (BRR_BLOCK_SIZE + 3) * 0x1000 - 1;
264 voice->block_header = 0; /* "previous" BRR header */
265 }
266 #else
267 {
268 voice->position = 3 * 0x1000 - 1;
269 struct cache_entry_t* const wave_entry =
270 &this->wave_entry [raw_voice->waveform];
271
272 /* predecode BRR if not already */
273 if ( wave_entry->start_addr != start_addr )
274 {
275 /* the following line can be replaced by the indicated block
276 in decode_brr() */
277 decode_brr( this, start_addr, voice, raw_voice );
278 }
279
280 voice->samples = wave_entry->samples;
281 voice->wave_end = wave_entry->end;
282 voice->wave_loop = wave_entry->loop;
283 }
284 #endif
285 }
286}
287
288void DSP_run_( struct Spc_Dsp* this, long count, int32_t* out_buf )
289{
290 #undef RAM
291#ifdef CPU_ARM
292 uint8_t* const ram_ = ram.ram;
293 #define RAM ram_
294#else
295 #define RAM ram.ram
296#endif
297#if 0
298 EXIT_TIMER(cpu);
299 ENTER_TIMER(dsp);
300#endif
301
302 /* Here we check for keys on/off. Docs say that successive writes
303 to KON/KOF must be separated by at least 2 Ts periods or risk
304 being neglected. Therefore DSP only looks at these during an
305 update, and not at the time of the write. Only need to do this
306 once however, since the regs haven't changed over the whole
307 period we need to catch up with. */
308
309 {
310 int key_ons = this->r.g.key_ons;
311 int key_offs = this->r.g.key_offs;
312 /* keying on a voice resets that bit in ENDX */
313 this->r.g.wave_ended &= ~key_ons;
314 /* key_off bits prevent key_on from being acknowledged */
315 this->r.g.key_ons = key_ons & key_offs;
316
317 /* process key events outside loop, since they won't re-occur */
318 struct voice_t* voice = this->voice_state + 8;
319 int vbit = 0x80;
320 do
321 {
322 --voice;
323 if ( key_offs & vbit )
324 {
325 voice->env_mode = state_release;
326 voice->key_on_delay = 0;
327 }
328 else if ( key_ons & vbit )
329 {
330 voice->key_on_delay = 8;
331 }
332 }
333 while ( (vbit >>= 1) != 0 );
334 }
335
336 struct src_dir const* const sd =
337 (struct src_dir*) &RAM [this->r.g.wave_page * 0x100];
338
339 #ifdef ROCKBOX_BIG_ENDIAN
340 /* Convert endiannesses before entering loops - these
341 get used alot */
342 const uint32_t rates[VOICE_COUNT] =
343 {
344 GET_LE16A( this->r.voice[0].rate ) & 0x3FFF,
345 GET_LE16A( this->r.voice[1].rate ) & 0x3FFF,
346 GET_LE16A( this->r.voice[2].rate ) & 0x3FFF,
347 GET_LE16A( this->r.voice[3].rate ) & 0x3FFF,
348 GET_LE16A( this->r.voice[4].rate ) & 0x3FFF,
349 GET_LE16A( this->r.voice[5].rate ) & 0x3FFF,
350 GET_LE16A( this->r.voice[6].rate ) & 0x3FFF,
351 GET_LE16A( this->r.voice[7].rate ) & 0x3FFF,
352 };
353 #define VOICE_RATE(x) *(x)
354 #define IF_RBE(...) __VA_ARGS__
355 #ifdef CPU_COLDFIRE
356 /* Initialize mask register with the buffer address mask */
357 asm volatile ("move.l %[m], %%mask" : : [m]"i"(FIR_BUF_MASK));
358 const int echo_wrap = (this->r.g.echo_delay & 15) * 0x800;
359 const int echo_start = this->r.g.echo_page * 0x100;
360 #endif /* CPU_COLDFIRE */
361 #else
362 #define VOICE_RATE(x) (INT16A(raw_voice->rate) & 0x3FFF)
363 #define IF_RBE(...)
364 #endif /* ROCKBOX_BIG_ENDIAN */
365
366#if !SPC_NOINTERP
367 int const slow_gaussian = (this->r.g.pitch_mods >> 1) |
368 this->r.g.noise_enables;
369#endif
370 /* (g.flags & 0x40) ? 30 : 14 */
371 int const global_muting = ((this->r.g.flags & 0x40) >> 2) + 14 - 8;
372 int const global_vol_0 = this->r.g.volume_0;
373 int const global_vol_1 = this->r.g.volume_1;
374
375 /* each rate divides exactly into 0x7800 without remainder */
376 int const env_rate_init = 0x7800;
377 static unsigned short const env_rates [0x20] ICONST_ATTR =
378 {
379 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
380 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
381 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
382 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
383 };
384
385 do /* one pair of output samples per iteration */
386 {
387 /* Noise */
388 if ( this->r.g.noise_enables )
389 {
390 if ( (this->noise_count -=
391 env_rates [this->r.g.flags & 0x1F]) <= 0 )
392 {
393 this->noise_count = env_rate_init;
394 int feedback = (this->noise << 13) ^ (this->noise << 14);
395 this->noise = (feedback & 0x8000) ^ (this->noise >> 1 & ~1);
396 }
397 }
398
399#if !SPC_NOECHO
400 int echo_0 = 0;
401 int echo_1 = 0;
402#endif
403 long prev_outx = 0; /* TODO: correct value for first channel? */
404 int chans_0 = 0;
405 int chans_1 = 0;
406 /* TODO: put raw_voice pointer in voice_t? */
407 struct raw_voice_t * raw_voice = this->r.voice;
408 struct voice_t* voice = this->voice_state;
409 int vbit = 1;
410 IF_RBE( const uint32_t* vr = rates; )
411 for ( ; vbit < 0x100; vbit <<= 1, ++voice, ++raw_voice IF_RBE( , ++vr ) )
412 {
413 /* pregen involves checking keyon, etc */
414#if 0
415 ENTER_TIMER(dsp_pregen);
416#endif
417
418 /* Key on events are delayed */
419 int key_on_delay = voice->key_on_delay;
420
421 if ( --key_on_delay >= 0 ) /* <1% of the time */
422 {
423 key_on(this,voice,sd,raw_voice,key_on_delay,vbit);
424 }
425
426 if ( !(this->keys_down & vbit) ) /* Silent channel */
427 {
428 silent_chan:
429 raw_voice->envx = 0;
430 raw_voice->outx = 0;
431 prev_outx = 0;
432 continue;
433 }
434
435 /* Envelope */
436 {
437 int const ENV_RANGE = 0x800;
438 int env_mode = voice->env_mode;
439 int adsr0 = raw_voice->adsr [0];
440 int env_timer;
441 if ( env_mode != state_release ) /* 99% of the time */
442 {
443 env_timer = voice->env_timer;
444 if ( adsr0 & 0x80 ) /* 79% of the time */
445 {
446 int adsr1 = raw_voice->adsr [1];
447 if ( env_mode == state_sustain ) /* 74% of the time */
448 {
449 if ( (env_timer -= env_rates [adsr1 & 0x1F]) > 0 )
450 goto write_env_timer;
451
452 int envx = voice->envx;
453 envx--; /* envx *= 255 / 256 */
454 envx -= envx >> 8;
455 voice->envx = envx;
456 /* TODO: should this be 8? */
457 raw_voice->envx = envx >> 4;
458 goto init_env_timer;
459 }
460 else if ( env_mode < 0 ) /* 25% state_decay */
461 {
462 int envx = voice->envx;
463 if ( (env_timer -=
464 env_rates [(adsr0 >> 3 & 0x0E) + 0x10]) <= 0 )
465 {
466 envx--; /* envx *= 255 / 256 */
467 envx -= envx >> 8;
468 voice->envx = envx;
469 /* TODO: should this be 8? */
470 raw_voice->envx = envx >> 4;
471 env_timer = env_rate_init;
472 }
473
474 int sustain_level = adsr1 >> 5;
475 if ( envx <= (sustain_level + 1) * 0x100 )
476 voice->env_mode = state_sustain;
477
478 goto write_env_timer;
479 }
480 else /* state_attack */
481 {
482 int t = adsr0 & 0x0F;
483 if ( (env_timer -= env_rates [t * 2 + 1]) > 0 )
484 goto write_env_timer;
485
486 int envx = voice->envx;
487
488 int const step = ENV_RANGE / 64;
489 envx += step;
490 if ( t == 15 )
491 envx += ENV_RANGE / 2 - step;
492
493 if ( envx >= ENV_RANGE )
494 {
495 envx = ENV_RANGE - 1;
496 voice->env_mode = state_decay;
497 }
498 voice->envx = envx;
499 /* TODO: should this be 8? */
500 raw_voice->envx = envx >> 4;
501 goto init_env_timer;
502 }
503 }
504 else /* gain mode */
505 {
506 int t = raw_voice->gain;
507 if ( t < 0x80 )
508 {
509 raw_voice->envx = t;
510 voice->envx = t << 4;
511 goto env_end;
512 }
513 else
514 {
515 if ( (env_timer -= env_rates [t & 0x1F]) > 0 )
516 goto write_env_timer;
517
518 int envx = voice->envx;
519 int mode = t >> 5;
520 if ( mode <= 5 ) /* decay */
521 {
522 int step = ENV_RANGE / 64;
523 if ( mode == 5 ) /* exponential */
524 {
525 envx--; /* envx *= 255 / 256 */
526 step = envx >> 8;
527 }
528 if ( (envx -= step) < 0 )
529 {
530 envx = 0;
531 if ( voice->env_mode == state_attack )
532 voice->env_mode = state_decay;
533 }
534 }
535 else /* attack */
536 {
537 int const step = ENV_RANGE / 64;
538 envx += step;
539 if ( mode == 7 &&
540 envx >= ENV_RANGE * 3 / 4 + step )
541 envx += ENV_RANGE / 256 - step;
542
543 if ( envx >= ENV_RANGE )
544 envx = ENV_RANGE - 1;
545 }
546 voice->envx = envx;
547 /* TODO: should this be 8? */
548 raw_voice->envx = envx >> 4;
549 goto init_env_timer;
550 }
551 }
552 }
553 else /* state_release */
554 {
555 int envx = voice->envx;
556 if ( (envx -= ENV_RANGE / 256) > 0 )
557 {
558 voice->envx = envx;
559 raw_voice->envx = envx >> 8;
560 goto env_end;
561 }
562 else
563 {
564 /* bit was set, so this clears it */
565 this->keys_down ^= vbit;
566 voice->envx = 0;
567 goto silent_chan;
568 }
569 }
570 init_env_timer:
571 env_timer = env_rate_init;
572 write_env_timer:
573 voice->env_timer = env_timer;
574 env_end:;
575 }
576#if 0
577 EXIT_TIMER(dsp_pregen);
578
579 ENTER_TIMER(dsp_gen);
580#endif
581 #if !SPC_BRRCACHE
582 /* Decode BRR block */
583 if ( voice->position >= BRR_BLOCK_SIZE * 0x1000 )
584 {
585 voice->position -= BRR_BLOCK_SIZE * 0x1000;
586
587 uint8_t const* addr = voice->addr;
588 if ( addr >= RAM + 0x10000 )
589 addr -= 0x10000;
590
591 /* action based on previous block's header */
592 if ( voice->block_header & 1 )
593 {
594 addr = RAM + GET_LE16A( sd [raw_voice->waveform].loop );
595 this->r.g.wave_ended |= vbit;
596 if ( !(voice->block_header & 2) ) /* 1% of the time */
597 {
598 /* first block was end block;
599 don't play anything (verified) */
600 /* bit was set, so this clears it */
601 this->keys_down ^= vbit;
602
603 /* since voice->envx is 0,
604 samples and position don't matter */
605 raw_voice->envx = 0;
606 voice->envx = 0;
607 goto skip_decode;
608 }
609 }
610
611 /* header */
612 int const block_header = *addr;
613 addr += 9;
614 voice->addr = addr;
615 voice->block_header = block_header;
616 int const filter = (block_header & 0x0C) - 0x08;
617
618 /* scaling (invalid scaling gives -4096 for neg nybble,
619 0 for pos) */
620 static unsigned char const right_shifts [16] = {
621 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 29,
622 };
623 static unsigned char const left_shifts [16] = {
624 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
625 };
626 int const scale = block_header >> 4;
627 int const right_shift = right_shifts [scale];
628 int const left_shift = left_shifts [scale];
629
630 /* previous samples */
631 int smp2 = voice->samples [BRR_BLOCK_SIZE + 1];
632 int smp1 = voice->samples [BRR_BLOCK_SIZE + 2];
633 voice->samples [0] = voice->samples [BRR_BLOCK_SIZE];
634
635 /* output position */
636 short* out = voice->samples + (1 + BRR_BLOCK_SIZE);
637 int offset = -BRR_BLOCK_SIZE << 2;
638
639 /* if next block has end flag set,
640 this block ends early (verified) */
641 if ( (block_header & 3) != 3 && (*addr & 3) == 1 )
642 {
643 /* arrange for last 9 samples to be skipped */
644 int const skip = 9;
645 out += (skip & 1);
646 voice->samples [skip] = voice->samples [BRR_BLOCK_SIZE];
647 voice->position += skip * 0x1000;
648 offset = (-BRR_BLOCK_SIZE + (skip & ~1)) << 2;
649 addr -= skip / 2;
650 /* force sample to end on next decode */
651 voice->block_header = 1;
652 }
653
654 do /* decode and filter 16 samples */
655 {
656 /* Get nybble, sign-extend, then scale
657 get byte, select which nybble, sign-extend, then shift
658 based on scaling. also handles invalid scaling values.*/
659 int delta = (int) (int8_t) (addr [offset >> 3] <<
660 (offset & 4)) >> right_shift << left_shift;
661
662 out [offset >> 2] = smp2;
663
664 if ( filter == 0 ) /* mode 0x08 (30-90% of the time) */
665 {
666 delta -= smp2 >> 1;
667 delta += smp2 >> 5;
668 smp2 = smp1;
669 delta += smp1;
670 delta += (-smp1 - (smp1 >> 1)) >> 5;
671 }
672 else
673 {
674 if ( filter == -4 ) /* mode 0x04 */
675 {
676 delta += smp1 >> 1;
677 delta += (-smp1) >> 5;
678 }
679 else if ( filter > -4 ) /* mode 0x0C */
680 {
681 delta -= smp2 >> 1;
682 delta += (smp2 + (smp2 >> 1)) >> 4;
683 delta += smp1;
684 delta += (-smp1 * 13) >> 7;
685 }
686 smp2 = smp1;
687 }
688
689 delta = CLAMP16( delta );
690 smp1 = (int16_t) (delta * 2); /* sign-extend */
691 }
692 while ( (offset += 4) != 0 );
693
694 out [0] = smp2;
695 out [1] = smp1;
696
697 skip_decode:;
698 }
699 #endif
700
701 /* Get rate (with possible modulation) */
702 int rate = VOICE_RATE(vr);
703 if ( this->r.g.pitch_mods & vbit )
704 rate = (rate * (prev_outx + 32768)) >> 15;
705
706 #if !SPC_NOINTERP
707 /* Interleved gauss table (to improve cache coherency). */
708 /* gauss [i * 2 + j] = normal_gauss [(1 - j) * 256 + i] */
709 static short const gauss [512] =
710 {
711370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
712339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
713311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
714283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
715257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
716233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
717210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
718188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
719168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
720150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
721132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
722117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
723102,1102, 100,1098, 99,1094, 97,1090, 95,1086, 94,1082, 92,1078, 90,1074,
724 89,1070, 87,1066, 86,1061, 84,1057, 83,1053, 81,1049, 80,1045, 78,1040,
725 77,1036, 76,1032, 74,1027, 73,1023, 71,1019, 70,1014, 69,1010, 67,1005,
726 66,1001, 65, 997, 64, 992, 62, 988, 61, 983, 60, 978, 59, 974, 58, 969,
727 56, 965, 55, 960, 54, 955, 53, 951, 52, 946, 51, 941, 50, 937, 49, 932,
728 48, 927, 47, 923, 46, 918, 45, 913, 44, 908, 43, 904, 42, 899, 41, 894,
729 40, 889, 39, 884, 38, 880, 37, 875, 36, 870, 36, 865, 35, 860, 34, 855,
730 33, 851, 32, 846, 32, 841, 31, 836, 30, 831, 29, 826, 29, 821, 28, 816,
731 27, 811, 27, 806, 26, 802, 25, 797, 24, 792, 24, 787, 23, 782, 23, 777,
732 22, 772, 21, 767, 21, 762, 20, 757, 20, 752, 19, 747, 19, 742, 18, 737,
733 17, 732, 17, 728, 16, 723, 16, 718, 15, 713, 15, 708, 15, 703, 14, 698,
734 14, 693, 13, 688, 13, 683, 12, 678, 12, 674, 11, 669, 11, 664, 11, 659,
735 10, 654, 10, 649, 10, 644, 9, 640, 9, 635, 9, 630, 8, 625, 8, 620,
736 8, 615, 7, 611, 7, 606, 7, 601, 6, 596, 6, 592, 6, 587, 6, 582,
737 5, 577, 5, 573, 5, 568, 5, 563, 4, 559, 4, 554, 4, 550, 4, 545,
738 4, 540, 3, 536, 3, 531, 3, 527, 3, 522, 3, 517, 2, 513, 2, 508,
739 2, 504, 2, 499, 2, 495, 2, 491, 2, 486, 1, 482, 1, 477, 1, 473,
740 1, 469, 1, 464, 1, 460, 1, 456, 1, 451, 1, 447, 1, 443, 1, 439,
741 0, 434, 0, 430, 0, 426, 0, 422, 0, 418, 0, 414, 0, 410, 0, 405,
742 0, 401, 0, 397, 0, 393, 0, 389, 0, 385, 0, 381, 0, 378, 0, 374,
743 };
744 /* Gaussian interpolation using most recent 4 samples */
745 long position = voice->position;
746 voice->position += rate;
747 short const* interp = voice->samples + (position >> 12);
748 int offset = position >> 4 & 0xFF;
749
750 /* Only left half of gaussian kernel is in table, so we must mirror
751 for right half */
752 short const* fwd = gauss + offset * 2;
753 short const* rev = gauss + 510 - offset * 2;
754
755 /* Use faster gaussian interpolation when exact result isn't needed
756 by pitch modulator of next channel */
757 int amp_0, amp_1;
758 if ( !(slow_gaussian & vbit) ) /* 99% of the time */
759 {
760 /* Main optimization is lack of clamping. Not a problem since
761 output never goes more than +/- 16 outside 16-bit range and
762 things are clamped later anyway. Other optimization is to
763 preserve fractional accuracy, eliminating several masks. */
764 int output = (((fwd [0] * interp [0] +
765 fwd [1] * interp [1] +
766 rev [1] * interp [2] +
767 rev [0] * interp [3] ) >> 11) * voice->envx) >> 11;
768
769 /* duplicated here to give compiler more to run in parallel */
770 amp_0 = voice->volume [0] * output;
771 amp_1 = voice->volume [1] * output;
772 raw_voice->outx = output >> 8;
773 }
774 else
775 {
776 int output = *(int16_t*) &this->noise;
777 if ( !(this->r.g.noise_enables & vbit) )
778 {
779 output = (fwd [0] * interp [0]) & ~0xFFF;
780 output = (output + fwd [1] * interp [1]) & ~0xFFF;
781 output = (output + rev [1] * interp [2]) >> 12;
782 output = (int16_t) (output * 2);
783 output += ((rev [0] * interp [3]) >> 12) * 2;
784 output = CLAMP16( output );
785 }
786 output = (output * voice->envx) >> 11 & ~1;
787
788 /* duplicated here to give compiler more to run in parallel */
789 amp_0 = voice->volume [0] * output;
790 amp_1 = voice->volume [1] * output;
791 prev_outx = output;
792 raw_voice->outx = (int8_t) (output >> 8);
793 }
794 #else /* SPCNOINTERP */
795 /* two-point linear interpolation */
796 #ifdef CPU_COLDFIRE
797 int amp_0 = (int16_t)this->noise;
798 int amp_1;
799
800 if ( (this->r.g.noise_enables & vbit) == 0 )
801 {
802 uint32_t f = voice->position;
803 int32_t y0;
804
805 /**
806 * Formula (fastest found so far of MANY):
807 * output = y0 + f*y1 - f*y0
808 */
809 asm volatile (
810 /* separate fractional and whole parts */
811 "move.l %[f], %[y1] \r\n"
812 "and.l #0xfff, %[f] \r\n"
813 "lsr.l %[sh], %[y1] \r\n"
814 /* load samples y0 (upper) & y1 (lower) */
815 "move.l 2(%[s], %[y1].l*2), %[y1] \r\n"
816 /* %acc0 = f*y1 */
817 "mac.w %[f]l, %[y1]l, %%acc0 \r\n"
818 /* %acc0 -= f*y0 */
819 "msac.w %[f]l, %[y1]u, %%acc0 \r\n"
820 /* separate out y0 and sign extend */
821 "swap %[y1] \r\n"
822 "movea.w %[y1], %[y0] \r\n"
823 /* fetch result, scale down and add y0 */
824 "movclr.l %%acc0, %[y1] \r\n"
825 /* output = y0 + (result >> 12) */
826 "asr.l %[sh], %[y1] \r\n"
827 "add.l %[y0], %[y1] \r\n"
828 : [f]"+d"(f), [y0]"=&a"(y0), [y1]"=&d"(amp_0)
829 : [s]"a"(voice->samples), [sh]"d"(12)
830 );
831 }
832
833 /* apply voice envelope to output */
834 asm volatile (
835 "mac.w %[output]l, %[envx]l, %%acc0 \r\n"
836 :
837 : [output]"r"(amp_0), [envx]"r"(voice->envx)
838 );
839
840 /* advance voice position */
841 voice->position += rate;
842
843 /* fetch output, scale and apply left and right
844 voice volume */
845 asm volatile (
846 "movclr.l %%acc0, %[output] \r\n"
847 "asr.l %[sh], %[output] \r\n"
848 "mac.l %[vvol_0], %[output], %%acc0 \r\n"
849 "mac.l %[vvol_1], %[output], %%acc1 \r\n"
850 : [output]"=&d"(amp_0)
851 : [vvol_0]"r"((int)voice->volume[0]),
852 [vvol_1]"r"((int)voice->volume[1]),
853 [sh]"d"(11)
854 );
855
856 /* save this output into previous, scale and save in
857 output register */
858 prev_outx = amp_0;
859 raw_voice->outx = amp_0 >> 8;
860
861 /* fetch final voice output */
862 asm volatile (
863 "movclr.l %%acc0, %[amp_0] \r\n"
864 "movclr.l %%acc1, %[amp_1] \r\n"
865 : [amp_0]"=r"(amp_0), [amp_1]"=r"(amp_1)
866 );
867 #elif defined (CPU_ARM)
868 int amp_0, amp_1;
869
870 if ( (this->r.g.noise_enables & vbit) != 0 ) {
871 amp_0 = *(int16_t *)&this->noise;
872 } else {
873 uint32_t f = voice->position;
874 amp_0 = (uint32_t)voice->samples;
875
876 asm volatile(
877 "mov %[y1], %[f], lsr #12 \r\n"
878 "eor %[f], %[f], %[y1], lsl #12 \r\n"
879 "add %[y1], %[y0], %[y1], lsl #1 \r\n"
880 "ldrsh %[y0], [%[y1], #2] \r\n"
881 "ldrsh %[y1], [%[y1], #4] \r\n"
882 "sub %[y1], %[y1], %[y0] \r\n"
883 "mul %[f], %[y1], %[f] \r\n"
884 "add %[y0], %[y0], %[f], asr #12 \r\n"
885 : [f]"+r"(f), [y0]"+r"(amp_0), [y1]"=&r"(amp_1)
886 );
887 }
888
889 voice->position += rate;
890
891 asm volatile(
892 "mul %[amp_1], %[amp_0], %[envx] \r\n"
893 "mov %[amp_0], %[amp_1], asr #11 \r\n"
894 "mov %[amp_1], %[amp_0], asr #8 \r\n"
895 : [amp_0]"+r"(amp_0), [amp_1]"=&r"(amp_1)
896 : [envx]"r"(voice->envx)
897 );
898
899 prev_outx = amp_0;
900 raw_voice->outx = (int8_t)amp_1;
901
902 asm volatile(
903 "mul %[amp_1], %[amp_0], %[vol_1] \r\n"
904 "mul %[amp_0], %[vol_0], %[amp_0] \r\n"
905 : [amp_0]"+r"(amp_0), [amp_1]"+r"(amp_1)
906 : [vol_0]"r"((int)voice->volume[0]),
907 [vol_1]"r"((int)voice->volume[1])
908 );
909 #else /* Unoptimized CPU */
910 int output;
911
912 if ( (this->r.g.noise_enables & vbit) == 0 )
913 {
914 int const fraction = voice->position & 0xfff;
915 short const* const pos = (voice->samples + (voice->position >> 12)) + 1;
916 output = pos[0] + ((fraction * (pos[1] - pos[0])) >> 12);
917 } else {
918 output = *(int16_t *)&this->noise;
919 }
920
921 voice->position += rate;
922
923 output = (output * voice->envx) >> 11;
924
925 /* duplicated here to give compiler more to run in parallel */
926 int amp_0 = voice->volume [0] * output;
927 int amp_1 = voice->volume [1] * output;
928
929 prev_outx = output;
930 raw_voice->outx = (int8_t) (output >> 8);
931 #endif /* CPU_* */
932 #endif /* SPCNOINTERP */
933
934 #if SPC_BRRCACHE
935 if ( voice->position >= voice->wave_end )
936 {
937 long loop_len = voice->wave_loop << 12;
938 voice->position -= loop_len;
939 this->r.g.wave_ended |= vbit;
940 if ( !loop_len )
941 {
942 this->keys_down ^= vbit;
943 raw_voice->envx = 0;
944 voice->envx = 0;
945 }
946 }
947 #endif
948#if 0
949 EXIT_TIMER(dsp_gen);
950
951 ENTER_TIMER(dsp_mix);
952#endif
953 chans_0 += amp_0;
954 chans_1 += amp_1;
955 #if !SPC_NOECHO
956 if ( this->r.g.echo_ons & vbit )
957 {
958 echo_0 += amp_0;
959 echo_1 += amp_1;
960 }
961 #endif
962#if 0
963 EXIT_TIMER(dsp_mix);
964#endif
965 }
966 /* end of voice loop */
967
968 #if !SPC_NOECHO
969 #ifdef CPU_COLDFIRE
970 /* Read feedback from echo buffer */
971 int echo_pos = this->echo_pos;
972 uint8_t* const echo_ptr = RAM + ((echo_start + echo_pos) & 0xFFFF);
973 echo_pos += 4;
974 if ( echo_pos >= echo_wrap )
975 echo_pos = 0;
976 this->echo_pos = echo_pos;
977 int fb = swap_odd_even32(*(int32_t *)echo_ptr);
978 int out_0, out_1;
979
980 /* Keep last 8 samples */
981 *this->last_fir_ptr = fb;
982 this->last_fir_ptr = this->fir_ptr;
983
984 /* Apply echo FIR filter to output samples read from echo buffer -
985 circular buffer is hardware incremented and masked; FIR
986 coefficients and buffer history are loaded in parallel with
987 multiply accumulate operations. Shift left by one here and once
988 again when calculating feedback to have sample values justified
989 to bit 31 in the output to ease endian swap, interleaving and
990 clamping before placing result in the program's echo buffer. */
991 int _0, _1, _2;
992 asm volatile (
993 "move.l (%[fir_c]) , %[_2] \r\n"
994 "mac.w %[fb]u, %[_2]u, <<, (%[fir_p])+&, %[_0], %%acc0 \r\n"
995 "mac.w %[fb]l, %[_2]u, <<, (%[fir_p])& , %[_1], %%acc1 \r\n"
996 "mac.w %[_0]u, %[_2]l, << , %%acc0 \r\n"
997 "mac.w %[_0]l, %[_2]l, <<, 4(%[fir_c]) , %[_2], %%acc1 \r\n"
998 "mac.w %[_1]u, %[_2]u, <<, 4(%[fir_p])& , %[_0], %%acc0 \r\n"
999 "mac.w %[_1]l, %[_2]u, <<, 8(%[fir_p])& , %[_1], %%acc1 \r\n"
1000 "mac.w %[_0]u, %[_2]l, << , %%acc0 \r\n"
1001 "mac.w %[_0]l, %[_2]l, <<, 8(%[fir_c]) , %[_2], %%acc1 \r\n"
1002 "mac.w %[_1]u, %[_2]u, <<, 12(%[fir_p])& , %[_0], %%acc0 \r\n"
1003 "mac.w %[_1]l, %[_2]u, <<, 16(%[fir_p])& , %[_1], %%acc1 \r\n"
1004 "mac.w %[_0]u, %[_2]l, << , %%acc0 \r\n"
1005 "mac.w %[_0]l, %[_2]l, <<, 12(%[fir_c]) , %[_2], %%acc1 \r\n"
1006 "mac.w %[_1]u, %[_2]u, <<, 20(%[fir_p])& , %[_0], %%acc0 \r\n"
1007 "mac.w %[_1]l, %[_2]u, << , %%acc1 \r\n"
1008 "mac.w %[_0]u, %[_2]l, << , %%acc0 \r\n"
1009 "mac.w %[_0]l, %[_2]l, << , %%acc1 \r\n"
1010 : [_0]"=&r"(_0), [_1]"=&r"(_1), [_2]"=&r"(_2),
1011 [fir_p]"+a"(this->fir_ptr)
1012 : [fir_c]"a"(this->fir_coeff), [fb]"r"(fb)
1013 );
1014
1015 /* Generate output */
1016 asm volatile (
1017 /* fetch filter results _after_ gcc loads asm
1018 block parameters to eliminate emac stalls */
1019 "movclr.l %%acc0, %[out_0] \r\n"
1020 "movclr.l %%acc1, %[out_1] \r\n"
1021 /* apply global volume */
1022 "mac.l %[chans_0], %[gv_0] , %%acc2 \r\n"
1023 "mac.l %[chans_1], %[gv_1] , %%acc3 \r\n"
1024 /* apply echo volume and add to final output */
1025 "mac.l %[ev_0], %[out_0], >>, %%acc2 \r\n"
1026 "mac.l %[ev_1], %[out_1], >>, %%acc3 \r\n"
1027 : [out_0]"=&r"(out_0), [out_1]"=&r"(out_1)
1028 : [chans_0]"r"(chans_0), [gv_0]"r"(global_vol_0),
1029 [ev_0]"r"((int)this->r.g.echo_volume_0),
1030 [chans_1]"r"(chans_1), [gv_1]"r"(global_vol_1),
1031 [ev_1]"r"((int)this->r.g.echo_volume_1)
1032 );
1033
1034 /* Feedback into echo buffer */
1035 if ( !(this->r.g.flags & 0x20) )
1036 {
1037 asm volatile (
1038 /* scale echo voices; saturate if overflow */
1039 "mac.l %[sh], %[e1] , %%acc1 \r\n"
1040 "mac.l %[sh], %[e0] , %%acc0 \r\n"
1041 /* add scaled output from FIR filter */
1042 "mac.l %[out_1], %[ef], <<, %%acc1 \r\n"
1043 "mac.l %[out_0], %[ef], <<, %%acc0 \r\n"
1044 /* swap and fetch feedback results - simply
1045 swap_odd_even32 mixed in between macs and
1046 movclrs to mitigate stall issues */
1047 "move.l #0x00ff00ff, %[sh] \r\n"
1048 "movclr.l %%acc1, %[e1] \r\n"
1049 "swap %[e1] \r\n"
1050 "movclr.l %%acc0, %[e0] \r\n"
1051 "move.w %[e1], %[e0] \r\n"
1052 "and.l %[e0], %[sh] \r\n"
1053 "eor.l %[sh], %[e0] \r\n"
1054 "lsl.l #8, %[sh] \r\n"
1055 "lsr.l #8, %[e0] \r\n"
1056 "or.l %[sh], %[e0] \r\n"
1057 /* save final feedback into echo buffer */
1058 "move.l %[e0], (%[echo_ptr]) \r\n"
1059 : [e0]"+d"(echo_0), [e1]"+d"(echo_1)
1060 : [out_0]"r"(out_0), [out_1]"r"(out_1),
1061 [ef]"r"((int)this->r.g.echo_feedback),
1062 [echo_ptr]"a"((int32_t *)echo_ptr),
1063 [sh]"d"(1 << 9)
1064 );
1065 }
1066
1067 /* Output final samples */
1068 asm volatile (
1069 /* fetch output saved in %acc2 and %acc3 */
1070 "movclr.l %%acc2, %[out_0] \r\n"
1071 "movclr.l %%acc3, %[out_1] \r\n"
1072 /* scale right by global_muting shift */
1073 "asr.l %[gm], %[out_0] \r\n"
1074 "asr.l %[gm], %[out_1] \r\n"
1075 : [out_0]"=&d"(out_0), [out_1]"=&d"(out_1)
1076 : [gm]"d"(global_muting)
1077 );
1078
1079 out_buf [ 0] = out_0;
1080 out_buf [WAV_CHUNK_SIZE] = out_1;
1081 out_buf ++;
1082 #elif defined (CPU_ARM)
1083 /* Read feedback from echo buffer */
1084 int echo_pos = this->echo_pos;
1085 uint8_t* const echo_ptr = RAM +
1086 ((this->r.g.echo_page * 0x100 + echo_pos) & 0xFFFF);
1087 echo_pos += 4;
1088 if ( echo_pos >= (this->r.g.echo_delay & 15) * 0x800 )
1089 echo_pos = 0;
1090 this->echo_pos = echo_pos;
1091
1092 int fb_0 = GET_LE16SA( echo_ptr );
1093 int fb_1 = GET_LE16SA( echo_ptr + 2 );
1094
1095 /* Keep last 8 samples */
1096 int32_t *fir_ptr = this->fir_ptr;
1097
1098 /* Apply FIR */
1099 asm volatile (
1100 "str %[fb_0], [%[fir_p]], #4 \r\n"
1101 "str %[fb_1], [%[fir_p]], #4 \r\n"
1102 /* duplicate at +8 eliminates wrap checking below */
1103 "str %[fb_0], [%[fir_p], #56] \r\n"
1104 "str %[fb_1], [%[fir_p], #60] \r\n"
1105 : [fir_p]"+r"(fir_ptr)
1106 : [fb_0]"r"(fb_0), [fb_1]"r"(fb_1)
1107 );
1108
1109 this->fir_ptr = (int32_t *)((intptr_t)fir_ptr & FIR_BUF_MASK);
1110 int32_t *fir_coeff = this->fir_coeff;
1111
1112 asm volatile (
1113 "ldmia %[fir_c]!, { r0-r1 } \r\n"
1114 "ldmia %[fir_p]!, { r4-r5 } \r\n"
1115 "mul %[fb_0], r0, %[fb_0] \r\n"
1116 "mul %[fb_1], r0, %[fb_1] \r\n"
1117 "mla %[fb_0], r4, r1, %[fb_0] \r\n"
1118 "mla %[fb_1], r5, r1, %[fb_1] \r\n"
1119 "ldmia %[fir_c]!, { r0-r1 } \r\n"
1120 "ldmia %[fir_p]!, { r2-r5 } \r\n"
1121 "mla %[fb_0], r2, r0, %[fb_0] \r\n"
1122 "mla %[fb_1], r3, r0, %[fb_1] \r\n"
1123 "mla %[fb_0], r4, r1, %[fb_0] \r\n"
1124 "mla %[fb_1], r5, r1, %[fb_1] \r\n"
1125 "ldmia %[fir_c]!, { r0-r1 } \r\n"
1126 "ldmia %[fir_p]!, { r2-r5 } \r\n"
1127 "mla %[fb_0], r2, r0, %[fb_0] \r\n"
1128 "mla %[fb_1], r3, r0, %[fb_1] \r\n"
1129 "mla %[fb_0], r4, r1, %[fb_0] \r\n"
1130 "mla %[fb_1], r5, r1, %[fb_1] \r\n"
1131 "ldmia %[fir_c]!, { r0-r1 } \r\n"
1132 "ldmia %[fir_p]!, { r2-r5 } \r\n"
1133 "mla %[fb_0], r2, r0, %[fb_0] \r\n"
1134 "mla %[fb_1], r3, r0, %[fb_1] \r\n"
1135 "mla %[fb_0], r4, r1, %[fb_0] \r\n"
1136 "mla %[fb_1], r5, r1, %[fb_1] \r\n"
1137 : [fb_0]"+r"(fb_0), [fb_1]"+r"(fb_1),
1138 [fir_p]"+r"(fir_ptr), [fir_c]"+r"(fir_coeff)
1139 :
1140 : "r0", "r1", "r2", "r3", "r4", "r5"
1141 );
1142
1143 /* Generate output */
1144 int amp_0 = (chans_0 * global_vol_0 + fb_0 * this->r.g.echo_volume_0)
1145 >> global_muting;
1146 int amp_1 = (chans_1 * global_vol_1 + fb_1 * this->r.g.echo_volume_1)
1147 >> global_muting;
1148
1149 out_buf [ 0] = amp_0;
1150 out_buf [WAV_CHUNK_SIZE] = amp_1;
1151 out_buf ++;
1152
1153 if ( !(this->r.g.flags & 0x20) )
1154 {
1155 /* Feedback into echo buffer */
1156 int e0 = (echo_0 >> 7) + ((fb_0 * this->r.g.echo_feedback) >> 14);
1157 int e1 = (echo_1 >> 7) + ((fb_1 * this->r.g.echo_feedback) >> 14);
1158 e0 = CLAMP16( e0 );
1159 SET_LE16A( echo_ptr , e0 );
1160 e1 = CLAMP16( e1 );
1161 SET_LE16A( echo_ptr + 2, e1 );
1162 }
1163 #else /* Unoptimized CPU */
1164 /* Read feedback from echo buffer */
1165 int echo_pos = this->echo_pos;
1166 uint8_t* const echo_ptr = RAM +
1167 ((this->r.g.echo_page * 0x100 + echo_pos) & 0xFFFF);
1168 echo_pos += 4;
1169 if ( echo_pos >= (this->r.g.echo_delay & 15) * 0x800 )
1170 echo_pos = 0;
1171 this->echo_pos = echo_pos;
1172 int fb_0 = GET_LE16SA( echo_ptr );
1173 int fb_1 = GET_LE16SA( echo_ptr + 2 );
1174
1175 /* Keep last 8 samples */
1176 int (* const fir_ptr) [2] = this->fir_buf + this->fir_pos;
1177 this->fir_pos = (this->fir_pos + 1) & (FIR_BUF_HALF - 1);
1178 fir_ptr [ 0] [0] = fb_0;
1179 fir_ptr [ 0] [1] = fb_1;
1180 /* duplicate at +8 eliminates wrap checking below */
1181 fir_ptr [FIR_BUF_HALF] [0] = fb_0;
1182 fir_ptr [FIR_BUF_HALF] [1] = fb_1;
1183
1184 /* Apply FIR */
1185 fb_0 *= this->fir_coeff [0];
1186 fb_1 *= this->fir_coeff [0];
1187
1188 #define DO_PT( i )\
1189 fb_0 += fir_ptr [i] [0] * this->fir_coeff [i];\
1190 fb_1 += fir_ptr [i] [1] * this->fir_coeff [i];
1191
1192 DO_PT( 1 )
1193 DO_PT( 2 )
1194 DO_PT( 3 )
1195 DO_PT( 4 )
1196 DO_PT( 5 )
1197 DO_PT( 6 )
1198 DO_PT( 7 )
1199
1200 /* Generate output */
1201 int amp_0 = (chans_0 * global_vol_0 + fb_0 * this->r.g.echo_volume_0)
1202 >> global_muting;
1203 int amp_1 = (chans_1 * global_vol_1 + fb_1 * this->r.g.echo_volume_1)
1204 >> global_muting;
1205 out_buf [ 0] = amp_0;
1206 out_buf [WAV_CHUNK_SIZE] = amp_1;
1207 out_buf ++;
1208
1209 if ( !(this->r.g.flags & 0x20) )
1210 {
1211 /* Feedback into echo buffer */
1212 int e0 = (echo_0 >> 7) + ((fb_0 * this->r.g.echo_feedback) >> 14);
1213 int e1 = (echo_1 >> 7) + ((fb_1 * this->r.g.echo_feedback) >> 14);
1214 e0 = CLAMP16( e0 );
1215 SET_LE16A( echo_ptr , e0 );
1216 e1 = CLAMP16( e1 );
1217 SET_LE16A( echo_ptr + 2, e1 );
1218 }
1219 #endif /* CPU_* */
1220 #else /* SPCNOECHO == 1*/
1221 /* Generate output */
1222 int amp_0 = (chans_0 * global_vol_0) >> global_muting;
1223 int amp_1 = (chans_1 * global_vol_1) >> global_muting;
1224 out_buf [ 0] = amp_0;
1225 out_buf [WAV_CHUNK_SIZE] = amp_1;
1226 out_buf ++;
1227 #endif /* SPCNOECHO */
1228 }
1229 while ( --count );
1230#if 0
1231 EXIT_TIMER(dsp);
1232 ENTER_TIMER(cpu);
1233#endif
1234}
1235
1236void DSP_reset( struct Spc_Dsp* this )
1237{
1238 this->keys_down = 0;
1239 this->echo_pos = 0;
1240 this->noise_count = 0;
1241 this->noise = 2;
1242
1243 this->r.g.flags = 0xE0; /* reset, mute, echo off */
1244 this->r.g.key_ons = 0;
1245
1246 ci->memset( this->voice_state, 0, sizeof this->voice_state );
1247
1248 int i;
1249 for ( i = VOICE_COUNT; --i >= 0; )
1250 {
1251 struct voice_t* v = this->voice_state + i;
1252 v->env_mode = state_release;
1253 v->addr = ram.ram;
1254 }
1255
1256 #if SPC_BRRCACHE
1257 this->oldsize = 0;
1258 for ( i = 0; i < 256; i++ )
1259 this->wave_entry [i].start_addr = -1;
1260 #endif
1261
1262#if defined(CPU_COLDFIRE)
1263 this->fir_ptr = fir_buf;
1264 this->last_fir_ptr = &fir_buf [7];
1265 ci->memset( fir_buf, 0, sizeof fir_buf );
1266#elif defined (CPU_ARM)
1267 this->fir_ptr = fir_buf;
1268 ci->memset( fir_buf, 0, sizeof fir_buf );
1269#else
1270 this->fir_pos = 0;
1271 ci->memset( this->fir_buf, 0, sizeof this->fir_buf );
1272#endif
1273
1274 assert( offsetof (struct globals_t,unused9 [2]) == REGISTER_COUNT );
1275 assert( sizeof (this->r.voice) == REGISTER_COUNT );
1276}
diff --git a/apps/codecs/spc/spc_emu.c b/apps/codecs/spc/spc_emu.c
deleted file mode 100644
index e646e08ae6..0000000000
--- a/apps/codecs/spc/spc_emu.c
+++ /dev/null
@@ -1,384 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
11 * Copyright (C) 2004-2007 Shay Green (blargg)
12 * Copyright (C) 2002 Brad Martin
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "codec.h"
24#include "codecs.h"
25#include "spc_codec.h"
26#include "spc_profiler.h"
27
28/* lovingly ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
29/* DSP Based on Brad Martin's OpenSPC DSP emulator */
30/* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */
31
32struct cpu_ram_t ram CACHEALIGN_ATTR;
33
34/**************** Timers ****************/
35
36void Timer_run_( struct Timer* t, long time )
37{
38 /* when disabled, next_tick should always be in the future */
39 assert( t->enabled );
40
41 int elapsed = ((time - t->next_tick) >> t->shift) + 1;
42 t->next_tick += elapsed << t->shift;
43
44 elapsed += t->count;
45 if ( elapsed >= t->period ) /* avoid unnecessary division */
46 {
47 int n = elapsed / t->period;
48 elapsed -= n * t->period;
49 t->counter = (t->counter + n) & 15;
50 }
51 t->count = elapsed;
52}
53
54/**************** SPC emulator ****************/
55/* 1.024 MHz clock / 32000 samples per second */
56
57static void SPC_enable_rom( THIS, int enable )
58{
59 if ( this->rom_enabled != enable )
60 {
61 this->rom_enabled = enable;
62 ci->memcpy( RAM + ROM_ADDR, (enable ? this->boot_rom : this->extra_ram), ROM_SIZE );
63 /* TODO: ROM can still get overwritten when DSP writes to echo buffer */
64 }
65}
66
67void SPC_Init( THIS )
68{
69 this->timer [0].shift = 4 + 3; /* 8 kHz */
70 this->timer [1].shift = 4 + 3; /* 8 kHz */
71 this->timer [2].shift = 4; /* 8 kHz */
72
73 /* Put STOP instruction around memory to catch PC underflow/overflow. */
74 ci->memset( ram.padding1, 0xFF, sizeof ram.padding1 );
75 ci->memset( ram.padding2, 0xFF, sizeof ram.padding2 );
76
77 /* A few tracks read from the last four bytes of IPL ROM */
78 this->boot_rom [sizeof this->boot_rom - 2] = 0xC0;
79 this->boot_rom [sizeof this->boot_rom - 1] = 0xFF;
80 ci->memset( this->boot_rom, 0, sizeof this->boot_rom - 2 );
81
82 /* Have DSP in a defined state in case EMU is run and hasn't loaded
83 * a program yet */
84 DSP_reset(&this->dsp);
85}
86
87static void SPC_load_state( THIS, struct cpu_regs_t const* cpu_state,
88 const void* new_ram, const void* dsp_state )
89{
90 ci->memcpy(&(this->r),cpu_state,sizeof this->r);
91
92 /* ram */
93 ci->memcpy( RAM, new_ram, sizeof RAM );
94 ci->memcpy( this->extra_ram, RAM + ROM_ADDR, sizeof this->extra_ram );
95
96 /* boot rom (have to force enable_rom() to update it) */
97 this->rom_enabled = !(RAM [0xF1] & 0x80);
98 SPC_enable_rom( this, !this->rom_enabled );
99
100 /* dsp */
101 /* some SPCs rely on DSP immediately generating one sample */
102 this->extra_cycles = 32;
103 DSP_reset( &this->dsp );
104 int i;
105 for ( i = 0; i < REGISTER_COUNT; i++ )
106 DSP_write( &this->dsp, i, ((uint8_t const*) dsp_state) [i] );
107
108 /* timers */
109 for ( i = 0; i < TIMER_COUNT; i++ )
110 {
111 struct Timer* t = &this->timer [i];
112
113 t->next_tick = -EXTRA_CLOCKS;
114 t->enabled = (RAM [0xF1] >> i) & 1;
115 if ( !t->enabled )
116 t->next_tick = TIMER_DISABLED_TIME;
117 t->count = 0;
118 t->counter = RAM [0xFD + i] & 15;
119
120 int p = RAM [0xFA + i];
121 if ( !p )
122 p = 0x100;
123 t->period = p;
124 }
125
126 /* Handle registers which already give 0 when read by
127 setting RAM and not changing it.
128 Put STOP instruction in registers which can be read,
129 to catch attempted execution. */
130 RAM [0xF0] = 0;
131 RAM [0xF1] = 0;
132 RAM [0xF3] = 0xFF;
133 RAM [0xFA] = 0;
134 RAM [0xFB] = 0;
135 RAM [0xFC] = 0;
136 RAM [0xFD] = 0xFF;
137 RAM [0xFE] = 0xFF;
138 RAM [0xFF] = 0xFF;
139}
140
141static void clear_echo( THIS )
142{
143 if ( !(DSP_read( &this->dsp, 0x6C ) & 0x20) )
144 {
145 unsigned addr = 0x100 * DSP_read( &this->dsp, 0x6D );
146 size_t size = 0x800 * DSP_read( &this->dsp, 0x7D );
147 size_t max_size = sizeof RAM - addr;
148 if ( size > max_size )
149 size = sizeof RAM - addr;
150 ci->memset( RAM + addr, 0xFF, size );
151 }
152}
153
154int SPC_load_spc( THIS, const void* data, long size )
155{
156 struct spc_file_t const* spc = (struct spc_file_t const*) data;
157 struct cpu_regs_t regs;
158
159 if ( size < SPC_FILE_SIZE )
160 return -1;
161
162 if ( ci->memcmp( spc->signature, "SNES-SPC700 Sound File Data", 27 ) != 0 )
163 return -1;
164
165 regs.pc = spc->pc [1] * 0x100 + spc->pc [0];
166 regs.a = spc->a;
167 regs.x = spc->x;
168 regs.y = spc->y;
169 regs.status = spc->status;
170 regs.sp = spc->sp;
171
172 if ( (unsigned long) size >= sizeof *spc )
173 ci->memcpy( this->boot_rom, spc->ipl_rom, sizeof this->boot_rom );
174
175 SPC_load_state( this, &regs, spc->ram, spc->dsp );
176
177 clear_echo(this);
178
179 return 0;
180}
181
182/**************** DSP interaction ****************/
183void SPC_run_dsp_( THIS, long time )
184{
185 /* divide by CLOCKS_PER_SAMPLE */
186 int count = ((time - this->next_dsp) >> 5) + 1;
187 int32_t* buf = this->sample_buf;
188 this->sample_buf = buf + count;
189 this->next_dsp += count * CLOCKS_PER_SAMPLE;
190 DSP_run( &this->dsp, count, buf );
191}
192
193int SPC_read( THIS, unsigned addr, long const time )
194{
195 int result = RAM [addr];
196
197 if ( ((unsigned) (addr - 0xF0)) < 0x10 )
198 {
199 assert( 0xF0 <= addr && addr <= 0xFF );
200
201 /* counters */
202 int i = addr - 0xFD;
203 if ( i >= 0 )
204 {
205 struct Timer* t = &this->timer [i];
206 Timer_run( t, time );
207 result = t->counter;
208 t->counter = 0;
209 }
210 /* dsp */
211 else if ( addr == 0xF3 )
212 {
213 SPC_run_dsp( this, time );
214 result = DSP_read( &this->dsp, RAM [0xF2] & 0x7F );
215 }
216 }
217 return result;
218}
219
220void SPC_write( THIS, unsigned addr, int data, long const time )
221{
222 /* first page is very common */
223 if ( addr < 0xF0 )
224 {
225 RAM [addr] = (uint8_t) data;
226 }
227 else switch ( addr )
228 {
229 /* RAM */
230 default:
231 if ( addr < ROM_ADDR )
232 {
233 RAM [addr] = (uint8_t) data;
234 }
235 else
236 {
237 this->extra_ram [addr - ROM_ADDR] = (uint8_t) data;
238 if ( !this->rom_enabled )
239 RAM [addr] = (uint8_t) data;
240 }
241 break;
242
243 /* DSP */
244 /*case 0xF2:*/ /* mapped to RAM */
245 case 0xF3: {
246 SPC_run_dsp( this, time );
247 int reg = RAM [0xF2];
248 if ( reg < REGISTER_COUNT ) {
249 DSP_write( &this->dsp, reg, data );
250 }
251 else {
252 /*dprintf( "DSP write to $%02X\n", (int) reg ); */
253 }
254 break;
255 }
256
257 case 0xF0: /* Test register */
258 /*dprintf( "Wrote $%02X to $F0\n", (int) data ); */
259 break;
260
261 /* Config */
262 case 0xF1:
263 {
264 int i;
265 /* timers */
266 for ( i = 0; i < TIMER_COUNT; i++ )
267 {
268 struct Timer * t = this->timer+i;
269 if ( !(data & (1 << i)) )
270 {
271 t->enabled = 0;
272 t->next_tick = TIMER_DISABLED_TIME;
273 }
274 else if ( !t->enabled )
275 {
276 /* just enabled */
277 t->enabled = 1;
278 t->counter = 0;
279 t->count = 0;
280 t->next_tick = time;
281 }
282 }
283
284 /* port clears */
285 if ( data & 0x10 )
286 {
287 RAM [0xF4] = 0;
288 RAM [0xF5] = 0;
289 }
290 if ( data & 0x20 )
291 {
292 RAM [0xF6] = 0;
293 RAM [0xF7] = 0;
294 }
295
296 SPC_enable_rom( this, (data & 0x80) != 0 );
297 break;
298 }
299
300 /* Ports */
301 case 0xF4:
302 case 0xF5:
303 case 0xF6:
304 case 0xF7:
305 /* to do: handle output ports */
306 break;
307
308 /* verified on SNES that these are read/write (RAM) */
309 /*case 0xF8: */
310 /*case 0xF9: */
311
312 /* Timers */
313 case 0xFA:
314 case 0xFB:
315 case 0xFC: {
316 int i = addr - 0xFA;
317 struct Timer* t = &this->timer [i];
318 if ( (t->period & 0xFF) != data )
319 {
320 Timer_run( t, time );
321 this->timer[i].period = data ? data : 0x100;
322 }
323 break;
324 }
325
326 /* Counters (cleared on write) */
327 case 0xFD:
328 case 0xFE:
329 case 0xFF:
330 /*dprintf( "Wrote to counter $%02X\n", (int) addr ); */
331 this->timer [addr - 0xFD].counter = 0;
332 break;
333 }
334}
335
336/**************** Sample generation ****************/
337int SPC_play( THIS, long count, int32_t* out )
338{
339 int i;
340 assert( count % 2 == 0 ); /* output is always in pairs of samples */
341
342 long start_time = -(count >> 1) * CLOCKS_PER_SAMPLE - EXTRA_CLOCKS;
343
344 /* DSP output is made on-the-fly when DSP registers are read or written */
345 this->sample_buf = out;
346 this->next_dsp = start_time + CLOCKS_PER_SAMPLE;
347
348 /* Localize timer next_tick times and run them to the present to prevent
349 a running but ignored timer's next_tick from getting too far behind
350 and overflowing. */
351 for ( i = 0; i < TIMER_COUNT; i++ )
352 {
353 struct Timer* t = &this->timer [i];
354 if ( t->enabled )
355 {
356 t->next_tick += start_time + EXTRA_CLOCKS;
357 Timer_run( t, start_time );
358 }
359 }
360
361 /* Run from start_time to 0, pre-advancing by extra cycles from last run */
362 this->extra_cycles = CPU_run( this, start_time + this->extra_cycles ) +
363 EXTRA_CLOCKS;
364 if ( this->extra_cycles < 0 )
365 {
366 /*dprintf( "Unhandled instruction $%02X, pc = $%04X\n",
367 (int) CPU_read( r.pc ), (unsigned) r.pc ); */
368
369 return -1;
370 }
371
372 /* Catch DSP up to present */
373#if 0
374 ENTER_TIMER(cpu);
375#endif
376 SPC_run_dsp( this, -EXTRA_CLOCKS );
377#if 0
378 EXIT_TIMER(cpu);
379#endif
380 assert( this->next_dsp == CLOCKS_PER_SAMPLE - EXTRA_CLOCKS );
381 assert( this->sample_buf - out == count );
382
383 return 0;
384}
diff --git a/apps/codecs/spc/spc_profiler.c b/apps/codecs/spc/spc_profiler.c
deleted file mode 100644
index 5dc516258f..0000000000
--- a/apps/codecs/spc/spc_profiler.c
+++ /dev/null
@@ -1,66 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22/* lovingly ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
23/* DSP Based on Brad Martin's OpenSPC DSP emulator */
24/* tag reading from sexyspc by John Brawn (John_Brawn@yahoo.com) and others */
25
26#if defined(SPC_PROFILE) && defined(USEC_TIMER)
27
28#include "codec.h"
29#include "spc_codec.h"
30#define SPC_DEFINE_PROFILER_TIMERS
31#include "spc_profiler.h"
32
33void reset_profile_timers(void)
34{
35 RESET_TIMER(total);
36 RESET_TIMER(render);
37#if 0
38 RESET_TIMER(cpu);
39 RESET_TIMER(dsp);
40 RESET_TIMER(dsp_pregen);
41 RESET_TIMER(dsp_gen);
42 RESET_TIMER(dsp_mix);
43#endif
44}
45
46void print_timers(char * path)
47{
48 int logfd = ci->open("/spclog.txt",O_WRONLY|O_CREAT|O_APPEND);
49 ci->fdprintf(logfd,"%s:\t",path);
50 ci->fdprintf(logfd,"%10ld total\t",READ_TIMER(total));
51 PRINT_TIMER_PCT(render,total,"render");
52#if 0
53 PRINT_TIMER_PCT(cpu,total,"CPU");
54 PRINT_TIMER_PCT(dsp,total,"DSP");
55 ci->fdprintf(logfd,"(");
56 PRINT_TIMER_PCT(dsp_pregen,dsp,"pregen");
57 PRINT_TIMER_PCT(dsp_gen,dsp,"gen");
58 PRINT_TIMER_PCT(dsp_mix,dsp,"mix");
59#endif
60 ci->fdprintf(logfd,"\n");
61
62 ci->close(logfd);
63 logfd=-1;
64}
65
66#endif /* #if defined(SPC_PROFILE) && defined(USEC_TIMER) */
diff --git a/apps/codecs/spc/spc_profiler.h b/apps/codecs/spc/spc_profiler.h
deleted file mode 100644
index 405ee43ef9..0000000000
--- a/apps/codecs/spc/spc_profiler.h
+++ /dev/null
@@ -1,72 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22/* a fun simple elapsed time profiler */
23#ifndef _SPC_PROFILER_H_
24#define _SPC_PROFILER_H_
25
26#if defined(SPC_PROFILE) && defined(USEC_TIMER)
27
28#ifdef SPC_DEFINE_PROFILER_TIMERS
29#define CREATE_TIMER(name) uint32_t spc_timer_##name##_start,\
30 spc_timer_##name##_total
31#else
32#define CREATE_TIMER(name) extern uint32_t spc_timer_##name##_start,\
33 spc_timer_##name##_total
34#endif
35
36#define ENTER_TIMER(name) spc_timer_##name##_start=USEC_TIMER
37#define EXIT_TIMER(name) spc_timer_##name##_total+=\
38 (USEC_TIMER-spc_timer_##name##_start)
39#define READ_TIMER(name) (spc_timer_##name##_total)
40#define RESET_TIMER(name) spc_timer_##name##_total=0
41
42#define PRINT_TIMER_PCT(bname,tname,nstr) ci->fdprintf( \
43 logfd,"%10ld ",READ_TIMER(bname));\
44 ci->fdprintf(logfd,"(%3d%%) " nstr "\t",\
45 ((uint64_t)READ_TIMER(bname))*100/READ_TIMER(tname))
46
47CREATE_TIMER(total);
48CREATE_TIMER(render);
49#if 0
50CREATE_TIMER(cpu);
51CREATE_TIMER(dsp);
52CREATE_TIMER(dsp_pregen);
53CREATE_TIMER(dsp_gen);
54CREATE_TIMER(dsp_mix);
55#endif
56
57void reset_profile_timers(void);
58void print_timers(char * path);
59
60#else
61
62#define CREATE_TIMER(name)
63#define ENTER_TIMER(name)
64#define EXIT_TIMER(name)
65#define READ_TIMER(name)
66#define RESET_TIMER(name)
67#define print_timers(path)
68#define reset_profile_timers()
69
70#endif
71
72#endif /* _SPC_PROFILER_H_ */
diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c
index e13f53c5a5..74d582ebb3 100644
--- a/apps/codecs/vorbis.c
+++ b/apps/codecs/vorbis.c
@@ -20,8 +20,8 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "codeclib.h" 22#include "codeclib.h"
23#include "Tremor/ivorbisfile.h" 23#include "libtremor/ivorbisfile.h"
24#include "Tremor/ogg.h" 24#include "libtremor/ogg.h"
25 25
26CODEC_HEADER 26CODEC_HEADER
27 27
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
index c9405a49b9..19d062286c 100644
--- a/apps/plugins/Makefile
+++ b/apps/plugins/Makefile
@@ -18,7 +18,7 @@ ifdef APPEXTRA
18endif 18endif
19 19
20ifdef SOFTWARECODECS 20ifdef SOFTWARECODECS
21 CODECLIBS = -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack 21 CODECLIBS = -lmad -la52 -lffmpegFLAC -ltremor -lwavpack -lmusepack
22endif 22endif
23 23
24# Set up the bitmap libraries 24# Set up the bitmap libraries