<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://beardedmaker.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Code%3A_unecm</id>
		<title>Code: unecm - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://beardedmaker.com/wiki/index.php?action=history&amp;feed=atom&amp;title=Code%3A_unecm"/>
		<link rel="alternate" type="text/html" href="https://beardedmaker.com/wiki/index.php?title=Code:_unecm&amp;action=history"/>
		<updated>2026-05-10T10:56:18Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.27.4</generator>

	<entry>
		<id>https://beardedmaker.com/wiki/index.php?title=Code:_unecm&amp;diff=3279&amp;oldid=prev</id>
		<title>Beard at 16:50, 26 July 2019</title>
		<link rel="alternate" type="text/html" href="https://beardedmaker.com/wiki/index.php?title=Code:_unecm&amp;diff=3279&amp;oldid=prev"/>
				<updated>2019-07-26T16:50:21Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;tr style='vertical-align: top;' lang='en'&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;Revision as of 16:50, 26 July 2019&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l14&quot; &gt;Line 14:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 14:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The uncompressed image file is now called &amp;lt;code&amp;gt;filename.img&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;.ecm&lt;/del&gt;&amp;lt;/code&amp;gt; in the same folder as the original.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The uncompressed image file is now called &amp;lt;code&amp;gt;filename.img&amp;lt;/code&amp;gt; in the same folder as the original.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;b&amp;gt;Source code ([https://beardedmaker.com/gpl-2.0.txt license]):&amp;lt;/b&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;b&amp;gt;Source code ([https://beardedmaker.com/gpl-2.0.txt license]):&amp;lt;/b&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Beard</name></author>	</entry>

	<entry>
		<id>https://beardedmaker.com/wiki/index.php?title=Code:_unecm&amp;diff=3278&amp;oldid=prev</id>
		<title>Beard at 16:46, 26 July 2019</title>
		<link rel="alternate" type="text/html" href="https://beardedmaker.com/wiki/index.php?title=Code:_unecm&amp;diff=3278&amp;oldid=prev"/>
				<updated>2019-07-26T16:46:31Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;tr style='vertical-align: top;' lang='en'&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;Revision as of 16:46, 26 July 2019&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l16&quot; &gt;Line 16:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 16:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The uncompressed image file is now called &amp;lt;code&amp;gt;filename.img.ecm&amp;lt;/code&amp;gt; in the same folder as the original.&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;The uncompressed image file is now called &amp;lt;code&amp;gt;filename.img.ecm&amp;lt;/code&amp;gt; in the same folder as the original.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;b&amp;gt;Source code:&amp;lt;/b&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color:black; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;b&amp;gt;Source code &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;([https://beardedmaker.com/gpl-2.0.txt license])&lt;/ins&gt;:&amp;lt;/b&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f9f9f9; color: #333333; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #e6e6e6; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Beard</name></author>	</entry>

	<entry>
		<id>https://beardedmaker.com/wiki/index.php?title=Code:_unecm&amp;diff=2168&amp;oldid=prev</id>
		<title>Beard at 19:38, 8 May 2018</title>
		<link rel="alternate" type="text/html" href="https://beardedmaker.com/wiki/index.php?title=Code:_unecm&amp;diff=2168&amp;oldid=prev"/>
				<updated>2018-05-08T19:38:58Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This program decodes a compressed .ecm file. Code obtained from http://www.stramaxon.com/2012/04/how-to-convert-ecm-file-to-bin.html. I've confirmed it works.&lt;br /&gt;
&lt;br /&gt;
Copy the source code below to a file &amp;lt;code&amp;gt;unecm.c&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Now Compile it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gcc -o unecm unecm.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After you've compiled it, run it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./unecm filename.img.ecm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The uncompressed image file is now called &amp;lt;code&amp;gt;filename.img.ecm&amp;lt;/code&amp;gt; in the same folder as the original.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Source code:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
/*&lt;br /&gt;
** UNECM - Decoder for ECM (Error Code Modeler) format.&lt;br /&gt;
** Version 1.0&lt;br /&gt;
** Copyright (C) 2002 Neill Corlett&lt;br /&gt;
**&lt;br /&gt;
** This program is free software; you can redistribute it and/or&lt;br /&gt;
** modify it under the terms of the GNU General Public License&lt;br /&gt;
** as published by the Free Software Foundation; either version 2&lt;br /&gt;
** of the License, or (at your option) any later version.&lt;br /&gt;
**&lt;br /&gt;
** This program is distributed in the hope that it will be useful,&lt;br /&gt;
** but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
** GNU General Public License for more details.&lt;br /&gt;
**&lt;br /&gt;
** You should have received a copy of the GNU General Public License&lt;br /&gt;
** along with this program; if not, write to the Free Software&lt;br /&gt;
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt;
*/&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
/*&lt;br /&gt;
** Portability notes:&lt;br /&gt;
**&lt;br /&gt;
** - Assumes a 32-bit or higher integer size&lt;br /&gt;
** - No assumptions about byte order&lt;br /&gt;
** - No assumptions about struct packing&lt;br /&gt;
** - No unaligned memory access&lt;br /&gt;
*/&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void banner(void) {&lt;br /&gt;
  fprintf(stderr,&lt;br /&gt;
    &amp;quot;UNECM - Decoder for Error Code Modeler format v1.0\n&amp;quot;&lt;br /&gt;
    &amp;quot;Copyright (C) 2002 Neill Corlett\n\n&amp;quot;&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
&lt;br /&gt;
/* Data types */&lt;br /&gt;
#define ecc_uint8 unsigned char&lt;br /&gt;
#define ecc_uint16 unsigned short&lt;br /&gt;
#define ecc_uint32 unsigned&lt;br /&gt;
&lt;br /&gt;
/* LUTs used for computing ECC/EDC */&lt;br /&gt;
static ecc_uint8 ecc_f_lut[256];&lt;br /&gt;
static ecc_uint8 ecc_b_lut[256];&lt;br /&gt;
static ecc_uint32 edc_lut[256];&lt;br /&gt;
&lt;br /&gt;
/* Init routine */&lt;br /&gt;
static void eccedc_init(void) {&lt;br /&gt;
  ecc_uint32 i, j, edc;&lt;br /&gt;
  for(i = 0; i &amp;lt; 256; i++) {&lt;br /&gt;
    j = (i &amp;lt;&amp;lt; 1) ^ (i &amp;amp; 0x80 ? 0x11D : 0);&lt;br /&gt;
    ecc_f_lut[i] = j;&lt;br /&gt;
    ecc_b_lut[i ^ j] = i;&lt;br /&gt;
    edc = i;&lt;br /&gt;
    for(j = 0; j &amp;lt; 8; j++) edc = (edc &amp;gt;&amp;gt; 1) ^ (edc &amp;amp; 1 ? 0xD8018001 : 0);&lt;br /&gt;
    edc_lut[i] = edc;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
/*&lt;br /&gt;
** Compute EDC for a block&lt;br /&gt;
*/&lt;br /&gt;
ecc_uint32 edc_partial_computeblock(&lt;br /&gt;
        ecc_uint32  edc,&lt;br /&gt;
  const ecc_uint8  *src,&lt;br /&gt;
        ecc_uint16  size&lt;br /&gt;
) {&lt;br /&gt;
  while(size--) edc = (edc &amp;gt;&amp;gt; 8) ^ edc_lut[(edc ^ (*src++)) &amp;amp; 0xFF];&lt;br /&gt;
  return edc;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void edc_computeblock(&lt;br /&gt;
  const ecc_uint8  *src,&lt;br /&gt;
        ecc_uint16  size,&lt;br /&gt;
        ecc_uint8  *dest&lt;br /&gt;
) {&lt;br /&gt;
  ecc_uint32 edc = edc_partial_computeblock(0, src, size);&lt;br /&gt;
  dest[0] = (edc &amp;gt;&amp;gt;  0) &amp;amp; 0xFF;&lt;br /&gt;
  dest[1] = (edc &amp;gt;&amp;gt;  8) &amp;amp; 0xFF;&lt;br /&gt;
  dest[2] = (edc &amp;gt;&amp;gt; 16) &amp;amp; 0xFF;&lt;br /&gt;
  dest[3] = (edc &amp;gt;&amp;gt; 24) &amp;amp; 0xFF;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
/*&lt;br /&gt;
** Compute ECC for a block (can do either P or Q)&lt;br /&gt;
*/&lt;br /&gt;
static void ecc_computeblock(&lt;br /&gt;
  ecc_uint8 *src,&lt;br /&gt;
  ecc_uint32 major_count,&lt;br /&gt;
  ecc_uint32 minor_count,&lt;br /&gt;
  ecc_uint32 major_mult,&lt;br /&gt;
  ecc_uint32 minor_inc,&lt;br /&gt;
  ecc_uint8 *dest&lt;br /&gt;
) {&lt;br /&gt;
  ecc_uint32 size = major_count * minor_count;&lt;br /&gt;
  ecc_uint32 major, minor;&lt;br /&gt;
  for(major = 0; major &amp;lt; major_count; major++) {&lt;br /&gt;
    ecc_uint32 index = (major &amp;gt;&amp;gt; 1) * major_mult + (major &amp;amp; 1);&lt;br /&gt;
    ecc_uint8 ecc_a = 0;&lt;br /&gt;
    ecc_uint8 ecc_b = 0;&lt;br /&gt;
    for(minor = 0; minor &amp;lt; minor_count; minor++) {&lt;br /&gt;
      ecc_uint8 temp = src[index];&lt;br /&gt;
      index += minor_inc;&lt;br /&gt;
      if(index &amp;gt;= size) index -= size;&lt;br /&gt;
      ecc_a ^= temp;&lt;br /&gt;
      ecc_b ^= temp;&lt;br /&gt;
      ecc_a = ecc_f_lut[ecc_a];&lt;br /&gt;
    }&lt;br /&gt;
    ecc_a = ecc_b_lut[ecc_f_lut[ecc_a] ^ ecc_b];&lt;br /&gt;
    dest[major              ] = ecc_a;&lt;br /&gt;
    dest[major + major_count] = ecc_a ^ ecc_b;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Generate ECC P and Q codes for a block&lt;br /&gt;
*/&lt;br /&gt;
static void ecc_generate(&lt;br /&gt;
  ecc_uint8 *sector,&lt;br /&gt;
  int        zeroaddress&lt;br /&gt;
) {&lt;br /&gt;
  ecc_uint8 address[4], i;&lt;br /&gt;
  /* Save the address and zero it out */&lt;br /&gt;
  if(zeroaddress) for(i = 0; i &amp;lt; 4; i++) {&lt;br /&gt;
    address[i] = sector[12 + i];&lt;br /&gt;
    sector[12 + i] = 0;&lt;br /&gt;
  }&lt;br /&gt;
  /* Compute ECC P code */&lt;br /&gt;
  ecc_computeblock(sector + 0xC, 86, 24,  2, 86, sector + 0x81C);&lt;br /&gt;
  /* Compute ECC Q code */&lt;br /&gt;
  ecc_computeblock(sector + 0xC, 52, 43, 86, 88, sector + 0x8C8);&lt;br /&gt;
  /* Restore the address */&lt;br /&gt;
  if(zeroaddress) for(i = 0; i &amp;lt; 4; i++) sector[12 + i] = address[i];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
/*&lt;br /&gt;
** Generate ECC/EDC information for a sector (must be 2352 = 0x930 bytes)&lt;br /&gt;
** Returns 0 on success&lt;br /&gt;
*/&lt;br /&gt;
void eccedc_generate(ecc_uint8 *sector, int type) {&lt;br /&gt;
  ecc_uint32 i;&lt;br /&gt;
  switch(type) {&lt;br /&gt;
  case 1: /* Mode 1 */&lt;br /&gt;
    /* Compute EDC */&lt;br /&gt;
    edc_computeblock(sector + 0x00, 0x810, sector + 0x810);&lt;br /&gt;
    /* Write out zero bytes */&lt;br /&gt;
    for(i = 0; i &amp;lt; 8; i++) sector[0x814 + i] = 0;&lt;br /&gt;
    /* Generate ECC P/Q codes */&lt;br /&gt;
    ecc_generate(sector, 0);&lt;br /&gt;
    break;&lt;br /&gt;
  case 2: /* Mode 2 form 1 */&lt;br /&gt;
    /* Compute EDC */&lt;br /&gt;
    edc_computeblock(sector + 0x10, 0x808, sector + 0x818);&lt;br /&gt;
    /* Generate ECC P/Q codes */&lt;br /&gt;
    ecc_generate(sector, 1);&lt;br /&gt;
    break;&lt;br /&gt;
  case 3: /* Mode 2 form 2 */&lt;br /&gt;
    /* Compute EDC */&lt;br /&gt;
    edc_computeblock(sector + 0x10, 0x91C, sector + 0x92C);&lt;br /&gt;
    break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
&lt;br /&gt;
unsigned mycounter;&lt;br /&gt;
unsigned mycounter_total;&lt;br /&gt;
&lt;br /&gt;
void resetcounter(unsigned total) {&lt;br /&gt;
  mycounter = 0;&lt;br /&gt;
  mycounter_total = total;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setcounter(unsigned n) {&lt;br /&gt;
  if((n &amp;gt;&amp;gt; 20) != (mycounter &amp;gt;&amp;gt; 20)) {&lt;br /&gt;
    unsigned a = (n+64)/128;&lt;br /&gt;
    unsigned d = (mycounter_total+64)/128;&lt;br /&gt;
    if(!d) d = 1;&lt;br /&gt;
    fprintf(stderr, &amp;quot;Decoding (%02d%%)\r&amp;quot;, (100*a) / d);&lt;br /&gt;
  }&lt;br /&gt;
  mycounter = n;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int unecmify(&lt;br /&gt;
  FILE *in,&lt;br /&gt;
  FILE *out&lt;br /&gt;
) {&lt;br /&gt;
  unsigned checkedc = 0;&lt;br /&gt;
  unsigned char sector[2352];&lt;br /&gt;
  unsigned type;&lt;br /&gt;
  unsigned num;&lt;br /&gt;
  fseek(in, 0, SEEK_END);&lt;br /&gt;
  resetcounter(ftell(in));&lt;br /&gt;
  fseek(in, 0, SEEK_SET);&lt;br /&gt;
  if(&lt;br /&gt;
    (fgetc(in) != 'E') ||&lt;br /&gt;
    (fgetc(in) != 'C') ||&lt;br /&gt;
    (fgetc(in) != 'M') ||&lt;br /&gt;
    (fgetc(in) != 0x00)&lt;br /&gt;
  ) {&lt;br /&gt;
    fprintf(stderr, &amp;quot;Header not found!\n&amp;quot;);&lt;br /&gt;
    goto corrupt;&lt;br /&gt;
  }&lt;br /&gt;
  for(;;) {&lt;br /&gt;
    int c = fgetc(in);&lt;br /&gt;
    int bits = 5;&lt;br /&gt;
    if(c == EOF) goto uneof;&lt;br /&gt;
    type = c &amp;amp; 3;&lt;br /&gt;
    num = (c &amp;gt;&amp;gt; 2) &amp;amp; 0x1F;&lt;br /&gt;
    while(c &amp;amp; 0x80) {&lt;br /&gt;
      c = fgetc(in);&lt;br /&gt;
      if(c == EOF) goto uneof;&lt;br /&gt;
      num |= ((unsigned)(c &amp;amp; 0x7F)) &amp;lt;&amp;lt; bits;&lt;br /&gt;
      bits += 7;&lt;br /&gt;
    }&lt;br /&gt;
    if(num == 0xFFFFFFFF) break;&lt;br /&gt;
    num++;&lt;br /&gt;
    if(num &amp;gt;= 0x80000000) goto corrupt;&lt;br /&gt;
    if(!type) {&lt;br /&gt;
      while(num) {&lt;br /&gt;
        int b = num;&lt;br /&gt;
        if(b &amp;gt; 2352) b = 2352;&lt;br /&gt;
        if(fread(sector, 1, b, in) != b) goto uneof;&lt;br /&gt;
        checkedc = edc_partial_computeblock(checkedc, sector, b);&lt;br /&gt;
        fwrite(sector, 1, b, out);&lt;br /&gt;
        num -= b;&lt;br /&gt;
        setcounter(ftell(in));&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      while(num--) {&lt;br /&gt;
        memset(sector, 0, sizeof(sector));&lt;br /&gt;
        memset(sector + 1, 0xFF, 10);&lt;br /&gt;
        switch(type) {&lt;br /&gt;
        case 1:&lt;br /&gt;
          sector[0x0F] = 0x01;&lt;br /&gt;
          if(fread(sector + 0x00C, 1, 0x003, in) != 0x003) goto uneof;&lt;br /&gt;
          if(fread(sector + 0x010, 1, 0x800, in) != 0x800) goto uneof;&lt;br /&gt;
          eccedc_generate(sector, 1);&lt;br /&gt;
          checkedc = edc_partial_computeblock(checkedc, sector, 2352);&lt;br /&gt;
          fwrite(sector, 2352, 1, out);&lt;br /&gt;
          setcounter(ftell(in));&lt;br /&gt;
          break;&lt;br /&gt;
        case 2:&lt;br /&gt;
          sector[0x0F] = 0x02;&lt;br /&gt;
          if(fread(sector + 0x014, 1, 0x804, in) != 0x804) goto uneof;&lt;br /&gt;
          sector[0x10] = sector[0x14];&lt;br /&gt;
          sector[0x11] = sector[0x15];&lt;br /&gt;
          sector[0x12] = sector[0x16];&lt;br /&gt;
          sector[0x13] = sector[0x17];&lt;br /&gt;
          eccedc_generate(sector, 2);&lt;br /&gt;
          checkedc = edc_partial_computeblock(checkedc, sector + 0x10, 2336);&lt;br /&gt;
          fwrite(sector + 0x10, 2336, 1, out);&lt;br /&gt;
          setcounter(ftell(in));&lt;br /&gt;
          break;&lt;br /&gt;
        case 3:&lt;br /&gt;
          sector[0x0F] = 0x02;&lt;br /&gt;
          if(fread(sector + 0x014, 1, 0x918, in) != 0x918) goto uneof;&lt;br /&gt;
          sector[0x10] = sector[0x14];&lt;br /&gt;
          sector[0x11] = sector[0x15];&lt;br /&gt;
          sector[0x12] = sector[0x16];&lt;br /&gt;
          sector[0x13] = sector[0x17];&lt;br /&gt;
          eccedc_generate(sector, 3);&lt;br /&gt;
          checkedc = edc_partial_computeblock(checkedc, sector + 0x10, 2336);&lt;br /&gt;
          fwrite(sector + 0x10, 2336, 1, out);&lt;br /&gt;
          setcounter(ftell(in));&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  if(fread(sector, 1, 4, in) != 4) goto uneof;&lt;br /&gt;
  fprintf(stderr, &amp;quot;Decoded %ld bytes -&amp;gt; %ld bytes\n&amp;quot;, ftell(in), ftell(out));&lt;br /&gt;
  if(&lt;br /&gt;
    (sector[0] != ((checkedc &amp;gt;&amp;gt;  0) &amp;amp; 0xFF)) ||&lt;br /&gt;
    (sector[1] != ((checkedc &amp;gt;&amp;gt;  8) &amp;amp; 0xFF)) ||&lt;br /&gt;
    (sector[2] != ((checkedc &amp;gt;&amp;gt; 16) &amp;amp; 0xFF)) ||&lt;br /&gt;
    (sector[3] != ((checkedc &amp;gt;&amp;gt; 24) &amp;amp; 0xFF))&lt;br /&gt;
  ) {&lt;br /&gt;
    fprintf(stderr, &amp;quot;EDC error (%08X, should be %02X%02X%02X%02X)\n&amp;quot;,&lt;br /&gt;
      checkedc,&lt;br /&gt;
      sector[3],&lt;br /&gt;
      sector[2],&lt;br /&gt;
      sector[1],&lt;br /&gt;
      sector[0]&lt;br /&gt;
    );&lt;br /&gt;
    goto corrupt;&lt;br /&gt;
  }&lt;br /&gt;
  fprintf(stderr, &amp;quot;Done; file is OK\n&amp;quot;);&lt;br /&gt;
  return 0;&lt;br /&gt;
uneof:&lt;br /&gt;
  fprintf(stderr, &amp;quot;Unexpected EOF!\n&amp;quot;);&lt;br /&gt;
corrupt:&lt;br /&gt;
  fprintf(stderr, &amp;quot;Corrupt ECM file!\n&amp;quot;);&lt;br /&gt;
  return 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/***************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char **argv) {&lt;br /&gt;
  FILE *fin, *fout;&lt;br /&gt;
  char *infilename;&lt;br /&gt;
  char *outfilename;&lt;br /&gt;
  banner();&lt;br /&gt;
  /*&lt;br /&gt;
  ** Initialize the ECC/EDC tables&lt;br /&gt;
  */&lt;br /&gt;
  eccedc_init();&lt;br /&gt;
  /*&lt;br /&gt;
  ** Check command line&lt;br /&gt;
  */&lt;br /&gt;
  if((argc != 2) &amp;amp;&amp;amp; (argc != 3)) {&lt;br /&gt;
    fprintf(stderr, &amp;quot;usage: %s ecmfile [outputfile]\n&amp;quot;, argv[0]);&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
  /*&lt;br /&gt;
  ** Verify that the input filename is valid&lt;br /&gt;
  */&lt;br /&gt;
  infilename = argv[1];&lt;br /&gt;
  if(strlen(infilename) &amp;lt; 5) {&lt;br /&gt;
    fprintf(stderr, &amp;quot;filename '%s' is too short\n&amp;quot;, infilename);&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
  if(strcasecmp(infilename + strlen(infilename) - 4, &amp;quot;.ecm&amp;quot;)) {&lt;br /&gt;
    fprintf(stderr, &amp;quot;filename must end in .ecm\n&amp;quot;);&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
  /*&lt;br /&gt;
  ** Figure out what the output filename should be&lt;br /&gt;
  */&lt;br /&gt;
  if(argc == 3) {&lt;br /&gt;
    outfilename = argv[2];&lt;br /&gt;
  } else {&lt;br /&gt;
    outfilename = malloc(strlen(infilename) - 3);&lt;br /&gt;
    if(!outfilename) abort();&lt;br /&gt;
    memcpy(outfilename, infilename, strlen(infilename) - 4);&lt;br /&gt;
    outfilename[strlen(infilename) - 4] = 0;&lt;br /&gt;
  }&lt;br /&gt;
  fprintf(stderr, &amp;quot;Decoding %s to %s.\n&amp;quot;, infilename, outfilename);&lt;br /&gt;
  /*&lt;br /&gt;
  ** Open both files&lt;br /&gt;
  */&lt;br /&gt;
  fin = fopen(infilename, &amp;quot;rb&amp;quot;);&lt;br /&gt;
  if(!fin) {&lt;br /&gt;
    perror(infilename);&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
  fout = fopen(outfilename, &amp;quot;wb&amp;quot;);&lt;br /&gt;
  if(!fout) {&lt;br /&gt;
    perror(outfilename);&lt;br /&gt;
    fclose(fin);&lt;br /&gt;
    return 1;&lt;br /&gt;
  }&lt;br /&gt;
  /*&lt;br /&gt;
  ** Decode&lt;br /&gt;
  */&lt;br /&gt;
  unecmify(fin, fout);&lt;br /&gt;
  /*&lt;br /&gt;
  ** Close everything&lt;br /&gt;
  */&lt;br /&gt;
  fclose(fout);&lt;br /&gt;
  fclose(fin);&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Beard</name></author>	</entry>

	</feed>