summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/cassimg.h
blob: 550e1d16a95a8f9537d18ed01d956f67af03687c (plain) (blame)
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
/*********************************************************************

    cassimg.h

    Cassette tape image abstraction code

*********************************************************************/

#ifndef CASSIMG_H
#define CASSIMG_H

#include "osdcore.h"
#include "pool.h"
#include "ioprocs.h"

#ifndef LOG_FORMATS
#define LOG_FORMATS if (0) printf
#endif

/***************************************************************************

    Constants

***************************************************************************/

#define CASSETTE_FLAG_READWRITE         0
#define CASSETTE_FLAG_READONLY          1
#define CASSETTE_FLAG_NOSAVEONEXIT      0
#define CASSETTE_FLAG_SAVEONEXIT        2

#define CASSETTE_WAVEFORM_8BIT          0
#define CASSETTE_WAVEFORM_16BIT         2
#define CASSETTE_WAVEFORM_16BIT_FLIP    3
#define CASSETTE_WAVEFORM_32BIT         4
#define CASSETTE_WAVEFORM_32BIT_FLIP    5
#define CASSETTE_WAVEFORM_ENDIAN_FLIP   1
#define CASSETTE_WAVEFORM_UNSIGNED      8

#define CASSETTE_MODULATION_SQUAREWAVE  0
#define CASSETTE_MODULATION_SINEWAVE    1


#ifdef LSB_FIRST
#define CASSETTE_WAVEFORM_16BITBE       CASSETTE_WAVEFORM_16BIT_FLIP
#define CASSETTE_WAVEFORM_16BITLE       CASSETTE_WAVEFORM_16BIT
#define CASSETTE_WAVEFORM_32BITBE       CASSETTE_WAVEFORM_32BIT_FLIP
#define CASSETTE_WAVEFORM_32BITLE       CASSETTE_WAVEFORM_32BIT
#else
#define CASSETTE_WAVEFORM_16BITBE       CASSETTE_WAVEFORM_16BIT
#define CASSETTE_WAVEFORM_16BITLE       CASSETTE_WAVEFORM_16BIT_FLIP
#define CASSETTE_WAVEFORM_32BITBE       CASSETTE_WAVEFORM_32BIT
#define CASSETTE_WAVEFORM_32BITLE       CASSETTE_WAVEFORM_32BIT_FLIP
#endif


/***************************************************************************

    Type definitions

***************************************************************************/

typedef enum
{
	CASSETTE_ERROR_SUCCESS,         /* no error */
	CASSETTE_ERROR_INTERNAL,        /* fatal internal error */
	CASSETTE_ERROR_UNSUPPORTED,     /* this operation is unsupported */
	CASSETTE_ERROR_OUTOFMEMORY,     /* ran out of memory */
	CASSETTE_ERROR_INVALIDIMAGE,    /* invalid image */
	CASSETTE_ERROR_INVALIDARG
}
casserr_t;

struct sample_block
{
	INT32 *block;
	size_t sample_count;
};

struct CassetteOptions
{
	int channels;
	int bits_per_sample;
	UINT32 sample_frequency;
};

struct CassetteInfo
{
	int channels;
	int bits_per_sample;
	UINT32 sample_frequency;
	size_t sample_count;
};

struct cassette_image
{
	const struct CassetteFormat *format;
	struct io_generic io;
	object_pool *pool;

	int channels;
	int flags;
	UINT32 sample_frequency;

	struct sample_block *blocks;
	size_t block_count;
	size_t sample_count;
};

struct CassetteFormat
{
	const char *extensions;
	casserr_t (*identify)(cassette_image *cassette, struct CassetteOptions *opts);
	casserr_t (*load)(cassette_image *cassette);
	casserr_t (*save)(cassette_image *cassette, const struct CassetteInfo *info);
};

/* used for the core modulation code */
struct CassetteModulation
{
	int flags;
	double zero_frequency_low;
	double zero_frequency_cannonical;
	double zero_frequency_high;
	double one_frequency_low;
	double one_frequency_cannonical;
	double one_frequency_high;
};

/* code to adapt existing legacy fill_wave functions */
struct CassetteLegacyWaveFiller
{
	int (*fill_wave)(INT16 *, int, UINT8 *);
	int chunk_size;
	int chunk_samples;
	int (*chunk_sample_calc)(const UINT8 *bytes, int length);
	UINT32 sample_frequency;
	int header_samples;
	int trailer_samples;
};

/* builtin formats */
extern const struct CassetteFormat wavfile_format;

/* macros for specifying format lists */
#define CASSETTE_FORMATLIST_EXTERN(name)    \
	extern const struct CassetteFormat *const name[]

#define CASSETTE_FORMATLIST_START(name)     \
	const struct CassetteFormat *const name[] = \
	{                                       \
		&wavfile_format,                    \

#define CASSETTE_FORMAT(name)               \
		&(name),                            \

#define CASSETTE_FORMATLIST_END             \
		NULL                                \
	};

CASSETTE_FORMATLIST_EXTERN(cassette_default_formats);

/***************************************************************************

    Prototypes

***************************************************************************/

casserr_t cassette_open(void *file, const struct io_procs *procs,
	const struct CassetteFormat *format, int flags, cassette_image **outcassette);
casserr_t cassette_open_choices(void *file, const struct io_procs *procs, const char *extension,
	const struct CassetteFormat *const *formats, int flags, cassette_image **outcassette);
casserr_t cassette_create(void *file, const struct io_procs *procs, const struct CassetteFormat *format,
	const struct CassetteOptions *opts, int flags, cassette_image **outcassette);
casserr_t cassette_save(cassette_image *cassette);
void cassette_close(cassette_image *cassette);
void cassette_change(cassette_image *cassette, void *file, const struct io_procs *procs, const struct CassetteFormat *format, int flags);
void cassette_get_info(cassette_image *cassette, struct CassetteInfo *info);

/* calls for accessing the raw cassette image */
void cassette_image_read(cassette_image *cassette, void *buffer, UINT64 offset, size_t length);
void cassette_image_write(cassette_image *cassette, const void *buffer, UINT64 offset, size_t length);
UINT64 cassette_image_size(cassette_image *cassette);

/* waveform accesses */
casserr_t cassette_get_samples(cassette_image *cassette, int channel,
	double time_index, double sample_period, size_t sample_count, size_t sample_bytes,
	void *samples, int waveform_flags);
casserr_t cassette_put_samples(cassette_image *cassette, int channel,
	double time_index, double sample_period, size_t sample_count, size_t sample_bytes,
	const void *samples, int waveform_flags);
casserr_t cassette_get_sample(cassette_image *cassette, int channel,
	double time_index, double sample_period, INT32 *sample);
casserr_t cassette_put_sample(cassette_image *cassette, int channel,
	double time_index, double sample_period, INT32 sample);

/* waveform accesses to/from the raw image */
casserr_t cassette_read_samples(cassette_image *cassette, int channels, double time_index,
	double sample_period, size_t sample_count, UINT64 offset, int waveform_flags);
casserr_t cassette_write_samples(cassette_image *cassette, int channels, double time_index,
	double sample_period, size_t sample_count, UINT64 offset, int waveform_flags);

/* modulation support */
casserr_t cassette_modulation_identify(cassette_image *cassette, const struct CassetteModulation *modulation,
	struct CassetteOptions *opts);
casserr_t cassette_put_modulated_data(cassette_image *cassette, int channel, double time_index,
	const void *data, size_t data_length, const struct CassetteModulation *modulation,
	double *time_displacement);
casserr_t cassette_put_modulated_filler(cassette_image *cassette, int channel, double time_index,
	UINT8 filler, size_t filler_length, const struct CassetteModulation *modulation,
	double *time_displacement);
casserr_t cassette_read_modulated_data(cassette_image *cassette, int channel, double time_index,
	UINT64 offset, UINT64 length, const struct CassetteModulation *modulation,
	double *time_displacement);
casserr_t cassette_put_modulated_data_bit(cassette_image *cassette, int channel, double time_index,
	UINT8 data, const struct CassetteModulation *modulation,
	double *time_displacement);

/* debug calls */
void cassette_dump(cassette_image *image, const char *filename);

/* legacy code support */
#define CODE_HEADER     ((UINT8*)-1)
#define CODE_TRAILER    ((UINT8*)-2)
casserr_t cassette_legacy_identify(cassette_image *cassette, struct CassetteOptions *opts,
	const struct CassetteLegacyWaveFiller *legacy_args);
casserr_t cassette_legacy_construct(cassette_image *cassette,
	const struct CassetteLegacyWaveFiller *legacy_args);

#endif /* CASSIMG_H */