Experimental on-fly decoding of ECM file format. For now compiles also with --enable-ccdda
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@87140 e17a0e51-4ae3-4d35-97c3-1a29b211df97
This commit is contained in:
parent
8bdccd853a
commit
59132f7e4e
|
@ -40,6 +40,8 @@
|
|||
#include "libavutil/mathematics.h"
|
||||
#include "libavformat/avformat.h"
|
||||
|
||||
#include "ecm.h"
|
||||
|
||||
#define INBUF_SIZE 4096
|
||||
#define AUDIO_INBUF_SIZE INBUF_SIZE*4
|
||||
#define AUDIO_REFILL_THRESH 4096
|
||||
|
@ -1325,6 +1327,192 @@ static int cdread_2048(FILE *f, unsigned int base, void *dest, int sector)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CCDDA // TODO: experimental... test reliability & possibly move these functions to ecm.h
|
||||
/* Adapted from ecm.c:unecmify() (C) Neill Corlett */
|
||||
static int cdread_ecm_decode(FILE *f, unsigned int base, void *dest, int sector) {
|
||||
u32 output_edc = 0, b, writebytecount=0, sectorcount=0, num;
|
||||
s8 type; // mode type 0 (META) or 1, 2 or 3 for CDROM type
|
||||
u8 sector_buffer[CD_FRAMESIZE_RAW];
|
||||
boolean processsectors = (boolean)decoded_ecm_sectors; // this flag tells if to decode all sectors or just skip to wanted sector
|
||||
|
||||
ECMFILELUT* pos = &(ecm_savetable[sector-0]); // get sector from LUT which points to wanted sector or to beginning
|
||||
// if suitable sector was not found from LUT use last sector if less than wanted sector
|
||||
if (pos->filepos <= ECM_HEADER_SIZE && sector > lastsector) pos=&(ecm_savetable[lastsector]);
|
||||
|
||||
if (decoded_ecm_sectors && sector < decoded_ecm_sectors) {
|
||||
//printf("ReadSector %i %i\n", sector, savedsectors);
|
||||
return cdimg_read_func_o(decoded_ecm, base, dest, sector);
|
||||
}/* else if (sector > len_ecm_savetable) {
|
||||
SysPrintf("ECM: invalid sector requested\n");
|
||||
return -1;
|
||||
}*/
|
||||
//printf("SeekSector %i %i %i\n", sector, pos->sector, lastsector);
|
||||
|
||||
writebytecount = pos->sector * CD_FRAMESIZE_RAW;
|
||||
sectorcount = pos->sector;
|
||||
if (decoded_ecm_sectors) fseek(decoded_ecm, writebytecount, SEEK_SET); // rewind to last pos
|
||||
fseek(f, base+pos->filepos, SEEK_SET);
|
||||
while(sector >= sectorcount) { // decode ecm file until we are past wanted sector
|
||||
int c = fgetc(f);
|
||||
int bits = 5;
|
||||
if(c == EOF) { goto error_in; }
|
||||
type = c & 3;
|
||||
num = (c >> 2) & 0x1F;
|
||||
//printf("ECM1 file; count %x\n", c);
|
||||
while(c & 0x80) {
|
||||
c = fgetc(f);
|
||||
//printf("ECM2 file; count %x\n", c);
|
||||
if(c == EOF) { goto error_in; }
|
||||
if( (bits > 31) ||
|
||||
((uint32_t)(c & 0x7F)) >= (((uint32_t)0x80000000LU) >> (bits-1))
|
||||
) {
|
||||
//SysMessage(_("Corrupt ECM file; invalid sector count\n"));
|
||||
goto error;
|
||||
}
|
||||
num |= ((uint32_t)(c & 0x7F)) << bits;
|
||||
bits += 7;
|
||||
}
|
||||
if(num == 0xFFFFFFFF) {
|
||||
// End indicator
|
||||
break;
|
||||
}
|
||||
num++;
|
||||
while(num) {
|
||||
if (!processsectors && sectorcount >= (sector-1)) { // ensure that we read the sector we are supposed to
|
||||
processsectors = TRUE;
|
||||
//printf("Saving at %i\n", sectorcount);
|
||||
}
|
||||
/*printf("Type %i Num %i SeekSector %i ProcessedSectors %i(%i) Bytecount %i Pos %li Write %u\n",
|
||||
type, num, sector, sectorcount, pos->sector, writebytecount, ftell(f), processsectors);*/
|
||||
switch(type) {
|
||||
case 0: // META
|
||||
b = num;
|
||||
if(b > sizeof(sector_buffer)) { b = sizeof(sector_buffer); }
|
||||
writebytecount += b;
|
||||
if (!processsectors) { fseek(f, +b, SEEK_CUR); break; } // seek only
|
||||
if(fread(sector_buffer, 1, b, f) != b) {
|
||||
goto error_in;
|
||||
}
|
||||
//output_edc = edc_compute(output_edc, sector_buffer, b);
|
||||
if(decoded_ecm_sectors && fwrite(sector_buffer, 1, b, decoded_ecm) != b) { // just seek or write also
|
||||
goto error_out;
|
||||
}
|
||||
break;
|
||||
case 1: //Mode 1
|
||||
b=1;
|
||||
writebytecount += ECM_SECTOR_SIZE[type];
|
||||
if(fread(sector_buffer + 0x00C, 1, 0x003, f) != 0x003) { goto error_in; }
|
||||
if(fread(sector_buffer + 0x010, 1, 0x800, f) != 0x800) { goto error_in; }
|
||||
if (!processsectors) break; // seek only
|
||||
reconstruct_sector(sector_buffer, 1);
|
||||
//output_edc = edc_compute(output_edc, sector_buffer, ECM_SECTOR_SIZE[type]);
|
||||
if(decoded_ecm_sectors && fwrite(sector_buffer, 1, ECM_SECTOR_SIZE[type], decoded_ecm) != ECM_SECTOR_SIZE[type]) { goto error_out; }
|
||||
break;
|
||||
case 2: //Mode 2 (XA), form 1
|
||||
b=1;
|
||||
writebytecount += ECM_SECTOR_SIZE[type];
|
||||
if (!processsectors) { fseek(f, +0x804, SEEK_CUR); break; } // seek only
|
||||
if(fread(sector_buffer + 0x014, 1, 0x804, f) != 0x804) { goto error_in; }
|
||||
reconstruct_sector(sector_buffer, 2);
|
||||
//output_edc = edc_compute(output_edc, sector_buffer + 0x10, ECM_SECTOR_SIZE[type]);
|
||||
if(decoded_ecm_sectors && fwrite(sector_buffer + 0x10, 1, ECM_SECTOR_SIZE[type], decoded_ecm) != ECM_SECTOR_SIZE[type]) { goto error_out; }
|
||||
break;
|
||||
case 3: //Mode 2 (XA), form 2
|
||||
b=1;
|
||||
writebytecount += ECM_SECTOR_SIZE[type];
|
||||
if (!processsectors) { fseek(f, +0x918, SEEK_CUR); break; } // seek only
|
||||
if(fread(sector_buffer + 0x014, 1, 0x918, f) != 0x918) { goto error_in; }
|
||||
reconstruct_sector(sector_buffer, 3);
|
||||
//output_edc = edc_compute(output_edc, sector_buffer + 0x10, ECM_SECTOR_SIZE[type]);
|
||||
if(decoded_ecm_sectors && fwrite(sector_buffer + 0x10, 1, ECM_SECTOR_SIZE[type], decoded_ecm) != ECM_SECTOR_SIZE[type]) { goto error_out; }
|
||||
break;
|
||||
}
|
||||
sectorcount=((writebytecount/CD_FRAMESIZE_RAW) - 0);
|
||||
num -= b;
|
||||
}
|
||||
if (sectorcount > 0 && ecm_savetable[sectorcount].filepos <= ECM_HEADER_SIZE ) {
|
||||
ecm_savetable[sectorcount].filepos = ftell(f)-base;
|
||||
ecm_savetable[sectorcount].sector = sectorcount;
|
||||
//printf("Marked %i at pos %i\n", ecm_savetable[sectorcount].sector, ecm_savetable[sectorcount].filepos);
|
||||
}
|
||||
}
|
||||
|
||||
if (decoded_ecm_sectors) {
|
||||
fflush(decoded_ecm);
|
||||
fseek(decoded_ecm, -1*CD_FRAMESIZE_RAW, SEEK_CUR);
|
||||
num = fread(sector_buffer, 1, CD_FRAMESIZE_RAW, decoded_ecm);
|
||||
decoded_ecm_sectors = MAX(decoded_ecm_sectors, sectorcount);
|
||||
} else {
|
||||
num = CD_FRAMESIZE_RAW;
|
||||
}
|
||||
|
||||
memcpy(dest, sector_buffer, CD_FRAMESIZE_RAW);
|
||||
lastsector = sectorcount;
|
||||
//printf("OK: Frame decoded %i %i\n", sectorcount-1, writebytecount);
|
||||
return num;
|
||||
|
||||
error_in:
|
||||
error:
|
||||
error_out:
|
||||
//memset(dest, 0x0, CD_FRAMESIZE_RAW);
|
||||
SysPrintf("Error decoding ECM image: WantedSector %i Type %i Sectors %i Pos %i(%li)\n",
|
||||
sector, type, sectorcount, writebytecount, ftell(f));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int handleecm(const char *isoname) {
|
||||
#ifdef ENABLE_CCDDA
|
||||
// Rewind to start and check ECM header and filename suffix validity
|
||||
fseek(cdHandle, 0, SEEK_SET);
|
||||
if(
|
||||
(fgetc(cdHandle) == 'E') &&
|
||||
(fgetc(cdHandle) == 'C') &&
|
||||
(fgetc(cdHandle) == 'M') &&
|
||||
(fgetc(cdHandle) == 0x00) &&
|
||||
(strncmp((isoname+strlen(isoname)-5), ".ecm", 4))
|
||||
) {
|
||||
SysPrintf(_("\nDetected ECM file with proper header and filename suffix.\n"));
|
||||
|
||||
// Save real function used to read CD
|
||||
cdimg_read_func_o = cdimg_read_func;
|
||||
cdimg_read_func = cdread_ecm_decode;
|
||||
|
||||
// Based in file length use LUT of variable size
|
||||
fseek(cdHandle, 0, SEEK_END);
|
||||
//len_ecm_savetable = savedsectors ? len_ecm_savetable : (ftell(cdHandle)/CD_FRAMESIZE_RAW)/100;
|
||||
len_ecm_savetable = 2*(ftell(cdHandle)/CD_FRAMESIZE_RAW); // todo: optimize size...
|
||||
|
||||
// Full image decoded??
|
||||
if (decoded_ecm_sectors) {
|
||||
len_decoded_ecm_buffer = len_ecm_savetable*CD_FRAMESIZE_RAW;
|
||||
decoded_ecm_buffer = malloc(len_decoded_ecm_buffer);
|
||||
if (decoded_ecm_buffer) {
|
||||
//printf("Memory ok1 %u %p\n", len_decoded_ecm_buffer, decoded_ecm_buffer);
|
||||
decoded_ecm = fmemopen(decoded_ecm_buffer, len_decoded_ecm_buffer, "w+b");
|
||||
decoded_ecm_sectors = 1;
|
||||
} else {
|
||||
SysMessage("Could not reserve memory for full ECM buffer. Only LUT will be used.");
|
||||
decoded_ecm_sectors = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Init ECC/EDC tables
|
||||
eccedc_init();
|
||||
|
||||
// Last accessed sector
|
||||
lastsector = 0;
|
||||
|
||||
// Index 0 always points to beginning of ECM data
|
||||
ecm_savetable = calloc(len_ecm_savetable, sizeof(ECMFILELUT));
|
||||
ecm_savetable[0].filepos = ECM_HEADER_SIZE;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static unsigned char * CALLBACK ISOgetBuffer_compr(void) {
|
||||
return compr_img->buff_raw[compr_img->sector_in_blk] + 12;
|
||||
}
|
||||
|
@ -1422,6 +1610,10 @@ static long CALLBACK ISOopen(void) {
|
|||
else if (isMode1ISO)
|
||||
cdimg_read_func = cdread_2048;
|
||||
|
||||
if (handleecm(GetIsoFile()) == 0) {
|
||||
SysPrintf("[+ecm]");
|
||||
}
|
||||
|
||||
// make sure we have another handle open for cdda
|
||||
if (numtracks > 1 && ti[1].handle == NULL) {
|
||||
ti[1].handle = fopen(GetIsoFile(), "rb");
|
||||
|
@ -1448,6 +1640,12 @@ static long CALLBACK ISOclose(void) {
|
|||
compr_img = NULL;
|
||||
}
|
||||
|
||||
// ECM LUT
|
||||
#ifdef ENABLE_CCDDA
|
||||
free(ecm_savetable);
|
||||
ecm_savetable = NULL;
|
||||
#endif
|
||||
|
||||
for (i = 1; i <= numtracks; i++) {
|
||||
if (ti[i].handle != NULL) {
|
||||
fclose(ti[i].handle);
|
||||
|
@ -1476,6 +1674,15 @@ long CALLBACK ISOinit(void) {
|
|||
|
||||
static long CALLBACK ISOshutdown(void) {
|
||||
ISOclose();
|
||||
|
||||
#ifdef ENABLE_CCDDA
|
||||
if (decoded_ecm != NULL) {
|
||||
fclose(decoded_ecm);
|
||||
free(decoded_ecm_buffer);
|
||||
decoded_ecm_buffer = NULL;
|
||||
decoded_ecm = NULL;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
278
libpcsxcore/ecm.h
Normal file
278
libpcsxcore/ecm.h
Normal file
|
@ -0,0 +1,278 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
#define TITLE "ecm - Encoder/decoder for Error Code Modeler format"
|
||||
#define COPYR "Copyright (C) 2002-2011 Neill Corlett"
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#include "common.h"
|
||||
//#include "banner.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Sector types
|
||||
//
|
||||
// Mode 1
|
||||
// -----------------------------------------------------
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
// 0000h 00 FF FF FF FF FF FF FF FF FF FF 00 [-ADDR-] 01
|
||||
// 0010h [---DATA...
|
||||
// ...
|
||||
// 0800h ...DATA---]
|
||||
// 0810h [---EDC---] 00 00 00 00 00 00 00 00 [---ECC...
|
||||
// ...
|
||||
// 0920h ...ECC---]
|
||||
// -----------------------------------------------------
|
||||
//
|
||||
// Mode 2 (XA), form 1
|
||||
// -----------------------------------------------------
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
// 0000h 00 FF FF FF FF FF FF FF FF FF FF 00 [-ADDR-] 02
|
||||
// 0010h [--FLAGS--] [--FLAGS--] [---DATA...
|
||||
// ...
|
||||
// 0810h ...DATA---] [---EDC---] [---ECC...
|
||||
// ...
|
||||
// 0920h ...ECC---]
|
||||
// -----------------------------------------------------
|
||||
//
|
||||
// Mode 2 (XA), form 2
|
||||
// -----------------------------------------------------
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
// 0000h 00 FF FF FF FF FF FF FF FF FF FF 00 [-ADDR-] 02
|
||||
// 0010h [--FLAGS--] [--FLAGS--] [---DATA...
|
||||
// ...
|
||||
// 0920h ...DATA---] [---EDC---]
|
||||
// -----------------------------------------------------
|
||||
//
|
||||
// ADDR: Sector address, encoded as minutes:seconds:frames in BCD
|
||||
// FLAGS: Used in Mode 2 (XA) sectors describing the type of sector; repeated
|
||||
// twice for redundancy
|
||||
// DATA: Area of the sector which contains the actual data itself
|
||||
// EDC: Error Detection Code
|
||||
// ECC: Error Correction Code
|
||||
//
|
||||
|
||||
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#define ECM_HEADER_SIZE 4
|
||||
u32 len_decoded_ecm_buffer, len_ecm_savetable, lastsector;
|
||||
u32 decoded_ecm_sectors = 0; // setting this to 1 makes whole ECM to be decoded in-memory
|
||||
FILE* decoded_ecm = NULL;
|
||||
void *decoded_ecm_buffer;
|
||||
|
||||
int (*cdimg_read_func_o)(FILE *f, unsigned int base, void *dest, int sector);
|
||||
|
||||
typedef struct ECMFILELUT {
|
||||
s32 sector;
|
||||
s32 filepos;
|
||||
} ECMFILELUT;
|
||||
|
||||
ECMFILELUT* ecm_savetable = NULL;
|
||||
|
||||
static const size_t ECM_SECTOR_SIZE[4] = {
|
||||
1,
|
||||
2352,
|
||||
2336,
|
||||
2336
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint32_t get32lsb(const uint8_t* src) {
|
||||
return
|
||||
(((uint32_t)(src[0])) << 0) |
|
||||
(((uint32_t)(src[1])) << 8) |
|
||||
(((uint32_t)(src[2])) << 16) |
|
||||
(((uint32_t)(src[3])) << 24);
|
||||
}
|
||||
|
||||
static void put32lsb(uint8_t* dest, uint32_t value) {
|
||||
dest[0] = (uint8_t)(value );
|
||||
dest[1] = (uint8_t)(value >> 8);
|
||||
dest[2] = (uint8_t)(value >> 16);
|
||||
dest[3] = (uint8_t)(value >> 24);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LUTs used for computing ECC/EDC
|
||||
//
|
||||
static uint8_t ecc_f_lut[256];
|
||||
static uint8_t ecc_b_lut[256];
|
||||
static uint32_t edc_lut [256];
|
||||
|
||||
static void eccedc_init(void) {
|
||||
size_t i;
|
||||
for(i = 0; i < 256; i++) {
|
||||
uint32_t edc = i;
|
||||
size_t j = (i << 1) ^ (i & 0x80 ? 0x11D : 0);
|
||||
ecc_f_lut[i] = j;
|
||||
ecc_b_lut[i ^ j] = i;
|
||||
for(j = 0; j < 8; j++) {
|
||||
edc = (edc >> 1) ^ (edc & 1 ? 0xD8018001 : 0);
|
||||
}
|
||||
edc_lut[i] = edc;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Compute EDC for a block
|
||||
//
|
||||
static uint32_t edc_compute(
|
||||
uint32_t edc,
|
||||
const uint8_t* src,
|
||||
size_t size
|
||||
) {
|
||||
for(; size; size--) {
|
||||
edc = (edc >> 8) ^ edc_lut[(edc ^ (*src++)) & 0xFF];
|
||||
}
|
||||
return edc;
|
||||
}
|
||||
|
||||
//
|
||||
// Write ECC block (either P or Q)
|
||||
//
|
||||
static void ecc_writepq(
|
||||
const uint8_t* address,
|
||||
const uint8_t* data,
|
||||
size_t major_count,
|
||||
size_t minor_count,
|
||||
size_t major_mult,
|
||||
size_t minor_inc,
|
||||
uint8_t* ecc
|
||||
) {
|
||||
size_t size = major_count * minor_count;
|
||||
size_t major;
|
||||
for(major = 0; major < major_count; major++) {
|
||||
size_t index = (major >> 1) * major_mult + (major & 1);
|
||||
uint8_t ecc_a = 0;
|
||||
uint8_t ecc_b = 0;
|
||||
size_t minor;
|
||||
for(minor = 0; minor < minor_count; minor++) {
|
||||
uint8_t temp;
|
||||
if(index < 4) {
|
||||
temp = address[index];
|
||||
} else {
|
||||
temp = data[index - 4];
|
||||
}
|
||||
index += minor_inc;
|
||||
if(index >= size) { index -= size; }
|
||||
ecc_a ^= temp;
|
||||
ecc_b ^= temp;
|
||||
ecc_a = ecc_f_lut[ecc_a];
|
||||
}
|
||||
ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];
|
||||
ecc[major ] = (ecc_a );
|
||||
ecc[major + major_count] = (ecc_a ^ ecc_b);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Write ECC P and Q codes for a sector
|
||||
//
|
||||
static void ecc_writesector(
|
||||
const uint8_t *address,
|
||||
const uint8_t *data,
|
||||
uint8_t *ecc
|
||||
) {
|
||||
ecc_writepq(address, data, 86, 24, 2, 86, ecc); // P
|
||||
ecc_writepq(address, data, 52, 43, 86, 88, ecc + 0xAC); // Q
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const uint8_t zeroaddress[4] = {0, 0, 0, 0};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reconstruct a sector based on type
|
||||
//
|
||||
static void reconstruct_sector(
|
||||
uint8_t* sector, // must point to a full 2352-byte sector
|
||||
int8_t type
|
||||
) {
|
||||
//
|
||||
// Sync
|
||||
//
|
||||
sector[0x000] = 0x00;
|
||||
sector[0x001] = 0xFF;
|
||||
sector[0x002] = 0xFF;
|
||||
sector[0x003] = 0xFF;
|
||||
sector[0x004] = 0xFF;
|
||||
sector[0x005] = 0xFF;
|
||||
sector[0x006] = 0xFF;
|
||||
sector[0x007] = 0xFF;
|
||||
sector[0x008] = 0xFF;
|
||||
sector[0x009] = 0xFF;
|
||||
sector[0x00A] = 0xFF;
|
||||
sector[0x00B] = 0x00;
|
||||
|
||||
switch(type) {
|
||||
case 1:
|
||||
//
|
||||
// Mode
|
||||
//
|
||||
sector[0x00F] = 0x01;
|
||||
//
|
||||
// Reserved
|
||||
//
|
||||
sector[0x814] = 0x00;
|
||||
sector[0x815] = 0x00;
|
||||
sector[0x816] = 0x00;
|
||||
sector[0x817] = 0x00;
|
||||
sector[0x818] = 0x00;
|
||||
sector[0x819] = 0x00;
|
||||
sector[0x81A] = 0x00;
|
||||
sector[0x81B] = 0x00;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
//
|
||||
// Mode
|
||||
//
|
||||
sector[0x00F] = 0x02;
|
||||
//
|
||||
// Flags
|
||||
//
|
||||
sector[0x010] = sector[0x014];
|
||||
sector[0x011] = sector[0x015];
|
||||
sector[0x012] = sector[0x016];
|
||||
sector[0x013] = sector[0x017];
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Compute EDC
|
||||
//
|
||||
switch(type) {
|
||||
case 1: put32lsb(sector+0x810, edc_compute(0, sector , 0x810)); break;
|
||||
case 2: put32lsb(sector+0x818, edc_compute(0, sector+0x10, 0x808)); break;
|
||||
case 3: put32lsb(sector+0x92C, edc_compute(0, sector+0x10, 0x91C)); break;
|
||||
}
|
||||
|
||||
//
|
||||
// Compute ECC
|
||||
//
|
||||
switch(type) {
|
||||
case 1: ecc_writesector(sector+0xC , sector+0x10, sector+0x81C); break;
|
||||
case 2: ecc_writesector(zeroaddress, sector+0x10, sector+0x81C); break;
|
||||
}
|
||||
|
||||
//
|
||||
// Done
|
||||
//
|
||||
}
|
Loading…
Reference in New Issue
Block a user