Browse Source

Add the aym utility

The aym utility encodes, decodes and plays AYM sound files.
master
Hampa Hug 2 years ago
parent
commit
c9206688ad
9 changed files with 1103 additions and 0 deletions
  1. 26
    0
      Makefile.dep
  2. 1
    0
      Makefile.inc.in
  3. 43
    0
      src/utils/aym/Makefile.inc
  4. 38
    0
      src/utils/aym/aym.1
  5. 179
    0
      src/utils/aym/decode.c
  6. 355
    0
      src/utils/aym/encode.c
  7. 236
    0
      src/utils/aym/main.c
  8. 52
    0
      src/utils/aym/main.h
  9. 173
    0
      src/utils/aym/play.c

+ 26
- 0
Makefile.dep View File

@@ -2546,6 +2546,32 @@ src/libini/write.o: src/libini/write.c \
2546 2546
 	src/config.h \
2547 2547
 	src/libini/libini.h
2548 2548
 
2549
+src/utils/aym/decode.o: src/utils/aym/decode.c \
2550
+	src/config.h \
2551
+	src/drivers/sound/filter.h \
2552
+	src/drivers/sound/sound.h \
2553
+	src/utils/aym/main.h
2554
+
2555
+src/utils/aym/encode.o: src/utils/aym/encode.c \
2556
+	src/config.h \
2557
+	src/drivers/sound/filter.h \
2558
+	src/drivers/sound/sound.h \
2559
+	src/utils/aym/main.h
2560
+
2561
+src/utils/aym/main.o: src/utils/aym/main.c \
2562
+	src/config.h \
2563
+	src/drivers/sound/filter.h \
2564
+	src/drivers/sound/sound.h \
2565
+	src/lib/getopt.h \
2566
+	src/utils/aym/main.h
2567
+
2568
+src/utils/aym/play.o: src/utils/aym/play.c \
2569
+	src/arch/atarist/psg.h \
2570
+	src/config.h \
2571
+	src/drivers/sound/filter.h \
2572
+	src/drivers/sound/sound.h \
2573
+	src/utils/aym/main.h
2574
+
2549 2575
 src/utils/pce-img/commit.o: src/utils/pce-img/commit.c \
2550 2576
 	src/config.h \
2551 2577
 	src/drivers/block/block.h \

+ 1
- 0
Makefile.inc.in View File

@@ -163,6 +163,7 @@ include $(srcdir)/src/arch/sim6502/Makefile.inc
163 163
 include $(srcdir)/src/arch/simarm/Makefile.inc
164 164
 include $(srcdir)/src/arch/sims32/Makefile.inc
165 165
 include $(srcdir)/src/utils/Makefile.inc
166
+include $(srcdir)/src/utils/aym/Makefile.inc
166 167
 include $(srcdir)/src/utils/pce-img/Makefile.inc
167 168
 include $(srcdir)/src/utils/pri/Makefile.inc
168 169
 include $(srcdir)/src/utils/psi/Makefile.inc

+ 43
- 0
src/utils/aym/Makefile.inc View File

@@ -0,0 +1,43 @@
1
+# src/utils/aym/Makefile.inc
2
+
3
+rel := src/utils/aym
4
+
5
+DIRS += $(rel)
6
+DIST += $(rel)/Makefile.inc
7
+
8
+AYM_BAS := \
9
+	decode \
10
+	encode \
11
+	play \
12
+	main
13
+
14
+AYM_SRC := $(foreach f,$(AYM_BAS),$(rel)/$(f).c)
15
+AYM_OBJ := $(foreach f,$(AYM_BAS),$(rel)/$(f).o)
16
+AYM_HDR := $(rel)/main.h
17
+AYM_MAN1 := $(rel)/aym.1
18
+AYM_BIN := $(rel)/aym$(EXEEXT)
19
+
20
+AYM_OBJ_EXT := \
21
+	src/arch/atarist/psg.o \
22
+	src/lib/getopt.o \
23
+	src/drivers/options.o \
24
+	src/drivers/sound/sound.a
25
+
26
+ifeq "$(PCE_ENABLE_SDL)" "1"
27
+	AYM_CFLAGS += $(PCE_SDL_CFLAGS)
28
+	AYM_LIBS += $(PCE_SDL_LIBS)
29
+endif
30
+
31
+BIN  += $(AYM_BIN)
32
+MAN1 += $(AYM_MAN1)
33
+CLN  += $(AYM_BIN) $(AYM_OBJ)
34
+DIST += $(AYM_SRC) $(AYM_HDR) $(AYM_MAN1)
35
+
36
+$(rel)/decode.o:     $(rel)/decode.c
37
+$(rel)/encode.o:     $(rel)/encode.c
38
+$(rel)/play.o:       $(rel)/play.c
39
+$(rel)/main.o:       $(rel)/main.c
40
+
41
+$(rel)/aym$(EXEEXT): $(AYM_OBJ_EXT) $(AYM_OBJ)
42
+	$(QP)echo "  LD     $@"
43
+	$(QR)$(LD) $(LDFLAGS_DEFAULT) -o $@ $(AYM_OBJ) $(AYM_OBJ_EXT) $(AYM_LIBS) -lm

+ 38
- 0
src/utils/aym/aym.1 View File

@@ -0,0 +1,38 @@
1
+.TH AYM 1 "2015-05-21" "HH" "pce"
2
+\
3
+.SH NAME
4
+aym \- convert and play AYM sound files
5
+
6
+.SH SYNOPSIS
7
+.BI aym " [options] [input-file output-file]]"
8
+
9
+.SH DESCRIPTION
10
+\fBaym\fR(1) is used to convert and play AYM sound files.
11
+
12
+.SH OPTIONS
13
+.TP
14
+.BI "-i, --input " filename
15
+Load an image from \fIfilename\fR.
16
+\
17
+.TP
18
+.BI "-o, --output " filename
19
+Set the output file name. Before exiting, the current image will
20
+be written to this file.
21
+\
22
+.TP
23
+.B "-v, --verbose"
24
+Enable verbose operation.
25
+\
26
+.TP
27
+.B --help
28
+Print usage information.
29
+\
30
+.TP
31
+.B --version
32
+Print version information.
33
+
34
+.SH SEE ALSO
35
+.BR pce-atarist "(1)"
36
+
37
+.SH AUTHOR
38
+Hampa Hug <hampa@hampa.ch>

+ 179
- 0
src/utils/aym/decode.c View File

@@ -0,0 +1,179 @@
1
+/*****************************************************************************
2
+ * pce                                                                       *
3
+ *****************************************************************************/
4
+
5
+/*****************************************************************************
6
+ * File name:   src/utils/aym/decode.c                                       *
7
+ * Created:     2015-05-21 by Hampa Hug <hampa@hampa.ch>                     *
8
+ * Copyright:   (C) 2015 Hampa Hug <hampa@hampa.ch>                          *
9
+ *****************************************************************************/
10
+
11
+/*****************************************************************************
12
+ * This program is free software. You can redistribute it and / or modify it *
13
+ * under the terms of the GNU General Public License version 2 as  published *
14
+ * by the Free Software Foundation.                                          *
15
+ *                                                                           *
16
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
17
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
19
+ * Public License for more details.                                          *
20
+ *****************************************************************************/
21
+
22
+
23
+#include "main.h"
24
+
25
+#include <stdlib.h>
26
+#include <stdio.h>
27
+#include <string.h>
28
+
29
+
30
+static
31
+int aym_decode_fp (FILE *inp, FILE *out, unsigned long mark)
32
+{
33
+	unsigned           i;
34
+	int                c1, c2;
35
+	unsigned long      vers;
36
+	unsigned long long delay;
37
+	unsigned long long total;
38
+	unsigned char      v1, v2;
39
+	unsigned char      buf[8];
40
+	unsigned char      reg[16];
41
+
42
+	if (fread (buf, 1, 8, inp) != 8) {
43
+		return (1);
44
+	}
45
+
46
+	if (aym_get_uint32_be (buf, 0) != AYM_MAGIC) {
47
+		fprintf (stderr, "%s: not a aym file\n", arg0);
48
+		return (1);
49
+	}
50
+
51
+	vers = aym_get_uint32_be (buf, 4);
52
+
53
+	if (vers != 0) {
54
+		fprintf (stderr, "%s: unknown aym version (%lu)\n", arg0, vers);
55
+		return (1);
56
+	}
57
+
58
+	fprintf (out, "AYM %lu\n\n", vers);
59
+
60
+	for (i = 0; i < 16; i++) {
61
+		reg[i] = 0;
62
+	}
63
+
64
+	delay = 0;
65
+	total = 0;
66
+
67
+	while (1) {
68
+		c1 = fgetc (inp);
69
+		c2 = fgetc (inp);
70
+
71
+		if ((c1 == EOF) || (c2 == EOF)) {
72
+			fprintf (stderr, "%s: premature end of file\n", arg0);
73
+			return (0);
74
+		}
75
+
76
+		v1 = c1 & 0xff;
77
+		v2 = c2 & 0xff;
78
+
79
+		switch ((v1 >> 4) & 0x0f) {
80
+		case 0:
81
+			if ((mark > 0) && (total <= mark) && ((total + delay) > mark)) {
82
+				fprintf (out, "\n# MARK %lu.%06lu\n",
83
+					mark / 1000000, mark % 1000000
84
+				);
85
+
86
+				for (i = 0; i < 14; i++) {
87
+					fprintf (out, "# REG %02X %02X\n", i, reg[i]);
88
+				}
89
+
90
+				fputs ("\n", out);
91
+			}
92
+
93
+			if (delay > 0) {
94
+				total += delay;
95
+				fprintf (out, "\n# %llu.%06llu + %llu.%06llu = %llu.%06llu\n",
96
+					(total - delay) / 1000000, (total - delay) % 1000000,
97
+					delay / 1000000, delay % 1000000,
98
+					total / 1000000, total % 1000000
99
+				);
100
+				fprintf (out, "DEL %llu\n\n", delay);
101
+				delay = 0;
102
+			}
103
+
104
+			reg[v1 & 0x0f] = v2;
105
+
106
+			fprintf (out, "REG %02X %02X\n", v1 & 0x0f, v2);
107
+			break;
108
+
109
+		case 1:
110
+			delay += ((v1 & 0x0f) << 8) | v2;
111
+			break;
112
+
113
+		case 2:
114
+			delay += (((unsigned long long) (v1 & 0x0f) << 8) | v2) << 12;
115
+			break;
116
+
117
+		case 3:
118
+			delay += (((unsigned long long) (v1 & 0x0f) << 8) | v2) << 24;
119
+			break;
120
+
121
+		case 8:
122
+			fprintf (out, "TXT %u ", v1 & 0x0f);
123
+			while (v2 > 0) {
124
+				if ((c1 = fgetc (inp)) == EOF) {
125
+					return (1);
126
+				}
127
+
128
+				fputc (c1, out);
129
+
130
+				v2 -= 1;
131
+			}
132
+			fputs ("\n\n", out);
133
+			break;
134
+
135
+		case 15:
136
+			if ((v1 == 0xff) && (v2 == 0xff)) {
137
+				fprintf (out, "END\n");
138
+			}
139
+			return (0);
140
+		}
141
+	}
142
+
143
+	return (0);
144
+}
145
+
146
+int aym_decode (const char *inp, const char *out, unsigned long mark)
147
+{
148
+	int  r;
149
+	FILE *finp, *fout;
150
+
151
+	if (inp == NULL) {
152
+		finp = stdin;
153
+	}
154
+	else if ((finp = fopen (inp, "rb")) == NULL) {
155
+		fprintf (stderr, "%s: can't open input file (%s)\n", arg0, inp);
156
+		return (1);
157
+	}
158
+
159
+	if (out == NULL) {
160
+		fout = stdout;
161
+	}
162
+	else if ((fout = fopen (out, "w")) == NULL) {
163
+		fprintf (stderr, "%s: can't open output file (%s)\n", arg0, out);
164
+		fclose (finp);
165
+		return (1);
166
+	}
167
+
168
+	r = aym_decode_fp (finp, fout, mark);
169
+
170
+	if (fout != stdout) {
171
+		fclose (fout);
172
+	}
173
+
174
+	if (finp != stdin) {
175
+		fclose (finp);
176
+	}
177
+
178
+	return (r);
179
+}

+ 355
- 0
src/utils/aym/encode.c View File

@@ -0,0 +1,355 @@
1
+/*****************************************************************************
2
+ * pce                                                                       *
3
+ *****************************************************************************/
4
+
5
+/*****************************************************************************
6
+ * File name:   src/utils/aym/encode.c                                       *
7
+ * Created:     2015-05-21 by Hampa Hug <hampa@hampa.ch>                     *
8
+ * Copyright:   (C) 2015 Hampa Hug <hampa@hampa.ch>                          *
9
+ *****************************************************************************/
10
+
11
+/*****************************************************************************
12
+ * This program is free software. You can redistribute it and / or modify it *
13
+ * under the terms of the GNU General Public License version 2 as  published *
14
+ * by the Free Software Foundation.                                          *
15
+ *                                                                           *
16
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
17
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
19
+ * Public License for more details.                                          *
20
+ *****************************************************************************/
21
+
22
+
23
+#include "main.h"
24
+
25
+#include <stdlib.h>
26
+#include <stdio.h>
27
+#include <string.h>
28
+
29
+
30
+static
31
+int aym_skip_space (FILE *fp)
32
+{
33
+	int c, com;
34
+
35
+	com = 0;
36
+
37
+	while ((c = fgetc (fp)) != EOF) {
38
+		if (c == '#') {
39
+			com = 1;
40
+		}
41
+		else if ((c == 0x0a) || (c == 0x0d)) {
42
+			com = 0;
43
+		}
44
+		else if ((c == ' ') || (c == '\t')) {
45
+			;
46
+		}
47
+		else if (com) {
48
+			;
49
+		}
50
+		else {
51
+			ungetc (c, fp);
52
+			return (0);
53
+		}
54
+	}
55
+
56
+	return (0);
57
+}
58
+
59
+static
60
+int aym_get_str (FILE *fp, char *dst, unsigned max)
61
+{
62
+	int      c;
63
+	unsigned i;
64
+
65
+	aym_skip_space (fp);
66
+
67
+	i = 0;
68
+
69
+	while (i < max) {
70
+		if ((c = fgetc (fp)) == EOF) {
71
+			break;
72
+		}
73
+
74
+		if ((c >= 'A') && (c <= 'Z')) {
75
+			;
76
+		}
77
+		else {
78
+			ungetc (c, fp);
79
+			break;
80
+		}
81
+
82
+		dst[i++] = c;
83
+	}
84
+
85
+	if ((i == 0) || (i >= max)) {
86
+		return (1);
87
+	}
88
+
89
+	dst[i++] = 0;
90
+
91
+	return (0);
92
+}
93
+
94
+static
95
+int aym_get_int (FILE *fp, unsigned long long *val)
96
+{
97
+	int      c, ok;
98
+	unsigned dig;
99
+
100
+	aym_skip_space (fp);
101
+
102
+	ok = 0;
103
+
104
+	*val = 0;
105
+
106
+	while (1) {
107
+		if ((c = fgetc (fp)) == EOF) {
108
+			break;
109
+		}
110
+
111
+		if ((c >= '0') && (c <= '9')) {
112
+			dig = c - '0';
113
+		}
114
+		else {
115
+			ungetc (c, fp);
116
+			break;
117
+		}
118
+
119
+		*val = 10 * *val + dig;
120
+
121
+		ok = 1;
122
+	}
123
+
124
+	return (ok == 0);
125
+}
126
+
127
+static
128
+int aym_get_byte (FILE *fp, unsigned *val)
129
+{
130
+	int      c, ok;
131
+	unsigned dig;
132
+
133
+	aym_skip_space (fp);
134
+
135
+	ok = 0;
136
+
137
+	*val = 0;
138
+
139
+	while (1) {
140
+		if ((c = fgetc (fp)) == EOF) {
141
+			break;
142
+		}
143
+
144
+		if ((c >= '0') && (c <= '9')) {
145
+			dig = c - '0';
146
+		}
147
+		else if ((c >= 'A') && (c <= 'F')) {
148
+			dig = c - 'A' + 10;
149
+		}
150
+		else if ((c >= 'a') && (c <= 'f')) {
151
+			dig = c - 'a' + 10;
152
+		}
153
+		else {
154
+			ungetc (c, fp);
155
+			break;
156
+		}
157
+
158
+		*val = 16 * *val + dig;
159
+
160
+		ok = 1;
161
+	}
162
+
163
+	return (ok == 0);
164
+}
165
+
166
+static
167
+void aym_write_delay (FILE *out, unsigned long long val)
168
+{
169
+	while (val >= 0xfff000000) {
170
+		fputc (0x3f, out);
171
+		fputc (0xff, out);
172
+		val -= 0xfff000000;
173
+	}
174
+
175
+	if (val & 0xfff000000) {
176
+		fputc (0x30 | ((val >> 32) & 0x0f), out);
177
+		fputc ((val >> 24) & 0xff, out);
178
+	}
179
+
180
+	if (val & 0x00fff000) {
181
+		fputc (0x20 | ((val >> 20) & 0x0f), out);
182
+		fputc ((val >> 12) & 0xff, out);
183
+	}
184
+
185
+	if (val & 0x00000fff) {
186
+		fputc (0x10 | ((val >> 8) & 0x0f), out);
187
+		fputc (val & 0xff, out);
188
+	}
189
+}
190
+
191
+static
192
+int aym_encode_text (FILE *inp, FILE *out)
193
+{
194
+	int                c;
195
+	unsigned           i, n, type;
196
+	unsigned long long val;
197
+	char               str[256];
198
+
199
+	if (aym_get_int (inp, &val)) {
200
+		return (1);
201
+	}
202
+
203
+	type = val & 0x0f;
204
+
205
+	n = 0;
206
+
207
+	while ((n < 256) && ((c = fgetc (inp)) != EOF)) {
208
+		if ((c == 0x0d) || (c == 0x0a)) {
209
+			break;
210
+		}
211
+
212
+		if ((n == 0) && ((c == ' ') || (c == 't'))) {
213
+			continue;
214
+		}
215
+
216
+		str[n++] = c;
217
+	}
218
+
219
+	if (n > 255) {
220
+		return (1);
221
+	}
222
+
223
+	while ((n > 0) && ((str[n - 1] == ' ') || (str[n - 1] == '\t'))) {
224
+		n -= 1;
225
+	}
226
+
227
+	fputc (0x80 | type, out);
228
+	fputc (n, out);
229
+
230
+	for (i = 0; i < n; i++) {
231
+		fputc (str[i], out);
232
+	}
233
+
234
+	return (0);
235
+}
236
+
237
+static
238
+int aym_encode_fp (FILE *inp, FILE *out)
239
+{
240
+	unsigned long long vers, delay;
241
+	unsigned char      buf[8];
242
+	char               str[256];
243
+
244
+	if (aym_get_str (inp, str, 256)) {
245
+		return (1);
246
+	}
247
+
248
+	if (strcmp (str, "AYM") != 0) {
249
+		fprintf (stderr, "%s: bad magic (%s)\n", arg0, str);
250
+		return (1);
251
+	}
252
+
253
+	if (aym_get_int (inp, &vers)) {
254
+		return (1);
255
+	}
256
+
257
+	if (vers != 0) {
258
+		fprintf (stderr, "%s: unknown version (%llu)\n", arg0, vers);
259
+		return (1);
260
+	}
261
+
262
+	aym_set_uint32_be (buf, 0, AYM_MAGIC);
263
+	aym_set_uint32_be (buf, 4, 0);
264
+
265
+	if (fwrite (buf, 1, 8, out) != 8) {
266
+		return (1);
267
+	}
268
+
269
+	delay = 0;
270
+
271
+	while (1) {
272
+		if (aym_get_str (inp, str, 256)) {
273
+			return (1);
274
+		}
275
+
276
+		if (strcmp (str, "DEL") == 0) {
277
+			unsigned long long val;
278
+
279
+			if (aym_get_int (inp, &val)) {
280
+				return (1);
281
+			}
282
+
283
+			delay += val;
284
+		}
285
+		else if (strcmp (str, "END") == 0) {
286
+			fputc (0xff, out);
287
+			fputc (0xff, out);
288
+			break;
289
+		}
290
+		else if (strcmp (str, "REG") == 0) {
291
+			unsigned v1, v2;
292
+
293
+			aym_write_delay (out, delay);
294
+
295
+			delay = 0;
296
+
297
+			if (aym_get_byte (inp, &v1)) {
298
+				return (1);
299
+			}
300
+
301
+			if (aym_get_byte (inp, &v2)) {
302
+				return (1);
303
+			}
304
+
305
+			fputc (v1 & 0x0f, out);
306
+			fputc (v2 & 0xff, out);
307
+		}
308
+		else if (strcmp (str, "TXT") == 0) {
309
+			if (aym_encode_text (inp, out)) {
310
+				return (1);
311
+			}
312
+		}
313
+		else {
314
+			fprintf (stderr, "%s: bad keyword (%s)\n", arg0, str);
315
+			return (1);
316
+		}
317
+	}
318
+
319
+	return (0);
320
+}
321
+
322
+int aym_encode (const char *inp, const char *out)
323
+{
324
+	int  r;
325
+	FILE *finp, *fout;
326
+
327
+	if (inp == NULL) {
328
+		finp = stdin;
329
+	}
330
+	else if ((finp = fopen (inp, "r")) == NULL) {
331
+		fprintf (stderr, "%s: can't open input file (%s)\n", arg0, inp);
332
+		return (1);
333
+	}
334
+
335
+	if (out == NULL) {
336
+		fout = stdout;
337
+	}
338
+	else if ((fout = fopen (out, "wb")) == NULL) {
339
+		fprintf (stderr, "%s: can't open output file (%s)\n", arg0, out);
340
+		fclose (finp);
341
+		return (1);
342
+	}
343
+
344
+	r = aym_encode_fp (finp, fout);
345
+
346
+	if (fout != stdout) {
347
+		fclose (fout);
348
+	}
349
+
350
+	if (finp != stdin) {
351
+		fclose (finp);
352
+	}
353
+
354
+	return (r);
355
+}

+ 236
- 0
src/utils/aym/main.c View File

@@ -0,0 +1,236 @@
1
+/*****************************************************************************
2
+ * pce                                                                       *
3
+ *****************************************************************************/
4
+
5
+/*****************************************************************************
6
+ * File name:   src/utils/aym/main.c                                         *
7
+ * Created:     2015-05-21 by Hampa Hug <hampa@hampa.ch>                     *
8
+ * Copyright:   (C) 2015 Hampa Hug <hampa@hampa.ch>                          *
9
+ *****************************************************************************/
10
+
11
+/*****************************************************************************
12
+ * This program is free software. You can redistribute it and / or modify it *
13
+ * under the terms of the GNU General Public License version 2 as  published *
14
+ * by the Free Software Foundation.                                          *
15
+ *                                                                           *
16
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
17
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
19
+ * Public License for more details.                                          *
20
+ *****************************************************************************/
21
+
22
+
23
+#include "main.h"
24
+
25
+#include <stdlib.h>
26
+#include <stdio.h>
27
+#include <string.h>
28
+
29
+#include <lib/getopt.h>
30
+
31
+#include <drivers/sound/sound.h>
32
+
33
+
34
+const char           *arg0 = NULL;
35
+
36
+char                 par_verbose = 0;
37
+
38
+unsigned long        par_srate = 48000;
39
+
40
+static unsigned long par_lowpass = 0;
41
+static char          par_highpass = 0;
42
+
43
+static const char    *par_driver = "oss:lowpass=0";
44
+static char          par_driver_tmp[256];
45
+
46
+static unsigned long par_mark = 0;
47
+
48
+
49
+static pce_option_t opts[] = {
50
+	{ '?', 0, "help", NULL, "Print usage information" },
51
+	{ 'd', 0, "decode", NULL, "Decode AYM to text" },
52
+	{ 'e', 0, "encode", NULL, "Encode text to AYM" },
53
+	{ 'h', 0, "highpass", NULL, "Enable the highpass filter [no]" },
54
+	{ 'i', 1, "input", "filename", "Set the input file name" },
55
+	{ 'l', 1, "lowpass", "freq", "Set lowpass frequency [0]" },
56
+	{ 'm', 1, "mark", "pos", "Mark a file position when decoding" },
57
+	{ 'o', 1, "output", "filename", "Set the output file name" },
58
+	{ 'p', 0, "play", NULL, "Play an AYM file" },
59
+	{ 'r', 1, "srate", "rate", "Set the sample rate [48000]" },
60
+	{ 's', 1, "driver", "driver", "Set the sound driver [oss]" },
61
+	{ 'V', 0, "version", NULL, "Print version information" },
62
+	{ 'w', 1, "wav", "file", "Save to a WAV file" },
63
+	{  -1, 0, NULL, NULL, NULL }
64
+};
65
+
66
+
67
+static
68
+void print_help (void)
69
+{
70
+	pce_getopt_help (
71
+		"aym: encode and decode PCE AYM files",
72
+		"usage: aym [options] [input [output]]",
73
+		opts
74
+	);
75
+
76
+	fflush (stdout);
77
+}
78
+
79
+static
80
+void print_version (void)
81
+{
82
+	fputs (
83
+		"aym version " PCE_VERSION_STR
84
+		"\n\n"
85
+		"Copyright (C) 2015 Hampa Hug <hampa@hampa.ch>\n",
86
+		stdout
87
+	);
88
+
89
+	fflush (stdout);
90
+}
91
+
92
+unsigned long aym_get_uint32_be (const void *buf, unsigned i)
93
+{
94
+	unsigned long       val;
95
+	const unsigned char *tmp;
96
+
97
+	tmp = (const unsigned char *) buf + i;
98
+
99
+	val = tmp[0] & 0xff;
100
+	val = (val << 8) | (tmp[1] & 0xff);
101
+	val = (val << 8) | (tmp[2] & 0xff);
102
+	val = (val << 8) | (tmp[3] & 0xff);
103
+
104
+	return (val);
105
+}
106
+
107
+void aym_set_uint32_be (void *buf, unsigned i, unsigned long val)
108
+{
109
+	unsigned char *tmp;
110
+
111
+	tmp = (unsigned char *) buf + i;
112
+
113
+	tmp[0] = (val >> 24) & 0xff;
114
+	tmp[1] = (val >> 16) & 0xff;
115
+	tmp[2] = (val >> 8) & 0xff;
116
+	tmp[3] = val;
117
+}
118
+
119
+int main (int argc, char **argv)
120
+{
121
+	int        r, op;
122
+	char       **optarg;
123
+	const char *inp, *out;
124
+
125
+	if (argc < 2) {
126
+		print_help();
127
+		return (1);
128
+	}
129
+
130
+	arg0 = argv[0];
131
+
132
+	op = 0;
133
+
134
+	inp = NULL;
135
+	out = NULL;
136
+
137
+	while (1) {
138
+		r = pce_getopt (argc, argv, &optarg, opts);
139
+
140
+		if (r == GETOPT_DONE) {
141
+			break;
142
+		}
143
+
144
+		if (r < 0) {
145
+			return (1);
146
+		}
147
+
148
+		switch (r) {
149
+		case '?':
150
+			print_help();
151
+			return (0);
152
+
153
+		case 'V':
154
+			print_version();
155
+			return (0);
156
+
157
+		case 'd':
158
+			op = 0;
159
+			break;
160
+
161
+		case 'e':
162
+			op = 1;
163
+			break;
164
+
165
+		case 'h':
166
+			par_highpass = 1;
167
+			break;
168
+
169
+		case 'i':
170
+			inp = optarg[0];
171
+			break;
172
+
173
+		case 'l':
174
+			par_lowpass = strtoul (optarg[0], NULL, 0);
175
+			break;
176
+
177
+		case 'm':
178
+			par_mark = strtoul (optarg[0], NULL, 0);
179
+			break;
180
+
181
+		case 'o':
182
+			out = optarg[0];
183
+			break;
184
+
185
+		case 'p':
186
+			op = 2;
187
+			break;
188
+
189
+		case 'r':
190
+			par_srate = strtoul (optarg[0], NULL, 0);
191
+			break;
192
+
193
+		case 's':
194
+			par_driver = optarg[0];
195
+			break;
196
+
197
+		case 'w':
198
+			op = 2;
199
+			sprintf (par_driver_tmp, "wav:wav=%s:wavfilter=0", optarg[0]);
200
+			par_driver = par_driver_tmp;
201
+			break;
202
+
203
+		case 0:
204
+			if (inp == NULL) {
205
+				inp = optarg[0];
206
+			}
207
+			else if (out == NULL) {
208
+				out = optarg[0];
209
+			}
210
+			else {
211
+				fprintf (stderr, "%s: too many files (%s)\n", arg0, optarg[0]);
212
+				return (1);
213
+			}
214
+			break;
215
+
216
+		default:
217
+			return (1);
218
+		}
219
+	}
220
+
221
+	if (op == 0) {
222
+		r = aym_decode (inp, out, par_mark);
223
+	}
224
+	else if (op == 1) {
225
+		r = aym_encode (inp, out);
226
+	}
227
+	else {
228
+		r = aym_play (inp, par_driver, par_lowpass, par_highpass);
229
+	}
230
+
231
+	if (r) {
232
+		return (1);
233
+	}
234
+
235
+	return (0);
236
+}

+ 52
- 0
src/utils/aym/main.h View File

@@ -0,0 +1,52 @@
1
+/*****************************************************************************
2
+ * pce                                                                       *
3
+ *****************************************************************************/
4
+
5
+/*****************************************************************************
6
+ * File name:   src/utils/aym/main.h                                         *
7
+ * Created:     2015-05-21 by Hampa Hug <hampa@hampa.ch>                     *
8
+ * Copyright:   (C) 2015 Hampa Hug <hampa@hampa.ch>                          *
9
+ *****************************************************************************/
10
+
11
+/*****************************************************************************
12
+ * This program is free software. You can redistribute it and / or modify it *
13
+ * under the terms of the GNU General Public License version 2 as  published *
14
+ * by the Free Software Foundation.                                          *
15
+ *                                                                           *
16
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
17
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
19
+ * Public License for more details.                                          *
20
+ *****************************************************************************/
21
+
22
+
23
+#ifndef AYM_MAIN_H
24
+#define AYM_MAIN_H 1
25
+
26
+
27
+#include <config.h>
28
+
29
+#include <drivers/sound/sound.h>
30
+
31
+
32
+#define AYM_MAGIC 0x41594d1a
33
+
34
+
35
+extern const char    *arg0;
36
+
37
+extern char          par_verbose;
38
+
39
+extern unsigned long par_srate;
40
+
41
+
42
+unsigned long aym_get_uint32_be (const void *buf, unsigned i);
43
+void aym_set_uint32_be (void *buf, unsigned i, unsigned long val);
44
+
45
+int aym_decode (const char *inp, const char *out, unsigned long mark);
46
+
47
+int aym_encode (const char *inp, const char *out);
48
+
49
+int aym_play (const char *fname, const char *snddrv, unsigned long lp, int hp);
50
+
51
+
52
+#endif

+ 173
- 0
src/utils/aym/play.c View File

@@ -0,0 +1,173 @@
1
+/*****************************************************************************
2
+ * pce                                                                       *
3
+ *****************************************************************************/
4
+
5
+/*****************************************************************************
6
+ * File name:   src/utils/aym/play.c                                         *
7
+ * Created:     2015-05-21 by Hampa Hug <hampa@hampa.ch>                     *
8
+ * Copyright:   (C) 2015 Hampa Hug <hampa@hampa.ch>                          *
9
+ *****************************************************************************/
10
+
11
+/*****************************************************************************
12
+ * This program is free software. You can redistribute it and / or modify it *
13
+ * under the terms of the GNU General Public License version 2 as  published *
14
+ * by the Free Software Foundation.                                          *
15
+ *                                                                           *
16
+ * This program is distributed in the hope  that  it  will  be  useful,  but *
17
+ * WITHOUT  ANY   WARRANTY,   without   even   the   implied   warranty   of *
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  General *
19
+ * Public License for more details.                                          *
20
+ *****************************************************************************/
21
+
22
+
23
+#include "main.h"
24
+
25
+#include <stdlib.h>
26
+#include <stdio.h>
27
+#include <string.h>
28
+
29
+#include <arch/atarist/psg.h>
30
+#include <drivers/sound/sound.h>
31
+
32
+
33
+static
34
+void aym_delay (st_psg_t *psg, unsigned long long val)
35
+{
36
+	while (val > 255) {
37
+		st_psg_clock (psg, 8 * 256);
38
+		val -= 256;
39
+	}
40
+
41
+	while (val > 0) {
42
+		st_psg_clock (psg, 8);
43
+		val -= 1;
44
+	}
45
+}
46
+
47
+static
48
+int aym_play_psg (FILE *fp, st_psg_t *psg)
49
+{
50
+	int           c1, c2;
51
+	unsigned char v1, v2;
52
+	unsigned long vers;
53
+	unsigned char buf[8];
54
+
55
+	if (fread (buf, 1, 8, fp) != 8) {
56
+		return (1);
57
+	}
58
+
59
+	if (aym_get_uint32_be (buf, 0) != AYM_MAGIC) {
60
+		fprintf (stderr, "%s: not an aym file\n", arg0);
61
+		return (1);
62
+	}
63
+
64
+	if ((vers = aym_get_uint32_be (buf, 4)) != 0) {
65
+		fprintf (stderr, "%s: unknown aym version (%lu)\n", arg0, vers);
66
+		return (1);
67
+	}
68
+
69
+	while (1) {
70
+		c1 = fgetc (fp);
71
+		c2 = fgetc (fp);
72
+
73
+		if ((c1 == EOF) || (c2 == EOF)) {
74
+			fprintf (stderr, "%s: premature end of file\n", arg0);
75
+			return (0);
76
+		}
77
+
78
+		v1 = c1 & 0xff;
79
+		v2 = c2 & 0xff;
80
+
81
+		switch ((v1 >> 4) & 0x0f) {
82
+		case 0:
83
+			st_psg_set_select (psg, v1 & 0x0f);
84
+			st_psg_set_data (psg, v2);
85
+			break;
86
+
87
+		case 1:
88
+			aym_delay (psg, ((v1 & 0x0f) << 8) | v2);
89
+			break;
90
+
91
+		case 2:
92
+			aym_delay (psg, (unsigned long long) (((v1 & 0x0f) << 8) | v2) << 12);
93
+			break;
94
+
95
+		case 3:
96
+			aym_delay (psg, (unsigned long long) (((v1 & 0x0f) << 8) | v2) << 24);
97
+			break;
98
+
99
+		case 8:
100
+			printf ("TXT %u: ", v1 & 0x0f);
101
+
102
+			while (v2 > 0) {
103
+				if ((c1 = fgetc (fp)) == EOF) {
104
+					return (1);
105
+				}
106
+
107
+				fputc (c1, stdout);
108
+
109
+				v2 -= 1;
110
+			}
111
+			fputc ('\n', stdout);
112
+			break;
113
+
114
+		case 15:
115
+			if ((v1 == 0xff) && (v2 == 0xff)) {
116
+				aym_delay (psg, 250000);
117
+				return (0);
118
+			}
119
+		}
120
+	}
121
+
122
+	return (0);
123
+}
124
+
125
+static
126
+int aym_play_fp (FILE *fp, const char *snddrv, unsigned long lp, int hp)
127
+{
128
+	int         r;
129
+	sound_drv_t *drv;
130
+	st_psg_t    psg;
131
+
132
+	st_psg_init (&psg);
133
+
134
+	st_psg_set_srate (&psg, par_srate);
135
+
136
+	if (st_psg_set_driver (&psg, snddrv)) {
137
+		fprintf (stderr, "%s: bad sound driver (%s)\n", arg0, snddrv);
138
+		st_psg_free (&psg);
139
+		return (1);
140
+	}
141
+
142
+	drv = st_psg_get_driver (&psg);
143
+
144
+	snd_set_opts (drv, SND_OPT_NONBLOCK, 0);
145
+
146
+	st_psg_set_lowpass (&psg, lp);
147
+	st_psg_set_highpass (&psg, hp);
148
+
149
+	st_psg_reset (&psg);
150
+
151
+	r = aym_play_psg (fp, &psg);
152
+
153
+	st_psg_free (&psg);
154
+
155
+	return (r);
156
+}
157
+
158
+int aym_play (const char *fname, const char *snddrv, unsigned long lp, int hp)
159
+{
160
+	int  r;
161
+	FILE *fp;
162
+
163
+	if ((fp = fopen (fname, "rb")) == NULL) {
164
+		fprintf (stderr, "%s: can't open aym file (%s)\n", arg0, fname);
165
+		return (1);
166
+	}
167
+
168
+	r = aym_play_fp (fp, snddrv, lp, hp);
169
+
170
+	fclose (fp);
171
+
172
+	return (r);
173
+}

Loading…
Cancel
Save