fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
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-2016 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
30static
31int aym_decode_fp (FILE *inp, FILE *out, unsigned long th, 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) && (delay >= th)) {
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
146int aym_decode (const char *inp, const char *out, unsigned long th, 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, th, mark);
169
170 if (fout != stdout) {
171 fclose (fout);
172 }
173
174 if (finp != stdin) {
175 fclose (finp);
176 }
177
178 return (r);
179}