summaryrefslogtreecommitdiff
path: root/apps/plugins/mikmod/load_gt2.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/load_gt2.c')
-rw-r--r--apps/plugins/mikmod/load_gt2.c374
1 files changed, 374 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/load_gt2.c b/apps/plugins/mikmod/load_gt2.c
new file mode 100644
index 0000000000..996de0e61e
--- /dev/null
+++ b/apps/plugins/mikmod/load_gt2.c
@@ -0,0 +1,374 @@
1/* MikMod sound library
2 (c) 2003-2004 Raphael Assenat and others - see file
3 AUTHORS for complete list.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19*/
20
21/*==============================================================================
22
23 $Id: load_gt2.c,v 1.2 2005/03/30 19:09:35 realtech Exp $
24
25 Graoumf tracker format (.GT2)
26
27==============================================================================*/
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#ifdef HAVE_UNISTD_H
34#include <unistd.h>
35#endif
36
37#include <ctype.h>
38#include <stdio.h>
39#ifdef HAVE_MEMORY_H
40#include <memory.h>
41#endif
42#include <string.h>
43
44#include "mikmod_internals.h"
45
46typedef struct GT_NOTE {
47 UBYTE note; /* 24-127, 48 is middle C-2. 0 for no note */
48 UBYTE inst; /* instrument, 1-255, 0 for none */
49 UWORD effect; /* 0 for no FX */
50 UBYTE vv; /* volume, 1-255, 0 for no volume */
51} GT_NOTE;
52
53/* general info chunk */
54typedef struct GT2_CHUNK {
55 UBYTE magic[4]; /* must be 'GT2' */
56 UBYTE version; /* 01 = v0.7, 02=v0.726, 03=v0.731 */
57 ULONG chunk_size;
58 CHAR module_name[33]; /* 32 bytes in file */
59 CHAR comments_author[161]; /* 160 bytes in file */
60 UBYTE date_day;
61 UBYTE date_month;
62 UWORD date_year;
63 CHAR tracker_name[25]; /* 24 in file */
64 UWORD initial_speed;
65 UWORD initial_tempo;
66 UWORD initial_master_volume; /* 000 - fff */
67 UWORD num_voices; /* for the following panning section */
68 UWORD *voice_pannings; /* 000 - 800 - fff */
69} GT2_CHUNK;
70
71/* track volume chunk */
72typedef struct TVOL_CHUNK {
73 UBYTE id[4]; /* must be TVOL */
74 ULONG chunk_size;
75 UWORD num_tracks; /* for the following array */
76 UWORD *track_volumes; /* 0000 - 1000 - FFFF */
77} TVOL_CHUNK;
78
79/* extra-comment chunk */
80typedef struct XCOM_CHUNK {
81 UBYTE id[4]; /* must be XCOM */
82 ULONG chunk_size;
83 ULONG comment_len;
84 CHAR *comment; /* comment_len + 1 allocated */
85} XCOM_CHUNK;
86
87/* song chunk */
88typedef struct SONG_CHUNK {
89 UBYTE id[4]; /* must be SONG */
90 ULONG chunk_size;
91 UWORD song_length;
92 UWORD song_repeat_point;
93 UWORD *patterns; /* pattern numbers */
94} SONG_CHUNK;
95
96/* pattern set chunk */
97typedef struct PATS_CHUNK {
98 UBYTE id[4]; /* must be PATS */
99 ULONG chunk_size;
100 UWORD num_tracks; /* total number of tracks for the song */
101 UWORD num_patterns; /* number of patterns saved */
102} PATS_CHUNK;
103
104/* pattern chunk */
105typedef struct PATD_CHUNK {
106 UBYTE id[4]; /* must be PATD */
107 ULONG chunk_size;
108 UWORD pattern_number;
109 CHAR pattern_name[17]; /* 16 in file */
110 UWORD codage_version; /* only 0 expected for now */
111 /* version 0 (full pattern) */
112 UWORD num_lines;
113 UWORD num_tracks;
114 GT_NOTE *notes; /* sizeof(GT_NOTE) * num_lines * num_tracks */
115} PATD_CHUNK;
116
117/* instrument set chunk */
118typedef struct ORCH_CHUNK {
119 UBYTE id[4]; /* must be ORCH */
120 ULONG chunk_size;
121 UWORD num_instruments; /* number of instruments saved */
122} ORCH_CHUNK;
123
124typedef struct INST_NOTE {
125 UBYTE samp_number;/* sample number for midi note */
126 CHAR tranp; /* transposition for note */
127} INST_NOTE;
128
129/* instrument chunk */
130typedef struct INST_CHUNK {
131 UBYTE id[4]; /* must be INST */
132 ULONG chunk_size;
133 UWORD instrument_number;
134 CHAR name[29]; /* 28 in file */
135 UWORD type; /* 0 = sample */
136 UWORD volume; /* volume, 0-255 */
137 UWORD auto_panning; /* autopanning, 000 - 800 - fff, -1 no autopanning */
138 UWORD volume_enveloppe_number;
139 UWORD tone_enveloppe_number;
140 UWORD pan_enveloppe_number;
141 UBYTE reserved[10];
142 INST_NOTE note[128];
143} INST_CHUNK;
144
145typedef struct SAMP_CHUNK {
146 UBYTE id[4]; /* must be SAMP */
147 ULONG chunk_size;
148 UWORD sample_number;
149 CHAR name[29]; /* 28 in file */
150 UWORD flags; /* bit0: 0 = mono, 1 = stereo bit1: 0 normal loop, bit2: ping pong loop */
151 UWORD autopanning; /* 000 - 800 - fff */
152 UWORD num_bits; /* 8 or 16 */
153 UWORD rate; /* between 2000 and 65000 */
154 ULONG length; /* bytes */
155 ULONG loop_start; /* bytes */
156 ULONG loop_len; /* bytes */
157 UWORD volume; /* 0 - 255 */
158 UWORD finetune; /* (-8..+7 -> -1..+7/8 halftone) */
159 UWORD codage; /* 0 */
160 UBYTE *data;
161} SAMP_CHUNK;
162
163typedef struct xENV_CHUNK {
164 UBYTE id[4]; /* must be VENV, TENV or PENV */
165 ULONG chunk_size;
166 UWORD envelope_number;
167 CHAR name[21]; /* 20 in file */
168 UWORD keyoff_offset;
169 UBYTE *data;
170} xENV_CHUNK;
171
172typedef struct ENDC_CHUNK {
173 UBYTE id[4]; /* must be ENDC */
174 ULONG chunk_size;
175 ULONG total_module_size;
176} ENDC_CHUNK;
177
178
179typedef union GT_CHUNK
180{
181 UBYTE id[4]; /* must be TVOL */
182 GT2_CHUNK gt2;
183 TVOL_CHUNK tvol;
184 XCOM_CHUNK xcom;
185 SONG_CHUNK song;
186 PATS_CHUNK pats;
187 PATD_CHUNK patd;
188 ORCH_CHUNK orch;
189 INST_CHUNK inst;
190 SAMP_CHUNK samp;
191 xENV_CHUNK xenv;
192 ENDC_CHUNK endc;
193} GT_CHUNK;
194
195GT_CHUNK *loadChunk(void)
196{
197 GT_CHUNK *new_chunk = MikMod_malloc(sizeof(GT_CHUNK));
198
199 /* the file chunk id only use 3 bytes, others 4 */
200 _mm_read_UBYTES(new_chunk->id, 3, modreader);
201 if (! (new_chunk->id[0]=='G' &&
202 new_chunk->id[1]=='T' &&
203 new_chunk->id[2]=='2')
204 )
205 {
206 _mm_read_UBYTES(&new_chunk->id[3], 1, modreader);
207 }
208 else
209 {
210 new_chunk->id[3] = ' ';
211 }
212
213 printf(">> %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]);
214
215 if (!memcmp(new_chunk, "GT2", 3)) {
216 _mm_read_UBYTES(&new_chunk->gt2.version, 1, modreader);
217 _mm_read_M_ULONGS(&new_chunk->gt2.chunk_size, 1, modreader);
218 new_chunk->gt2.module_name[32] = 0;
219 _mm_read_UBYTES(&new_chunk->gt2.module_name, 32, modreader);
220 new_chunk->gt2.module_name[160] = 0;
221 _mm_read_UBYTES(&new_chunk->gt2.comments_author, 160, modreader);
222 _mm_read_UBYTES(&new_chunk->gt2.date_day, 1, modreader);
223 _mm_read_UBYTES(&new_chunk->gt2.date_month, 1, modreader);
224 _mm_read_M_UWORDS(&new_chunk->gt2.date_year, 1, modreader);
225 new_chunk->gt2.tracker_name[24] = 0;
226 _mm_read_UBYTES(&new_chunk->gt2.tracker_name, 24, modreader);
227 _mm_read_M_UWORDS(&new_chunk->gt2.initial_speed, 1, modreader);
228 _mm_read_M_UWORDS(&new_chunk->gt2.initial_tempo, 1, modreader);
229 _mm_read_M_UWORDS(&new_chunk->gt2.initial_master_volume, 1, modreader);
230 _mm_read_M_UWORDS(&new_chunk->gt2.num_voices, 1, modreader);
231 new_chunk->gt2.voice_pannings = MikMod_malloc(2*new_chunk->gt2.num_voices);
232 _mm_read_M_UWORDS(new_chunk->gt2.voice_pannings, new_chunk->gt2.num_voices, modreader);
233 return new_chunk;
234 }
235
236 if (!memcmp(new_chunk, "TVOL", 4)) {
237 new_chunk->tvol.chunk_size = _mm_read_M_ULONG(modreader);
238 new_chunk->tvol.num_tracks = _mm_read_M_UWORD(modreader);
239 new_chunk->tvol.track_volumes = MikMod_malloc(new_chunk->tvol.num_tracks * 2);
240 _mm_read_M_UWORDS(new_chunk->tvol.track_volumes, new_chunk->tvol.num_tracks, modreader);
241 return new_chunk;
242 }
243
244 if (!memcmp(new_chunk, "XCOM", 4)) {
245 new_chunk->xcom.chunk_size = _mm_read_M_ULONG(modreader);
246 new_chunk->xcom.comment_len = _mm_read_M_ULONG(modreader);
247 new_chunk->xcom.comment = MikMod_malloc(new_chunk->xcom.comment_len + 1);
248 _mm_read_UBYTES(new_chunk->xcom.comment, new_chunk->xcom.comment_len, modreader);
249 return new_chunk;
250 }
251
252 if (!memcmp(new_chunk, "SONG", 4)) {
253 new_chunk->song.chunk_size = _mm_read_M_ULONG(modreader);
254 new_chunk->song.song_length = _mm_read_M_UWORD(modreader);
255 new_chunk->song.song_repeat_point = _mm_read_M_UWORD(modreader);
256 new_chunk->song.patterns = MikMod_malloc(2*new_chunk->song.song_length);
257 _mm_read_M_UWORDS(new_chunk->song.patterns, new_chunk->song.song_length, modreader);
258 return new_chunk;
259 }
260
261 if (!memcmp(new_chunk, "PATS", 4)) {
262 new_chunk->pats.chunk_size = _mm_read_M_ULONG(modreader);
263 new_chunk->pats.num_tracks = _mm_read_M_UWORD(modreader);
264 new_chunk->pats.num_patterns = _mm_read_M_UWORD(modreader);
265 return new_chunk;
266 }
267
268 if (!memcmp(new_chunk, "PATD", 4)) {
269 new_chunk->patd.chunk_size = _mm_read_M_ULONG(modreader);
270 new_chunk->patd.pattern_number = _mm_read_M_UWORD(modreader);
271 new_chunk->patd.pattern_name[16] = 0;
272 _mm_read_UBYTES(new_chunk->patd.pattern_name, 16, modreader);
273 new_chunk->patd.codage_version = _mm_read_M_UWORD(modreader);
274 new_chunk->patd.num_lines = _mm_read_M_UWORD(modreader);
275 new_chunk->patd.num_tracks = _mm_read_M_UWORD(modreader);
276 new_chunk->patd.notes = MikMod_malloc(5 *
277 new_chunk->patd.num_lines *
278 new_chunk->patd.num_tracks);
279 _mm_read_UBYTES(new_chunk->patd.notes,
280 new_chunk->patd.num_lines * new_chunk->patd.num_tracks * 5,
281 modreader);
282 return new_chunk;
283 }
284
285 if (!memcmp(new_chunk, "ORCH", 4)) {
286 new_chunk->orch.chunk_size = _mm_read_M_ULONG(modreader);
287 new_chunk->orch.num_instruments = _mm_read_M_UWORD(modreader);
288 return new_chunk;
289 }
290 if (!memcmp(new_chunk, "INST", 4)) {
291 return new_chunk;
292 }
293 if (!memcmp(new_chunk, "SAMP", 4)) {
294 return new_chunk;
295 }
296 if (!memcmp(new_chunk, "VENV", 4)) {
297 return new_chunk;
298 }
299 if (!memcmp(new_chunk, "TENV", 4)) {
300 return new_chunk;
301 }
302 if (!memcmp(new_chunk, "PENV", 4)) {
303 return new_chunk;
304 }
305 if (!memcmp(new_chunk, "ENDC", 4)) {
306 return new_chunk;
307 }
308
309 printf("?? %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]);
310
311 MikMod_free(new_chunk);
312 return NULL; // unknown chunk
313}
314
315int GT2_Init(void)
316{
317 return 1;
318}
319
320int GT2_Test(void)
321{
322 UBYTE magic[3];
323 _mm_fseek(modreader, 0, SEEK_SET);
324
325 _mm_read_UBYTES(magic, 3, modreader);
326
327 if (magic[0] == 'G' && magic[1] == 'T' && magic[2] == '2') { return 1; }
328
329 return 0;
330}
331
332int GT2_Load(int curious)
333{
334 GT_CHUNK *tmp;
335
336 _mm_fseek(modreader, 0, SEEK_SET);
337 while ( (tmp = loadChunk() ))
338 {
339 printf("%c%c%c%c\n", tmp->id[0], tmp->id[1], tmp->id[2], tmp->id[3]);
340
341 }
342
343 return 0;
344}
345
346void GT2_Cleanup(void)
347{
348}
349
350CHAR *GT2_LoadTitle(void)
351{
352 CHAR title[33];
353 _mm_fseek(modreader, 8, SEEK_SET);
354
355 _mm_read_UBYTES(title, 32, modreader);
356 title[32]=0;
357
358 return (DupStr(title, 32, 1));
359}
360
361
362MIKMODAPI MLOADER load_gt2 = {
363 NULL,
364 "Graoumf Tracker 2 module",
365 "Graoumf Tracker 2",
366 GT2_Init,
367 GT2_Test,
368 GT2_Load,
369 GT2_Cleanup,
370 GT2_LoadTitle
371};
372
373
374