OpenCBM
gcr_4b5b.c
Go to the documentation of this file.
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 
21 #define DBG_USERMODE
22 
24 #define DBG_PROGNAME "OPENCBM.DLL"
25 
26 #include "debug.h"
27 
29 #define DLL
30 #include "opencbm.h"
31 
32 #include <stddef.h>
33 
80 int CBMAPIDECL
81 gcr_5_to_4_decode(const unsigned char *source, unsigned char *dest,
82  size_t sourceLength, size_t destLength)
83 {
84  int rv;
85 
86  FUNC_ENTER();
87 
88  DBG_ASSERT( (source != NULL ) && (sourceLength > 0) );
89  DBG_ASSERT( (dest != NULL ) && (destLength > 0) );
90  DBG_ASSERT( (dest < (source + 2)) || (dest > (source+4)) );
91 
92  if (sourceLength < 5)
93  {
94  DBG_WARN((DBG_PREFIX "*** source buffer is less than 5 bytes, only partial decoding done!"));
95  }
96  if (destLength < 4)
97  {
98  DBG_WARN((DBG_PREFIX "*** destination buffer is less than 4 bytes, only partial decoding done!"));
99  }
100 
101  if( (source == NULL) || (dest == NULL) || (sourceLength<=0) )
102  {
103  rv = -1;
104  }
105  else
106  {
107  int i;
108 
109  /* 255 denotes illegal GCR bytes, for error checking extensions */
110  static const unsigned char decodeGCR[32] =
111  {255,255,255,255,255,255,255,255,255, 8, 0, 1,255, 12, 4, 5,
112  255,255, 2, 3,255, 15, 6, 7,255, 9, 10, 11,255, 13, 14,255 };
113 
114  /* at least 24 bits for shifting into bits 16...20 */
115  register unsigned int tdest, nybble;
116 
117  rv = 0;
118 
119  tdest = *source;
120  tdest <<= 13;
121 
122  for(i = 5; (i < 13) && (destLength > 0); i += 2, dest++, destLength--)
123  {
124  source++, sourceLength--;
125  if(sourceLength > 0)
126  {
127  tdest |= ((unsigned int)(*source)) << i;
128  }
129  else
130  {
131  // no more input available, because GCR bytes
132  // with value 0 are not defined. But this must
133  // only be done, if at least one sourcebyte is
134  // already missing
135  if ( 0 == ((tdest >> 16) & 0x3ff) ) break;
136  }
137 
138  // "tdest >> 16" could be optimized to a word
139  // aligned access, hopefully the compiler does
140  // this for us (in a portable way)
141  nybble = decodeGCR[ (tdest >> 16) & 0x1f ];
142  if(nybble > 15) rv |= 2; // invalid GCR detected
143  *dest = nybble << 4;
144  tdest <<= 5;
145 
146  nybble = decodeGCR[ (tdest >> 16) & 0x1f ];
147  if(nybble > 15) rv |= 1; // invalid GCR detected
148  *dest |= (nybble & 0x0f);
149  tdest <<= 5;
150 
151  rv <<= 2; // mark invalid GCR codes, make room for new
152  }
153 
154  }
155 
156  FUNC_LEAVE_INT(rv);
157  return rv;
158 }
159 
205 int CBMAPIDECL
206 gcr_4_to_5_encode(const unsigned char *source, unsigned char *dest,
207  size_t sourceLength, size_t destLength)
208 {
209  int rv;
210 
211  FUNC_ENTER();
212 
213  DBG_ASSERT( (source != NULL ) && (sourceLength > 0) );
214  DBG_ASSERT( (dest != NULL ) && (destLength > 0) );
215  DBG_ASSERT( (dest <= source ) || (dest > (source+3)) );
216 
217  if (sourceLength < 4)
218  {
219  DBG_WARN((DBG_PREFIX "*** source buffer is less than 4 bytes, only partial decoding done!"));
220  }
221  if (destLength < 5)
222  {
223  DBG_WARN((DBG_PREFIX "*** destination buffer is less than 5 bytes, only partial decoding done!"));
224  }
225 
226  if( (source == NULL) || (dest == NULL) || (sourceLength<=0) )
227  {
228  rv = -1;
229  }
230  else
231  {
232  static const unsigned char encodeGCR[16] =
233  { 10, 11, 18, 19, 14, 15, 22, 23, 9, 25, 26, 27, 13, 29, 30, 21 };
234  int i;
235  /* at least 16 bits for overflow shifting */
236  register unsigned int tdest = 0;
237 
238  rv = 0;
239 
240  for( i = 2;
241  (i < 10) && (sourceLength > 0) && (destLength > 0);
242  i += 2, source++, sourceLength--, dest++, destLength--)
243  {
244  tdest <<= 5; /* make room for the upper nybble */
245  tdest |= encodeGCR[ (*source) >> 4 ];
246 
247  tdest <<= 5; /* make room for the lower nybble */
248  tdest |= encodeGCR[ (*source) & 0x0f ];
249 
250  *dest = (unsigned char)(tdest >> i);
251  }
252 
253  // (i == 10), if the loop exited normally
254  if(destLength > 0)
255  {
256  // There're bits in the line, either because it is the
257  // last one with bits from 0...7 or because the source
258  // buffer got to its end and the remaining bits could
259  // be written out partially.
260 
261  *dest = ((unsigned char)(tdest)) << ((10-i) & 0x07);
262  }
263  }
264 
265  FUNC_LEAVE_INT(rv);
266  return rv;
267 }
#define DBG_WARN(_xxx)
Definition: debug.h:395
#define FUNC_LEAVE_INT(_xxx)
Definition: debug.h:358
Define makros for debugging purposes.
#define CBMAPIDECL
Definition: opencbm.h:85
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
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
#define FUNC_ENTER()
Definition: debug.h:347
#define DBG_PREFIX
Definition: debug.h:320
DLL interface for accessing the driver.
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