fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/utils/pri/decode.c *
7 * Created: 2013-12-19 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2013-2025 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 <stdio.h>
26#include <string.h>
27
28#include <drivers/psi/psi-img.h>
29#include <drivers/psi/psi.h>
30
31#include <drivers/pri/pri.h>
32#include <drivers/pri/pri-img.h>
33#include <drivers/pri/pri-enc-fm.h>
34#include <drivers/pri/pri-enc-gcr.h>
35#include <drivers/pri/pri-enc-mfm.h>
36
37
38struct pri_decode_psi_s {
39 psi_img_t *img;
40 pri_dec_mfm_t mfm;
41};
42
43
44extern pri_dec_mfm_t par_dec_mfm;
45
46
47static
48int pri_decode_fm_raw_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
49{
50 FILE *fp;
51 unsigned outbuf, outcnt;
52 unsigned val, clk;
53 unsigned long bit;
54
55 fp = opaque;
56
57 pri_trk_set_pos (trk, 0);
58
59 val = 0;
60 clk = 0xffff;
61
62 outbuf = 0;
63 outcnt = 0;
64
65 while (trk->wrap == 0) {
66 pri_trk_get_bits (trk, &bit, 1);
67
68 val = ((val << 1) | (bit & 1)) & 0xffff;
69 clk = (clk << 1) | (~clk & val & 1);
70
71 if ((val == 0xf57e) || (val == 0xf56f) || (val == 0xf56a)) {
72 clk = 0xaaaa;
73
74 if (outcnt > 0) {
75 outbuf = outbuf << (8 - outcnt);
76 outcnt = 8;
77 }
78 }
79 else if ((clk & 0x8000) == 0) {
80 outbuf = (outbuf << 1) | ((val >> 15) & 1);
81 outcnt += 1;
82 }
83
84 if (outcnt >= 8) {
85 fputc (outbuf & 0xff, fp);
86 outbuf = 0;
87 outcnt = 0;
88 }
89 }
90
91 return (0);
92}
93
94static
95int pri_decode_fm_raw (pri_img_t *img, const char *fname)
96{
97 int r;
98 FILE *fp;
99
100 if ((fp = fopen (fname, "wb")) == NULL) {
101 return (1);
102 }
103
104 r = pri_for_all_tracks (img, pri_decode_fm_raw_cb, fp);
105
106 fclose (fp);
107
108 return (r);
109}
110
111
112static
113int pri_decode_gcr_raw_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
114{
115 FILE *fp;
116 unsigned val;
117 unsigned long bit;
118
119 fp = opaque;
120
121 pri_trk_set_pos (trk, 0);
122
123 val = 0;
124
125 while (trk->wrap == 0) {
126 pri_trk_get_bits (trk, &bit, 1);
127
128 val = (val << 1) | (bit & 1);
129
130 if (val & 0x80) {
131 fputc (val, fp);
132 val = 0;
133 }
134 }
135
136 return (0);
137}
138
139static
140int pri_decode_gcr_raw (pri_img_t *img, const char *fname)
141{
142 int r;
143 FILE *fp;
144
145 fp = fopen (fname, "wb");
146
147 if (fp == NULL) {
148 return (1);
149 }
150
151 r = pri_for_all_tracks (img, pri_decode_gcr_raw_cb, fp);
152
153 fclose (fp);
154
155 return (r);
156}
157
158
159static
160int pri_decode_mfm_raw_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
161{
162 FILE *fp;
163 unsigned outbuf, outcnt;
164 unsigned val, clk;
165 unsigned long bit;
166
167 fp = opaque;
168
169 pri_trk_set_pos (trk, 0);
170
171 val = 0;
172 clk = 0;
173
174 outbuf = 0;
175 outcnt = 0;
176
177 while (trk->wrap == 0) {
178 pri_trk_get_bits (trk, &bit, 1);
179
180 val = (val << 1) | (bit & 1);
181 clk = (clk << 1) | (~clk & 1);
182
183 if ((clk & 1) == 0) {
184 outbuf = (outbuf << 1) | (val & 1);
185 outcnt += 1;
186 }
187
188 if ((val & 0xffff) == 0x4489) {
189 outbuf = 0xa1;
190 outcnt = 8;
191 clk = 0;
192 }
193
194 if (outcnt >= 8) {
195 fputc (outbuf & 0xff, fp);
196 outbuf = 0;
197 outcnt = 0;
198 }
199 }
200
201 return (0);
202}
203
204static
205int pri_decode_mfm_raw (pri_img_t *img, const char *fname)
206{
207 int r;
208 FILE *fp;
209
210 fp = fopen (fname, "wb");
211
212 if (fp == NULL) {
213 return (1);
214 }
215
216 r = pri_for_all_tracks (img, pri_decode_mfm_raw_cb, fp);
217
218 fclose (fp);
219
220 return (r);
221}
222
223
224static
225int pri_decode_raw_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
226{
227 FILE *fp;
228
229 fp = opaque;
230
231 if (fwrite (trk->data, (trk->size + 7) / 8, 1, fp) != 1) {
232 return (1);
233 }
234
235 return (0);
236}
237
238int pri_decode_raw (pri_img_t *img, const char *fname)
239{
240 int r;
241 FILE *fp;
242
243 fp = fopen (fname, "wb");
244
245 if (fp == NULL) {
246 return (1);
247 }
248
249 r = pri_for_all_tracks (img, pri_decode_raw_cb, fp);
250
251 fclose (fp);
252
253 return (r);
254}
255
256
257static
258int pri_decode_psi_auto_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
259{
260 psi_trk_t *dtrk;
261 struct pri_decode_psi_s *dec;
262
263 dec = opaque;
264
265 if ((dtrk = pri_decode_mfm_trk (trk, c, h, &dec->mfm)) == NULL) {
266 return (1);
267 }
268
269 if (dtrk->sct_cnt == 0) {
270 psi_trk_del (dtrk);
271
272 if ((dtrk = pri_decode_fm_trk (trk, h)) == NULL) {
273 return (1);
274 }
275 }
276
277 if (dtrk->sct_cnt == 0) {
278 psi_trk_del (dtrk);
279
280 if ((dtrk = pri_decode_gcr_trk (trk, h)) == NULL) {
281 return (1);
282 }
283 }
284
285 if (psi_img_set_track (dec->img, dtrk, c, h)) {
286 psi_trk_del (dtrk);
287 return (1);
288 }
289
290 return (0);
291}
292
293static
294int pri_decode_psi_mfm_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
295{
296 psi_trk_t *dtrk;
297 struct pri_decode_psi_s *dec;
298
299 dec = opaque;
300
301 if ((dtrk = pri_decode_mfm_trk (trk, c, h, &dec->mfm)) == NULL) {
302 return (1);
303 }
304
305 if (psi_img_set_track (dec->img, dtrk, c, h)) {
306 psi_trk_del (dtrk);
307 return (1);
308 }
309
310 return (0);
311}
312
313static
314int pri_decode_psi_fm_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
315{
316 psi_trk_t *dtrk;
317 struct pri_decode_psi_s *dec;
318
319 dec = opaque;
320
321 if ((dtrk = pri_decode_fm_trk (trk, h)) == NULL) {
322 return (1);
323 }
324
325 if (psi_img_set_track (dec->img, dtrk, c, h)) {
326 psi_trk_del (dtrk);
327 return (1);
328 }
329
330 return (0);
331}
332
333static
334int pri_decode_psi_gcr_cb (pri_img_t *img, pri_trk_t *trk, unsigned long c, unsigned long h, void *opaque)
335{
336 psi_trk_t *dtrk;
337 struct pri_decode_psi_s *dec;
338
339 dec = opaque;
340
341 if ((dtrk = pri_decode_gcr_trk (trk, h)) == NULL) {
342 return (1);
343 }
344
345 if (psi_img_set_track (dec->img, dtrk, c, h)) {
346 psi_trk_del (dtrk);
347 return (1);
348 }
349
350 return (0);
351}
352
353static
354int pri_decode_psi (pri_img_t *img, const char *type, const char *fname)
355{
356 int r;
357 pri_trk_cb fct;
358 struct pri_decode_psi_s dec;
359
360 dec.mfm = par_dec_mfm;
361
362 if (strcmp2 (type, "auto", "mfm-fm") == 0) {
363 fct = pri_decode_psi_auto_cb;
364 }
365 else if (strcmp2 (type, "ibm-fm", "fm") == 0) {
366 fct = pri_decode_psi_fm_cb;
367 }
368 else if (strcmp2 (type, "mac-gcr", "gcr") == 0) {
369 fct = pri_decode_psi_gcr_cb;
370 }
371 else if (strcmp2 (type, "ibm-mfm", "mfm") == 0) {
372 fct = pri_decode_psi_mfm_cb;
373 }
374 else {
375 fprintf (stderr, "%s: unknown decode type (%s)\n", arg0, type);
376 return (1);
377 }
378
379 if ((dec.img = psi_img_new()) == NULL) {
380 return (1);
381 }
382
383 if (pri_for_all_tracks (img, fct, &dec)) {
384 psi_img_del (dec.img);
385 return (1);
386 }
387
388 if (img->comment_size > 0) {
389 psi_img_set_comment (dec.img, img->comment, img->comment_size);
390 }
391
392 if (par_psi_dec_pos == 0) {
393 psi_img_clear_position (dec.img);
394 }
395
396 r = psi_save (fname, dec.img, PSI_FORMAT_NONE);
397
398 psi_img_del (dec.img);
399
400 return (r);
401}
402
403
404int pri_decode (pri_img_t *img, const char *type, const char *fname)
405{
406 if (strcmp (type, "fm-raw") == 0) {
407 return (pri_decode_fm_raw (img, fname));
408 }
409 else if (strcmp (type, "gcr-raw") == 0) {
410 return (pri_decode_gcr_raw (img, fname));
411 }
412 else if (strcmp (type, "mfm-raw") == 0) {
413 return (pri_decode_mfm_raw (img, fname));
414 }
415 else if (strcmp (type, "text") == 0) {
416 return (pri_decode_text (img, fname, PRI_TEXT_AUTO));
417 }
418 else if (strcmp (type, "text-fm") == 0) {
419 return (pri_decode_text (img, fname, PRI_TEXT_FM));
420 }
421 else if (strcmp (type, "text-mac") == 0) {
422 return (pri_decode_text (img, fname, PRI_TEXT_MAC));
423 }
424 else if (strcmp (type, "text-mfm") == 0) {
425 return (pri_decode_text (img, fname, PRI_TEXT_MFM));
426 }
427 else if (strcmp (type, "text-raw") == 0) {
428 return (pri_decode_text (img, fname, PRI_TEXT_RAW));
429 }
430 else if (strcmp (type, "raw") == 0) {
431 return (pri_decode_raw (img, fname));
432 }
433 else {
434 return (pri_decode_psi (img, type, fname));
435 }
436}