···11+/*****************************************************************************
22+ * pce *
33+ *****************************************************************************/
44+55+/*****************************************************************************
66+ * File name: src/drivers/pfi/pfi-a2r.c *
77+ * Created: 2019-06-18 by Hampa Hug <hampa@hampa.ch> *
88+ * Copyright: (C) 2019 Hampa Hug <hampa@hampa.ch> *
99+ *****************************************************************************/
1010+1111+/*****************************************************************************
1212+ * This program is free software. You can redistribute it and / or modify it *
1313+ * under the terms of the GNU General Public License version 2 as published *
1414+ * by the Free Software Foundation. *
1515+ * *
1616+ * This program is distributed in the hope that it will be useful, but *
1717+ * WITHOUT ANY WARRANTY, without even the implied warranty of *
1818+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
1919+ * Public License for more details. *
2020+ *****************************************************************************/
2121+2222+2323+#include <stdlib.h>
2424+#include <stdio.h>
2525+#include <string.h>
2626+2727+#include "pfi.h"
2828+#include "pfi-io.h"
2929+#include "pfi-a2r.h"
3030+3131+3232+#ifndef DEBUG_A2R
3333+#define DEBUG_A2R 0
3434+#endif
3535+3636+3737+#define A2R_CLOCK 8000000
3838+3939+#define A2R_MAGIC_A2R2 0x32523241
4040+#define A2R_MAGIC_2 0x0a0d0aff
4141+#define A2R_MAGIC_INFO 0x4f464e49
4242+#define A2R_MAGIC_STRM 0x4d525453
4343+#define A2R_MAGIC_META 0x4154454d
4444+4545+4646+typedef struct {
4747+ FILE *fp;
4848+ pfi_img_t *img;
4949+ pfi_trk_t *trk;
5050+5151+ unsigned long c;
5252+ unsigned long h;
5353+ unsigned long loop;
5454+5555+ char have_info;
5656+ unsigned char disk_type;
5757+ unsigned char write_protected;
5858+ unsigned char synchronized;
5959+ char creator[33];
6060+} a2r_load_t;
6161+6262+6363+static
6464+void a2r_get_string (char *dst, const unsigned char *src, unsigned max)
6565+{
6666+ unsigned i;
6767+6868+ for (i = 0; i < max; i++) {
6969+ if ((dst[i] = src[i]) == 0) {
7070+ break;
7171+ }
7272+ }
7373+7474+ while ((i > 0) && (dst[i - 1] == 0x20)) {
7575+ i -= 1;
7676+ }
7777+7878+ dst[i] = 0;
7979+}
8080+8181+static
8282+int a2r_load_header (a2r_load_t *a2r)
8383+{
8484+ unsigned char buf[8];
8585+8686+ if (pfi_read (a2r->fp, buf, 8)) {
8787+ return (1);
8888+ }
8989+9090+ if (pfi_get_uint32_le (buf, 0) != A2R_MAGIC_A2R2) {
9191+ fprintf (stderr, "a2r: bad magic 1\n");
9292+ return (1);
9393+ }
9494+9595+ if (pfi_get_uint32_le (buf, 4) != A2R_MAGIC_2) {
9696+ fprintf (stderr, "a2r: bad magic 2\n");
9797+ return (1);
9898+ }
9999+100100+ return (0);
101101+}
102102+103103+static
104104+int a2r_load_meta (a2r_load_t *a2r, unsigned long size)
105105+{
106106+ unsigned n;
107107+ unsigned char buf[256];
108108+109109+ while (size > 0) {
110110+ n = (size < 256) ? size : 256;
111111+112112+ if (pfi_read (a2r->fp, buf, n)) {
113113+ return (1);
114114+ }
115115+116116+ if (pfi_img_add_comment (a2r->img, buf, n)) {
117117+ return (1);
118118+ }
119119+120120+ size -= n;
121121+ }
122122+123123+ return (0);
124124+}
125125+126126+static
127127+int a2r_load_info (a2r_load_t *a2r, unsigned long size)
128128+{
129129+ unsigned char buf[36];
130130+131131+ if (size < 36) {
132132+ return (1);
133133+ }
134134+135135+ if (pfi_read (a2r->fp, buf, 36)) {
136136+ return (1);
137137+ }
138138+139139+ if (buf[0] < 1) {
140140+ fprintf (stderr, "a2r: bad info version (%u)\n", buf[0]);
141141+ return (1);
142142+ }
143143+144144+ a2r_get_string (a2r->creator, buf + 1, 32);
145145+146146+ a2r->disk_type = buf[33];
147147+ a2r->write_protected = buf[34];
148148+ a2r->synchronized = buf[34];
149149+150150+#if DEBUG_A2R >= 1
151151+ fprintf (stderr, "a2r: creator = '%s'\n", a2r->creator);
152152+ fprintf (stderr, "a2r: disk type = %u\n", a2r->disk_type);
153153+ fprintf (stderr, "a2r: write protected = %u\n", a2r->write_protected);
154154+ fprintf (stderr, "a2r: synchronized = %u\n", a2r->synchronized);
155155+#endif
156156+157157+ if (pfi_skip (a2r->fp, size - 36)) {
158158+ return (1);
159159+ }
160160+161161+ return (0);
162162+}
163163+164164+static
165165+int a2r_load_capture (a2r_load_t *a2r, unsigned long size)
166166+{
167167+ unsigned i, n;
168168+ unsigned long pulse, index, total;
169169+ unsigned char buf[256];
170170+171171+ pulse = 0;
172172+ total = 0;
173173+ index = 0;
174174+175175+ i = 0;
176176+ n = 0;
177177+178178+ while (size > 0) {
179179+ if (total >= index) {
180180+ if (pfi_trk_add_index (a2r->trk, total)) {
181181+ return (1);
182182+ }
183183+184184+ index += a2r->loop;
185185+ }
186186+187187+ if (i >= n) {
188188+ i = 0;
189189+ n = (size < 256) ? size : 256;
190190+191191+ if (pfi_read (a2r->fp, buf, n)) {
192192+ return (1);
193193+ }
194194+ }
195195+196196+ if (buf[i] < 255) {
197197+ pulse += buf[i];
198198+199199+ if (pulse > 0) {
200200+ if (pfi_trk_add_pulse (a2r->trk, pulse)) {
201201+ return (1);
202202+ }
203203+ }
204204+205205+ total += pulse;
206206+ pulse = 0;
207207+ }
208208+ else {
209209+ pulse += 255;
210210+ }
211211+212212+ i += 1;
213213+ size -= 1;
214214+ }
215215+216216+ pfi_trk_clean (a2r->trk);
217217+218218+ return (0);
219219+}
220220+221221+static
222222+int a2r_load_strm (a2r_load_t *a2r, unsigned long size)
223223+{
224224+ unsigned long cnt;
225225+ unsigned char buf[10];
226226+227227+ while (size > 0) {
228228+ if (pfi_read (a2r->fp, buf, 1)) {
229229+ return (1);
230230+ }
231231+232232+ size -= 1;
233233+234234+ if (buf[0] == 0xff) {
235235+ break;
236236+ }
237237+238238+ if (size < 9) {
239239+ return (1);
240240+ }
241241+242242+ if (pfi_read (a2r->fp, buf + 1, 9)) {
243243+ return (1);
244244+ }
245245+246246+ size -= 9;
247247+248248+ if (a2r->disk_type == 1) {
249249+ a2r->c = buf[0];
250250+ a2r->h = 0;
251251+ }
252252+ else {
253253+ a2r->c = buf[0] >> 1;
254254+ a2r->h = buf[0] & 1;
255255+ }
256256+257257+ cnt = pfi_get_uint32_le (buf, 2);
258258+259259+ if (cnt > size) {
260260+ return (1);
261261+ }
262262+263263+ a2r->loop = pfi_get_uint32_le (buf, 6);
264264+265265+#if DEBUG_A2R >= 2
266266+ fprintf (stderr, "a2r: %lu/%lu TYPE=%u SIZE=%lu LOOP=%lu\n",
267267+ a2r->c, a2r->h, buf[1], cnt, a2r->loop
268268+ );
269269+#endif
270270+271271+ if ((buf[1] == 1) || (buf[1] == 3)) {
272272+ a2r->trk = pfi_img_get_track (a2r->img, a2r->c, a2r->h, 1);
273273+274274+ if (a2r->trk == NULL) {
275275+ return (1);
276276+ }
277277+278278+ pfi_trk_reset (a2r->trk);
279279+ pfi_trk_set_clock (a2r->trk, A2R_CLOCK);
280280+281281+ if (a2r_load_capture (a2r, cnt)) {
282282+ return (1);
283283+ }
284284+ }
285285+ else {
286286+ fprintf (stderr,
287287+ "a2r: warning: unsupported capture type (%u)\n",
288288+ buf[1]
289289+ );
290290+291291+ if (pfi_skip (a2r->fp, cnt)) {
292292+ return (1);
293293+ }
294294+ }
295295+296296+ size -= cnt;
297297+ }
298298+299299+ if (size > 0) {
300300+ fprintf (stderr,
301301+ "a2r: warning: %lu extra bytes in STRM chunk\n",
302302+ size
303303+ );
304304+305305+ if (pfi_skip (a2r->fp, size)) {
306306+ return (1);
307307+ }
308308+ }
309309+310310+ return (0);
311311+}
312312+313313+static
314314+int a2r_load_image (a2r_load_t *a2r)
315315+{
316316+ unsigned long type, size;
317317+ unsigned char buf[8];
318318+319319+ if (a2r_load_header (a2r)) {
320320+ return (1);
321321+ }
322322+323323+ a2r->have_info = 0;
324324+325325+ while (pfi_read (a2r->fp, buf, 8) == 0) {
326326+ type = pfi_get_uint32_le (buf, 0);
327327+ size = pfi_get_uint32_le (buf, 4);
328328+329329+#if DEBUG_A2R >= 2
330330+ fprintf (stderr, "chunk %08lX + %08lX\n", type, size);
331331+#endif
332332+333333+ if (type == A2R_MAGIC_INFO) {
334334+ if (a2r_load_info (a2r, size)) {
335335+ return (1);
336336+ }
337337+338338+ a2r->have_info = 1;
339339+ }
340340+ else if (type == A2R_MAGIC_STRM) {
341341+ if (a2r->have_info == 0) {
342342+ return (1);
343343+ }
344344+345345+ if (a2r_load_strm (a2r, size)) {
346346+ return (1);
347347+ }
348348+ }
349349+ else if (type == A2R_MAGIC_META) {
350350+ if (a2r_load_meta (a2r, size)) {
351351+ return (1);
352352+ }
353353+ }
354354+ else {
355355+ fprintf (stderr, "a2r: unknown chunck type (%08lX)\n",
356356+ type
357357+ );
358358+359359+ if (pfi_skip (a2r->fp, size)) {
360360+ return (1);
361361+ }
362362+ }
363363+ }
364364+365365+ return (0);
366366+}
367367+368368+pfi_img_t *pfi_load_a2r (FILE *fp)
369369+{
370370+ a2r_load_t a2r;
371371+372372+ a2r.fp = fp;
373373+ a2r.img = NULL;
374374+ a2r.trk = NULL;
375375+ a2r.have_info = 0;
376376+377377+ if ((a2r.img = pfi_img_new()) == NULL) {
378378+ return (NULL);
379379+ }
380380+381381+ if (a2r_load_image (&a2r)) {
382382+ pfi_img_del (a2r.img);
383383+ return (NULL);
384384+ }
385385+386386+ return (a2r.img);
387387+}
388388+389389+int pfi_probe_a2r_fp (FILE *fp)
390390+{
391391+ unsigned char buf[8];
392392+393393+ if (pfi_read (fp, buf, 8)) {
394394+ return (0);
395395+ }
396396+397397+ if (pfi_get_uint32_le (buf, 0) != A2R_MAGIC_A2R2) {
398398+ return (0);
399399+ }
400400+401401+ if (pfi_get_uint32_le (buf, 4) != A2R_MAGIC_2) {
402402+ return (0);
403403+ }
404404+405405+ return (1);
406406+}
407407+408408+int pfi_probe_a2r (const char *fname)
409409+{
410410+ int r;
411411+ FILE *fp;
412412+413413+ if ((fp = fopen (fname, "rb")) == NULL) {
414414+ return (0);
415415+ }
416416+417417+ r = pfi_probe_a2r_fp (fp);
418418+419419+ fclose (fp);
420420+421421+ return (r);
422422+}
+38
src/drivers/pfi/pfi-a2r.h
···11+/*****************************************************************************
22+ * pce *
33+ *****************************************************************************/
44+55+/*****************************************************************************
66+ * File name: src/drivers/pfi/pfi-a2r.h *
77+ * Created: 2019-06-18 by Hampa Hug <hampa@hampa.ch> *
88+ * Copyright: (C) 2019 Hampa Hug <hampa@hampa.ch> *
99+ *****************************************************************************/
1010+1111+/*****************************************************************************
1212+ * This program is free software. You can redistribute it and / or modify it *
1313+ * under the terms of the GNU General Public License version 2 as published *
1414+ * by the Free Software Foundation. *
1515+ * *
1616+ * This program is distributed in the hope that it will be useful, but *
1717+ * WITHOUT ANY WARRANTY, without even the implied warranty of *
1818+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
1919+ * Public License for more details. *
2020+ *****************************************************************************/
2121+2222+2323+#ifndef PFI_IMG_A2R_H
2424+#define PFI_IMG_A2R_H 1
2525+2626+2727+#include <drivers/pfi/pfi.h>
2828+2929+3030+pfi_img_t *pfi_load_a2r (FILE *fp);
3131+3232+int pfi_save_a2r (FILE *fp, const pfi_img_t *img);
3333+3434+int pfi_probe_a2r_fp (FILE *fp);
3535+int pfi_probe_a2r (const char *fname);
3636+3737+3838+#endif