1 /*
2 * Schism Tracker - a cross-platform Impulse Tracker clone
3 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5 * copyright (c) 2009 Storlek & Mrs. Brisby
6 * copyright (c) 2010-2012 Storlek
7 * URL: http://schismtracker.org/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 /* FIXME this file is redundant and needs to go away -- s3m.c already does all of this */
25
26 #define NEED_BYTESWAP
27 #include "headers.h"
28 #include "fmt.h"
29
30 #include "song.h"
31 #include "sndfile.h"
32
33 #pragma pack(push, 1)
34 /* Note: This struct must match the disk layout struct */
35 struct s3i_header {
36 //00
37 unsigned char type;
38 char dosfn[12];
39 unsigned char memseg[3];
40 //10
41 unsigned int length; // 32 bits
42 unsigned int loopbeg; // 32 bits
43 unsigned int loopend; // 32 bits
44 unsigned char volume;
45 char dummy1;
46 unsigned char packed;
47 unsigned char flags;
48 //20
49 unsigned int c2spd; // 32 bits
50 char dummy2[4];
51 unsigned short dummy_gp;
52 unsigned short dummy_512;
53 unsigned int dummy_last;
54 //30
55 char samplename[28];
56 //4C
57 char samplesig[4]; /* SCRS or SCRI */
58 //50
59 };
60 #pragma pack(pop)
61
load_s3i_sample(const uint8_t * data,size_t length,song_sample_t * smp)62 static int load_s3i_sample(const uint8_t *data, size_t length, song_sample_t *smp)
63 {
64 const struct s3i_header* header = (const struct s3i_header*) data;
65 /*
66 fprintf(stderr, "%X-%X-%X-%X-%X\n",
67 (((char*)&(header->type ))-((char*)&(header->type))),
68 (((char*)&(header->length ))-((char*)&(header->type))),
69 (((char*)&(header->c2spd ))-((char*)&(header->type))),
70 (((char*)&(header->samplename))-((char*)&(header->type))),
71 (((char*)&(header->samplesig))-((char*)&(header->type)))
72 );
73
74 fprintf(stderr, "Considering %d byte sample (%.4s), %d\n",
75 (int)length,
76 header->samplesig,
77 header->length);
78 */
79 if(length < 0x50)
80 return 0; // too small
81 if (strncmp(header->samplesig, "SCRS", 4) != 0
82 && strncmp(header->samplesig, "SCRI", 4) != 0)
83 return 0; // It should be either SCRS or SCRI.
84
85 size_t samp_length = bswapLE32(header->length);
86 int bytes_per_sample = (header->type == 1 ? ((header->flags & 2) ? 2 : 1) : 0); // no sample data
87
88 if (length < 0x50 + smp->length * bytes_per_sample)
89 return 0;
90
91 smp->length = samp_length;
92 smp->global_volume = 64;
93 smp->volume = header->volume*256/64;
94 smp->loop_start = header->loopbeg;
95 smp->loop_end = header->loopend;
96 smp->c5speed = header->c2spd;
97 smp->flags = 0;
98 if (header->flags & 1)
99 smp->flags |= CHN_LOOP;
100 if (header->flags & 2)
101 smp->flags |= CHN_STEREO;
102 if (header->flags & 4)
103 smp->flags |= CHN_16BIT;
104
105 if (header->type == 2) {
106 smp->flags |= CHN_ADLIB;
107 smp->flags &= ~(CHN_LOOP|CHN_16BIT);
108
109 memcpy(smp->adlib_bytes, &header->length, 11);
110
111 smp->length = 1;
112 smp->loop_start = 0;
113 smp->loop_end = 0;
114
115 smp->data = csf_allocate_sample(1);
116 }
117
118 int format = SF_M | SF_LE; // endianness; channels
119 format |= (smp->flags & CHN_16BIT) ? (SF_16 | SF_PCMS) : (SF_8 | SF_PCMU); // bits; encoding
120
121 csf_read_sample((song_sample_t *) smp, format,
122 (const char *) (data + 0x50), (uint32_t) (length - 0x50));
123
124 strncpy(smp->filename, header->dosfn, 11);
125 strncpy(smp->name, header->samplename, 25);
126
127 return 1;
128 }
129
130
fmt_s3i_read_info(dmoz_file_t * file,const uint8_t * data,size_t length)131 int fmt_s3i_read_info(dmoz_file_t *file, const uint8_t *data, size_t length)
132 {
133 song_sample_t tmp;
134 song_sample_t *smp = &tmp;
135 if (!load_s3i_sample(data, length, smp))
136 return 0;
137
138 file->smp_length = smp->length;
139 file->smp_flags = smp->flags;
140 file->smp_defvol = smp->volume;
141 file->smp_gblvol = smp->global_volume;
142 file->smp_loop_start = smp->loop_start;
143 file->smp_loop_end = smp->loop_end;
144 file->smp_speed = smp->c5speed;
145 file->smp_filename = strn_dup(smp->filename, 12);
146
147 file->description = "Scream Tracker Sample";
148 file->title = strn_dup(smp->name, 25);
149 file->type = TYPE_SAMPLE_EXTD | TYPE_INST_OTHER;
150 return 1;
151 }
152
fmt_s3i_load_sample(const uint8_t * data,size_t length,song_sample_t * smp)153 int fmt_s3i_load_sample(const uint8_t *data, size_t length, song_sample_t *smp)
154 {
155 // what the crap?
156 return load_s3i_sample(data, length, smp);
157 }
158
159