From 25bb37bb6851c85e21fb0cecfd9617eebe6c7a56 Mon Sep 17 00:00:00 2001 From: Dominik Wenger Date: Sat, 26 Jul 2008 15:16:10 +0000 Subject: commit asap codec. plays .sap files. At the moment it only plays the default song. So subSongs are ignored. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18121 a1c6a512-1295-4272-9138-f99709370657 --- apps/SOURCES | 1 + apps/codecs.c | 2 +- apps/codecs.h | 1 + apps/codecs/Makefile | 12 +- apps/codecs/SOURCES | 1 + apps/codecs/asap.c | 131 ++++++++++++++++++++ apps/codecs/asap/README.rockbox | 25 ++++ apps/codecs/asap/SOURCES | 3 + apps/codecs/asap/apokeysnd.c | 3 +- apps/codecs/asap/asap.c | 14 ++- apps/codecs/asap/asap.h | 2 +- apps/filetypes.c | 1 + apps/metadata.c | 12 +- apps/metadata/asap.c | 256 +++++++++++++++++++++++++++++++++++++++ apps/metadata/metadata_parsers.h | 1 + apps/plugins/test_codec.c | 2 +- firmware/export/id3.h | 1 + firmware/id3.c | 3 + 18 files changed, 461 insertions(+), 10 deletions(-) create mode 100644 apps/codecs/asap.c create mode 100644 apps/codecs/asap/README.rockbox create mode 100644 apps/codecs/asap/SOURCES create mode 100644 apps/metadata/asap.c diff --git a/apps/SOURCES b/apps/SOURCES index e70e32b73d..74535bfb0c 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -141,6 +141,7 @@ metadata/vorbis.c metadata/wave.c metadata/wavpack.c metadata/a52.c +metadata/asap.c #endif #ifdef HAVE_TAGCACHE tagcache.c diff --git a/apps/codecs.c b/apps/codecs.c index aa3f81d2e6..c31fd843b3 100644 --- a/apps/codecs.c +++ b/apps/codecs.c @@ -124,7 +124,7 @@ struct codec_api ci = { memmove, memcmp, memchr, - + strcasestr, #if defined(DEBUG) || defined(SIMULATOR) debugf, #endif diff --git a/apps/codecs.h b/apps/codecs.h index b0cf187097..bfa0de72d9 100644 --- a/apps/codecs.h +++ b/apps/codecs.h @@ -196,6 +196,7 @@ struct codec_api { void* (*memmove)(void *out, const void *in, size_t n); int (*memcmp)(const void *s1, const void *s2, size_t n); void *(*memchr)(const void *s1, int c, size_t n); + char *(*strcasestr) (const char* phaystack, const char* pneedle); #if defined(DEBUG) || defined(SIMULATOR) void (*debugf)(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2); diff --git a/apps/codecs/Makefile b/apps/codecs/Makefile index 7c066d284d..9dd88e5e7d 100644 --- a/apps/codecs/Makefile +++ b/apps/codecs/Makefile @@ -17,8 +17,8 @@ ifdef APPEXTRA endif ifdef SOFTWARECODECS - CODECLIBS = -lspc -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex -ldemac -lwma - OUTPUT = libspc libmad liba52 libffmpegFLAC libwma libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac + CODECLIBS = -lspc -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex -ldemac -lwma -lasap + OUTPUT = libspc libmad liba52 libffmpegFLAC libwma libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac libasap endif # we "borrow" the plugin LDS file @@ -40,7 +40,7 @@ DIRS = . CODECDEPS = $(LINKCODEC) $(BUILDDIR)/libcodec.a -.PHONY: libspc libmad liba52 libffmpegFLAC libTremor libspeex libwavpack libmusepack libalac libfaad libm4a libdemac libwma +.PHONY: libspc libmad liba52 libffmpegFLAC libTremor libspeex libwavpack libmusepack libalac libfaad libm4a libdemac libwma libasap all: $(LINKCODEC) $(ROCKS) @@ -70,6 +70,7 @@ $(OBJDIR)/aiff_enc.elf: $(OBJDIR)/aiff_enc.o $(OBJDIR)/codec_crt0.o $(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o $(OBJDIR)/codec_crt0.o $(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o $(OBJDIR)/codec_crt0.o $(OBJDIR)/wavpack_enc.elf: $(OBJDIR)/wavpack_enc.o $(BUILDDIR)/libwavpack.a $(OBJDIR)/codec_crt0.o +$(OBJDIR)/asap.elf : $(OBJDIR)/asap.o $(BUILDDIR)/libasap.a $(OBJDIR)/codec_crt0.o $(OBJDIR)/%.elf: $(OBJDIR)/codec_crt0.o $(call PRINTS,LD $(@F))$(CC) $(CFLAGS) -o $@ $^ -L$(BUILDDIR) -lcodec -lgcc \ @@ -218,6 +219,11 @@ libdemac: $(SILENT)mkdir -p $(OBJDIR)/libdemac $(call PRINTS,MAKE in libdemac)$(MAKE) -C demac/libdemac OBJDIR=$(OBJDIR)/libdemac OUTPUT=$(BUILDDIR)/libdemac.a +$(BUILDDIR)/libasap.a: libasap + +libasap: + $(SILENT)mkdir -p $(OBJDIR)/asap + $(call PRINTS,MAKE in asap)$(MAKE) -C asap OBJDIR=$(OBJDIR)/asap OUTPUT=$(BUILDDIR)/libasap.a clean: $(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 $(SILENT)$(MAKE) -C spc clean OBJDIR=$(OBJDIR)/spc diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES index 3c0118c1ce..25ca5490d4 100644 --- a/apps/codecs/SOURCES +++ b/apps/codecs/SOURCES @@ -21,6 +21,7 @@ sid.c adx.c nsf.c spc.c +asap.c #if defined(HAVE_RECORDING) && !defined(SIMULATOR) /* encoders */ aiff_enc.c diff --git a/apps/codecs/asap.c b/apps/codecs/asap.c new file mode 100644 index 0000000000..f6fa68f4f4 --- /dev/null +++ b/apps/codecs/asap.c @@ -0,0 +1,131 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: asap.c 17847 2008-06-28 18:10:04Z domonoky $ + * + * Copyright (C) 2008 Dominik Wenger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "codeclib.h" +#include "asap/asap.h" + +CODEC_HEADER + +#define CHUNK_SIZE (1024*8) + +static byte samples[CHUNK_SIZE]; /* The sample buffer */ +static ASAP_State asap; /* asap codec state */ + +/* this is the codec entry point */ +enum codec_status codec_main(void) +{ + int n_bytes; + int song; + int duration; + char* module; + + /* Generic codec initialisation */ + ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); + +next_track: + if (codec_init()) { + DEBUGF("codec init failed\n"); + return CODEC_ERROR; + } + + while (!*ci->taginfo_ready && !ci->stop_codec) + ci->sleep(1); + + codec_set_replaygain(ci->id3); + + int bytes_done =0; + int filesize; + ci->seek_buffer(0); + module = ci->request_buffer(&filesize, ci->filesize); + if (!module || (size_t)filesize < (size_t)ci->filesize) + { + DEBUGF("loading error\n"); + return CODEC_ERROR; + } + + /*Init ASAP */ + if (!ASAP_Load(&asap, ci->id3->path, module, filesize)) + { + DEBUGF("%s: format not supported",ci->id3->path); + return CODEC_ERROR; + } + + /* Make use of 44.1khz */ + ci->configure(DSP_SET_FREQUENCY, 44100); + /* Sample depth is 16 bit little endian */ + ci->configure(DSP_SET_SAMPLE_DEPTH, 16); + /* Stereo or Mono output ? */ + if(asap.module_info.channels ==1) + ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); + else + ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); + + /* reset eleapsed */ + ci->set_elapsed(0); + + song = asap.module_info.default_song; + duration = asap.module_info.durations[song]; + if (duration < 0) + duration = 180 * 1000; + + ASAP_PlaySong(&asap, song, duration); + ASAP_MutePokeyChannels(&asap, 0); + + /* The main decoder loop */ + while (1) { + ci->yield(); + if (ci->stop_codec || ci->new_track) + break; + + if (ci->seek_time) { + /* New time is ready in ci->seek_time */ + + /* seek to pos */ + ASAP_Seek(&asap,ci->seek_time); + /* update elapsed */ + ci->set_elapsed(ci->seek_time); + /* update bytes_done */ + bytes_done = ci->seek_time*44.1*2; + /* seek ready */ + ci->seek_complete(); + } + + /* Generate a buffer full of Audio */ + #ifdef ROCKBOX_LITTLE_ENDIAN + n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_LE); + #else + n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_BE); + #endif + + ci->pcmbuf_insert(samples, NULL, n_bytes /2); + + bytes_done += n_bytes; + ci->set_elapsed((bytes_done / 2) / 44.1); + + if(n_bytes != sizeof(samples)) + break; + } + + if (ci->request_next_track()) + goto next_track; + + return CODEC_OK; +} diff --git a/apps/codecs/asap/README.rockbox b/apps/codecs/asap/README.rockbox new file mode 100644 index 0000000000..322c130358 --- /dev/null +++ b/apps/codecs/asap/README.rockbox @@ -0,0 +1,25 @@ +Library: asap-1.2.0 +Imported: 2008-26-07 by Dominik Wenger + +This directory contains a local version of asap (http://asap.sourceforge.net/) for decoding Atari 8bit .sap +audio streams. + +LICENSING INFORMATION + +Asap is available under the terms of the GPL v2 or later +license, which is both an open source and free software license. +The Licence is the same as the rest of Rockbox. + + +IMPORT DETAILS + +The .[ch] files in apps/codec/asap are copied from ASAP. +Some #defines were added, so it uses the ci-> Pointer. + +A small modification was needed in asap.h Line 120. +(changed the delta buffer to signed char) + +Also players.h (contains binarys of players) was generated and copied +into Rockbox. + + diff --git a/apps/codecs/asap/SOURCES b/apps/codecs/asap/SOURCES new file mode 100644 index 0000000000..0d1f1f46fa --- /dev/null +++ b/apps/codecs/asap/SOURCES @@ -0,0 +1,3 @@ +acpu.c +asap.c +apokeysnd.c diff --git a/apps/codecs/asap/apokeysnd.c b/apps/codecs/asap/apokeysnd.c index d0a4b1bd91..1d48bc20d2 100644 --- a/apps/codecs/asap/apokeysnd.c +++ b/apps/codecs/asap/apokeysnd.c @@ -20,13 +20,14 @@ * along with ASAP; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - +#include "codeclib.h" #if !defined(JAVA) && !defined(CSHARP) #include #endif #include "asap_internal.h" +#define memset ci->memset #define ULTRASOUND_CYCLES 112 #define MUTE_FREQUENCY 1 diff --git a/apps/codecs/asap/asap.c b/apps/codecs/asap/asap.c index 084708af4c..31de730d93 100644 --- a/apps/codecs/asap/asap.c +++ b/apps/codecs/asap/asap.c @@ -20,7 +20,7 @@ * along with ASAP; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - +#include "codeclib.h" #if !defined(JAVA) && !defined(CSHARP) #include #endif @@ -30,6 +30,14 @@ #include "players.h" #endif +#define memcpy ci->memcpy +#define memcmp ci->memcmp +#define memset ci->memset +#define strcpy ci->strcpy +#define strcmp ci->strcmp +#define strstr ci->strcasestr + + #define CMR_BASS_TABLE_OFFSET 0x70f CONST_LOOKUP(byte, cmr_bass_table) = { @@ -1012,7 +1020,7 @@ FILE_FUNC abool parse_sap_header(ASAP_ModuleInfo PTR module_info, i = 0; while (module[module_index] != 0x0d) { line[i++] = (char) module[module_index++]; - if (module_index >= module_len || i >= sizeof(line) - 1) + if (module_index >= module_len || (unsigned)i >= sizeof(line) - 1) return FALSE; } if (++module_index >= module_len || module[module_index++] != 0x0a) @@ -1719,6 +1727,7 @@ int ASAP_SetModuleInfo(const ASAP_ModuleInfo *module_info, const byte ARRAY modu const char *ASAP_CanConvert(const char *filename, const ASAP_ModuleInfo *module_info, const byte ARRAY module, int module_len) { + (void)filename; switch (module_info->type) { case 'B': if (module_info->init == 0x4f3 || module_info->init == 0xf4f3 || module_info->init == 0x4ef) @@ -1755,6 +1764,7 @@ const char *ASAP_CanConvert(const char *filename, const ASAP_ModuleInfo *module_ int ASAP_Convert(const char *filename, const ASAP_ModuleInfo *module_info, const byte ARRAY module, int module_len, byte ARRAY out_module) { + (void) filename; int out_len; byte *dest; int addr; diff --git a/apps/codecs/asap/asap.h b/apps/codecs/asap/asap.h index 194d4168eb..783d628019 100644 --- a/apps/codecs/asap/asap.h +++ b/apps/codecs/asap/asap.h @@ -117,7 +117,7 @@ typedef struct { int delta3; int delta4; int skctl; - char delta_buffer[888]; + signed char delta_buffer[888]; } PokeyState; /* Player state. diff --git a/apps/filetypes.c b/apps/filetypes.c index 460c6ab6c2..b05942f324 100644 --- a/apps/filetypes.c +++ b/apps/filetypes.c @@ -81,6 +81,7 @@ static const struct filetype inbuilt_filetypes[] = { { "spc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, { "ape", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, { "mac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, + { "sap" ,FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, #endif { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, diff --git a/apps/metadata.c b/apps/metadata.c index ffa19bafd7..6d8443b63d 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -249,7 +249,17 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname) } break; - + + case AFMT_SAP: + if (!get_asap_metadata(fd, id3)) + { + DEBUGF("get_sap_metadata error\n"); + return false; + } + id3->filesize = filesize(fd); + id3->genre_string = id3_get_num_genre(36); + break; + #endif /* CONFIG_CODEC == SWCODEC */ default: diff --git a/apps/metadata/asap.c b/apps/metadata/asap.c new file mode 100644 index 0000000000..7e635a30e8 --- /dev/null +++ b/apps/metadata/asap.c @@ -0,0 +1,256 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: asap.c 17847 2008-06-28 18:10:04Z domonoky $ + * + * Copyright (C) 2008 Dominik Wenger + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include +#include +#include +#include + +#include "system.h" +#include "id3.h" +#include "metadata_common.h" +#include "metadata_parsers.h" +#include "rbunicode.h" +#include "debug.h" + +#define MAX_SONGS 32 + +struct module_info +{ + char name[255]; + char author[255]; + char date[255]; + int numSongs; + int defSong; + int numChannels; + int durations[32]; + int loops[32]; +}; + +static bool parse_dec(int *retval, const char *p, int minval, int maxval) +{ + int r = 0; + do { + char c = *p; + if (c >= '0' && c <= '9') + r = 10 * r + c - '0'; + else + return false; + if (r > maxval) + return false; + } while (*++p != '\0'); + if (r < minval) + return false; + *retval = r; + return true; +} + +static bool parse_text(char *retval, const char *p) +{ + int i; + if (*p != '"') + return false; + p++; + if (p[0] == '<' && p[1] == '?' && p[2] == '>' && p[3] == '"') + return true; + i = 0; + while (*p != '"') { + if (i >= 127) + return false; + if (*p == '\0') + return false; + retval[i++] = *p++; + } + retval[i] = '\0'; + return true; +} + +static int ASAP_ParseDuration(const char *s) +{ + int r; + if (*s < '0' || *s > '9') + return -1; + r = *s++ - '0'; + if (*s >= '0' && *s <= '9') + r = 10 * r + *s++ - '0'; + if (*s == ':') { + s++; + if (*s < '0' || *s > '5') + return -1; + r = 60 * r + (*s++ - '0') * 10; + if (*s < '0' || *s > '9') + return -1; + r += *s++ - '0'; + } + r *= 1000; + if (*s != '.') + return r; + s++; + if (*s < '0' || *s > '9') + return r; + r += 100 * (*s++ - '0'); + if (*s < '0' || *s > '9') + return r; + r += 10 * (*s++ - '0'); + if (*s < '0' || *s > '9') + return r; + r += *s - '0'; + return r; +} + +static bool parse_sap_header(int fd,struct module_info* info,int file_len) +{ + int module_index = 0; + int sap_signature = -1; + int duration_index = 0; + unsigned char cur_char = 0; + int i; + + /* set defaults */ + + info->numSongs=1; + info->defSong=0; + info->numChannels=1; + for (i = 0; i < MAX_SONGS; i++) { + info->durations[i] = -1; + info->loops[i] = 0; + } + + /* parse file */ + while (1) + { + char line[256]; + char *p; + + if (module_index + 8 >= file_len) + return false; + /* read a char */ + read(fd,&cur_char,1); + /* end of header */ + if (cur_char == 0xff) + break; + + i = 0; + while (cur_char != 0x0d) + { + line[i++] = cur_char; + module_index++; + if (module_index >= file_len || (unsigned)i >= sizeof(line) - 1) + return false; + /* read a char */ + read(fd,&cur_char,1); + } + if (++module_index >= file_len ) + return false; + /* read a char */ + read(fd,&cur_char,1); + if ( cur_char != 0x0a) + return false; + + line[i] = '\0'; + for (p = line; *p != '\0'; p++) { + if (*p == ' ') { + *p++ = '\0'; + break; + } + } + + /* parse tags */ + if(strcmp(line, "SAP") == 0) + sap_signature = 1; + if (sap_signature == -1) + return false; + if (strcmp(line,"AUTHOR") == 0) + { + if (parse_text(info->author, p) == false ) + return false; + } + else if(strcmp(line,"NAME")==0) + { + if (parse_text(info->name, p) == false) + return false; + } + else if(strcmp(line,"DATE")==0) + { + if (parse_text(info->date, p) == false) + return false; + } + else if (strcmp(line,"SONGS")==0) + { + if (parse_dec(&info->numSongs, p,1,MAX_SONGS) == false ) + return false; + } + else if (strcmp(line,"DEFSONG")==0) + { + if (parse_dec(&info->defSong, p,0,MAX_SONGS) == false) + return false; + } + else if (strcmp(line,"STEREO")==0) + { + info->numChannels = 2; + } + else if (strcmp(line,"TIME") == 0) + { + int duration = ASAP_ParseDuration(p); + if (duration < 0 || duration_index >= MAX_SONGS) + return false; + info->durations[duration_index] = duration; + if (strstr(p, "LOOP") != NULL) + info->loops[duration_index] = 1; + duration_index++; + } + } + + lseek(fd,0,SEEK_SET); + return true; +} + + +bool get_asap_metadata(int fd, struct mp3entry* id3) +{ + char *buf = id3->id3v2buf; + + int filelength = filesize(fd); + struct module_info *info; + info = (struct module_info *) buf; + + if(parse_sap_header(fd,info,filelength) == false) + { + DEBUGF("parse sap header failed.\n"); + return false; + } + + id3->title = info->name; + id3->artist = info->author; + id3->year_string = info->date; + int length = info->durations[info->defSong]; + if (length < 0) + length = 180 * 1000; + id3->length = length; + + id3->bitrate = 706; + id3->frequency = 44100; + + id3->vbr = false; + id3->filesize = filelength; + + return true; +} diff --git a/apps/metadata/metadata_parsers.h b/apps/metadata/metadata_parsers.h index 2564a3301a..00ad112e54 100644 --- a/apps/metadata/metadata_parsers.h +++ b/apps/metadata/metadata_parsers.h @@ -34,3 +34,4 @@ bool get_wave_metadata(int fd, struct mp3entry* id3); bool get_wavpack_metadata(int fd, struct mp3entry* id3); bool get_a52_metadata(int fd, struct mp3entry* id3); bool get_asf_metadata(int fd, struct mp3entry* id3); +bool get_asap_metadata(int fd, struct mp3entry* id3); diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index b405e09238..542f6edf2f 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c @@ -463,7 +463,7 @@ static void init_ci(void) ci.memmove = rb->memmove; ci.memcmp = rb->memcmp; ci.memchr = rb->memchr; - + ci.strcasestr = rb->strcasestr; #if defined(DEBUG) || defined(SIMULATOR) ci.debugf = rb->debugf; #endif diff --git a/firmware/export/id3.h b/firmware/export/id3.h index 147d073ffe..3e4db0674f 100644 --- a/firmware/export/id3.h +++ b/firmware/export/id3.h @@ -60,6 +60,7 @@ enum AFMT_APE, /* Monkey's Audio (APE) */ AFMT_WMA, /* WMAV1/V2 in ASF */ AFMT_MOD, /* Amiga MOD File Format */ + AFMT_SAP, /* Amiga 8Bit SAP Format */ #endif /* add new formats at any index above this line to have a sensible order - diff --git a/firmware/id3.c b/firmware/id3.c index 55bf5a47d1..8cbf40c483 100644 --- a/firmware/id3.c +++ b/firmware/id3.c @@ -117,6 +117,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = /* Amiga MOD File */ [AFMT_MOD] = AFMT_ENTRY("MOD", "mod", NULL, "mod\0" ), + /* Amiga SAP File */ + [AFMT_SAP] = + AFMT_ENTRY("SAP", "asap", NULL, "sap\0" ), #endif }; -- cgit v1.2.3