~thestr4ng3r/mymcplus

21d7ce08df04fe795f359e6765e40eb72e86d3aa — Florian Märkl 3 years ago 7050f67
Clean up ecc code
1 files changed, 26 insertions(+), 46 deletions(-)

M mymcplus/ps2mc_ecc.py
M mymcplus/ps2mc_ecc.py => mymcplus/ps2mc_ecc.py +26 -46
@@ 24,20 24,14 @@ import array

from .round import div_round_up

try:
    import ctypes
    import mymcsup
except ImportError:
    mymcsup = None

__ALL__ = ["ECC_CHECK_OK", "ECC_CHECK_CORRECTED", "ECC_CHECK_FAILED",
       "ecc_calculate", "ecc_check",
       "ecc_calculate_page", "ecc_check_page"]
           "ecc_calculate", "ecc_check", "ecc_calculate_page", "ecc_check_page"]

ECC_CHECK_OK = 0
ECC_CHECK_CORRECTED = 1
ECC_CHECK_FAILED = 2


def _popcount(a):
    count = 0
    while a != 0:


@@ 45,16 39,17 @@ def _popcount(a):
        count += 1
    return count


def _parityb(a):
    a = (a ^ (a >> 1))
    a = (a ^ (a >> 2))
    a = (a ^ (a >> 4))
    return a & 1


def _make_ecc_tables():
    parity_table = [_parityb(b)
            for b in range(256)]
    cpmasks = [0x55, 0x33, 0x0F, 0x00, 0xAA, 0xCC, 0xF0] 
    parity_table = [_parityb(b) for b in range(256)]
    cpmasks = [0x55, 0x33, 0x0F, 0x00, 0xAA, 0xCC, 0xF0]

    column_parity_masks = [None] * 256
    for b in range(256):


@@ 65,11 60,13 @@ def _make_ecc_tables():

    return parity_table, column_parity_masks


_parity_table, _column_parity_masks = _make_ecc_tables()


def _ecc_calculate(s):
    "Calculate the Hamming code for a 128 byte long string or byte array."
    

    if not isinstance(s, array.array):
        a = array.array('B')
        a.fromstring(s)


@@ 85,6 82,7 @@ def _ecc_calculate(s):
            line_parity_1 ^= i
    return [column_parity, line_parity_0 & 0x7F, line_parity_1]


def _ecc_check(s, ecc):
    """Detect and correct any single bit errors.
    


@@ 100,9 98,9 @@ def _ecc_check(s, ecc):
    #_print_bin(0, s.tostring())
    #print "computed %02x %02x %02x" % tuple(computed)
    #print "actual %02x %02x %02x" % tuple(ecc)
    

    # ECC mismatch
        

    cp_diff = (computed[0] ^ ecc[0]) & 0x77
    lp0_diff = (computed[1] ^ ecc[1]) & 0x7F
    lp1_diff = (computed[2] ^ ecc[2]) & 0x7F


@@ 118,7 116,7 @@ def _ecc_check(s, ecc):
        s[lp1_diff] ^= 1 << (cp_diff >> 4)
        return ECC_CHECK_CORRECTED
    if ((cp_diff == 0 and lp0_diff == 0 and lp1_diff == 0)
          or _popcount(lp_comp) + _popcount(cp_comp) == 1):
            or _popcount(lp_comp) + _popcount(cp_comp) == 1):
        print("corrected 2")
        # correctable 1 bit error in ECC
        # (and/or one of the unused bits was set)


@@ 130,14 128,16 @@ def _ecc_check(s, ecc):
    # uncorrectable error
    return ECC_CHECK_FAILED


def ecc_calculate_page(page):
    """Return a list of the ECC codes for a PS2 memory card page."""
    return [ecc_calculate(page[i * 128 : i * 128 + 128])
        for i in range(div_round_up(len(page), 128))]
            for i in range(div_round_up(len(page), 128))]


def ecc_check_page(page, spare):
    "Check and correct any single bit errors in a PS2 memory card page."
    

    failed = False
    corrected = False



@@ 150,41 150,21 @@ def ecc_check_page(page, spare):
        a = array.array('B')
        a.fromstring(page[i * 128 : i * 128 + 128])
        chunks.append((a, list(spare[i * 3 : i * 3 + 3])))
    

    r = [ecc_check(s, ecc)
         for (s, ecc) in chunks]
    ret = ECC_CHECK_OK
    if ECC_CHECK_CORRECTED in r:
        # rebuild sector and spare from the corrected versions
        page = "".join([a[0].tostring()
                for a in chunks])
        page = "".join([a[0].tostring() for a in chunks])
        spare = "".join([chr(a[1][i])
                 for a in chunks
                 for i in range(3)])
                         for a in chunks
                         for i in range(3)])
        ret = ECC_CHECK_CORRECTED
    if ECC_CHECK_FAILED in r:
        ret = ECC_CHECK_FAILED
    return (ret, page, spare)

if mymcsup == None:
    ecc_calculate = _ecc_calculate
    ecc_check = _ecc_check
else:
    # _c_ubyte_p = ctypes.POINTER(ctypes.c_ubyte)
    def ecc_calculate(s):
        aecc = array.array('B', "\0\0\0")
        cecc = ctypes.c_ubyte.from_address(aecc.buffer_info()[0])
        mymcsup.ecc_calculate(s, len(s), cecc)
        return list(aecc)

    def ecc_check(s, ecc):
        cs = ctypes.c_ubyte.from_address(s.buffer_info()[0])
        # print "%08X" % s.buffer_info()[0]
        aecc = array.array('B', ecc)
        cecc = ctypes.c_ubyte.from_address(aecc.buffer_info()[0])
        ret = mymcsup.ecc_check(cs, len(s), cecc)
        ecc[0] = aecc[0]
        ecc[1] = aecc[1]
        ecc[2] = aecc[2]
        return ret
        
    return ret, page, spare


ecc_calculate = _ecc_calculate
ecc_check = _ecc_check