diff --git a/src/Makefile b/src/Makefile
index 6a9db907..f9517368 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -134,7 +134,8 @@ META_OBJS=meta/adx_header.o \
meta/kraw.o \
meta/ps2_xa2.o \
meta/idsp.o \
- meta/ngc_ymf.o
+ meta/ngc_ymf.o \
+ meta/nds_sad.o
OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS)
diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj
index d87c42b3..725a040b 100644
--- a/src/libvgmstream.vcproj
+++ b/src/libvgmstream.vcproj
@@ -317,6 +317,10 @@
RelativePath=".\meta\musx.c"
>
+
+
diff --git a/src/meta/Makefile.unix.am b/src/meta/Makefile.unix.am
index b76aab1e..3ed5345f 100644
--- a/src/meta/Makefile.unix.am
+++ b/src/meta/Makefile.unix.am
@@ -103,4 +103,5 @@ libmeta_la_SOURCES += kraw.c
libmeta_la_SOURCES += ps2_xa2.c
libmeta_la_SOURCES += idsp.c
libmeta_la_SOURCES += ngc_ymf.c
+libmeta_la_SOURCES += nds_sad.c
EXTRA_DIST = meta.h
diff --git a/src/meta/meta.h b/src/meta/meta.h
index cf39ffe6..9da9611a 100644
--- a/src/meta/meta.h
+++ b/src/meta/meta.h
@@ -227,4 +227,6 @@ VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE * streamFile);
+VGMSTREAM * init_vgmstream_sadl(STREAMFILE * streamFile);
+
#endif
diff --git a/src/meta/nds_sad.c b/src/meta/nds_sad.c
new file mode 100644
index 00000000..4d160f52
--- /dev/null
+++ b/src/meta/nds_sad.c
@@ -0,0 +1,69 @@
+#include "meta.h"
+#include "../util.h"
+
+/* sadl (only the Professor Layton interleaved IMA version) */
+VGMSTREAM * init_vgmstream_sadl(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+
+ int loop_flag;
+ int channel_count;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("sad",filename_extension(filename))) goto fail;
+
+ /* check header */
+ if (read_32bitBE(0x00,streamFile) != 0x7361646c) /* "sadl" */
+ goto fail;
+
+ /* check file size */
+ if (read_32bitLE(0x40,streamFile) != get_streamfile_size(streamFile) )
+ goto fail;
+
+ /* check for the simple IMA type that we can handle */
+ if (read_8bit(0xc,streamFile) != 0x11)
+ goto fail;
+
+ loop_flag = 0;
+ channel_count = 2;
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,loop_flag);
+ if (!vgmstream) goto fail;
+
+ /* fill in the vital statistics */
+ start_offset = 0x100;
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = 16000;
+ vgmstream->coding_type = coding_INT_IMA;
+ vgmstream->num_samples = read_32bitLE(0x50,streamFile);;
+ vgmstream->interleave_block_size=0x10;
+
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->meta_type = meta_SADL;
+
+ /* open the file for reading */
+ {
+ int i;
+ STREAMFILE * file;
+ file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
+ if (!file) goto fail;
+ for (i=0;ich[i].streamfile = file;
+
+ vgmstream->ch[i].channel_start_offset=
+ vgmstream->ch[i].offset=start_offset+
+ vgmstream->interleave_block_size*i;
+
+ }
+ }
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/src/vgmstream.c b/src/vgmstream.c
index 86499066..963fbb5d 100644
--- a/src/vgmstream.c
+++ b/src/vgmstream.c
@@ -129,6 +129,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_xa2,
init_vgmstream_idsp,
init_vgmstream_ngc_ymf,
+ init_vgmstream_sadl,
};
#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]))
@@ -545,6 +546,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_EACS_IMA:
case coding_IMA:
return 1;
+ case coding_INT_IMA:
case coding_INT_DVI_IMA:
case coding_AICA:
return 2;
@@ -629,6 +631,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 1; // the frame is variant in size
case coding_WS:
return vgmstream->current_block_size;
+ case coding_INT_IMA:
case coding_INT_DVI_IMA:
case coding_AICA:
return 1;
@@ -837,6 +840,7 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
}
break;
case coding_IMA:
+ case coding_INT_IMA:
for (chan=0;chanchannels;chan++) {
decode_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
@@ -1145,6 +1149,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case coding_EACS_IMA:
snprintf(temp,TEMPSIZE,"EACS 4-bit IMA ADPCM");
break;
+ case coding_INT_IMA:
+ snprintf(temp,TEMPSIZE,"Interleaved 4-bit IMA ADPCM");
+ break;
case coding_IMA:
snprintf(temp,TEMPSIZE,"4-bit IMA ADPCM");
break;
@@ -1507,6 +1514,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case meta_DSP_SADB:
snprintf(temp,TEMPSIZE,"sadb header");
break;
+ case meta_SADL:
+ snprintf(temp,TEMPSIZE,"sadl header");
+ break;
case meta_PS2_BMDX:
snprintf(temp,TEMPSIZE,"Beatmania .bmdx header");
break;
diff --git a/src/vgmstream.h b/src/vgmstream.h
index 70e1b5ec..96c1e640 100644
--- a/src/vgmstream.h
+++ b/src/vgmstream.h
@@ -64,6 +64,7 @@ typedef enum {
coding_INT_DVI_IMA, /* Interleaved DVI */
coding_EACS_IMA,
coding_IMA, /* bare IMA, low nibble first */
+ coding_INT_IMA, /* */
coding_WS, /* Westwood Studios' custom VBR ADPCM */
#ifdef VGM_USE_MPEG
coding_fake_MPEG2_L2, /* MPEG-2 Layer 2 (AHX), with lying headers */
@@ -235,6 +236,7 @@ typedef enum {
meta_PS2_XA2, /* XA2 XG3 file */
meta_IDSP, /* Chronicles of Narnia */
meta_NGC_YMF, /* WWE WrestleMania X8 */
+ meta_SADL, /* .sad */
meta_XBOX_WAVM, /* XBOX WAVM File */
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */