OpenCBM
gcr.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2006 Wolfgang Moser (http://d81.de)
8  */
9 
10 #include "gcr.h"
11 
12 int gcr_decode(unsigned const char *gcr, unsigned char *decoded)
13 {
14  unsigned char chkref[4], chksum = 0;
15  int i,j;
16 
17  /* FIXME:
18  * Let's introduce buffer length specifiers and sanity checks,
19  * so the the following assumptions of length specifications
20  * of 4 and 5 become true.
21  */
22  gcr_5_to_4_decode(gcr, chkref, 5, sizeof(chkref));
23  gcr += 5;
24 
25  if(chkref[0] != 0x07)
26  {
27  return 4;
28  }
29 
30  /* move over the remaining three bytes */
31  for(j = 1; j < 4; j++, decoded++)
32  {
33  *decoded = chkref[j];
34  chksum ^= chkref[j];
35  }
36 
37  /* main block processing loop */
38  for(i = 1; i < BLOCKSIZE/4; i++)
39  {
40  gcr_5_to_4_decode(gcr, decoded, 5, 4);
41  gcr += 5;
42 
43  for(j = 0; j < 4; j++, decoded++)
44  {
45  chksum ^= *decoded;
46  }
47  }
48 
49  gcr_5_to_4_decode(gcr, chkref, 5, 4);
50  /* move over the remaining last byte */
51  *decoded = chkref[0];
52  chksum ^= chkref[0];
53 
54  return (chkref[1] != chksum) ? 5 : 0;
55 }
56 
57 int gcr_encode(unsigned const char *block, unsigned char *encoded)
58 {
59 
60  unsigned char chkref[4] = { 0x07, 0, 0, 0};
61  int i,j;
62 
63  /* FIXME:
64  * Let's introduce buffer length specifiers and sanity checks,
65  * so the the following assumptions of length specifications
66  * of 4 and 5 become true.
67  */
68 
69  /* start with encoding the data block
70  * identifier and the first three bytes
71  */
72  for(j = 1; j < 4; j++, block++)
73  {
74  chkref[j] = *block;
75  }
76  gcr_4_to_5_encode(chkref, encoded, sizeof(chkref), 5);
77  encoded += 5;
78 
79  /* add the three bytes into one checksum */
80  chkref[1] ^= (chkref[2] ^ chkref[3]);
81 
82  /* main block processing loop */
83  for(i = 1; i < BLOCKSIZE/4; i++)
84  {
85  gcr_4_to_5_encode(block, encoded, 4, 5);
86  encoded += 5;
87 
88  for(j = 0; j < 4; j++, block++)
89  {
90  /* directly encode the checksum */
91  chkref[1] ^= *block;
92  }
93  }
94 
95  /* move over the remaining last byte */
96  chkref[0] = *block;
97  /* add the last byte to the checksum */
98  chkref[1] ^= *block;
99 
100  /* clear trailing unused bytes, not necessary but somehow nicer */
101  chkref[2] = chkref[3] = 0;
102 
103  gcr_4_to_5_encode(chkref, encoded, 4, 5);
104 
105  return 0;
106 }
int CBMAPIDECL gcr_4_to_5_encode(const unsigned char *source, unsigned char *dest, size_t sourceLength, size_t destLength)
Encode GCR data.
Definition: gcr_4b5b.c:206
int CBMAPIDECL gcr_5_to_4_decode(const unsigned char *source, unsigned char *dest, size_t sourceLength, size_t destLength)
Decode GCR data.
Definition: gcr_4b5b.c:81