diff options
Diffstat (limited to 'apps/codecs')
-rw-r--r-- | apps/codecs/Makefile | 45 | ||||
-rw-r--r-- | apps/codecs/asap.c | 2 | ||||
-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.c | 4 | ||||
-rw-r--r-- | apps/codecs/spc/Makefile | 44 | ||||
-rw-r--r-- | apps/codecs/spc/SOURCES | 4 | ||||
-rw-r--r-- | apps/codecs/spc/spc_codec.h | 454 | ||||
-rw-r--r-- | apps/codecs/spc/spc_cpu.c | 1050 | ||||
-rw-r--r-- | apps/codecs/spc/spc_dsp.c | 1276 | ||||
-rw-r--r-- | apps/codecs/spc/spc_emu.c | 384 | ||||
-rw-r--r-- | apps/codecs/spc/spc_profiler.c | 66 | ||||
-rw-r--r-- | apps/codecs/spc/spc_profiler.h | 72 | ||||
-rw-r--r-- | apps/codecs/vorbis.c | 4 |
62 files changed, 37 insertions, 3372 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 | |||
17 | endif | 17 | endif |
18 | 18 | ||
19 | ifdef SOFTWARECODECS | 19 | ifdef 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 |
22 | endif | 22 | endif |
23 | 23 | ||
24 | # we "borrow" the plugin LDS file | 24 | # we "borrow" the plugin LDS file |
@@ -41,7 +41,7 @@ DIRS = . | |||
41 | CODECLIB := $(BUILDDIR)/libcodec.a | 41 | CODECLIB := $(BUILDDIR)/libcodec.a |
42 | CODECDEPS = $(LINKCODEC) $(CODECLIB) | 42 | CODECDEPS = $(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 | ||
46 | all: $(LINKCODEC) $(ROCKS) | 46 | all: $(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 | ||
141 | libspc: | 141 | libspc: |
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 | ||
171 | libTremor: | 171 | libtremor: |
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 | ||
219 | libasap: | 219 | libasap: |
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 |
222 | clean: | 222 | clean: |
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 | ||
239 | ifneq ($(MAKECMDGOALS),clean) | 254 | ifneq ($(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 | ||
25 | CODEC_HEADER | 25 | CODEC_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 | |||
30 | SOURCES = $(SRC) | 30 | SOURCES = $(SRC) |
31 | OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o) | 31 | OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o) |
32 | OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2)) | 32 | OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2)) |
33 | DEPFILE = $(OBJDIR)/dep-Tremor | 33 | DEPFILE = $(OBJDIR)/dep-libtremor |
34 | DIRS = | 34 | DIRS = |
35 | 35 | ||
36 | all: $(OUTPUT) | 36 | all: $(OUTPUT) |
@@ -42,7 +42,7 @@ $(OUTPUT): $(OBJS) | |||
42 | include $(TOOLSDIR)/make.inc | 42 | include $(TOOLSDIR)/make.inc |
43 | 43 | ||
44 | clean: | 44 | clean: |
45 | $(call PRINTS,cleaning Tremor)rm -f $(OBJS) $(OUTPUT) $(DEPFILE) | 45 | $(call PRINTS,cleaning libtremor)rm -f $(OBJS) $(OUTPUT) $(DEPFILE) |
46 | 46 | ||
47 | ifneq ($(MAKECMDGOALS),clean) | 47 | ifneq ($(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 | ||
32 | CODEC_HEADER | 32 | CODEC_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 | |||
10 | INCLUDES=-I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \ | ||
11 | -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(BUILDDIR) | ||
12 | |||
13 | ifdef APPEXTRA | ||
14 | INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA))) | ||
15 | endif | ||
16 | |||
17 | SPCOPTS = -O -DROCKBOX | ||
18 | |||
19 | CFLAGS = $(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 | ||
23 | include $(TOOLSDIR)/makesrc.inc | ||
24 | |||
25 | SOURCES = $(SRC) | ||
26 | OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o) | ||
27 | OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2)) | ||
28 | DEPFILE = $(OBJDIR)/dep-spc | ||
29 | DIRS = | ||
30 | |||
31 | all: $(OUTPUT) | ||
32 | |||
33 | $(OUTPUT): $(OBJS) | ||
34 | $(call PRINTS,AR+RANLIB $(@F))$(AR) ruv $@ $+ >/dev/null 2>&1 | ||
35 | $(SILENT)$(RANLIB) $@ | ||
36 | |||
37 | include $(TOOLSDIR)/make.inc | ||
38 | |||
39 | clean: | ||
40 | $(call PRINTS,cleaning spc)rm -f $(OBJS) $(OUTPUT) $(DEPFILE) | ||
41 | |||
42 | ifneq ($(MAKECMDGOALS),clean) | ||
43 | -include $(DEPFILE) | ||
44 | endif | ||
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 @@ | |||
1 | spc_cpu.c | ||
2 | spc_dsp.c | ||
3 | spc_emu.c | ||
4 | spc_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 | |||
119 | static inline unsigned get_le16( void const* p ) | ||
120 | { | ||
121 | return ((unsigned char const*) p) [1] * 0x100u + | ||
122 | ((unsigned char const*) p) [0]; | ||
123 | } | ||
124 | |||
125 | static inline int get_le16s( void const* p ) | ||
126 | { | ||
127 | return ((signed char const*) p) [1] * 0x100 + | ||
128 | ((unsigned char const*) p) [0]; | ||
129 | } | ||
130 | |||
131 | static 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 | |||
152 | struct Spc_Emu; | ||
153 | #define THIS struct Spc_Emu* const this | ||
154 | |||
155 | /* The CPU portion (shock!) */ | ||
156 | |||
157 | struct 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 | |||
167 | struct 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 | ||
179 | extern struct cpu_ram_t ram; | ||
180 | |||
181 | long CPU_run( THIS, long start_time ) ICODE_ATTR; | ||
182 | void CPU_Init( THIS ); | ||
183 | |||
184 | /* The DSP portion (awe!) */ | ||
185 | enum { VOICE_COUNT = 8 }; | ||
186 | enum { REGISTER_COUNT = 128 }; | ||
187 | |||
188 | struct 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 | |||
200 | struct 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 | |||
229 | enum 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 | |||
237 | struct 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 | |||
245 | enum { BRR_BLOCK_SIZE = 16 }; | ||
246 | enum { BRR_CACHE_SIZE = 0x20000 + 32} ; | ||
247 | |||
248 | struct 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 */ | ||
269 | extern int16_t BRRcache [BRR_CACHE_SIZE]; | ||
270 | #endif | ||
271 | |||
272 | enum { 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 | */ | ||
278 | enum | ||
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) | ||
286 | enum | ||
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 | |||
295 | struct 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 | |||
340 | struct src_dir | ||
341 | { | ||
342 | char start [2]; | ||
343 | char loop [2]; | ||
344 | }; | ||
345 | |||
346 | void DSP_run_( struct Spc_Dsp* this, long count, int32_t* out_buf ) ICODE_ATTR; | ||
347 | void DSP_reset( struct Spc_Dsp* this ); | ||
348 | |||
349 | static 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 */ | ||
361 | enum { CLOCKS_PER_SAMPLE = 32 }; | ||
362 | |||
363 | enum { EXTRA_CLOCKS = CLOCKS_PER_SAMPLE / 2 }; | ||
364 | |||
365 | /* using this disables timer (since this will always be in the future) */ | ||
366 | enum { TIMER_DISABLED_TIME = 127 }; | ||
367 | |||
368 | enum { ROM_SIZE = 64 }; | ||
369 | enum { ROM_ADDR = 0xFFC0 }; | ||
370 | |||
371 | enum { TIMER_COUNT = 3 }; | ||
372 | |||
373 | struct Timer | ||
374 | { | ||
375 | long next_tick; | ||
376 | int period; | ||
377 | int count; | ||
378 | int shift; | ||
379 | int enabled; | ||
380 | int counter; | ||
381 | }; | ||
382 | |||
383 | void Timer_run_( struct Timer* t, long time ) ICODE_ATTR; | ||
384 | |||
385 | static inline void Timer_run( struct Timer* t, long time ) | ||
386 | { | ||
387 | if ( time >= t->next_tick ) | ||
388 | Timer_run_( t, time ); | ||
389 | } | ||
390 | |||
391 | struct 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 | |||
409 | enum { SPC_FILE_SIZE = 0x10180 }; | ||
410 | |||
411 | struct 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 | |||
427 | void SPC_Init( THIS ); | ||
428 | |||
429 | int SPC_load_spc( THIS, const void* data, long size ); | ||
430 | |||
431 | /**************** DSP interaction ****************/ | ||
432 | void DSP_write( struct Spc_Dsp* this, int i, int data ) ICODE_ATTR; | ||
433 | |||
434 | static 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 | |||
440 | void SPC_run_dsp_( THIS, long time ) ICODE_ATTR; | ||
441 | |||
442 | static inline void SPC_run_dsp( THIS, long time ) | ||
443 | { | ||
444 | if ( time >= this->next_dsp ) | ||
445 | SPC_run_dsp_( this, time ); | ||
446 | } | ||
447 | |||
448 | int SPC_read( THIS, unsigned addr, long const time ) ICODE_ATTR; | ||
449 | void SPC_write( THIS, unsigned addr, int data, long const time ) ICODE_ATTR; | ||
450 | |||
451 | /**************** Sample generation ****************/ | ||
452 | int 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 | |||
47 | static 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 | |||
68 | static unsigned CPU_mem_bit( THIS, uint8_t const* pc, long const spc_time_ ) | ||
69 | ICODE_ATTR; | ||
70 | |||
71 | static 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 */ | ||
79 | enum { st_n = 0x80 }; | ||
80 | enum { st_v = 0x40 }; | ||
81 | enum { st_p = 0x20 }; | ||
82 | enum { st_b = 0x10 }; | ||
83 | enum { st_h = 0x08 }; | ||
84 | enum { st_i = 0x04 }; | ||
85 | enum { st_z = 0x02 }; | ||
86 | enum { 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 | |||
115 | long 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 */ | ||
151 | cbranch_taken_loop: | ||
152 | pc += *(int8_t const*) pc; | ||
153 | spc_time_ += 2; | ||
154 | inc_pc_loop: | ||
155 | pc++; | ||
156 | loop: | ||
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 | |||
1025 | out_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 | |||
1046 | void 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) | ||
32 | int32_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 */ | ||
37 | int16_t BRRcache [BRR_CACHE_SIZE] CACHEALIGN_ATTR; | ||
38 | #endif | ||
39 | |||
40 | void 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 | ||
71 | static 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; | ||
74 | static 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; | ||
232 | wave_in_cache:; | ||
233 | } | ||
234 | } | ||
235 | #endif | ||
236 | |||
237 | static 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; | ||
241 | static 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 | |||
288 | void 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 | { | ||
711 | 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303, | ||
712 | 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299, | ||
713 | 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292, | ||
714 | 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282, | ||
715 | 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269, | ||
716 | 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253, | ||
717 | 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234, | ||
718 | 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213, | ||
719 | 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190, | ||
720 | 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164, | ||
721 | 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136, | ||
722 | 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106, | ||
723 | 102,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 | |||
1236 | void 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 | |||
32 | struct cpu_ram_t ram CACHEALIGN_ATTR; | ||
33 | |||
34 | /**************** Timers ****************/ | ||
35 | |||
36 | void 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 | |||
57 | static 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 | |||
67 | void 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 | |||
87 | static 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 | |||
141 | static 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 | |||
154 | int 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, ®s, spc->ram, spc->dsp ); | ||
176 | |||
177 | clear_echo(this); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | /**************** DSP interaction ****************/ | ||
183 | void 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 | |||
193 | int 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 | |||
220 | void 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 ****************/ | ||
337 | int 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 | |||
33 | void 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 | |||
46 | void 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 | |||
47 | CREATE_TIMER(total); | ||
48 | CREATE_TIMER(render); | ||
49 | #if 0 | ||
50 | CREATE_TIMER(cpu); | ||
51 | CREATE_TIMER(dsp); | ||
52 | CREATE_TIMER(dsp_pregen); | ||
53 | CREATE_TIMER(dsp_gen); | ||
54 | CREATE_TIMER(dsp_mix); | ||
55 | #endif | ||
56 | |||
57 | void reset_profile_timers(void); | ||
58 | void 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 | ||
26 | CODEC_HEADER | 26 | CODEC_HEADER |
27 | 27 | ||