mirror of
https://github.com/zeldaret/oot.git
synced 2024-11-27 20:30:31 +00:00
86 lines
1.7 KiB
C
86 lines
1.7 KiB
C
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "n64chksum.h"
|
|
#include "util.h"
|
|
|
|
//Based on uCON64's N64 checksum algorithm by Andreas Sterbenz
|
|
|
|
#define ROL(i, b) (((i) << (b)) | ((i) >> (32 - (b))))
|
|
|
|
bool n64chksum_calculate(const uint8_t *romData, int cicType, uint32_t *chksum)
|
|
{
|
|
unsigned int seed;
|
|
unsigned int t1, t2, t3, t4, t5, t6;
|
|
size_t pos;
|
|
|
|
const size_t START = 0x1000;
|
|
const size_t END = START + 0x100000;
|
|
|
|
// determine initial seed
|
|
switch (cicType)
|
|
{
|
|
case 6101:
|
|
case 6102:
|
|
seed = 0xF8CA4DDC;
|
|
break;
|
|
case 6103:
|
|
seed = 0xA3886759;
|
|
break;
|
|
case 6105:
|
|
seed = 0xDF26F436;
|
|
break;
|
|
case 6106:
|
|
seed = 0x1FEA617A;
|
|
break;
|
|
default:
|
|
return false; // unknown CIC type
|
|
}
|
|
|
|
t1 = t2 = t3 = t4 = t5 = t6 = seed;
|
|
|
|
for (pos = START; pos < END; pos += 4)
|
|
{
|
|
unsigned int d = util_read_uint32_be(romData + pos);
|
|
unsigned int r = ROL(d, (d & 0x1F));
|
|
|
|
// increment t4 if t6 overflows
|
|
if ((t6 + d) < t6)
|
|
t4++;
|
|
|
|
t6 += d;
|
|
t3 ^= d;
|
|
t5 += r;
|
|
|
|
if (t2 > d)
|
|
t2 ^= r;
|
|
else
|
|
t2 ^= t6 ^ d;
|
|
|
|
if (cicType == 6105)
|
|
t1 += util_read_uint32_be(&romData[0x0750 + (pos & 0xFF)]) ^ d;
|
|
else
|
|
t1 += t5 ^ d;
|
|
}
|
|
|
|
if (cicType == 6103)
|
|
{
|
|
chksum[0] = (t6 ^ t4) + t3;
|
|
chksum[1] = (t5 ^ t2) + t1;
|
|
}
|
|
else if (cicType == 6106)
|
|
{
|
|
chksum[0] = (t6 * t4) + t3;
|
|
chksum[1] = (t5 * t2) + t1;
|
|
}
|
|
else
|
|
{
|
|
chksum[0] = t6 ^ t4 ^ t3;
|
|
chksum[1] = t5 ^ t2 ^ t1;
|
|
}
|
|
|
|
return true;
|
|
}
|