···11+/*****************************************************************************
22+ * pce *
33+ *****************************************************************************/
44+55+/*****************************************************************************
66+ * File name: src/drivers/pri/pri-img-pri.c *
77+ * Created: 2012-01-31 by Hampa Hug <hampa@hampa.ch> *
88+ * Copyright: (C) 2012-2013 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 "pri.h"
2828+#include "pri-img.h"
2929+#include "pri-img-pri.h"
3030+3131+3232+#define PRI_CHUNK_PRI 0x50524920
3333+#define PRI_CHUNK_TEXT 0x54455854
3434+#define PRI_CHUNK_TRAK 0x5452414b
3535+#define PRI_CHUNK_DATA 0x44415441
3636+#define PRI_CHUNK_CLOK 0x434c4f4b
3737+#define PRI_CHUNK_END 0x454e4420
3838+3939+#define PRI_CRC_POLY 0x1edc6f41
4040+4141+4242+static
4343+unsigned long pri_crc (unsigned long crc, const void *buf, unsigned cnt)
4444+{
4545+ unsigned i, j;
4646+ unsigned val;
4747+ unsigned long reg;
4848+ const unsigned char *src;
4949+ static int tab_ok = 0;
5050+ static unsigned long tab[256];
5151+5252+ if (tab_ok == 0) {
5353+ for (i = 0; i < 256; i++) {
5454+ reg = (unsigned long) i << 24;
5555+5656+ for (j = 0; j < 8; j++) {
5757+ if (reg & 0x80000000) {
5858+ reg = (reg << 1) ^ PRI_CRC_POLY;
5959+ }
6060+ else {
6161+ reg = reg << 1;
6262+ }
6363+ }
6464+6565+ tab[i] = reg;
6666+ }
6767+6868+ tab_ok = 1;
6969+ }
7070+7171+ src = buf;
7272+7373+ while (cnt > 0) {
7474+ val = (crc >> 24) ^ *(src++);
7575+ crc = (crc << 8) ^ tab[val & 0xff];
7676+ cnt -= 1;
7777+ }
7878+7979+ return (crc & 0xffffffff);
8080+}
8181+8282+static
8383+int pri_read_crc (FILE *fp, void *buf, unsigned cnt, unsigned long *crc)
8484+{
8585+ if (pri_read (fp, buf, cnt)) {
8686+ return (1);
8787+ }
8888+8989+ if (crc != NULL) {
9090+ *crc = pri_crc (*crc, buf, cnt);
9191+ }
9292+9393+ return (0);
9494+}
9595+9696+static
9797+int pri_write_crc (FILE *fp, const void *buf, unsigned cnt, unsigned long *crc)
9898+{
9999+ if (crc != NULL) {
100100+ *crc = pri_crc (*crc, buf, cnt);
101101+ }
102102+103103+ if (pri_write (fp, buf, cnt)) {
104104+ return (1);
105105+ }
106106+107107+ return (0);
108108+}
109109+110110+static
111111+int pri_skip_chunk (FILE *fp, unsigned long size, unsigned long crc)
112112+{
113113+ unsigned cnt;
114114+ unsigned char buf[256];
115115+116116+ while (size > 0) {
117117+ cnt = (size < 256) ? size : 256;
118118+119119+ if (pri_read_crc (fp, buf, cnt, &crc)) {
120120+ return (1);
121121+ }
122122+123123+ size -= cnt;
124124+ }
125125+126126+ if (pri_read (fp, buf, 4)) {
127127+ return (1);
128128+ }
129129+130130+ if (pri_get_uint32_be (buf, 0) != crc) {
131131+ fprintf (stderr, "pri: crc error\n");
132132+ return (1);
133133+ }
134134+135135+ return (0);
136136+}
137137+138138+static
139139+int pri_load_header (FILE *fp, pri_img_t *img, unsigned long size, unsigned long crc)
140140+{
141141+ unsigned char buf[4];
142142+ unsigned vers;
143143+144144+ if (size < 4) {
145145+ return (1);
146146+ }
147147+148148+ if (pri_read_crc (fp, buf, 4, &crc)) {
149149+ return (1);
150150+ }
151151+152152+ vers = pri_get_uint16_be (buf, 0);
153153+154154+ if (vers != 0) {
155155+ fprintf (stderr, "pri: unknown version number (%u)\n", vers);
156156+ return (1);
157157+ }
158158+159159+ if (pri_skip_chunk (fp, size - 4, crc)) {
160160+ return (1);
161161+ }
162162+163163+ return (0);
164164+}
165165+166166+static
167167+int pri_load_text (FILE *fp, pri_img_t *img, unsigned long size, unsigned long crc)
168168+{
169169+ int r;
170170+ unsigned long i, n;
171171+ unsigned char *buf;
172172+173173+ if (size == 0) {
174174+ return (pri_skip_chunk (fp, size, crc));
175175+ }
176176+177177+ if ((buf = malloc (size)) == NULL) {
178178+ return (1);
179179+ }
180180+181181+ if (pri_read_crc (fp, buf, size, &crc)) {
182182+ free (buf);
183183+ return (1);
184184+ }
185185+186186+ i = 0;
187187+ n = size;
188188+189189+ if (buf[0] == 0x0a) {
190190+ i = 1;
191191+ n -= 1;
192192+ }
193193+194194+ if ((n > 0) && (buf[n - 1] == 0x0a)) {
195195+ n -= 1;
196196+ }
197197+198198+ r = pri_img_add_comment (img, buf + i, n);
199199+200200+ free (buf);
201201+202202+ r |= pri_skip_chunk (fp, 0, crc);
203203+204204+ return (r);
205205+}
206206+207207+static
208208+int pri_load_trak (FILE *fp, pri_img_t *img, pri_trk_t **trk, unsigned long size, unsigned long crc)
209209+{
210210+ unsigned long c, h, n, clock;
211211+ unsigned char buf[16];
212212+213213+ if (size < 16) {
214214+ return (1);
215215+ }
216216+217217+ if (pri_read_crc (fp, buf, 16, &crc)) {
218218+ return (1);
219219+ }
220220+221221+ c = pri_get_uint32_be (buf, 0);
222222+ h = pri_get_uint32_be (buf, 4);
223223+ n = pri_get_uint32_be (buf, 8);
224224+ clock = pri_get_uint32_be (buf, 12);
225225+226226+ if ((*trk = pri_img_get_track (img, c, h, 1)) == NULL) {
227227+ return (1);
228228+ }
229229+230230+ if (pri_trk_set_size (*trk, n)) {
231231+ return (1);
232232+ }
233233+234234+ pri_trk_set_clock (*trk, clock);
235235+236236+ if (pri_skip_chunk (fp, size - 16, crc)) {
237237+ return (1);
238238+ }
239239+240240+ return (0);
241241+}
242242+243243+static
244244+int pri_load_data (FILE *fp, pri_img_t *img, pri_trk_t *trk, unsigned long size, unsigned long crc)
245245+{
246246+ unsigned long cnt;
247247+248248+ if (trk == NULL) {
249249+ return (1);
250250+ }
251251+252252+ cnt = (trk->size + 7) / 8;
253253+254254+ if (cnt > size) {
255255+ cnt = size;
256256+ }
257257+258258+ if (pri_read_crc (fp, trk->data, cnt, &crc)) {
259259+ return (1);
260260+ }
261261+262262+ if (pri_skip_chunk (fp, size - cnt, crc)) {
263263+ return (1);
264264+ }
265265+266266+ return (0);
267267+}
268268+269269+static
270270+int pri_load_image (FILE *fp, pri_img_t *img)
271271+{
272272+ unsigned long type, size;
273273+ unsigned long crc;
274274+ pri_trk_t *trk;
275275+ unsigned char buf[8];
276276+277277+ crc = 0;
278278+279279+ if (pri_read_crc (fp, buf, 4, &crc)) {
280280+ return (0);
281281+ }
282282+283283+ type = pri_get_uint32_be (buf, 0);
284284+285285+ if (type != PRI_CHUNK_PRI) {
286286+ return (1);
287287+ }
288288+289289+ if (pri_read_crc (fp, buf + 4, 4, &crc)) {
290290+ return (1);
291291+ }
292292+293293+ size = pri_get_uint32_be (buf, 4);
294294+295295+ if (pri_load_header (fp, img, size, crc)) {
296296+ return (1);
297297+ }
298298+299299+ trk = NULL;
300300+301301+ while (1) {
302302+ crc = 0;
303303+304304+ if (pri_read_crc (fp, buf, 8, &crc)) {
305305+ return (1);
306306+ }
307307+308308+ type = pri_get_uint32_be (buf, 0);
309309+ size = pri_get_uint32_be (buf, 4);
310310+311311+ switch (type) {
312312+ case PRI_CHUNK_END:
313313+ if (pri_skip_chunk (fp, size, crc)) {
314314+ return (1);
315315+ }
316316+ return (0);
317317+318318+ case PRI_CHUNK_TEXT:
319319+ if (pri_load_text (fp, img, size, crc)) {
320320+ return (1);
321321+ }
322322+ break;
323323+324324+ case PRI_CHUNK_TRAK:
325325+ if (pri_load_trak (fp, img, &trk, size, crc)) {
326326+ return (1);
327327+ }
328328+ break;
329329+330330+ case PRI_CHUNK_DATA:
331331+ if (pri_load_data (fp, img, trk, size, crc)) {
332332+ return (1);
333333+ }
334334+ break;
335335+336336+ default:
337337+ if (pri_skip_chunk (fp, size, crc)) {
338338+ return (1);
339339+ }
340340+ break;
341341+ }
342342+ }
343343+344344+ return (1);
345345+}
346346+347347+pri_img_t *pri_load_pri (FILE *fp)
348348+{
349349+ pri_img_t *img;
350350+351351+ if ((img = pri_img_new()) == NULL) {
352352+ return (NULL);
353353+ }
354354+355355+ if (pri_load_image (fp, img)) {
356356+ pri_img_del (img);
357357+ return (NULL);
358358+ }
359359+360360+ return (img);
361361+}
362362+363363+364364+static
365365+int pri_save_chunk (FILE *fp, unsigned ckid, unsigned size, const void *data)
366366+{
367367+ unsigned long crc;
368368+ unsigned char buf[8];
369369+370370+ pri_set_uint32_be (buf, 0, ckid);
371371+ pri_set_uint32_be (buf, 4, size);
372372+373373+ crc = 0;
374374+375375+ if (pri_write_crc (fp, buf, 8, &crc)) {
376376+ return (1);
377377+ }
378378+379379+ if (size > 0) {
380380+ if (pri_write_crc (fp, data, size, &crc)) {
381381+ return (1);
382382+ }
383383+ }
384384+385385+ pri_set_uint32_be (buf, 0, crc);
386386+387387+ if (pri_write_crc (fp, buf, 4, NULL)) {
388388+ return (1);
389389+ }
390390+391391+ return (0);
392392+}
393393+394394+static
395395+int pri_save_header (FILE *fp, const pri_img_t *img)
396396+{
397397+ unsigned char buf[4];
398398+399399+ pri_set_uint32_be (buf, 0, 0);
400400+401401+ if (pri_save_chunk (fp, PRI_CHUNK_PRI, 4, buf)) {
402402+ return (1);
403403+ }
404404+405405+ return (0);
406406+}
407407+408408+static
409409+int pri_save_text (FILE *fp, const pri_img_t *img)
410410+{
411411+ int r;
412412+ unsigned long crc;
413413+ unsigned char buf[16];
414414+415415+ if (img->comment_size == 0) {
416416+ return (0);
417417+ }
418418+419419+ pri_set_uint32_be (buf, 0, PRI_CHUNK_TEXT);
420420+ pri_set_uint32_be (buf, 4, img->comment_size + 2);
421421+422422+ buf[8] = 0x0a;
423423+424424+ crc = 0;
425425+426426+ r = pri_write_crc (fp, buf, 9, &crc);
427427+ r |= pri_write_crc (fp, img->comment, img->comment_size, &crc);
428428+ r |= pri_write_crc (fp, buf + 8, 1, &crc);
429429+ pri_set_uint32_be (buf, 0, crc);
430430+ r |= pri_write (fp, buf, 4);
431431+432432+ return (r);
433433+}
434434+435435+static
436436+int pri_save_trak (FILE *fp, const pri_trk_t *trk, unsigned long c, unsigned long h)
437437+{
438438+ unsigned char buf[16];
439439+440440+ pri_set_uint32_be (buf, 0, c);
441441+ pri_set_uint32_be (buf, 4, h);
442442+ pri_set_uint32_be (buf, 8, trk->size);
443443+ pri_set_uint32_be (buf, 12, trk->clock);
444444+445445+ if (pri_save_chunk (fp, PRI_CHUNK_TRAK, 16, buf)) {
446446+ return (1);
447447+ }
448448+449449+ return (0);
450450+}
451451+452452+static
453453+int pri_save_data (FILE *fp, const pri_trk_t *trk)
454454+{
455455+ unsigned long cnt, crc;
456456+ unsigned char buf[8];
457457+458458+ if (trk->size == 0) {
459459+ return (0);
460460+ }
461461+462462+ crc = 0;
463463+464464+ cnt = (trk->size + 7) / 8;
465465+466466+ pri_set_uint32_be (buf, 0, PRI_CHUNK_DATA);
467467+ pri_set_uint32_be (buf, 4, cnt);
468468+469469+ if (pri_write_crc (fp, buf, 8, &crc)) {
470470+ return (1);
471471+ }
472472+473473+ if (pri_write_crc (fp, trk->data, cnt, &crc)) {
474474+ return (1);
475475+ }
476476+477477+ pri_set_uint32_be (buf, 0, crc);
478478+479479+ if (pri_write (fp, buf, 4)) {
480480+ return (1);
481481+ }
482482+483483+ return (0);
484484+}
485485+486486+static
487487+int pri_save_track (FILE *fp, const pri_trk_t *trk, unsigned long c, unsigned long h)
488488+{
489489+ if (pri_save_trak (fp, trk, c, h)) {
490490+ return (1);
491491+ }
492492+493493+ if (pri_save_data (fp, trk)) {
494494+ return (1);
495495+ }
496496+497497+ return (0);
498498+}
499499+500500+int pri_save_pri (FILE *fp, const pri_img_t *img)
501501+{
502502+ unsigned long c, h;
503503+ pri_cyl_t *cyl;
504504+ pri_trk_t *trk;
505505+506506+ if (pri_save_header (fp, img)) {
507507+ return (1);
508508+ }
509509+510510+ if (pri_save_text (fp, img)) {
511511+ return (1);
512512+ }
513513+514514+ for (c = 0; c < img->cyl_cnt; c++) {
515515+ if ((cyl = img->cyl[c]) == NULL) {
516516+ continue;
517517+ }
518518+519519+ for (h = 0; h < cyl->trk_cnt; h++) {
520520+ if ((trk = cyl->trk[h]) == NULL) {
521521+ continue;
522522+ }
523523+524524+ if (pri_save_track (fp, trk, c, h)) {
525525+ return (1);
526526+ }
527527+ }
528528+ }
529529+530530+ if (pri_save_chunk (fp, PRI_CHUNK_END, 0, NULL)) {
531531+ return (1);
532532+ }
533533+534534+ return (0);
535535+}
536536+537537+538538+int pri_probe_pri_fp (FILE *fp)
539539+{
540540+ unsigned char buf[4];
541541+542542+ if (pri_read_ofs (fp, 0, buf, 4)) {
543543+ return (0);
544544+ }
545545+546546+ if (pri_get_uint32_be (buf, 0) != PRI_CHUNK_PRI) {
547547+ return (0);
548548+ }
549549+550550+ return (1);
551551+}
552552+553553+int pri_probe_pri (const char *fname)
554554+{
555555+ int r;
556556+ FILE *fp;
557557+558558+ if ((fp = fopen (fname, "rb")) == NULL) {
559559+ return (0);
560560+ }
561561+562562+ r = pri_probe_pri_fp (fp);
563563+564564+ fclose (fp);
565565+566566+ return (r);
567567+}
+38
src/drivers/pri/pri-img-pri.h
···11+/*****************************************************************************
22+ * pce *
33+ *****************************************************************************/
44+55+/*****************************************************************************
66+ * File name: src/drivers/pri/pri-img-pri.h *
77+ * Created: 2012-01-31 by Hampa Hug <hampa@hampa.ch> *
88+ * Copyright: (C) 2012-2013 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 PCE_PRI_IMG_PRI_H
2424+#define PCE_PRI_IMG_PRI_H 1
2525+2626+2727+#include <drivers/pri/pri.h>
2828+2929+3030+pri_img_t *pri_load_pri (FILE *fp);
3131+3232+int pri_save_pri (FILE *fp, const pri_img_t *img);
3333+3434+int pri_probe_pri_fp (FILE *fp);
3535+int pri_probe_pfdc (const char *fname);
3636+3737+3838+#endif
···5252.RS
5353.TP
5454.B pbit
5555-The native PBIT file format.
5555+The PBIT file format. This has been superseded by PRI.
5656+.TP
5757+.B pri
5858+The native PCE raw image file format.
5659.TP
5760.B tc
5861Transcopy dump format. Support for this format is highly experimental.