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
21 /*==============================================================================
23 $Id: load_gt2.c,v 1.2 2005/03/30 19:09:35 realtech Exp $
25 Graoumf tracker format (.GT2)
27 ==============================================================================*/
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 */
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 */
58 CHAR module_name
[33]; /* 32 bytes in file */
59 CHAR comments_author
[161]; /* 160 bytes in file */
63 CHAR tracker_name
[25]; /* 24 in file */
66 UWORD initial_master_volume
; /* 000 - fff */
67 UWORD num_voices
; /* for the following panning section */
68 UWORD
*voice_pannings
; /* 000 - 800 - fff */
71 /* track volume chunk */
72 typedef struct TVOL_CHUNK
{
73 UBYTE id
[4]; /* must be TVOL */
75 UWORD num_tracks
; /* for the following array */
76 UWORD
*track_volumes
; /* 0000 - 1000 - FFFF */
79 /* extra-comment chunk */
80 typedef struct XCOM_CHUNK
{
81 UBYTE id
[4]; /* must be XCOM */
84 CHAR
*comment
; /* comment_len + 1 allocated */
88 typedef struct SONG_CHUNK
{
89 UBYTE id
[4]; /* must be SONG */
92 UWORD song_repeat_point
;
93 UWORD
*patterns
; /* pattern numbers */
96 /* pattern set chunk */
97 typedef struct PATS_CHUNK
{
98 UBYTE id
[4]; /* must be PATS */
100 UWORD num_tracks
; /* total number of tracks for the song */
101 UWORD num_patterns
; /* number of patterns saved */
105 typedef struct PATD_CHUNK
{
106 UBYTE id
[4]; /* must be PATD */
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) */
114 GT_NOTE
*notes
; /* sizeof(GT_NOTE) * num_lines * num_tracks */
117 /* instrument set chunk */
118 typedef struct ORCH_CHUNK
{
119 UBYTE id
[4]; /* must be ORCH */
121 UWORD num_instruments
; /* number of instruments saved */
124 typedef struct INST_NOTE
{
125 UBYTE samp_number
;/* sample number for midi note */
126 CHAR tranp
; /* transposition for note */
129 /* instrument chunk */
130 typedef struct INST_CHUNK
{
131 UBYTE id
[4]; /* must be INST */
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
;
145 typedef struct SAMP_CHUNK
{
146 UBYTE id
[4]; /* must be SAMP */
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 */
163 typedef struct xENV_CHUNK
{
164 UBYTE id
[4]; /* must be VENV, TENV or PENV */
166 UWORD envelope_number
;
167 CHAR name
[21]; /* 20 in file */
172 typedef struct ENDC_CHUNK
{
173 UBYTE id
[4]; /* must be ENDC */
175 ULONG total_module_size
;
179 typedef union GT_CHUNK
181 UBYTE id
[4]; /* must be TVOL */
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
);
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
);
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
);
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
);
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
);
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
);
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,
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
);
290 if (!memcmp(new_chunk
, "INST", 4)) {
293 if (!memcmp(new_chunk
, "SAMP", 4)) {
296 if (!memcmp(new_chunk
, "VENV", 4)) {
299 if (!memcmp(new_chunk
, "TENV", 4)) {
302 if (!memcmp(new_chunk
, "PENV", 4)) {
305 if (!memcmp(new_chunk
, "ENDC", 4)) {
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
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; }
332 int GT2_Load(int curious
)
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]);
346 void GT2_Cleanup(void)
350 CHAR
*GT2_LoadTitle(void)
353 _mm_fseek(modreader
, 8, SEEK_SET
);
355 _mm_read_UBYTES(title
, 32, modreader
);
358 return (DupStr(title
, 32, 1));
362 MIKMODAPI MLOADER load_gt2
= {
364 "Graoumf Tracker 2 module",