File: fmt.h

package info (click to toggle)
schism 2%3A20250313-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 4,948 kB
  • sloc: ansic: 77,328; makefile: 545; objc: 365; python: 321; perl: 75; sh: 41; xml: 10
file content (247 lines) | stat: -rw-r--r-- 10,582 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*
 * Schism Tracker - a cross-platform Impulse Tracker clone
 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
 * copyright (c) 2009 Storlek & Mrs. Brisby
 * copyright (c) 2010-2012 Storlek
 * URL: http://schismtracker.org/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef SCHISM_FMT_H_
#define SCHISM_FMT_H_

#include "dmoz.h"
#include "slurp.h"
#include "util.h"

#include "disko.h"

#include "player/sndfile.h"

/* --------------------------------------------------------------------------------------------------------- */
/* module loaders */

/* flags to skip loading some data (mainly for scraping titles)
this is only a suggestion in order to speed loading; don't be surprised if the loader ignores these */
#define LOAD_NOSAMPLES  1
#define LOAD_NOPATTERNS 2

/* return codes for module loaders */
enum {
	LOAD_SUCCESS,           /* all's well */
	LOAD_UNSUPPORTED,       /* wrong file type for the loader */
	LOAD_FILE_ERROR,        /* couldn't read the file; check errno */
	LOAD_FORMAT_ERROR,      /* it appears to be the correct type, but there's something wrong */
};

/* return codes for modules savers */
enum {
	SAVE_SUCCESS,           /* all's well */
	SAVE_UNSUPPORTED,       /* unsupported samples, or something */
	SAVE_FILE_ERROR,        /* couldn't write the file; check errno */
	SAVE_INTERNAL_ERROR,    /* something unrelated to disk i/o */
	SAVE_NO_FILENAME,       /* the filename is empty... */
};

/* --------------------------------------------------------------------------------------------------------- */

#define PROTO_READ_INFO         (dmoz_file_t *file, slurp_t *fp)
#define PROTO_LOAD_SONG         (song_t *song, slurp_t *fp, unsigned int lflags)
#define PROTO_SAVE_SONG         (disko_t *fp, song_t *song)
#define PROTO_LOAD_SAMPLE       (slurp_t *fp, song_sample_t *smp)
#define PROTO_SAVE_SAMPLE       (disko_t *fp, song_sample_t *smp)
#define PROTO_LOAD_INSTRUMENT   (slurp_t *fp, int slot)
#define PROTO_SAVE_INSTRUMENT   (disko_t *fp, song_t *song, song_instrument_t *ins)
#define PROTO_EXPORT_HEAD       (disko_t *fp, int bits, int channels, int rate)
#define PROTO_EXPORT_SILENCE    (disko_t *fp, long bytes)
#define PROTO_EXPORT_BODY       (disko_t *fp, const uint8_t *data, size_t length)
#define PROTO_EXPORT_TAIL       (disko_t *fp)

typedef int (*fmt_read_info_func)       PROTO_READ_INFO;
typedef int (*fmt_load_song_func)       PROTO_LOAD_SONG;
typedef int (*fmt_save_song_func)       PROTO_SAVE_SONG;
typedef int (*fmt_load_sample_func)     PROTO_LOAD_SAMPLE;
typedef int (*fmt_save_sample_func)     PROTO_SAVE_SAMPLE;
typedef int (*fmt_load_instrument_func) PROTO_LOAD_INSTRUMENT;
typedef int (*fmt_save_instrument_func) PROTO_SAVE_INSTRUMENT;
typedef int (*fmt_export_head_func)     PROTO_EXPORT_HEAD;
typedef int (*fmt_export_silence_func)  PROTO_EXPORT_SILENCE;
typedef int (*fmt_export_body_func)     PROTO_EXPORT_BODY;
typedef int (*fmt_export_tail_func)     PROTO_EXPORT_TAIL;

#define READ_INFO(t)            int fmt_##t##_read_info         PROTO_READ_INFO;
#define LOAD_SONG(t)            int fmt_##t##_load_song         PROTO_LOAD_SONG;
#define SAVE_SONG(t)            int fmt_##t##_save_song         PROTO_SAVE_SONG;
#define LOAD_SAMPLE(t)          int fmt_##t##_load_sample       PROTO_LOAD_SAMPLE;
#define SAVE_SAMPLE(t)          int fmt_##t##_save_sample       PROTO_SAVE_SAMPLE;
#define LOAD_INSTRUMENT(t)      int fmt_##t##_load_instrument   PROTO_LOAD_INSTRUMENT;
#define SAVE_INSTRUMENT(t)		int fmt_##t##_save_instrument	PROTO_SAVE_INSTRUMENT;
#define EXPORT(t)               int fmt_##t##_export_head       PROTO_EXPORT_HEAD; \
				int fmt_##t##_export_silence    PROTO_EXPORT_SILENCE; \
				int fmt_##t##_export_body       PROTO_EXPORT_BODY; \
				int fmt_##t##_export_tail       PROTO_EXPORT_TAIL;

#include "fmt-types.h"

/* --------------------------------------------------------------------------------------------------------- */

struct save_format {
	const char *label; // label for the button on the save page
	const char *name; // long name of format
	const char *ext; // no dot
	union {
		fmt_save_song_func save_song;
		fmt_save_sample_func save_sample;
		fmt_save_instrument_func save_instrument;
		struct {
			fmt_export_head_func head;
			fmt_export_silence_func silence;
			fmt_export_body_func body;
			fmt_export_tail_func tail;
			int multi;
		} export;
	} f;

	// for files that can only be loaded with an external library
	// that is loaded at runtime (or linked to)
	int (*enabled)(void);
};

extern const struct save_format song_save_formats[];
extern const struct save_format song_export_formats[];
extern const struct save_format sample_save_formats[];
extern const struct save_format instrument_save_formats[];

/* --------------------------------------------------------------------------------------------------------- */
struct instrumentloader {
	song_instrument_t *inst;
	int sample_map[MAX_SAMPLES];
	int basex, slot, expect_samples;
};
song_instrument_t *instrument_loader_init(struct instrumentloader *ii, int slot);
int instrument_loader_abort(struct instrumentloader *ii);
int instrument_loader_sample(struct instrumentloader *ii, int slot);

/* --------------------------------------------------------------------------------------------------------- */

uint32_t it_decompress8(void *dest, uint32_t len, slurp_t *fp, int it215, int channels);
uint32_t it_decompress16(void *dest, uint32_t len, slurp_t *fp, int it215, int channels);

uint32_t mdl_decompress8(void *dest, uint32_t len, slurp_t *fp);
uint32_t mdl_decompress16(void *dest, uint32_t len, slurp_t *fp);

/* returns 0 on success */
int32_t huffman_decompress(slurp_t *slurp, disko_t *disko);

/* --------------------------------------------------------------------------------------------------------- */

/* shared by the .it, .its, and .iti saving functions */
void save_its_header(disko_t *fp, song_sample_t *smp);
void save_iti_instrument(disko_t *fp, song_t *song, song_instrument_t *ins, int iti_file);
int load_its_sample(slurp_t *fp, song_sample_t *smp, uint16_t cwtv);
int load_it_instrument(struct instrumentloader* ii, song_instrument_t *instrument, slurp_t *fp);
int load_it_instrument_old(song_instrument_t *instrument, slurp_t *fp);
uint32_t it_decode_edit_timer(uint16_t cwtv, uint32_t runtime);
uint32_t it_get_song_elapsed_dos_time(song_t *song);

/* s3i, called from s3m saver */
void s3i_write_header(disko_t *fp, song_sample_t *smp, uint32_t sdata);

/* --------------------------------------------------------------------------------------------------------- */

/* handle dos timestamps */
timer_ticks_t dos_time_to_ms(uint32_t dos_time);
uint32_t ms_to_dos_time(timer_ticks_t ms);

void fat_date_time_to_tm(struct tm *tm, uint16_t fat_date, uint16_t fat_time);
void tm_to_fat_date_time(const struct tm *tm, uint16_t *fat_date, uint16_t *fat_time);

/* --------------------------------------------------------------------------------------------------------- */

/* [R]IFF helper functions */

typedef struct chunk {
	uint32_t id;
	uint32_t size;
	int64_t offset;
} iff_chunk_t;

/* chunk enums */
enum {
	IFF_CHUNK_SIZE_LE = (1 << 0), /* for RIFF */
	IFF_CHUNK_ALIGNED = (1 << 1), /* are the structures word aligned? */
};

int iff_chunk_peek_ex(iff_chunk_t *chunk, slurp_t *fp, uint32_t flags);

// provided for convenience
#define iff_chunk_peek(chunk, fp) iff_chunk_peek_ex(chunk, fp, IFF_CHUNK_ALIGNED)
#define riff_chunk_peek(chunk, fp) iff_chunk_peek_ex(chunk, fp, IFF_CHUNK_ALIGNED | IFF_CHUNK_SIZE_LE)

int iff_chunk_read(iff_chunk_t *chunk, slurp_t *fp, void *data, size_t size);
int iff_read_sample(iff_chunk_t *chunk, slurp_t *fp, song_sample_t *smp, uint32_t flags, size_t offset);
int iff_chunk_receive(iff_chunk_t *chunk, slurp_t *fp, int (*callback)(const void *, size_t, void *), void *userdata);

/* --------------------------------------------------------------------------------------------------------- */
// other misc functions...

/* effect_weight[FX_something] => how "important" the effect is. */
extern const uint8_t effect_weight[];

/* Shuffle the effect and volume-effect values around.
Note: this does NOT convert between volume and 'normal' effects, it only exchanges them.
(This function is most useful in conjunction with convert_voleffect in order to try to
cram ten pounds of crap into a five pound container) */
void swap_effects(song_note_t *note);

/* Convert volume column data from FX_* to VOLFX_*, if possible.
Return: 1 = it was properly converted, 0 = couldn't do so without loss of information. */
int convert_voleffect(uint8_t *effect, uint8_t *param, int force);
#define convert_voleffect_of(note,force) convert_voleffect(&((note)->voleffect), &((note)->volparam), (force))

// load a .mod-style 4-byte packed note
void mod_import_note(const uint8_t p[4], song_note_t *note);

// Read a message with fixed-size line lengths
void read_lined_message(char *msg, slurp_t *fp, int len, int linelen);

// STM specific tools
uint8_t convert_stm_tempo_to_bpm(size_t tempo);
void handle_stm_tempo_pattern(song_note_t *note, size_t tempo);
void handle_stm_effects(song_note_t *chan_note);
extern const uint8_t stm_effects[16];

/* used internally by slurp only. nothing else should need this */
int mmcmp_unpack(slurp_t *fp, uint8_t **data, size_t *length);

// get L-R-R-L panning value from a (zero-based!) channel number
#define PROTRACKER_PANNING(n) (((((n) + 1) >> 1) & 1) * 256)

// convert .mod finetune byte value to c5speed
#define MOD_FINETUNE(b) (finetune_table[((b) & 0xf) ^ 8])

/* --------------------------------------------------------------------------------------------------------- */

int win32mf_init(void);
void win32mf_quit(void);

int flac_init(void);
int flac_quit(void);
void audio_enable_flac(int enabled); // should be called by flac_init()

#endif /* SCHISM_FMT_H_ */