Manual: Fix part 1 of FS#11874 - touchscreen region in the manual isn't 100% correct.
[kugel-rb.git] / apps / plugins / mikmod / load_gt2.c
blob996de0e61e5141d79cfc25f5daa40b256bb14c7d
1 /* MikMod sound library
2 (c) 2003-2004 Raphael Assenat and others - see file
3 AUTHORS for complete list.
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.
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.
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.
21 /*==============================================================================
23 $Id: load_gt2.c,v 1.2 2005/03/30 19:09:35 realtech Exp $
25 Graoumf tracker format (.GT2)
27 ==============================================================================*/
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include <ctype.h>
38 #include <stdio.h>
39 #ifdef HAVE_MEMORY_H
40 #include <memory.h>
41 #endif
42 #include <string.h>
44 #include "mikmod_internals.h"
46 typedef 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;
53 /* general info chunk */
54 typedef 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;
71 /* track volume chunk */
72 typedef 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;
79 /* extra-comment chunk */
80 typedef 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;
87 /* song chunk */
88 typedef 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;
96 /* pattern set chunk */
97 typedef 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;
104 /* pattern chunk */
105 typedef 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;
117 /* instrument set chunk */
118 typedef 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;
124 typedef struct INST_NOTE {
125 UBYTE samp_number;/* sample number for midi note */
126 CHAR tranp; /* transposition for note */
127 } INST_NOTE;
129 /* instrument chunk */
130 typedef 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;
145 typedef 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;
163 typedef 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;
172 typedef struct ENDC_CHUNK {
173 UBYTE id[4]; /* must be ENDC */
174 ULONG chunk_size;
175 ULONG total_module_size;
176 } ENDC_CHUNK;
179 typedef union GT_CHUNK
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;
195 GT_CHUNK *loadChunk(void)
197 GT_CHUNK *new_chunk = MikMod_malloc(sizeof(GT_CHUNK));
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')
206 _mm_read_UBYTES(&new_chunk->id[3], 1, modreader);
208 else
210 new_chunk->id[3] = ' ';
213 printf(">> %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]);
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;
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;
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;
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;
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;
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;
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;
290 if (!memcmp(new_chunk, "INST", 4)) {
291 return new_chunk;
293 if (!memcmp(new_chunk, "SAMP", 4)) {
294 return new_chunk;
296 if (!memcmp(new_chunk, "VENV", 4)) {
297 return new_chunk;
299 if (!memcmp(new_chunk, "TENV", 4)) {
300 return new_chunk;
302 if (!memcmp(new_chunk, "PENV", 4)) {
303 return new_chunk;
305 if (!memcmp(new_chunk, "ENDC", 4)) {
306 return new_chunk;
309 printf("?? %c%c%c%c\n", new_chunk->id[0], new_chunk->id[1], new_chunk->id[2], new_chunk->id[3]);
311 MikMod_free(new_chunk);
312 return NULL; // unknown chunk
315 int GT2_Init(void)
317 return 1;
320 int GT2_Test(void)
322 UBYTE magic[3];
323 _mm_fseek(modreader, 0, SEEK_SET);
325 _mm_read_UBYTES(magic, 3, modreader);
327 if (magic[0] == 'G' && magic[1] == 'T' && magic[2] == '2') { return 1; }
329 return 0;
332 int GT2_Load(int curious)
334 GT_CHUNK *tmp;
336 _mm_fseek(modreader, 0, SEEK_SET);
337 while ( (tmp = loadChunk() ))
339 printf("%c%c%c%c\n", tmp->id[0], tmp->id[1], tmp->id[2], tmp->id[3]);
343 return 0;
346 void GT2_Cleanup(void)
350 CHAR *GT2_LoadTitle(void)
352 CHAR title[33];
353 _mm_fseek(modreader, 8, SEEK_SET);
355 _mm_read_UBYTES(title, 32, modreader);
356 title[32]=0;
358 return (DupStr(title, 32, 1));
362 MIKMODAPI 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