Search
lxdream.org :: lxdream/src/gdrom/edc_ecc.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/edc_ecc.c
changeset 678:35eb00945316
prev669:ab344e42bca9
author nkeynes
date Tue Oct 14 08:44:37 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Fix a few more subtle flag problems
file annotate diff log raw
nkeynes@644
     1
/*
nkeynes@644
     2
 * Note: This file has been extracted from crkit 1.1.6 and modified to work within
nkeynes@669
     3
 * lxdream. 
nkeynes@644
     4
 */
nkeynes@644
     5
/*
nkeynes@644
     6
 * This file has been modified for the cdrkit suite.
nkeynes@644
     7
 *
nkeynes@644
     8
 * The behaviour and appearence of the program code below can differ to a major
nkeynes@644
     9
 * extent from the version distributed by the original author(s).
nkeynes@644
    10
 *
nkeynes@644
    11
 * For details, see Changelog file distributed with the cdrkit package. If you
nkeynes@644
    12
 * received this file from another source then ask the distributing person for
nkeynes@644
    13
 * a log of modifications.
nkeynes@644
    14
 *
nkeynes@644
    15
 */
nkeynes@644
    16
nkeynes@644
    17
/* @(#)edc_ecc.c	1.21 03/04/04 Copyright 1998-2002 Heiko Eissfeldt, Joerg Schilling */
nkeynes@644
    18
nkeynes@644
    19
/*
nkeynes@644
    20
 * Copyright 1998-2002 by Heiko Eissfeldt
nkeynes@644
    21
 * Copyright 2002 by Joerg Schilling
nkeynes@644
    22
 *
nkeynes@644
    23
 * This file contains protected intellectual property.
nkeynes@644
    24
 *
nkeynes@644
    25
 * reed-solomon encoder / decoder for compact discs.
nkeynes@644
    26
 *
nkeynes@644
    27
 */
nkeynes@644
    28
/*
nkeynes@644
    29
 * This program is free software; you can redistribute it and/or modify
nkeynes@644
    30
 * it under the terms of the GNU General Public License version 2
nkeynes@644
    31
 * as published by the Free Software Foundation.
nkeynes@644
    32
 *
nkeynes@644
    33
 * This program is distributed in the hope that it will be useful,
nkeynes@644
    34
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@644
    35
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@644
    36
 * GNU General Public License for more details.
nkeynes@644
    37
 *
nkeynes@644
    38
 * You should have received a copy of the GNU General Public License along with
nkeynes@644
    39
 * this program; see the file COPYING.  If not, write to the Free Software
nkeynes@644
    40
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
nkeynes@644
    41
 */
nkeynes@644
    42
nkeynes@644
    43
#include <stdint.h>
nkeynes@644
    44
#include <stdio.h>
nkeynes@644
    45
#include <string.h>
nkeynes@678
    46
#include "gdrom/gddriver.h"
nkeynes@644
    47
#include "ecc.h"
nkeynes@644
    48
nkeynes@644
    49
#define xaligned(a, s)          ((((uintptr_t)(a)) & (s)) == 0 )
nkeynes@644
    50
nkeynes@669
    51
int do_encode_L2(unsigned char inout[(12 + 4 + L2_RAW+4+8+L2_Q+L2_P)], 
nkeynes@669
    52
					  int sectortype, unsigned address);
nkeynes@644
    53
nkeynes@669
    54
int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR],
nkeynes@669
    55
		 unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
nkeynes@669
    56
		 int delay1, int delay2, int delay3, int permute);
nkeynes@669
    57
nkeynes@669
    58
int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
nkeynes@669
    59
		unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
nkeynes@669
    60
		int delay1, int permute);
nkeynes@669
    61
nkeynes@669
    62
int do_decode_L2(unsigned char in[(L2_RAW+L2_Q+L2_P)], 
nkeynes@669
    63
			unsigned char out[L2_RAW]);
nkeynes@669
    64
nkeynes@669
    65
int do_decode_L1(unsigned char in[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR],
nkeynes@669
    66
			unsigned char out[L1_RAW*FRAMES_PER_SECTOR],
nkeynes@669
    67
			int delay1, int delay2, int delay3, int permute);
nkeynes@669
    68
nkeynes@669
    69
int do_decode_sub(unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME],
nkeynes@669
    70
		  unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME],
nkeynes@669
    71
		  int delay1, int permute);
nkeynes@669
    72
nkeynes@644
    73
nkeynes@644
    74
nkeynes@644
    75
/* ------------- tables generated by gen_encodes --------------*/
nkeynes@644
    76
nkeynes@644
    77
#include "edc_scramble.h"
nkeynes@644
    78
nkeynes@644
    79
#define	DO4(a)	a;a;a;a;
nkeynes@644
    80
#define	DO13(a)	a;a;a;a;a;a;a;a;a;a;a;a;a;
nkeynes@644
    81
nkeynes@644
    82
/*
nkeynes@644
    83
 * Scrambles 2352 - 12 = 2340 bytes
nkeynes@644
    84
 */
nkeynes@644
    85
int scramble_L2(unsigned char *inout);
nkeynes@644
    86
nkeynes@644
    87
int scramble_L2(unsigned char *inout)
nkeynes@644
    88
{
nkeynes@644
    89
#ifndef	EDC_SCRAMBLE_NOSWAP
nkeynes@644
    90
	unsigned int *f = (unsigned int *)inout;
nkeynes@644
    91
#endif
nkeynes@644
    92
nkeynes@644
    93
	if (!xaligned(inout + 12, sizeof(uint32_t)-1)) {
nkeynes@644
    94
nkeynes@644
    95
		uint8_t		*r = inout + 12;
nkeynes@644
    96
		const uint8_t	*s = yellowbook_scrambler;
nkeynes@644
    97
		register int	i;
nkeynes@644
    98
nkeynes@644
    99
		for (i = (L2_RAW + L2_Q + L2_P +16)/sizeof(unsigned char)/4; --i >= 0;) {
nkeynes@644
   100
			DO4(*r++ ^= *s++);
nkeynes@644
   101
		}
nkeynes@644
   102
nkeynes@644
   103
	} else {
nkeynes@644
   104
		uint32_t	*r = (uint32_t *) (inout + 12);
nkeynes@644
   105
		const uint32_t  *s = yellowbook_scrambler_uint32;
nkeynes@644
   106
		register int	i;
nkeynes@644
   107
nkeynes@644
   108
		for (i = (L2_RAW + L2_Q + L2_P +16)/sizeof(uint32_t)/13; --i >= 0;) {
nkeynes@644
   109
			DO13(*r++ ^= *s++);
nkeynes@644
   110
		}
nkeynes@644
   111
	}
nkeynes@644
   112
nkeynes@644
   113
#ifndef	EDC_SCRAMBLE_NOSWAP
nkeynes@644
   114
nkeynes@644
   115
	/* generate F1 frames */
nkeynes@644
   116
	for (i = 2352/sizeof(unsigned int); i; i--) {
nkeynes@644
   117
		*f++ = ((*f & 0xff00ff00UL) >> 8) | ((*f & 0x00ff00ffUL) << 8);
nkeynes@644
   118
	}
nkeynes@644
   119
#endif
nkeynes@644
   120
nkeynes@644
   121
	return (0);
nkeynes@644
   122
}
nkeynes@644
   123
nkeynes@644
   124
#include "edc_l2sq.h"
nkeynes@644
   125
nkeynes@644
   126
static int encode_L2_Q(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q]);
nkeynes@644
   127
nkeynes@644
   128
static int encode_L2_Q(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P + L2_Q])
nkeynes@644
   129
{
nkeynes@644
   130
	unsigned char *dps;
nkeynes@644
   131
	unsigned char *dp;
nkeynes@644
   132
	unsigned char *Q;
nkeynes@644
   133
	register int i;
nkeynes@644
   134
	int j;
nkeynes@644
   135
nkeynes@644
   136
	Q = inout + 4 + L2_RAW + 4 + 8 + L2_P;
nkeynes@644
   137
nkeynes@644
   138
	dps = inout;
nkeynes@644
   139
	for (j = 0; j < 26; j++) {
nkeynes@644
   140
		register unsigned short a;
nkeynes@644
   141
		register unsigned short b;
nkeynes@644
   142
		a = b = 0;
nkeynes@644
   143
nkeynes@644
   144
		dp = dps;
nkeynes@644
   145
		for (i = 0; i < 43; i++) {
nkeynes@644
   146
nkeynes@644
   147
			/* LSB */
nkeynes@644
   148
			a ^= L2sq[i][*dp++];
nkeynes@644
   149
nkeynes@644
   150
			/* MSB */
nkeynes@644
   151
			b ^= L2sq[i][*dp];
nkeynes@644
   152
nkeynes@644
   153
			dp += 2*44-1;
nkeynes@644
   154
			if (dp >= &inout[(4 + L2_RAW + 4 + 8 + L2_P)]) {
nkeynes@644
   155
				dp -= (4 + L2_RAW + 4 + 8 + L2_P);
nkeynes@644
   156
			} 
nkeynes@644
   157
		}
nkeynes@644
   158
		Q[0]      = a >> 8;
nkeynes@644
   159
		Q[26*2]   = a;
nkeynes@644
   160
		Q[1]      = b >> 8;
nkeynes@644
   161
		Q[26*2+1] = b;
nkeynes@644
   162
nkeynes@644
   163
		Q += 2;
nkeynes@644
   164
		dps += 2*43;
nkeynes@644
   165
	}
nkeynes@644
   166
	return (0);
nkeynes@644
   167
}
nkeynes@644
   168
nkeynes@644
   169
static int encode_L2_P(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P]);
nkeynes@644
   170
nkeynes@644
   171
static int encode_L2_P(unsigned char inout[4 + L2_RAW + 4 + 8 + L2_P])
nkeynes@644
   172
{
nkeynes@644
   173
	unsigned char *dp;
nkeynes@644
   174
	unsigned char *P;
nkeynes@644
   175
	register int i;
nkeynes@644
   176
	int j;
nkeynes@644
   177
nkeynes@644
   178
	P = inout + 4 + L2_RAW + 4 + 8;
nkeynes@644
   179
nkeynes@644
   180
	for (j = 0; j < 43; j++) {
nkeynes@644
   181
		register unsigned short a;
nkeynes@644
   182
		register unsigned short b;
nkeynes@644
   183
nkeynes@644
   184
		a = b = 0;
nkeynes@644
   185
		dp = inout;
nkeynes@644
   186
		for (i = 19; i < 43; i++) {
nkeynes@644
   187
nkeynes@644
   188
			/* LSB */
nkeynes@644
   189
			a ^= L2sq[i][*dp++];
nkeynes@644
   190
nkeynes@644
   191
			/* MSB */
nkeynes@644
   192
			b ^= L2sq[i][*dp];
nkeynes@644
   193
nkeynes@644
   194
			dp += 2*43 -1;
nkeynes@644
   195
		}
nkeynes@644
   196
		P[0]      = a >> 8;
nkeynes@644
   197
		P[43*2]   = a;
nkeynes@644
   198
		P[1]      = b >> 8;
nkeynes@644
   199
		P[43*2+1] = b;
nkeynes@644
   200
nkeynes@644
   201
		P += 2;
nkeynes@644
   202
		inout += 2;
nkeynes@644
   203
	}
nkeynes@644
   204
	return (0);
nkeynes@644
   205
}
nkeynes@644
   206
nkeynes@644
   207
static unsigned char bin2bcd(unsigned p);
nkeynes@644
   208
nkeynes@644
   209
static unsigned char bin2bcd(unsigned p)
nkeynes@644
   210
{
nkeynes@644
   211
	return ((p/10)<<4)|(p%10);
nkeynes@644
   212
}
nkeynes@644
   213
nkeynes@644
   214
int cd_build_address(unsigned char inout[], int sectortype, unsigned address)
nkeynes@644
   215
{
nkeynes@644
   216
	inout[12] = bin2bcd(address / (60*75));
nkeynes@644
   217
	inout[13] = bin2bcd((address / 75) % 60);
nkeynes@644
   218
	inout[14] = bin2bcd(address % 75);
nkeynes@644
   219
	if (sectortype == MODE_0)
nkeynes@644
   220
		inout[15] = 0;
nkeynes@644
   221
	else if (sectortype == MODE_1)
nkeynes@644
   222
		inout[15] = 1;
nkeynes@644
   223
	else if (sectortype == MODE_2)
nkeynes@644
   224
		inout[15] = 2;
nkeynes@644
   225
	else if (sectortype == MODE_2_FORM_1)
nkeynes@644
   226
		inout[15] = 2;
nkeynes@644
   227
	else if (sectortype == MODE_2_FORM_2)
nkeynes@644
   228
		inout[15] = 2;
nkeynes@644
   229
	else
nkeynes@644
   230
		return (-1);
nkeynes@644
   231
	return (0);
nkeynes@644
   232
}
nkeynes@644
   233
nkeynes@644
   234
#include "edc_crctable.h"
nkeynes@644
   235
nkeynes@644
   236
/*
nkeynes@644
   237
 * Called with 2064, 2056 or 2332 byte difference - all dividable by 4.
nkeynes@644
   238
 */
nkeynes@644
   239
unsigned int build_edc(unsigned char inout[], int from, int upto);
nkeynes@644
   240
nkeynes@644
   241
unsigned int build_edc(unsigned char inout[], int from, int upto)
nkeynes@644
   242
{
nkeynes@644
   243
	unsigned char *p = inout+from;
nkeynes@644
   244
	unsigned int result = 0;
nkeynes@644
   245
nkeynes@644
   246
	upto -= from-1;
nkeynes@644
   247
	upto /= 4;
nkeynes@644
   248
	while (--upto >= 0) {
nkeynes@644
   249
		result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
nkeynes@644
   250
		result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
nkeynes@644
   251
		result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
nkeynes@644
   252
		result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
nkeynes@644
   253
	}
nkeynes@644
   254
	return (result);
nkeynes@644
   255
}
nkeynes@644
   256
nkeynes@644
   257
/* Layer 2 Product code en/decoder */
nkeynes@669
   258
nkeynes@644
   259
int do_encode_L2(unsigned char inout[(12 + 4 + L2_RAW+4+8+L2_Q+L2_P)], 
nkeynes@669
   260
		 int sectortype, unsigned address)
nkeynes@644
   261
{
nkeynes@644
   262
	unsigned int result;
nkeynes@644
   263
nkeynes@644
   264
/*	SYNCPATTERN "\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" */
nkeynes@644
   265
#define SYNCPATTERN "\000\377\377\377\377\377\377\377\377\377\377"
nkeynes@644
   266
nkeynes@644
   267
	/* supply initial sync pattern */
nkeynes@644
   268
	memcpy(inout, SYNCPATTERN, sizeof(SYNCPATTERN));
nkeynes@644
   269
nkeynes@644
   270
	if (sectortype == MODE_0) {
nkeynes@644
   271
		memset(inout + sizeof(SYNCPATTERN), 0, 4 + L2_RAW + 12 + L2_P + L2_Q);
nkeynes@644
   272
		cd_build_address(inout, sectortype, address);
nkeynes@644
   273
		return (0);
nkeynes@644
   274
	}
nkeynes@644
   275
nkeynes@644
   276
	switch (sectortype) {
nkeynes@644
   277
nkeynes@644
   278
	case MODE_1:
nkeynes@644
   279
		cd_build_address(inout, sectortype, address);
nkeynes@644
   280
		result = build_edc(inout, 0, 16+2048-1);
nkeynes@644
   281
		inout[2064+0] = result >> 0L;
nkeynes@644
   282
		inout[2064+1] = result >> 8L;
nkeynes@644
   283
		inout[2064+2] = result >> 16L;
nkeynes@644
   284
		inout[2064+3] = result >> 24L;
nkeynes@644
   285
		memset(inout+2064+4, 0, 8);
nkeynes@644
   286
		encode_L2_P(inout+12);
nkeynes@644
   287
		encode_L2_Q(inout+12);
nkeynes@644
   288
		break;
nkeynes@644
   289
	case MODE_2:
nkeynes@644
   290
		cd_build_address(inout, sectortype, address);
nkeynes@644
   291
		break;
nkeynes@644
   292
	case MODE_2_FORM_1:
nkeynes@644
   293
		result = build_edc(inout, 16, 16+8+2048-1);
nkeynes@644
   294
		inout[2072+0] = result >> 0L;
nkeynes@644
   295
		inout[2072+1] = result >> 8L;
nkeynes@644
   296
		inout[2072+2] = result >> 16L;
nkeynes@644
   297
		inout[2072+3] = result >> 24L;
nkeynes@644
   298
nkeynes@644
   299
		/* clear header for P/Q parity calculation */
nkeynes@644
   300
		inout[12] = 0;
nkeynes@644
   301
		inout[12+1] = 0;
nkeynes@644
   302
		inout[12+2] = 0;
nkeynes@644
   303
		inout[12+3] = 0;
nkeynes@644
   304
		encode_L2_P(inout+12);
nkeynes@644
   305
		encode_L2_Q(inout+12);
nkeynes@644
   306
		cd_build_address(inout, sectortype, address);
nkeynes@644
   307
		break;
nkeynes@644
   308
	case MODE_2_FORM_2:
nkeynes@644
   309
		cd_build_address(inout, sectortype, address);
nkeynes@644
   310
		result = build_edc(inout, 16, 16+8+2324-1);
nkeynes@644
   311
		inout[2348+0] = result >> 0L;
nkeynes@644
   312
		inout[2348+1] = result >> 8L;
nkeynes@644
   313
		inout[2348+2] = result >> 16L;
nkeynes@644
   314
		inout[2348+3] = result >> 24L;
nkeynes@644
   315
		break;
nkeynes@644
   316
	default:
nkeynes@644
   317
		return (-1);
nkeynes@644
   318
	}
nkeynes@644
   319
nkeynes@644
   320
	return (0);
nkeynes@644
   321
}
nkeynes@644
   322
nkeynes@644
   323
nkeynes@644
   324
/*--------------------------------------------------------------------------*/
nkeynes@644
   325
#include "edc_encoder.h"
nkeynes@644
   326
nkeynes@644
   327
static int encode_L1_Q(unsigned char inout[L1_RAW + L1_Q]);
nkeynes@644
   328
nkeynes@644
   329
static int encode_L1_Q(unsigned char inout[L1_RAW + L1_Q])
nkeynes@644
   330
{
nkeynes@644
   331
	unsigned char *Q;
nkeynes@644
   332
	int	i;
nkeynes@644
   333
nkeynes@644
   334
	memmove(inout+L1_RAW/2+L1_Q, inout+L1_RAW/2, L1_RAW/2);
nkeynes@644
   335
	Q = inout + L1_RAW/2;
nkeynes@644
   336
nkeynes@644
   337
	memset(Q, 0, L1_Q);
nkeynes@644
   338
	for (i = 0; i < L1_RAW + L1_Q; i++) {
nkeynes@644
   339
		unsigned char data;
nkeynes@644
   340
nkeynes@644
   341
		if (i == L1_RAW/2) i += L1_Q;
nkeynes@644
   342
		data = inout[i];
nkeynes@644
   343
		if (data != 0) {
nkeynes@644
   344
			unsigned char base = rs_l12_log[data];
nkeynes@644
   345
nkeynes@644
   346
			Q[0] ^= rs_l12_alog[(base+AQ[0][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   347
			Q[1] ^= rs_l12_alog[(base+AQ[1][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   348
			Q[2] ^= rs_l12_alog[(base+AQ[2][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   349
			Q[3] ^= rs_l12_alog[(base+AQ[3][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   350
		}
nkeynes@644
   351
	}
nkeynes@644
   352
	return (0);
nkeynes@644
   353
}
nkeynes@644
   354
nkeynes@644
   355
static int encode_L1_P(unsigned char inout[L1_RAW + L1_Q + L1_P]);
nkeynes@644
   356
nkeynes@644
   357
static int encode_L1_P(unsigned char inout[L1_RAW + L1_Q + L1_P])
nkeynes@644
   358
{
nkeynes@644
   359
	unsigned char *P;
nkeynes@644
   360
	int	i;
nkeynes@644
   361
nkeynes@644
   362
	P = inout + L1_RAW + L1_Q;
nkeynes@644
   363
nkeynes@644
   364
	memset(P, 0, L1_P);
nkeynes@644
   365
	for (i = 0; i < L2_RAW + L2_Q + L2_P; i++) {
nkeynes@644
   366
		unsigned char data;
nkeynes@644
   367
nkeynes@644
   368
		data = inout[i];
nkeynes@644
   369
		if (data != 0) {
nkeynes@644
   370
			unsigned char base = rs_l12_log[data];
nkeynes@644
   371
nkeynes@644
   372
			P[0] ^= rs_l12_alog[(base+AP[0][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   373
			P[1] ^= rs_l12_alog[(base+AP[1][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   374
			P[2] ^= rs_l12_alog[(base+AP[2][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   375
			P[3] ^= rs_l12_alog[(base+AP[3][i]) % (unsigned)((1 << RS_L12_BITS)-1)];
nkeynes@644
   376
		}
nkeynes@644
   377
	}
nkeynes@644
   378
	return (0);
nkeynes@644
   379
}
nkeynes@644
   380
nkeynes@644
   381
static int decode_L1_Q(unsigned char inout[L1_RAW + L1_Q]);
nkeynes@644
   382
nkeynes@644
   383
static int decode_L1_Q(unsigned char inout[L1_RAW + L1_Q])
nkeynes@644
   384
{
nkeynes@644
   385
	return (0);
nkeynes@644
   386
}
nkeynes@644
   387
nkeynes@644
   388
static int decode_L1_P(unsigned char in[L1_RAW + L1_Q + L1_P]);
nkeynes@644
   389
nkeynes@644
   390
static int decode_L1_P(unsigned char in[L1_RAW + L1_Q + L1_P])
nkeynes@644
   391
{
nkeynes@644
   392
	return (0);
nkeynes@644
   393
}
nkeynes@644
   394
nkeynes@644
   395
int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q]);
nkeynes@644
   396
nkeynes@644
   397
int decode_L2_Q(unsigned char inout[4 + L2_RAW + 12 + L2_Q])
nkeynes@644
   398
{
nkeynes@644
   399
	return (0);
nkeynes@644
   400
}
nkeynes@644
   401
nkeynes@644
   402
int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P]);
nkeynes@644
   403
nkeynes@644
   404
int decode_L2_P(unsigned char inout[4 + L2_RAW + 12 + L2_Q + L2_P])
nkeynes@644
   405
{
nkeynes@644
   406
	return (0);
nkeynes@644
   407
}
nkeynes@644
   408
nkeynes@644
   409
static int encode_LSUB_Q(unsigned char inout[LSUB_RAW + LSUB_Q]);
nkeynes@644
   410
nkeynes@644
   411
static int encode_LSUB_Q(unsigned char inout[LSUB_RAW + LSUB_Q])
nkeynes@644
   412
{
nkeynes@644
   413
	unsigned char *Q;
nkeynes@644
   414
	int i;
nkeynes@644
   415
nkeynes@644
   416
	memmove(inout+LSUB_QRAW+LSUB_Q, inout+LSUB_QRAW, LSUB_RAW-LSUB_QRAW);
nkeynes@644
   417
	Q = inout + LSUB_QRAW;
nkeynes@644
   418
nkeynes@644
   419
	memset(Q, 0, LSUB_Q);
nkeynes@644
   420
nkeynes@644
   421
	for (i = 0; i < LSUB_QRAW; i++) {
nkeynes@644
   422
		unsigned char data;
nkeynes@644
   423
nkeynes@644
   424
		data = inout[i] & 0x3f;
nkeynes@644
   425
		if (data != 0) {
nkeynes@644
   426
			unsigned char base = rs_sub_rw_log[data];
nkeynes@644
   427
nkeynes@644
   428
			Q[0] ^= rs_sub_rw_alog[(base+SQ[0][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   429
			Q[1] ^= rs_sub_rw_alog[(base+SQ[1][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   430
		}
nkeynes@644
   431
	}
nkeynes@644
   432
	return (0);
nkeynes@644
   433
}
nkeynes@644
   434
nkeynes@644
   435
nkeynes@644
   436
static int encode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P]);
nkeynes@644
   437
nkeynes@644
   438
static int encode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P])
nkeynes@644
   439
{
nkeynes@644
   440
	unsigned char *P;
nkeynes@644
   441
	int i;
nkeynes@644
   442
nkeynes@644
   443
	P = inout + LSUB_RAW + LSUB_Q;
nkeynes@644
   444
nkeynes@644
   445
	memset(P, 0, LSUB_P);
nkeynes@644
   446
	for (i = 0; i < LSUB_RAW + LSUB_Q; i++) {
nkeynes@644
   447
		unsigned char data;
nkeynes@644
   448
nkeynes@644
   449
		data = inout[i] & 0x3f;
nkeynes@644
   450
		if (data != 0) {
nkeynes@644
   451
			unsigned char base = rs_sub_rw_log[data];
nkeynes@644
   452
nkeynes@644
   453
			P[0] ^= rs_sub_rw_alog[(base+SP[0][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   454
			P[1] ^= rs_sub_rw_alog[(base+SP[1][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   455
			P[2] ^= rs_sub_rw_alog[(base+SP[2][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   456
			P[3] ^= rs_sub_rw_alog[(base+SP[3][i]) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   457
		}
nkeynes@644
   458
	}
nkeynes@644
   459
	return (0);
nkeynes@644
   460
}
nkeynes@644
   461
nkeynes@644
   462
int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q]);
nkeynes@644
   463
nkeynes@644
   464
int decode_LSUB_Q(unsigned char inout[LSUB_QRAW + LSUB_Q])
nkeynes@644
   465
{
nkeynes@644
   466
	unsigned char Q[LSUB_Q];
nkeynes@644
   467
	int i;
nkeynes@644
   468
nkeynes@644
   469
	memset(Q, 0, LSUB_Q);
nkeynes@644
   470
	for (i = LSUB_QRAW + LSUB_Q -1; i>=0; i--) {
nkeynes@644
   471
		unsigned char data;
nkeynes@644
   472
nkeynes@644
   473
		data = inout[LSUB_QRAW + LSUB_Q -1 -i] & 0x3f;
nkeynes@644
   474
		if (data != 0) {
nkeynes@644
   475
			unsigned char base = rs_sub_rw_log[data];
nkeynes@644
   476
nkeynes@644
   477
			Q[0] ^= rs_sub_rw_alog[(base+0*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   478
			Q[1] ^= rs_sub_rw_alog[(base+1*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   479
		}
nkeynes@644
   480
	}
nkeynes@644
   481
	return (Q[0] != 0 || Q[1] != 0);
nkeynes@644
   482
}
nkeynes@644
   483
nkeynes@644
   484
int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P]);
nkeynes@644
   485
nkeynes@644
   486
int decode_LSUB_P(unsigned char inout[LSUB_RAW + LSUB_Q + LSUB_P])
nkeynes@644
   487
{
nkeynes@644
   488
	unsigned char P[LSUB_P];
nkeynes@644
   489
	int i;
nkeynes@644
   490
nkeynes@644
   491
	memset(P, 0, LSUB_P);
nkeynes@644
   492
	for (i = LSUB_RAW + LSUB_Q + LSUB_P-1; i>=0; i--) {
nkeynes@644
   493
		unsigned char data;
nkeynes@644
   494
nkeynes@644
   495
		data = inout[LSUB_RAW + LSUB_Q + LSUB_P -1 -i] & 0x3f;
nkeynes@644
   496
		if (data != 0) {
nkeynes@644
   497
			unsigned char base = rs_sub_rw_log[data];
nkeynes@644
   498
nkeynes@644
   499
			P[0] ^= rs_sub_rw_alog[(base+0*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   500
			P[1] ^= rs_sub_rw_alog[(base+1*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   501
			P[2] ^= rs_sub_rw_alog[(base+2*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   502
			P[3] ^= rs_sub_rw_alog[(base+3*i) % (unsigned)((1 << RS_SUB_RW_BITS)-1)];
nkeynes@644
   503
		}
nkeynes@644
   504
	}
nkeynes@644
   505
	return (P[0] != 0 || P[1] != 0 || P[2] != 0 || P[3] != 0);
nkeynes@644
   506
}
nkeynes@644
   507
nkeynes@644
   508
/* Layer 1 CIRC en/decoder */
nkeynes@644
   509
#define MAX_L1_DEL1 2
nkeynes@644
   510
static unsigned char l1_delay_line1[MAX_L1_DEL1][L1_RAW];
nkeynes@644
   511
#define MAX_L1_DEL2 108
nkeynes@644
   512
static unsigned char l1_delay_line2[MAX_L1_DEL2][L1_RAW+L1_Q];
nkeynes@644
   513
#define MAX_L1_DEL3 1
nkeynes@644
   514
static unsigned char l1_delay_line3[MAX_L1_DEL3][L1_RAW+L1_Q+L1_P];
nkeynes@644
   515
static unsigned l1_del_index;
nkeynes@644
   516
nkeynes@644
   517
int do_encode_L1(unsigned char in[L1_RAW*FRAMES_PER_SECTOR], 
nkeynes@644
   518
                 unsigned char out[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR], 
nkeynes@644
   519
                 int delay1, int delay2, int delay3, int permute)
nkeynes@644
   520
{
nkeynes@644
   521
	int i;
nkeynes@644
   522
nkeynes@644
   523
	for (i = 0; i < FRAMES_PER_SECTOR; i++) {
nkeynes@644
   524
		int j;
nkeynes@644
   525
		unsigned char t;
nkeynes@644
   526
nkeynes@644
   527
		if (in != out)
nkeynes@644
   528
			memcpy(out, in, L1_RAW);
nkeynes@644
   529
nkeynes@644
   530
		if (delay1) {
nkeynes@644
   531
			/* shift through delay line 1 */
nkeynes@644
   532
			for (j = 0; j < L1_RAW; j++) {
nkeynes@644
   533
				if (((j/4) % MAX_L1_DEL1) == 0) {
nkeynes@644
   534
					t = l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j];
nkeynes@644
   535
					l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j] = out[j];
nkeynes@644
   536
					out[j] = t;
nkeynes@644
   537
				}
nkeynes@644
   538
			}
nkeynes@644
   539
		}
nkeynes@644
   540
nkeynes@644
   541
		if (permute) {
nkeynes@644
   542
			/* permute */
nkeynes@644
   543
			t = out[2]; out[2] = out[8]; out[8] = out[10]; out[10] = out[18];
nkeynes@644
   544
			out[18] = out[6]; out [6] = t;
nkeynes@644
   545
			t = out[3]; out[3] = out[9]; out[9] = out[11]; out[11] = out[19];
nkeynes@644
   546
			out[19] = out[7]; out [7] = t;
nkeynes@644
   547
			t = out[4]; out[4] = out[16]; out[16] = out[20]; out[20] = out[14];
nkeynes@644
   548
			out[14] = out[12]; out [12] = t;
nkeynes@644
   549
			t = out[5]; out[5] = out[17]; out[17] = out[21]; out[21] = out[15];
nkeynes@644
   550
			out[15] = out[13]; out [13] = t;
nkeynes@644
   551
		}
nkeynes@644
   552
nkeynes@644
   553
		/* build Q parity */
nkeynes@644
   554
		encode_L1_Q(out);
nkeynes@644
   555
nkeynes@644
   556
		if (delay2) {
nkeynes@644
   557
			/* shift through delay line 2 */
nkeynes@644
   558
			for (j = 0; j < L1_RAW+L1_Q; j++) {
nkeynes@644
   559
				if (j != 0) {
nkeynes@644
   560
					t = l1_delay_line2[(l1_del_index) % MAX_L1_DEL2][j];
nkeynes@644
   561
					l1_delay_line2[(l1_del_index + j*4) % MAX_L1_DEL2][j] = out[j];
nkeynes@644
   562
					out[j] = t;
nkeynes@644
   563
				}
nkeynes@644
   564
			}
nkeynes@644
   565
		}
nkeynes@644
   566
nkeynes@644
   567
		/* build P parity */
nkeynes@644
   568
		encode_L1_P(out);
nkeynes@644
   569
nkeynes@644
   570
		if (delay3) {
nkeynes@644
   571
			/* shift through delay line 3 */
nkeynes@644
   572
			for (j = 0; j < L1_RAW+L1_Q+L1_P; j++) {
nkeynes@644
   573
				if (((j) & MAX_L1_DEL3) == 0) {
nkeynes@644
   574
					t = l1_delay_line3[0][j];
nkeynes@644
   575
					l1_delay_line3[0][j] = out[j];
nkeynes@644
   576
					out[j] = t;
nkeynes@644
   577
				}
nkeynes@644
   578
			}
nkeynes@644
   579
		}
nkeynes@644
   580
nkeynes@644
   581
		/* invert Q and P parity */
nkeynes@644
   582
		for (j = 0; j < L1_Q; j++)
nkeynes@644
   583
			out[j+12] = ~out[j+12];
nkeynes@644
   584
		for (j = 0; j < L1_P; j++)
nkeynes@644
   585
			out[j+28] = ~out[j+28];
nkeynes@644
   586
nkeynes@644
   587
		l1_del_index++;
nkeynes@644
   588
		out += L1_RAW+L1_Q+L1_P;
nkeynes@644
   589
		in += L1_RAW;
nkeynes@644
   590
	}
nkeynes@644
   591
	return (0);
nkeynes@644
   592
}
nkeynes@644
   593
nkeynes@644
   594
int do_decode_L1(unsigned char in[(L1_RAW+L1_Q+L1_P)*FRAMES_PER_SECTOR], 
nkeynes@669
   595
			unsigned char out[L1_RAW*FRAMES_PER_SECTOR], 
nkeynes@669
   596
			int delay1, int delay2, int delay3, int permute)
nkeynes@644
   597
{
nkeynes@644
   598
	int i;
nkeynes@644
   599
nkeynes@644
   600
	for (i = 0; i < FRAMES_PER_SECTOR; i++) {
nkeynes@644
   601
		int j;
nkeynes@644
   602
		unsigned char t;
nkeynes@644
   603
nkeynes@644
   604
		if (delay3) {
nkeynes@644
   605
			/* shift through delay line 3 */
nkeynes@644
   606
			for (j = 0; j < L1_RAW+L1_Q+L1_P; j++) {
nkeynes@644
   607
				if (((j) & MAX_L1_DEL3) != 0) {
nkeynes@644
   608
					t = l1_delay_line3[0][j];
nkeynes@644
   609
					l1_delay_line3[0][j] = in[j];
nkeynes@644
   610
					in[j] = t;
nkeynes@644
   611
				}
nkeynes@644
   612
			}
nkeynes@644
   613
		}
nkeynes@644
   614
nkeynes@644
   615
		/* invert Q and P parity */
nkeynes@644
   616
		for (j = 0; j < L1_Q; j++)
nkeynes@644
   617
			in[j+12] = ~in[j+12];
nkeynes@644
   618
		for (j = 0; j < L1_P; j++)
nkeynes@644
   619
			in[j+28] = ~in[j+28];
nkeynes@644
   620
nkeynes@644
   621
		/* build P parity */
nkeynes@644
   622
		decode_L1_P(in);
nkeynes@644
   623
nkeynes@644
   624
		if (delay2) {
nkeynes@644
   625
			/* shift through delay line 2 */
nkeynes@644
   626
			for (j = 0; j < L1_RAW+L1_Q; j++) {
nkeynes@644
   627
				if (j != L1_RAW+L1_Q-1) {
nkeynes@644
   628
					t = l1_delay_line2[(l1_del_index) % MAX_L1_DEL2][j];
nkeynes@644
   629
					l1_delay_line2[(l1_del_index + (MAX_L1_DEL2 - j*4)) % MAX_L1_DEL2][j] = in[j];
nkeynes@644
   630
					in[j] = t;
nkeynes@644
   631
				}
nkeynes@644
   632
			}
nkeynes@644
   633
		}
nkeynes@644
   634
nkeynes@644
   635
		/* build Q parity */
nkeynes@644
   636
		decode_L1_Q(in);
nkeynes@644
   637
nkeynes@644
   638
		if (permute) {
nkeynes@644
   639
			/* permute */
nkeynes@644
   640
			t = in[2]; in[2] = in[6]; in[6] = in[18]; in[18] = in[10];
nkeynes@644
   641
			in[10] = in[8]; in [8] = t;
nkeynes@644
   642
			t = in[3]; in[3] = in[7]; in[7] = in[19]; in[19] = in[11];
nkeynes@644
   643
			in[11] = in[9]; in [9] = t;
nkeynes@644
   644
			t = in[4]; in[4] = in[12]; in[12] = in[14]; in[14] = in[20];
nkeynes@644
   645
			in[20] = in[16]; in [16] = t;
nkeynes@644
   646
			t = in[5]; in[5] = in[13]; in[13] = in[15]; in[15] = in[21];
nkeynes@644
   647
			in[21] = in[17]; in [17] = t;
nkeynes@644
   648
		}
nkeynes@644
   649
nkeynes@644
   650
		if (delay1) {
nkeynes@644
   651
			/* shift through delay line 1 */
nkeynes@644
   652
			for (j = 0; j < L1_RAW; j++) {
nkeynes@644
   653
				if (((j/4) % MAX_L1_DEL1) != 0) {
nkeynes@644
   654
					t = l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j];
nkeynes@644
   655
					l1_delay_line1[l1_del_index % (MAX_L1_DEL1)][j] = in[j];
nkeynes@644
   656
					in[j] = t;
nkeynes@644
   657
				}
nkeynes@644
   658
			}
nkeynes@644
   659
		}
nkeynes@644
   660
nkeynes@644
   661
		if (in != out)
nkeynes@644
   662
			memcpy(out, in, (L1_RAW));
nkeynes@644
   663
nkeynes@644
   664
		l1_del_index++;
nkeynes@644
   665
		in += L1_RAW+L1_Q+L1_P;
nkeynes@644
   666
		out += L1_RAW;
nkeynes@644
   667
	}
nkeynes@644
   668
	return (0);
nkeynes@644
   669
}
nkeynes@644
   670
nkeynes@669
   671
int do_decode_L2(unsigned char in[(L2_RAW+L2_Q+L2_P)], 
nkeynes@644
   672
                        unsigned char out[L2_RAW])
nkeynes@644
   673
{
nkeynes@644
   674
	return (0);
nkeynes@644
   675
}
nkeynes@644
   676
nkeynes@644
   677
nkeynes@644
   678
nkeynes@644
   679
#define MAX_SUB_DEL 8
nkeynes@644
   680
static unsigned char sub_delay_line[MAX_SUB_DEL][LSUB_RAW+LSUB_Q+LSUB_P];
nkeynes@644
   681
static unsigned sub_del_index;
nkeynes@644
   682
nkeynes@644
   683
/* R-W Subchannel en/decoder */
nkeynes@644
   684
nkeynes@644
   685
int do_encode_sub(unsigned char in[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME], 
nkeynes@644
   686
                  unsigned char out[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME], 
nkeynes@644
   687
                  int delay1, int permute)
nkeynes@644
   688
{
nkeynes@644
   689
	int i;
nkeynes@644
   690
nkeynes@644
   691
	if (in == out) return -1;
nkeynes@644
   692
nkeynes@644
   693
	for (i = 0; i < PACKETS_PER_SUBCHANNELFRAME; i++) {
nkeynes@644
   694
		int j;
nkeynes@644
   695
		unsigned char t;
nkeynes@644
   696
nkeynes@644
   697
		memcpy(out, in, (LSUB_RAW));
nkeynes@644
   698
nkeynes@644
   699
		/* build Q parity */
nkeynes@644
   700
		encode_LSUB_Q(out);
nkeynes@644
   701
nkeynes@644
   702
		/* build P parity */
nkeynes@644
   703
		encode_LSUB_P(out);
nkeynes@644
   704
nkeynes@644
   705
		if (permute) {
nkeynes@644
   706
			/* permute */
nkeynes@644
   707
			t = out[1]; out[1] = out[18]; out[18] = t;
nkeynes@644
   708
			t = out[2]; out[2] = out[ 5]; out[ 5] = t;
nkeynes@644
   709
			t = out[3]; out[3] = out[23]; out[23] = t;
nkeynes@644
   710
		}
nkeynes@644
   711
nkeynes@644
   712
		if (delay1) {
nkeynes@644
   713
			/* shift through delay_line */
nkeynes@644
   714
			for (j = 0; j < LSUB_RAW+LSUB_Q+LSUB_P; j++) {
nkeynes@644
   715
				if ((j % MAX_SUB_DEL) != 0) {
nkeynes@644
   716
					t = sub_delay_line[(sub_del_index) % MAX_SUB_DEL][j];
nkeynes@644
   717
					sub_delay_line[(sub_del_index + j) % MAX_SUB_DEL][j] = out[j];
nkeynes@644
   718
					out[j] = t;
nkeynes@644
   719
				}
nkeynes@644
   720
			}
nkeynes@644
   721
		}
nkeynes@644
   722
		sub_del_index++;
nkeynes@644
   723
		out += LSUB_RAW+LSUB_Q+LSUB_P;
nkeynes@644
   724
		in += LSUB_RAW;
nkeynes@644
   725
	}
nkeynes@644
   726
	return (0);
nkeynes@644
   727
}
nkeynes@644
   728
nkeynes@669
   729
int do_decode_sub(unsigned char in[(LSUB_RAW+LSUB_Q+LSUB_P)*PACKETS_PER_SUBCHANNELFRAME], 
nkeynes@669
   730
		  unsigned char out[LSUB_RAW*PACKETS_PER_SUBCHANNELFRAME], 
nkeynes@669
   731
		  int delay1, int permute)
nkeynes@644
   732
{
nkeynes@644
   733
	int i;
nkeynes@644
   734
nkeynes@644
   735
	if (in == out) return -1;
nkeynes@644
   736
nkeynes@644
   737
	for (i = 0; i < PACKETS_PER_SUBCHANNELFRAME; i++) {
nkeynes@644
   738
		int j;
nkeynes@644
   739
		unsigned char t;
nkeynes@644
   740
nkeynes@644
   741
		if (delay1) {
nkeynes@644
   742
			/* shift through delay_line */
nkeynes@644
   743
			for (j = 0; j < LSUB_RAW+LSUB_Q+LSUB_P; j++) {
nkeynes@644
   744
				if ((j % MAX_SUB_DEL) != MAX_SUB_DEL-1) {
nkeynes@644
   745
					t = sub_delay_line[(sub_del_index) % MAX_SUB_DEL][j];
nkeynes@644
   746
					sub_delay_line[(sub_del_index + (MAX_SUB_DEL - j)) % MAX_SUB_DEL][j] = in[j];
nkeynes@644
   747
					in[j] = t;
nkeynes@644
   748
				}
nkeynes@644
   749
			}
nkeynes@644
   750
		}
nkeynes@644
   751
nkeynes@644
   752
		if (permute) {
nkeynes@644
   753
			/* permute */
nkeynes@644
   754
			t = in[1]; in[1] = in[18]; in[18] = t;
nkeynes@644
   755
			t = in[2]; in[2] = in[ 5]; in[ 5] = t;
nkeynes@644
   756
			t = in[3]; in[3] = in[23]; in[23] = t;
nkeynes@644
   757
		}
nkeynes@644
   758
nkeynes@644
   759
		/* build P parity */
nkeynes@644
   760
		decode_LSUB_P(in);
nkeynes@644
   761
nkeynes@644
   762
		/* build Q parity */
nkeynes@644
   763
		decode_LSUB_Q(in);
nkeynes@644
   764
nkeynes@644
   765
		memcpy(out, in, LSUB_QRAW);
nkeynes@644
   766
		memcpy(out+LSUB_QRAW, in+LSUB_QRAW+LSUB_Q, LSUB_RAW-LSUB_QRAW);
nkeynes@644
   767
nkeynes@644
   768
		sub_del_index++;
nkeynes@644
   769
		in += LSUB_RAW+LSUB_Q+LSUB_P;
nkeynes@644
   770
		out += LSUB_RAW;
nkeynes@644
   771
	}
nkeynes@644
   772
	return (0);
nkeynes@644
   773
}
nkeynes@644
   774
nkeynes@644
   775
static int sectortype = MODE_0;
nkeynes@644
   776
nkeynes@644
   777
int get_sector_type(void);
nkeynes@644
   778
nkeynes@644
   779
int get_sector_type()
nkeynes@644
   780
{
nkeynes@644
   781
	return (sectortype);
nkeynes@644
   782
}
nkeynes@644
   783
nkeynes@644
   784
int set_sector_type(int st);
nkeynes@644
   785
nkeynes@644
   786
int set_sector_type(int st)
nkeynes@644
   787
{
nkeynes@644
   788
	switch(st) {
nkeynes@644
   789
nkeynes@644
   790
	case MODE_0:
nkeynes@644
   791
	case MODE_1:
nkeynes@644
   792
	case MODE_2:
nkeynes@644
   793
	case MODE_2_FORM_1:
nkeynes@644
   794
	case MODE_2_FORM_2:
nkeynes@644
   795
		sectortype = st;
nkeynes@644
   796
		return 0;
nkeynes@644
   797
	default:
nkeynes@644
   798
		return -1;
nkeynes@644
   799
	}
nkeynes@644
   800
}
nkeynes@644
   801
.