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