mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
Conflicts fixed
This commit is contained in:
commit
6b0857dcff
2
asmjit
2
asmjit
@ -1 +1 @@
|
||||
Subproject commit 9ead0cfb4cb5eb1bcf8c12b4a1ea115e438c44fa
|
||||
Subproject commit 0cff228354124bd81050b949097282f78ad0e91a
|
6
bin/dev_hdd0/home/00000001/exdata/.gitignore
vendored
Normal file
6
bin/dev_hdd0/home/00000001/exdata/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Note: This folder has to exist. Once the User Account manager is implemented, make sure it creates this folder in case it's missing and delete this .gitignore file.
|
||||
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
548
rpcs3/Crypto/ec.cpp
Normal file
548
rpcs3/Crypto/ec.cpp
Normal file
@ -0,0 +1,548 @@
|
||||
// Copyright 2007,2008,2010 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
|
||||
void bn_print(char *name, u8 *a, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
printf("%s = ", name);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
printf("%02x", a[i]);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void bn_zero(u8 *d, u32 n)
|
||||
{
|
||||
memset(d, 0, n);
|
||||
}
|
||||
void bn_copy(u8 *d, u8 *a, u32 n)
|
||||
{
|
||||
memcpy(d, a, n);
|
||||
}
|
||||
|
||||
int bn_compare(u8 *a, u8 *b, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (a[i] < b[i])
|
||||
return -1;
|
||||
if (a[i] > b[i])
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 bn_add_1(u8 *d, u8 *a, u8 *b, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
u32 dig;
|
||||
u8 c;
|
||||
|
||||
c = 0;
|
||||
for (i = n - 1; i < n; i--) {
|
||||
dig = a[i] + b[i] + c;
|
||||
c = dig >> 8;
|
||||
d[i] = dig;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static u8 bn_sub_1(u8 *d, u8 *a, u8 *b, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
u32 dig;
|
||||
u8 c;
|
||||
|
||||
c = 1;
|
||||
for (i = n - 1; i < n; i--) {
|
||||
dig = a[i] + 255 - b[i] + c;
|
||||
c = dig >> 8;
|
||||
d[i] = dig;
|
||||
}
|
||||
|
||||
return 1 - c;
|
||||
}
|
||||
|
||||
void bn_reduce(u8 *d, u8 *N, u32 n)
|
||||
{
|
||||
if (bn_compare(d, N, n) >= 0)
|
||||
bn_sub_1(d, d, N, n);
|
||||
}
|
||||
|
||||
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
if (bn_add_1(d, a, b, n))
|
||||
bn_sub_1(d, d, N, n);
|
||||
|
||||
bn_reduce(d, N, n);
|
||||
}
|
||||
|
||||
void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
if (bn_sub_1(d, a, b, n))
|
||||
bn_add_1(d, d, N, n);
|
||||
}
|
||||
|
||||
static const u8 inv256[0x80] = {
|
||||
0x01, 0xab, 0xcd, 0xb7, 0x39, 0xa3, 0xc5, 0xef,
|
||||
0xf1, 0x1b, 0x3d, 0xa7, 0x29, 0x13, 0x35, 0xdf,
|
||||
0xe1, 0x8b, 0xad, 0x97, 0x19, 0x83, 0xa5, 0xcf,
|
||||
0xd1, 0xfb, 0x1d, 0x87, 0x09, 0xf3, 0x15, 0xbf,
|
||||
0xc1, 0x6b, 0x8d, 0x77, 0xf9, 0x63, 0x85, 0xaf,
|
||||
0xb1, 0xdb, 0xfd, 0x67, 0xe9, 0xd3, 0xf5, 0x9f,
|
||||
0xa1, 0x4b, 0x6d, 0x57, 0xd9, 0x43, 0x65, 0x8f,
|
||||
0x91, 0xbb, 0xdd, 0x47, 0xc9, 0xb3, 0xd5, 0x7f,
|
||||
0x81, 0x2b, 0x4d, 0x37, 0xb9, 0x23, 0x45, 0x6f,
|
||||
0x71, 0x9b, 0xbd, 0x27, 0xa9, 0x93, 0xb5, 0x5f,
|
||||
0x61, 0x0b, 0x2d, 0x17, 0x99, 0x03, 0x25, 0x4f,
|
||||
0x51, 0x7b, 0x9d, 0x07, 0x89, 0x73, 0x95, 0x3f,
|
||||
0x41, 0xeb, 0x0d, 0xf7, 0x79, 0xe3, 0x05, 0x2f,
|
||||
0x31, 0x5b, 0x7d, 0xe7, 0x69, 0x53, 0x75, 0x1f,
|
||||
0x21, 0xcb, 0xed, 0xd7, 0x59, 0xc3, 0xe5, 0x0f,
|
||||
0x11, 0x3b, 0x5d, 0xc7, 0x49, 0x33, 0x55, 0xff,
|
||||
};
|
||||
|
||||
static void bn_mon_muladd_dig(u8 *d, u8 *a, u8 b, u8 *N, u32 n)
|
||||
{
|
||||
u32 dig;
|
||||
u32 i;
|
||||
|
||||
u8 z = -(d[n-1] + a[n-1]*b) * inv256[N[n-1]/2];
|
||||
|
||||
dig = d[n-1] + a[n-1]*b + N[n-1]*z;
|
||||
dig >>= 8;
|
||||
|
||||
for (i = n - 2; i < n; i--) {
|
||||
dig += d[i] + a[i]*b + N[i]*z;
|
||||
d[i+1] = dig;
|
||||
dig >>= 8;
|
||||
}
|
||||
|
||||
d[0] = dig;
|
||||
dig >>= 8;
|
||||
|
||||
if (dig)
|
||||
bn_sub_1(d, d, N, n);
|
||||
|
||||
bn_reduce(d, N, n);
|
||||
}
|
||||
|
||||
void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
u8 t[512];
|
||||
u32 i;
|
||||
|
||||
bn_zero(t, n);
|
||||
|
||||
for (i = n - 1; i < n; i--)
|
||||
bn_mon_muladd_dig(t, a, b[i], N, n);
|
||||
|
||||
bn_copy(d, t, n);
|
||||
}
|
||||
|
||||
void bn_to_mon(u8 *d, u8 *N, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 8*n; i++)
|
||||
bn_add(d, d, d, N, n);
|
||||
}
|
||||
|
||||
void bn_from_mon(u8 *d, u8 *N, u32 n)
|
||||
{
|
||||
u8 t[512];
|
||||
|
||||
bn_zero(t, n);
|
||||
t[n-1] = 1;
|
||||
bn_mon_mul(d, d, t, N, n);
|
||||
}
|
||||
|
||||
static void bn_mon_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en)
|
||||
{
|
||||
u8 t[512];
|
||||
u32 i;
|
||||
u8 mask;
|
||||
|
||||
bn_zero(d, n);
|
||||
d[n-1] = 1;
|
||||
bn_to_mon(d, N, n);
|
||||
|
||||
for (i = 0; i < en; i++)
|
||||
for (mask = 0x80; mask != 0; mask >>= 1) {
|
||||
bn_mon_mul(t, d, d, N, n);
|
||||
if ((e[i] & mask) != 0)
|
||||
bn_mon_mul(d, t, a, N, n);
|
||||
else
|
||||
bn_copy(d, t, n);
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n)
|
||||
{
|
||||
u8 t[512], s[512];
|
||||
|
||||
bn_zero(s, n);
|
||||
s[n-1] = 2;
|
||||
bn_sub_1(t, N, s, n);
|
||||
bn_mon_exp(d, a, N, n, t, n);
|
||||
}
|
||||
|
||||
void bn_copy(u8 *d, u8 *a, u32 n);
|
||||
int bn_compare(u8 *a, u8 *b, u32 n);
|
||||
void bn_reduce(u8 *d, u8 *N, u32 n);
|
||||
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_to_mon(u8 *d, u8 *N, u32 n);
|
||||
void bn_from_mon(u8 *d, u8 *N, u32 n);
|
||||
void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n);
|
||||
|
||||
struct point {
|
||||
u8 x[20];
|
||||
u8 y[20];
|
||||
};
|
||||
|
||||
static u8 ec_p[20];
|
||||
static u8 ec_a[20]; // mon
|
||||
static u8 ec_b[20]; // mon
|
||||
static u8 ec_N[21];
|
||||
static struct point ec_G; // mon
|
||||
static struct point ec_Q; // mon
|
||||
static u8 ec_k[21];
|
||||
|
||||
static void elt_copy(u8 *d, u8 *a)
|
||||
{
|
||||
memcpy(d, a, 20);
|
||||
}
|
||||
|
||||
static void elt_zero(u8 *d)
|
||||
{
|
||||
memset(d, 0, 20);
|
||||
}
|
||||
|
||||
static int elt_is_zero(u8 *d)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
if (d[i] != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void elt_add(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
bn_add(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_sub(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
bn_sub(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_mul(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
bn_mon_mul(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_square(u8 *d, u8 *a)
|
||||
{
|
||||
elt_mul(d, a, a);
|
||||
}
|
||||
|
||||
static void elt_inv(u8 *d, u8 *a)
|
||||
{
|
||||
u8 s[20];
|
||||
elt_copy(s, a);
|
||||
bn_mon_inv(d, s, ec_p, 20);
|
||||
}
|
||||
|
||||
static void point_to_mon(struct point *p)
|
||||
{
|
||||
bn_to_mon(p->x, ec_p, 20);
|
||||
bn_to_mon(p->y, ec_p, 20);
|
||||
}
|
||||
|
||||
static void point_from_mon(struct point *p)
|
||||
{
|
||||
bn_from_mon(p->x, ec_p, 20);
|
||||
bn_from_mon(p->y, ec_p, 20);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int point_is_on_curve(u8 *p)
|
||||
{
|
||||
u8 s[20], t[20];
|
||||
u8 *x, *y;
|
||||
|
||||
x = p;
|
||||
y = p + 20;
|
||||
|
||||
elt_square(t, x);
|
||||
elt_mul(s, t, x);
|
||||
|
||||
elt_mul(t, x, ec_a);
|
||||
elt_add(s, s, t);
|
||||
|
||||
elt_add(s, s, ec_b);
|
||||
|
||||
elt_square(t, y);
|
||||
elt_sub(s, s, t);
|
||||
|
||||
return elt_is_zero(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void point_zero(struct point *p)
|
||||
{
|
||||
elt_zero(p->x);
|
||||
elt_zero(p->y);
|
||||
}
|
||||
|
||||
static int point_is_zero(struct point *p)
|
||||
{
|
||||
return elt_is_zero(p->x) && elt_is_zero(p->y);
|
||||
}
|
||||
|
||||
static void point_double(struct point *r, struct point *p)
|
||||
{
|
||||
u8 s[20], t[20];
|
||||
struct point pp;
|
||||
u8 *px, *py, *rx, *ry;
|
||||
|
||||
pp = *p;
|
||||
|
||||
px = pp.x;
|
||||
py = pp.y;
|
||||
rx = r->x;
|
||||
ry = r->y;
|
||||
|
||||
if (elt_is_zero(py)) {
|
||||
point_zero(r);
|
||||
return;
|
||||
}
|
||||
|
||||
elt_square(t, px); // t = px*px
|
||||
elt_add(s, t, t); // s = 2*px*px
|
||||
elt_add(s, s, t); // s = 3*px*px
|
||||
elt_add(s, s, ec_a); // s = 3*px*px + a
|
||||
elt_add(t, py, py); // t = 2*py
|
||||
elt_inv(t, t); // t = 1/(2*py)
|
||||
elt_mul(s, s, t); // s = (3*px*px+a)/(2*py)
|
||||
|
||||
elt_square(rx, s); // rx = s*s
|
||||
elt_add(t, px, px); // t = 2*px
|
||||
elt_sub(rx, rx, t); // rx = s*s - 2*px
|
||||
|
||||
elt_sub(t, px, rx); // t = -(rx-px)
|
||||
elt_mul(ry, s, t); // ry = -s*(rx-px)
|
||||
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
|
||||
}
|
||||
|
||||
static void point_add(struct point *r, struct point *p, struct point *q)
|
||||
{
|
||||
u8 s[20], t[20], u[20];
|
||||
u8 *px, *py, *qx, *qy, *rx, *ry;
|
||||
struct point pp, qq;
|
||||
|
||||
pp = *p;
|
||||
qq = *q;
|
||||
|
||||
px = pp.x;
|
||||
py = pp.y;
|
||||
qx = qq.x;
|
||||
qy = qq.y;
|
||||
rx = r->x;
|
||||
ry = r->y;
|
||||
|
||||
if (point_is_zero(&pp)) {
|
||||
elt_copy(rx, qx);
|
||||
elt_copy(ry, qy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (point_is_zero(&qq)) {
|
||||
elt_copy(rx, px);
|
||||
elt_copy(ry, py);
|
||||
return;
|
||||
}
|
||||
|
||||
elt_sub(u, qx, px);
|
||||
|
||||
if (elt_is_zero(u)) {
|
||||
elt_sub(u, qy, py);
|
||||
if (elt_is_zero(u))
|
||||
point_double(r, &pp);
|
||||
else
|
||||
point_zero(r);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
elt_inv(t, u); // t = 1/(qx-px)
|
||||
elt_sub(u, qy, py); // u = qy-py
|
||||
elt_mul(s, t, u); // s = (qy-py)/(qx-px)
|
||||
|
||||
elt_square(rx, s); // rx = s*s
|
||||
elt_add(t, px, qx); // t = px+qx
|
||||
elt_sub(rx, rx, t); // rx = s*s - (px+qx)
|
||||
|
||||
elt_sub(t, px, rx); // t = -(rx-px)
|
||||
elt_mul(ry, s, t); // ry = -s*(rx-px)
|
||||
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
|
||||
}
|
||||
|
||||
static void point_mul(struct point *d, u8 *a, struct point *b) // a is bignum
|
||||
{
|
||||
u32 i;
|
||||
u8 mask;
|
||||
|
||||
point_zero(d);
|
||||
|
||||
for (i = 0; i < 21; i++)
|
||||
for (mask = 0x80; mask != 0; mask >>= 1) {
|
||||
point_double(d, d);
|
||||
if ((a[i] & mask) != 0)
|
||||
point_add(d, d, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash)
|
||||
{
|
||||
u8 e[21];
|
||||
u8 kk[21];
|
||||
u8 m[21];
|
||||
u8 minv[21];
|
||||
struct point mG;
|
||||
|
||||
e[0] = 0;
|
||||
memcpy(e + 1, hash, 20);
|
||||
bn_reduce(e, ec_N, 21);
|
||||
|
||||
try_again:
|
||||
prng(m, 21);
|
||||
m[0] = 0;
|
||||
if (bn_compare(m, ec_N, 21) >= 0)
|
||||
goto try_again;
|
||||
|
||||
// R = (mG).x
|
||||
|
||||
point_mul(&mG, m, &ec_G);
|
||||
point_from_mon(&mG);
|
||||
R[0] = 0;
|
||||
elt_copy(R+1, mG.x);
|
||||
|
||||
// S = m**-1*(e + Rk) (mod N)
|
||||
|
||||
bn_copy(kk, k, 21);
|
||||
bn_reduce(kk, ec_N, 21);
|
||||
bn_to_mon(m, ec_N, 21);
|
||||
bn_to_mon(e, ec_N, 21);
|
||||
bn_to_mon(R, ec_N, 21);
|
||||
bn_to_mon(kk, ec_N, 21);
|
||||
|
||||
bn_mon_mul(S, R, kk, ec_N, 21);
|
||||
bn_add(kk, S, e, ec_N, 21);
|
||||
bn_mon_inv(minv, m, ec_N, 21);
|
||||
bn_mon_mul(S, minv, kk, ec_N, 21);
|
||||
|
||||
bn_from_mon(R, ec_N, 21);
|
||||
bn_from_mon(S, ec_N, 21);
|
||||
}
|
||||
|
||||
static int check_ecdsa(struct point *Q, u8 *R, u8 *S, u8 *hash)
|
||||
{
|
||||
u8 Sinv[21];
|
||||
u8 e[21];
|
||||
u8 w1[21], w2[21];
|
||||
struct point r1, r2;
|
||||
u8 rr[21];
|
||||
|
||||
e[0] = 0;
|
||||
memcpy(e + 1, hash, 20);
|
||||
bn_reduce(e, ec_N, 21);
|
||||
|
||||
bn_to_mon(R, ec_N, 21);
|
||||
bn_to_mon(S, ec_N, 21);
|
||||
bn_to_mon(e, ec_N, 21);
|
||||
|
||||
bn_mon_inv(Sinv, S, ec_N, 21);
|
||||
|
||||
bn_mon_mul(w1, e, Sinv, ec_N, 21);
|
||||
bn_mon_mul(w2, R, Sinv, ec_N, 21);
|
||||
|
||||
bn_from_mon(w1, ec_N, 21);
|
||||
bn_from_mon(w2, ec_N, 21);
|
||||
|
||||
point_mul(&r1, w1, &ec_G);
|
||||
point_mul(&r2, w2, Q);
|
||||
|
||||
point_add(&r1, &r1, &r2);
|
||||
|
||||
point_from_mon(&r1);
|
||||
|
||||
rr[0] = 0;
|
||||
memcpy(rr + 1, r1.x, 20);
|
||||
bn_reduce(rr, ec_N, 21);
|
||||
|
||||
bn_from_mon(R, ec_N, 21);
|
||||
bn_from_mon(S, ec_N, 21);
|
||||
|
||||
return (bn_compare(rr, R, 21) == 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void ec_priv_to_pub(u8 *k, u8 *Q)
|
||||
{
|
||||
point_mul(Q, k, ec_G);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ecdsa_set_curve(u8* p, u8* a, u8* b, u8* N, u8* Gx, u8* Gy)
|
||||
{
|
||||
memcpy(ec_p, p, 20);
|
||||
memcpy(ec_a, a, 20);
|
||||
memcpy(ec_b, b, 20);
|
||||
memcpy(ec_N, N, 21);
|
||||
memcpy(ec_G.x, Gx, 20);
|
||||
memcpy(ec_G.y, Gy, 20);
|
||||
|
||||
bn_to_mon(ec_a, ec_p, 20);
|
||||
bn_to_mon(ec_b, ec_p, 20);
|
||||
|
||||
point_to_mon(&ec_G);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ecdsa_set_pub(u8 *Q)
|
||||
{
|
||||
memcpy(ec_Q.x, Q, 20);
|
||||
memcpy(ec_Q.y, Q+20, 20);
|
||||
point_to_mon(&ec_Q);
|
||||
}
|
||||
|
||||
void ecdsa_set_priv(u8 *k)
|
||||
{
|
||||
memcpy(ec_k, k, sizeof ec_k);
|
||||
}
|
||||
|
||||
int ecdsa_verify(u8 *hash, u8 *R, u8 *S)
|
||||
{
|
||||
return check_ecdsa(&ec_Q, R, S, hash);
|
||||
}
|
||||
|
||||
void ecdsa_sign(u8 *hash, u8 *R, u8 *S)
|
||||
{
|
||||
generate_ecdsa(R, S, ec_k, hash);
|
||||
}
|
14
rpcs3/Crypto/ec.h
Normal file
14
rpcs3/Crypto/ec.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int ecdsa_set_curve(unsigned char *p, unsigned char *a, unsigned char *b, unsigned char *N, unsigned char *Gx, unsigned char *Gy);
|
||||
void ecdsa_set_pub(unsigned char *Q);
|
||||
void ecdsa_set_priv(unsigned char *k);
|
||||
int ecdsa_verify(unsigned char *hash, unsigned char *R, unsigned char *S);
|
||||
void ecdsa_sign(unsigned char *hash, unsigned char *R, unsigned char *S);
|
@ -8,10 +8,10 @@ SELF_KEY::SELF_KEY(u64 ver, u16 rev, u32 type, const std::string& e, const std::
|
||||
version = ver;
|
||||
revision = rev;
|
||||
self_type = type;
|
||||
hex_to_bytes(erk, e.c_str());
|
||||
hex_to_bytes(riv, r.c_str());
|
||||
hex_to_bytes(pub, pb.c_str());
|
||||
hex_to_bytes(priv, pr.c_str());
|
||||
hex_to_bytes(erk, e.c_str(), 0);
|
||||
hex_to_bytes(riv, r.c_str(), 0);
|
||||
hex_to_bytes(pub, pb.c_str(), 0);
|
||||
hex_to_bytes(priv, pr.c_str(), 0);
|
||||
curve_type = ct;
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,35 @@ static u8 EDAT_IV[0x10] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_P[0x14] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_A[0x14] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_B[0x14] = {
|
||||
0xA6, 0x8B, 0xED, 0xC3, 0x34, 0x18, 0x02, 0x9C, 0x1D, 0x3C, 0xE3, 0x3B, 0x9A, 0x32, 0x1F, 0xCC, 0xBB, 0x9E, 0x0F, 0x0B
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_N[0x15] = {
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xB5, 0xAE, 0x3C, 0x52, 0x3E, 0x63, 0x94, 0x4F, 0x21, 0x27
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_GX[0x14] = {
|
||||
0x12, 0x8E, 0xC4, 0x25, 0x64, 0x87, 0xFD, 0x8F, 0xDF, 0x64, 0xE2, 0x43, 0x7B, 0xC0, 0xA1, 0xF6, 0xD5, 0xAF, 0xDE, 0x2C
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_GY[0x14] = {
|
||||
0x59, 0x58, 0x55, 0x7E, 0xB1, 0xDB, 0x00, 0x12, 0x60, 0x42, 0x55, 0x24, 0xDB, 0xC3, 0x79, 0xD5, 0xAC, 0x5F, 0x4A, 0xDF
|
||||
};
|
||||
|
||||
static u8 VSH_PUB[0x28] = {
|
||||
0x62, 0x27, 0xB0, 0x0A, 0x02, 0x85, 0x6F, 0xB0, 0x41, 0x08, 0x87, 0x67, 0x19, 0xE0, 0xA0, 0x18, 0x32, 0x91, 0xEE, 0xB9,
|
||||
0x6E, 0x73, 0x6A, 0xBF, 0x81, 0xF7, 0x0E, 0xE9, 0x16, 0x1B, 0x0D, 0xDE, 0xB0, 0x26, 0x76, 0x1A, 0xFF, 0x7B, 0xC8, 0x5B
|
||||
};
|
||||
|
||||
class KeyVault
|
||||
{
|
||||
std::vector<SELF_KEY> sk_LV0_arr;
|
||||
|
@ -4,26 +4,20 @@
|
||||
|
||||
#include "lz.h"
|
||||
|
||||
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
|
||||
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
|
||||
{
|
||||
if (!((*range) >> 24))
|
||||
if (!((*range) >> 24))
|
||||
{
|
||||
(*range) <<= 8;
|
||||
*code = ((*code) << 8) + (*src)++[5];
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c)
|
||||
{
|
||||
unsigned int val = *range;
|
||||
|
||||
if (decode_range(range, code, src))
|
||||
val *= (*c);
|
||||
else
|
||||
val = (val >> 8) * (*c);
|
||||
decode_range(range, code, src);
|
||||
|
||||
unsigned int val = ((*range) >> 8) * (*c);
|
||||
|
||||
*c -= ((*c) >> 3);
|
||||
if (index) (*index) <<= 1;
|
||||
@ -47,12 +41,12 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
if (index >= 3)
|
||||
if (index >= 3)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
|
||||
if (index >= 4)
|
||||
decode_bit(range, code, &i, src, ptr + 0x18);
|
||||
if (index >= 4)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
|
||||
decode_bit(range, code, &i, src, ptr + 0x18);
|
||||
if (index >= 5)
|
||||
{
|
||||
decode_range(range, code, src);
|
||||
@ -60,8 +54,8 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
|
||||
{
|
||||
i <<= 1;
|
||||
(*range) >>= 1;
|
||||
if (*code < *range)
|
||||
i++;
|
||||
if (*code < *range)
|
||||
i++;
|
||||
else
|
||||
(*code) -= *range;
|
||||
}
|
||||
@ -69,16 +63,16 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
|
||||
}
|
||||
}
|
||||
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr); // Offset 0x960
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr);
|
||||
|
||||
if (index >= 1)
|
||||
if (index >= 1)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x8); // Offset 0x968
|
||||
if (index >= 2)
|
||||
decode_bit(range, code, &i, src, ptr + 0x8);
|
||||
if (index >= 2)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x10); // Offset 0x970
|
||||
decode_bit(range, code, &i, src, ptr + 0x10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
@ -88,12 +82,12 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
|
||||
int i = 1;
|
||||
index /= 8;
|
||||
|
||||
if (index >= 3)
|
||||
if (index >= 3)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
|
||||
if (index >= 4)
|
||||
decode_bit(range, code, &i, src, ptr + 4);
|
||||
if (index >= 4)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
|
||||
decode_bit(range, code, &i, src, ptr + 4);
|
||||
if (index >= 5)
|
||||
{
|
||||
decode_range(range, code, src);
|
||||
@ -101,8 +95,8 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
|
||||
{
|
||||
i <<= 1;
|
||||
(*range) >>= 1;
|
||||
if (*code < *range)
|
||||
i++;
|
||||
if (*code < *range)
|
||||
i++;
|
||||
else
|
||||
(*code) -= *range;
|
||||
}
|
||||
@ -110,16 +104,16 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
|
||||
}
|
||||
}
|
||||
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr + 3); // Offset 0x8A8 + 3
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr);
|
||||
|
||||
if (index >= 1)
|
||||
if (index >= 1)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 2); // Offset 0x8A8 + 2
|
||||
if (index >= 2)
|
||||
decode_bit(range, code, &i, src, ptr + 1);
|
||||
if (index >= 2)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 1); // Offset 0x8A8 + 1
|
||||
decode_bit(range, code, &i, src, ptr + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
@ -128,7 +122,7 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
||||
{
|
||||
int result;
|
||||
|
||||
unsigned char *tmp = new unsigned char[0xA70];
|
||||
unsigned char *tmp = new unsigned char[0xCC8];
|
||||
|
||||
int offset = 0;
|
||||
int bit_flag = 0;
|
||||
@ -159,11 +153,11 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
||||
else
|
||||
{
|
||||
// Set up a temporary buffer (sliding window).
|
||||
memset(tmp, 0x80, 0xA60);
|
||||
memset(tmp, 0x80, 0xCA8);
|
||||
while (1)
|
||||
{
|
||||
// Start reading at 0x920.
|
||||
tmp_sect1 = tmp + offset + 0x920;
|
||||
// Start reading at 0xB68.
|
||||
tmp_sect1 = tmp + offset + 0xB68;
|
||||
if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char.
|
||||
{
|
||||
// Adjust offset and check for stream end.
|
||||
@ -189,57 +183,65 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
||||
int index = -1;
|
||||
|
||||
// Identify the data length bit field.
|
||||
do {
|
||||
tmp_sect1 += 8;
|
||||
do
|
||||
{
|
||||
tmp_sect1 += 8;
|
||||
bit_flag = decode_bit(&range, &code, 0, &in, tmp_sect1);
|
||||
index += bit_flag;
|
||||
} while ((bit_flag != 0) && (index < 6));
|
||||
|
||||
// Default block size is 0x40.
|
||||
int b_size = 0x40;
|
||||
// Default block size is 0x160.
|
||||
int b_size = 0x160;
|
||||
tmp_sect2 = tmp + index + 0x7F1;
|
||||
|
||||
// If the data length was found, parse it as a number.
|
||||
if ((index >= 0) || (bit_flag != 0))
|
||||
if ((index >= 0) || (bit_flag != 0))
|
||||
{
|
||||
// Locate next section.
|
||||
int sect = (index << 5) | (((((start - out)) << index) & 3) << 3) | (offset & 7);
|
||||
tmp_sect1 = tmp + 0x960 + sect;
|
||||
int sect = (index << 5) | (((((int)(start - out)) << index) & 3) << 3) | (offset & 7);
|
||||
tmp_sect1 = tmp + 0xBA8 + sect;
|
||||
|
||||
// Decode the data length (8 bit fields).
|
||||
data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in);
|
||||
|
||||
// If we got valid parameters, seek to find data offset.
|
||||
if ((data_length != 3) && ((index > 0) || (bit_flag != 0))) {
|
||||
tmp_sect2 += 0x38;
|
||||
b_size = 0x80; // Block size is now 0x80.
|
||||
}
|
||||
} else {
|
||||
if (data_length == 0xFF) return (start - out); // End of stream.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume one byte of advance.
|
||||
data_length = 1;
|
||||
}
|
||||
|
||||
// If we got valid parameters, seek to find data offset.
|
||||
if ((data_length <= 2))
|
||||
{
|
||||
tmp_sect2 += 0xF8;
|
||||
b_size = 0x40; // Block size is now 0x40.
|
||||
}
|
||||
|
||||
int diff = 0;
|
||||
int shift = 1;
|
||||
|
||||
// Identify the data offset bit field.
|
||||
do {
|
||||
do
|
||||
{
|
||||
diff = (shift << 4) - b_size;
|
||||
bit_flag = decode_bit(&range, &code, &shift, &in, tmp_sect2 + (shift << 3));
|
||||
} while (diff < 0);
|
||||
|
||||
// If the data offset was found, parse it as a number.
|
||||
if ((diff > 0) || (bit_flag != 0))
|
||||
if ((diff > 0) || (bit_flag != 0))
|
||||
{
|
||||
// Adjust diff if needed.
|
||||
if (bit_flag == 0) diff -= 8;
|
||||
|
||||
// Locate section.
|
||||
tmp_sect3 = tmp + 0x8A8 + diff;
|
||||
tmp_sect3 = tmp + 0x928 + diff;
|
||||
|
||||
// Decode the data offset (1 bit fields).
|
||||
data_offset = decode_word(tmp_sect3, diff, &bit_flag, &range, &code, &in);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume one byte of advance.
|
||||
data_offset = 1;
|
||||
}
|
||||
@ -260,7 +262,8 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
||||
offset = ((((int)(buf_end - out)) + 1) & 1) + 6;
|
||||
|
||||
// Copy data.
|
||||
do {
|
||||
do
|
||||
{
|
||||
*start++ = *buf_start++;
|
||||
} while (start < buf_end);
|
||||
|
||||
@ -271,4 +274,4 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
||||
}
|
||||
delete[] tmp;
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,8 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
// Reverse-engineered custom Lempel–Ziv–Markov based compression.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c);
|
||||
int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
int decompress(unsigned char *out, unsigned char *in, unsigned int size);
|
||||
int decompress(unsigned char *out, unsigned char *in, unsigned int size);
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* \file sha1.h
|
||||
*
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
#include "key_vault.h"
|
||||
#include "unedat.h"
|
||||
#include "Utilities/Log.h"
|
||||
@ -7,7 +6,7 @@
|
||||
|
||||
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv)
|
||||
{
|
||||
int mode = (int) (crypto_mode & 0xF0000000);
|
||||
int mode = (int)(crypto_mode & 0xF0000000);
|
||||
switch (mode) {
|
||||
case 0x10000000:
|
||||
// Encrypted ERK.
|
||||
@ -32,7 +31,7 @@ void generate_key(int crypto_mode, int version, unsigned char *key_final, unsign
|
||||
|
||||
void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsigned char *hash)
|
||||
{
|
||||
int mode = (int) (hash_mode & 0xF0000000);
|
||||
int mode = (int)(hash_mode & 0xF0000000);
|
||||
switch (mode) {
|
||||
case 0x10000000:
|
||||
// Encrypted HASH.
|
||||
@ -52,7 +51,7 @@ void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsign
|
||||
};
|
||||
}
|
||||
|
||||
bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, int length, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash)
|
||||
bool decrypt(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, int length, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash)
|
||||
{
|
||||
// Setup buffers for key, iv and hash.
|
||||
unsigned char key_final[0x10] = {};
|
||||
@ -77,29 +76,30 @@ bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsi
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ((hash_mode & 0xFF) == 0x01) // 0x14 SHA1-HMAC
|
||||
{
|
||||
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash);
|
||||
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash, 0x14);
|
||||
}
|
||||
else if ((hash_mode & 0xFF) == 0x02) // 0x10 AES-CMAC
|
||||
{
|
||||
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash);
|
||||
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
|
||||
}
|
||||
else if ((hash_mode & 0xFF) == 0x04) //0x10 SHA1-HMAC
|
||||
{
|
||||
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash);
|
||||
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// EDAT/SDAT functions.
|
||||
unsigned char* dec_section(unsigned char* metadata)
|
||||
{
|
||||
unsigned char *dec = new unsigned char[0x10];
|
||||
@ -135,11 +135,11 @@ unsigned char* get_block_key(int block, NPD_HEADER *npd)
|
||||
return dest_key;
|
||||
}
|
||||
|
||||
// EDAT/SDAT functions.
|
||||
int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
|
||||
// EDAT/SDAT decryption.
|
||||
int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
|
||||
{
|
||||
// Get metadata info and setup buffers.
|
||||
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
|
||||
int metadata_offset = 0x100;
|
||||
|
||||
@ -148,78 +148,103 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
||||
unsigned char *b_key;
|
||||
unsigned char *iv;
|
||||
|
||||
unsigned char hash[0x10];
|
||||
unsigned char key_result[0x10];
|
||||
unsigned char hash_result[0x14];
|
||||
memset(hash, 0, 0x10);
|
||||
memset(key_result, 0, 0x10);
|
||||
memset(hash_result, 0, 0x14);
|
||||
|
||||
unsigned long long offset = 0;
|
||||
unsigned long long metadata_sec_offset = 0;
|
||||
int length = 0;
|
||||
int compression_end = 0;
|
||||
unsigned char empty_iv[0x10] = {};
|
||||
|
||||
// Decrypt the metadata.
|
||||
for (int i = 0; i < block_num; i++)
|
||||
int i;
|
||||
for (i = 0; i < block_num; i++)
|
||||
{
|
||||
in->Seek(metadata_offset + i * metadata_section_size);
|
||||
unsigned char hash_result[0x10];
|
||||
long offset;
|
||||
int length = 0;
|
||||
int compression_end = 0;
|
||||
memset(hash_result, 0, 0x14);
|
||||
|
||||
if ((edat->flags & EDAT_FLAG_0x04) != 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Flag 0x04 is not yet supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0)
|
||||
{
|
||||
unsigned char metadata[0x20];
|
||||
in->Read(metadata, 0x20);
|
||||
|
||||
// If the data is compressed, decrypt the metadata.
|
||||
unsigned char *result = dec_section(metadata);
|
||||
offset = ((swap32(*(int*)&result[0]) << 4) | (swap32(*(int*)&result[4])));
|
||||
length = swap32(*(int*)&result[8]);
|
||||
compression_end = swap32(*(int*)&result[12]);
|
||||
delete[] result;
|
||||
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
|
||||
in->Seek(metadata_sec_offset);
|
||||
|
||||
unsigned char metadata[0x20];
|
||||
memset(metadata, 0, 0x20);
|
||||
in->Read(metadata, 0x20);
|
||||
|
||||
// If the data is compressed, decrypt the metadata.
|
||||
// NOTE: For NPD version 1 the metadata is not encrypted.
|
||||
if (npd->version <= 1)
|
||||
{
|
||||
offset = swap64(*(unsigned long long*)&metadata[0x10]);
|
||||
length = swap32(*(int*)&metadata[0x18]);
|
||||
compression_end = swap32(*(int*)&metadata[0x1C]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char *result = dec_section(metadata);
|
||||
offset = swap64(*(unsigned long long*)&result[0]);
|
||||
length = swap32(*(int*)&result[8]);
|
||||
compression_end = swap32(*(int*)&result[12]);
|
||||
delete[] result;
|
||||
}
|
||||
|
||||
memcpy(hash_result, metadata, 0x10);
|
||||
}
|
||||
else if ((edat->flags & EDAT_FLAG_0x20) != 0)
|
||||
{
|
||||
// If FLAG 0x20, the metadata precedes each data block.
|
||||
in->Seek(metadata_offset + i * metadata_section_size + length);
|
||||
metadata_sec_offset = metadata_offset + (unsigned long long) i * (metadata_section_size + length);
|
||||
in->Seek(metadata_sec_offset);
|
||||
|
||||
unsigned char metadata[0x20];
|
||||
memset(metadata, 0, 0x20);
|
||||
in->Read(metadata, 0x20);
|
||||
memcpy(hash_result, metadata, 0x14);
|
||||
|
||||
// If FLAG 0x20 is set, apply custom xor.
|
||||
for (int j = 0; j < 0x10; j++) {
|
||||
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j+0x10]);
|
||||
}
|
||||
int j;
|
||||
for (j = 0; j < 0x10; j++)
|
||||
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j + 0x10]);
|
||||
|
||||
offset = metadata_offset + i * edat->block_size + (i + 1) * metadata_section_size;
|
||||
offset = metadata_sec_offset + 0x20;
|
||||
length = edat->block_size;
|
||||
|
||||
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
|
||||
length = (int) (edat->file_size % edat->block_size);
|
||||
length = (int)(edat->file_size % edat->block_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
|
||||
in->Seek(metadata_sec_offset);
|
||||
|
||||
in->Read(hash_result, 0x10);
|
||||
offset = metadata_offset + i * edat->block_size + block_num * metadata_section_size;
|
||||
offset = metadata_offset + (unsigned long long) i * edat->block_size + (unsigned long long) block_num * metadata_section_size;
|
||||
length = edat->block_size;
|
||||
|
||||
|
||||
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
|
||||
length = (int) (edat->file_size % edat->block_size);
|
||||
length = (int)(edat->file_size % edat->block_size);
|
||||
}
|
||||
|
||||
// Locate the real data.
|
||||
int pad_length = length;
|
||||
length = (int) ((pad_length + 0xF) & 0xFFFFFFF0);
|
||||
in->Seek(offset);
|
||||
length = (int)((pad_length + 0xF) & 0xFFFFFFF0);
|
||||
|
||||
// Setup buffers for decryption and read the data.
|
||||
enc_data = new unsigned char[length];
|
||||
dec_data = new unsigned char[length];
|
||||
unsigned char key_result[0x10];
|
||||
unsigned char hash[0x10];
|
||||
memset(enc_data, 0, length);
|
||||
memset(dec_data, 0, length);
|
||||
memset(hash, 0, 0x10);
|
||||
memset(key_result, 0, 0x10);
|
||||
|
||||
in->Seek(offset);
|
||||
in->Read(enc_data, length);
|
||||
|
||||
|
||||
// Generate a key for the current block.
|
||||
b_key = get_block_key(i, npd);
|
||||
|
||||
@ -247,7 +272,7 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
||||
hash_mode |= 0x10000000;
|
||||
}
|
||||
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
|
||||
{
|
||||
// Reset the flags.
|
||||
crypto_mode |= 0x01000000;
|
||||
@ -260,7 +285,13 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
||||
// IV is null if NPD version is 1 or 0.
|
||||
iv = (npd->version <= 1) ? empty_iv : npd->digest;
|
||||
// Call main crypto routine on this data block.
|
||||
crypto(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, length, key_result, iv, hash, hash_result);
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, length, key_result, iv, hash, hash_result))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Block at offset 0x%llx has invalid hash!", offset);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply additional compression if needed and write the decrypted data.
|
||||
@ -271,28 +302,28 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
||||
memset(decomp_data, 0, decomp_size);
|
||||
|
||||
if (verbose)
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressing...\n");
|
||||
|
||||
int res = lz_decompress(decomp_data, dec_data, decomp_size);
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressing data...");
|
||||
|
||||
int res = decompress(decomp_data, dec_data, decomp_size);
|
||||
out->Write(decomp_data, res);
|
||||
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d\n", pad_length);
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d\n", res);
|
||||
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d", pad_length);
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d", res);
|
||||
}
|
||||
|
||||
edat->file_size -= res;
|
||||
|
||||
if (edat->file_size == 0)
|
||||
if (edat->file_size == 0)
|
||||
{
|
||||
if (res < 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Decompression failed!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Decompression failed!");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
LOG_SUCCESS(LOADER, "EDAT: Data successfully decompressed!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: Successfully decompressed!");
|
||||
}
|
||||
|
||||
delete[] decomp_data;
|
||||
@ -309,158 +340,262 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool check_flags(EDAT_SDAT_HEADER *edat, NPD_HEADER *npd)
|
||||
int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose)
|
||||
{
|
||||
if (edat == nullptr || npd == nullptr)
|
||||
return false;
|
||||
f->Seek(0);
|
||||
unsigned char header[0xA0];
|
||||
unsigned char empty_header[0xA0];
|
||||
unsigned char header_hash[0x10];
|
||||
unsigned char metadata_hash[0x10];
|
||||
memset(header, 0, 0xA0);
|
||||
memset(empty_header, 0, 0xA0);
|
||||
memset(header_hash, 0, 0x10);
|
||||
memset(metadata_hash, 0, 0x10);
|
||||
|
||||
if (npd->version == 0 || npd->version == 1)
|
||||
// Check NPD version and flags.
|
||||
if ((npd->version == 0) || (npd->version == 1))
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFFE)
|
||||
if (edat->flags & 0x7EFFFFFE)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (npd->version == 2)
|
||||
else if (npd->version == 2)
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFE0)
|
||||
if (edat->flags & 0x7EFFFFE0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (npd->version == 3 || npd->version == 4)
|
||||
else if ((npd->version == 3) || (npd->version == 4))
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFC0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (npd->version > 4)
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown version - %d\n", npd->version);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose)
|
||||
{
|
||||
f->Seek(0);
|
||||
unsigned char *header = new unsigned char[0xA0];
|
||||
unsigned char *tmp = new unsigned char[0xA0];
|
||||
unsigned char *hash_result = new unsigned char[0x10];
|
||||
|
||||
// Check NPD version and EDAT flags.
|
||||
if (!check_flags(edat, npd))
|
||||
{
|
||||
delete[] header;
|
||||
delete[] tmp;
|
||||
delete[] hash_result;
|
||||
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown version!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read in the file header.
|
||||
f->Read(header, 0xA0);
|
||||
f->Read(hash_result, 0x10);
|
||||
|
||||
// Read in the header and metadata section hashes.
|
||||
f->Seek(0x90);
|
||||
f->Read(metadata_hash, 0x10);
|
||||
f->Read(header_hash, 0x10);
|
||||
|
||||
// Setup the hashing mode and the crypto mode used in the file.
|
||||
int crypto_mode = 0x1;
|
||||
int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002;
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: DEBUG data detected!\n");
|
||||
hash_mode |= 0x01000000;
|
||||
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: DEBUG data detected!");
|
||||
}
|
||||
|
||||
// Setup header key and iv buffers.
|
||||
unsigned char header_key[0x10] = {};
|
||||
unsigned char header_iv[0x10] = {};
|
||||
unsigned char header_key[0x10];
|
||||
unsigned char header_iv[0x10];
|
||||
memset(header_key, 0, 0x10);
|
||||
memset(header_iv, 0, 0x10);
|
||||
|
||||
// Test the header hash (located at offset 0xA0).
|
||||
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), header, tmp, 0xA0, header_key, header_iv, key, hash_result))
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), header, empty_header, 0xA0, header_key, header_iv, key, header_hash))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Header hash is invalid!\n");
|
||||
LOG_WARNING(LOADER, "EDAT: Header hash is invalid!");
|
||||
|
||||
// If the header hash test fails and the data is not DEBUG, then RAP/RIF/KLIC key is invalid.
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: RAP/RIF/KLIC key is invalid!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the metadata info.
|
||||
int metadata_section_size = 0x10;
|
||||
int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
|
||||
if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0))
|
||||
{
|
||||
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!\n");
|
||||
metadata_section_size = 0x20;
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!");
|
||||
}
|
||||
|
||||
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int bytes_read = 0;
|
||||
int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int metadata_offset = 0x100;
|
||||
int metadata_size = metadata_section_size * block_num;
|
||||
long long metadata_section_offset = metadata_offset;
|
||||
|
||||
long bytes_read = 0;
|
||||
long bytes_to_read = metadata_size;
|
||||
unsigned char *metadata = new unsigned char[metadata_size];
|
||||
unsigned char *empty_metadata = new unsigned char[metadata_size];
|
||||
|
||||
long bytes_to_read = metadata_section_size * block_num;
|
||||
while (bytes_to_read > 0)
|
||||
{
|
||||
// Locate the metadata blocks.
|
||||
int block_size = (0x3C00 > bytes_to_read) ? (int) bytes_to_read : 0x3C00; // 0x3C00 is the maximum block size.
|
||||
f->Seek(metadata_offset + bytes_read);
|
||||
unsigned char *data = new unsigned char[block_size];
|
||||
f->Seek(metadata_section_offset);
|
||||
|
||||
// Read in the metadata.
|
||||
tmp = new unsigned char[block_size];
|
||||
f->Read(data, block_size);
|
||||
|
||||
// Check the generated hash against the metadata hash located at offset 0x90 in the header.
|
||||
memset(hash_result, 0, 0x10);
|
||||
f->Seek(0x90);
|
||||
f->Read(hash_result, 0x10);
|
||||
|
||||
// Generate the hash for this block.
|
||||
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), data, tmp, block_size, header_key, header_iv, key, hash_result))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata hash from block 0x%08x is invalid!\n", metadata_offset + bytes_read);
|
||||
}
|
||||
f->Read(metadata + bytes_read, metadata_section_size);
|
||||
|
||||
// Adjust sizes.
|
||||
bytes_read += block_size;
|
||||
bytes_to_read -= block_size;
|
||||
bytes_read += metadata_section_size;
|
||||
bytes_to_read -= metadata_section_size;
|
||||
|
||||
delete[] data;
|
||||
if (((edat->flags & EDAT_FLAG_0x20) != 0)) // Metadata block before each data block.
|
||||
metadata_section_offset += (metadata_section_size + edat->block_size);
|
||||
else
|
||||
metadata_section_offset += metadata_section_size;
|
||||
}
|
||||
|
||||
// Test the metadata section hash (located at offset 0x90).
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), metadata, empty_metadata, metadata_size, header_key, header_iv, key, metadata_hash))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata section hash is invalid!");
|
||||
}
|
||||
|
||||
// Checking ECDSA signatures.
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) == 0)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "EDAT: Checking signatures...");
|
||||
|
||||
// Setup buffers.
|
||||
unsigned char metadata_signature[0x28];
|
||||
unsigned char header_signature[0x28];
|
||||
unsigned char signature_hash[20];
|
||||
unsigned char signature_r[0x15];
|
||||
unsigned char signature_s[0x15];
|
||||
unsigned char zero_buf[0x15];
|
||||
memset(metadata_signature, 0, 0x28);
|
||||
memset(header_signature, 0, 0x28);
|
||||
memset(signature_hash, 0, 20);
|
||||
memset(signature_r, 0, 0x15);
|
||||
memset(signature_s, 0, 0x15);
|
||||
memset(zero_buf, 0, 0x15);
|
||||
|
||||
// Setup ECDSA curve and public key.
|
||||
ecdsa_set_curve(VSH_CURVE_P, VSH_CURVE_A, VSH_CURVE_B, VSH_CURVE_N, VSH_CURVE_GX, VSH_CURVE_GY);
|
||||
ecdsa_set_pub(VSH_PUB);
|
||||
|
||||
|
||||
// Read in the metadata and header signatures.
|
||||
f->Seek(0xB0);
|
||||
f->Read(metadata_signature, 0x28);
|
||||
f->Seek(0xD8);
|
||||
f->Read(header_signature, 0x28);
|
||||
|
||||
// Checking metadata signature.
|
||||
// Setup signature r and s.
|
||||
memcpy(signature_r + 01, metadata_signature, 0x14);
|
||||
memcpy(signature_s + 01, metadata_signature + 0x14, 0x14);
|
||||
if ((!memcmp(signature_r, zero_buf, 0x15)) || (!memcmp(signature_s, zero_buf, 0x15)))
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata signature is invalid!");
|
||||
else
|
||||
{
|
||||
// Setup signature hash.
|
||||
if ((edat->flags & EDAT_FLAG_0x20) != 0) //Sony failed again, they used buffer from 0x100 with half size of real metadata.
|
||||
{
|
||||
int metadata_buf_size = block_num * 0x10;
|
||||
unsigned char *metadata_buf = new unsigned char[metadata_buf_size];
|
||||
f->Seek(metadata_offset);
|
||||
f->Read(metadata_buf, metadata_buf_size);
|
||||
sha1(metadata_buf, metadata_buf_size, signature_hash);
|
||||
delete[] metadata_buf;
|
||||
}
|
||||
else
|
||||
sha1(metadata, metadata_size, signature_hash);
|
||||
|
||||
if (!ecdsa_verify(signature_hash, signature_r, signature_s))
|
||||
{
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata signature is invalid!");
|
||||
if (((unsigned long long)edat->block_size * block_num) > 0x100000000)
|
||||
LOG_WARNING(LOADER, "EDAT: *Due to large file size, metadata signature status may be incorrect!");
|
||||
}
|
||||
else
|
||||
LOG_NOTICE(LOADER, "EDAT: Metadata signature is valid!");
|
||||
}
|
||||
|
||||
|
||||
// Checking header signature.
|
||||
// Setup header signature r and s.
|
||||
memset(signature_r, 0, 0x15);
|
||||
memset(signature_s, 0, 0x15);
|
||||
memcpy(signature_r + 01, header_signature, 0x14);
|
||||
memcpy(signature_s + 01, header_signature + 0x14, 0x14);
|
||||
|
||||
if ((!memcmp(signature_r, zero_buf, 0x15)) || (!memcmp(signature_s, zero_buf, 0x15)))
|
||||
LOG_WARNING(LOADER, "EDAT: Header signature is invalid!");
|
||||
else
|
||||
{
|
||||
// Setup header signature hash.
|
||||
memset(signature_hash, 0, 20);
|
||||
unsigned char *header_buf = new unsigned char[0xD8];
|
||||
f->Seek(0x00);
|
||||
f->Read(header_buf, 0xD8);
|
||||
sha1(header_buf, 0xD8, signature_hash );
|
||||
delete[] header_buf;
|
||||
|
||||
if (ecdsa_verify(signature_hash, signature_r, signature_s))
|
||||
LOG_NOTICE(LOADER, "EDAT: Header signature is valid!");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: Header signature is invalid!");
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
delete[] header;
|
||||
delete[] tmp;
|
||||
delete[] hash_result;
|
||||
delete[] metadata;
|
||||
delete[] empty_metadata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *npd, bool verbose)
|
||||
int validate_npd_hashes(const char* file_name, unsigned char *klicensee, NPD_HEADER *npd, bool verbose)
|
||||
{
|
||||
int title_hash_result = 0;
|
||||
int dev_hash_result = 0;
|
||||
|
||||
int file_name_length = (int)strlen(file_name);
|
||||
int file_name_length = (int) strlen(file_name);
|
||||
unsigned char *buf = new unsigned char[0x30 + file_name_length];
|
||||
unsigned char dev[0x60];
|
||||
unsigned char key[0x10];
|
||||
memset(dev, 0, 0x60);
|
||||
memset(key, 0, 0x10);
|
||||
|
||||
// Build the buffer (content_id + file_name).
|
||||
// Build the title buffer (content_id + file_name).
|
||||
memcpy(buf, npd->content_id, 0x30);
|
||||
memcpy(buf + 0x30, file_name, file_name_length);
|
||||
|
||||
// Hash with NP_OMAC_KEY_3 and compare with title_hash.
|
||||
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash);
|
||||
// Build the dev buffer (first 0x60 bytes of NPD header in big-endian).
|
||||
memcpy(dev, npd, 0x60);
|
||||
|
||||
// Fix endianness.
|
||||
int version = swap32(npd->version);
|
||||
int license = swap32(npd->license);
|
||||
int type = swap32(npd->type);
|
||||
memcpy(dev + 0x4, &version, 4);
|
||||
memcpy(dev + 0x8, &license, 4);
|
||||
memcpy(dev + 0xC, &type, 4);
|
||||
|
||||
// Hash with NPDRM_OMAC_KEY_3 and compare with title_hash.
|
||||
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash, 0x10);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (title_hash_result)
|
||||
LOG_SUCCESS(LOADER, "EDAT: NPD title hash is valid!\n");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: NPD title hash is invalid!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: NPD title hash is valid!");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: NPD title hash is invalid!");
|
||||
}
|
||||
|
||||
// Check for an empty dev_hash (can't validate if devklic is NULL);
|
||||
@ -477,40 +612,45 @@ void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *
|
||||
if (isDevklicEmpty)
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is empty!\n");
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is empty!");
|
||||
|
||||
// Allow empty dev hash.
|
||||
dev_hash_result = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate klicensee xor key.
|
||||
xor_(key, klicensee, NP_OMAC_KEY_2, 0x10);
|
||||
xor_key(key, klicensee, NP_OMAC_KEY_2, 0x10);
|
||||
|
||||
// Hash with generated key and compare with dev_hash.
|
||||
dev_hash_result = cmac_hash_compare(key, 0x10, (unsigned char *)npd, 0x60, npd->dev_hash);
|
||||
|
||||
dev_hash_result = cmac_hash_compare(key, 0x10, dev, 0x60, npd->dev_hash, 0x10);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (dev_hash_result)
|
||||
LOG_SUCCESS(LOADER, "EDAT: NPD dev hash is valid!\n");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: NPD dev hash is valid!");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!");
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
|
||||
return (title_hash_result && dev_hash_result);
|
||||
}
|
||||
|
||||
bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
|
||||
{
|
||||
// Setup NPD and EDAT/SDAT structs.
|
||||
NPD_HEADER *NPD = new NPD_HEADER();
|
||||
EDAT_SDAT_HEADER *EDAT = new EDAT_SDAT_HEADER();
|
||||
EDAT_HEADER *EDAT = new EDAT_HEADER();
|
||||
|
||||
// Read in the NPD and EDAT/SDAT headers.
|
||||
char npd_header[0x80];
|
||||
char edat_header[0x10];
|
||||
input->Read(npd_header, 0x80);
|
||||
input->Read(edat_header, 0x10);
|
||||
|
||||
input->Read(npd_header, sizeof(npd_header));
|
||||
input->Read(edat_header, sizeof(edat_header));
|
||||
|
||||
memcpy(NPD->magic, npd_header, 4);
|
||||
NPD->version = swap32(*(int*)&npd_header[4]);
|
||||
NPD->license = swap32(*(int*)&npd_header[8]);
|
||||
@ -523,7 +663,7 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
|
||||
NPD->unk2 = swap64(*(u64*)&npd_header[120]);
|
||||
|
||||
unsigned char npd_magic[4] = {0x4E, 0x50, 0x44, 0x00}; //NPD0
|
||||
if(memcmp(NPD->magic, npd_magic, 4))
|
||||
if (memcmp(NPD->magic, npd_magic, 4))
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: %s has invalid NPD header or already decrypted.", input_file_name);
|
||||
delete NPD;
|
||||
@ -537,41 +677,65 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "NPD HEADER\n");
|
||||
LOG_NOTICE(LOADER, "NPD version: %d\n", NPD->version);
|
||||
LOG_NOTICE(LOADER, "NPD license: %d\n", NPD->license);
|
||||
LOG_NOTICE(LOADER, "NPD type: %d\n", NPD->type);
|
||||
LOG_NOTICE(LOADER, "\n");
|
||||
LOG_NOTICE(LOADER, "EDAT HEADER\n");
|
||||
LOG_NOTICE(LOADER, "EDAT flags: 0x%08X\n", EDAT->flags);
|
||||
LOG_NOTICE(LOADER, "EDAT block size: 0x%08X\n", EDAT->block_size);
|
||||
LOG_NOTICE(LOADER, "EDAT file size: 0x%08X\n", EDAT->file_size);
|
||||
LOG_NOTICE(LOADER, "\n");
|
||||
LOG_NOTICE(LOADER, "NPD HEADER");
|
||||
LOG_NOTICE(LOADER, "NPD version: %d", NPD->version);
|
||||
LOG_NOTICE(LOADER, "NPD license: %d", NPD->license);
|
||||
LOG_NOTICE(LOADER, "NPD type: %d", NPD->type);
|
||||
}
|
||||
|
||||
// Set decryption key.
|
||||
unsigned char key[0x10];
|
||||
memset(key, 0, 0x10);
|
||||
|
||||
if((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
|
||||
// Check EDAT/SDAT flag.
|
||||
if ((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
|
||||
{
|
||||
LOG_WARNING(LOADER, "EDAT: SDAT detected!\n");
|
||||
xor_(key, NPD->dev_hash, SDAT_KEY, 0x10);
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "SDAT HEADER");
|
||||
LOG_NOTICE(LOADER, "SDAT flags: 0x%08X", EDAT->flags);
|
||||
LOG_NOTICE(LOADER, "SDAT block size: 0x%08X", EDAT->block_size);
|
||||
LOG_NOTICE(LOADER, "SDAT file size: 0x%08X", EDAT->file_size);
|
||||
}
|
||||
|
||||
// Generate SDAT key.
|
||||
xor_key(key, NPD->dev_hash, SDAT_KEY, 0x10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Perform header validation (optional step).
|
||||
validate_data(input_file_name, devklic, NPD, verbose);
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "EDAT HEADER");
|
||||
LOG_NOTICE(LOADER, "EDAT flags: 0x%08X", EDAT->flags);
|
||||
LOG_NOTICE(LOADER, "EDAT block size: 0x%08X", EDAT->block_size);
|
||||
LOG_NOTICE(LOADER, "EDAT file size: 0x%08X", EDAT->file_size);
|
||||
}
|
||||
|
||||
if ((NPD->license & 0x3) == 0x3) // Type 3: Use supplied devklic.
|
||||
// Perform header validation (EDAT only).
|
||||
char real_file_name[MAX_PATH];
|
||||
extract_file_name(input_file_name, real_file_name);
|
||||
if (!validate_npd_hashes(real_file_name, devklic, NPD, verbose))
|
||||
{
|
||||
// Ignore header validation in DEBUG data.
|
||||
if ((EDAT->flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: NPD hash validation failed!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Select EDAT key.
|
||||
if ((NPD->license & 0x3) == 0x3) // Type 3: Use supplied devklic.
|
||||
memcpy(key, devklic, 0x10);
|
||||
else if ((NPD->license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key).
|
||||
{
|
||||
else if ((NPD->license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key).
|
||||
{
|
||||
memcpy(key, rifkey, 0x10);
|
||||
|
||||
// Make sure we don't have an empty RIF key.
|
||||
int i, test = 0;
|
||||
for(i = 0; i < 0x10; i++)
|
||||
for (i = 0; i < 0x10; i++)
|
||||
{
|
||||
if (key[i] != 0)
|
||||
{
|
||||
@ -579,30 +743,65 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!test)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed!");
|
||||
LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed for this EDAT file!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if ((NPD->license & 0x1) == 0x1) // Type 1: Use network activation.
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Network license not supported!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
int i;
|
||||
LOG_NOTICE(LOADER, "DEVKLIC: ");
|
||||
for (i = 0; i < 0x10; i++)
|
||||
LOG_NOTICE(LOADER, "%02X", devklic[i]);
|
||||
|
||||
LOG_NOTICE(LOADER, "RIF KEY: ");
|
||||
for (i = 0; i < 0x10; i++)
|
||||
LOG_NOTICE(LOADER, "%02X", rifkey[i]);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "EDAT: Parsing data...\n");
|
||||
if (verbose)
|
||||
{
|
||||
int i;
|
||||
LOG_NOTICE(LOADER, "DECRYPTION KEY: ");
|
||||
for (i = 0; i < 0x10; i++)
|
||||
LOG_NOTICE(LOADER, "%02X", key[i]);
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "EDAT: Parsing data...");
|
||||
if (check_data(key, EDAT, NPD, input, verbose))
|
||||
LOG_ERROR(LOADER, "EDAT: Data parsing failed!\n");
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Data parsing failed!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
LOG_SUCCESS(LOADER, "EDAT: Data successfully parsed!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: Data successfully parsed!");
|
||||
|
||||
printf("\n");
|
||||
|
||||
LOG_NOTICE(LOADER, "EDAT: Decrypting data...\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: Decrypting data...");
|
||||
if (decrypt_data(input, output, EDAT, NPD, key, verbose))
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Data decryption failed!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
LOG_SUCCESS(LOADER, "EDAT: Data successfully decrypted!");
|
||||
LOG_NOTICE(LOADER, "EDAT: Data successfully decrypted!");
|
||||
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
@ -655,21 +854,21 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
|
||||
memcpy(devklic, custom_klic, 0x10);
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid mode!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid mode!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check the input/output files.
|
||||
if (!input.IsOpened() || !output.IsOpened())
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Failed to open files!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Failed to open files!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -692,11 +891,11 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
|
||||
input.Close();
|
||||
output.Close();
|
||||
rRemoveFile(output_file_name);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
input.Close();
|
||||
output.Close();
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
|
||||
#define SDAT_FLAG 0x01000000
|
||||
#define EDAT_COMPRESSED_FLAG 0x00000001
|
||||
#define EDAT_FLAG_0x02 0x00000002
|
||||
#define EDAT_FLAG_0x04 0x00000004
|
||||
#define EDAT_ENCRYPTED_KEY_FLAG 0x00000008
|
||||
#define EDAT_FLAG_0x10 0x00000010
|
||||
#define EDAT_FLAG_0x20 0x00000020
|
||||
@ -28,6 +31,6 @@ typedef struct
|
||||
int flags;
|
||||
int block_size;
|
||||
unsigned long long file_size;
|
||||
} EDAT_SDAT_HEADER;
|
||||
} EDAT_HEADER;
|
||||
|
||||
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose);
|
||||
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose);
|
@ -813,10 +813,10 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
|
||||
u8 rap_key[0x10];
|
||||
memset(rap_key, 0, 0x10);
|
||||
|
||||
// Try to find a matching RAP file under dev_usb000.
|
||||
// Try to find a matching RAP file under exdata folder.
|
||||
std::string ci_str((const char *)content_id);
|
||||
// TODO: This shouldn't use current dir
|
||||
std::string rap_path("./dev_usb000/" + ci_str + ".rap");
|
||||
std::string pf_str("00000001"); // TODO: Allow multiple profiles. Use default for now.
|
||||
std::string rap_path("dev_hdd0/home/" + pf_str + "/exdata/" + ci_str + ".rap");
|
||||
|
||||
// Check if we have a valid RAP file.
|
||||
if (!rExists(rap_path))
|
||||
|
@ -1,9 +1,13 @@
|
||||
#include "stdafx.h"
|
||||
#include "aes.h"
|
||||
#include "sha1.h"
|
||||
#include "utils.h"
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
// Endian swap auxiliary functions.
|
||||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
// Auxiliary functions (endian swap, xor and prng).
|
||||
u16 swap16(u16 i)
|
||||
{
|
||||
return ((i & 0xFF00) >> 8) | ((i & 0xFF) << 8);
|
||||
@ -22,7 +26,7 @@ u64 swap64(u64 i)
|
||||
((i & 0x00ff000000000000) >> 40) | ((i & 0xff00000000000000) >> 56);
|
||||
}
|
||||
|
||||
void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
|
||||
void xor_key(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < size; i++)
|
||||
@ -31,10 +35,24 @@ void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int siz
|
||||
}
|
||||
}
|
||||
|
||||
void prng(unsigned char *dest, int size)
|
||||
{
|
||||
unsigned char *buffer = new unsigned char[size];
|
||||
srand((u32)time(0));
|
||||
|
||||
int i;
|
||||
for(i = 0; i < size; i++)
|
||||
buffer[i] = (unsigned char)(rand() & 0xFF);
|
||||
|
||||
memcpy(dest, buffer, size);
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// Hex string conversion auxiliary functions.
|
||||
u64 hex_to_u64(const char* hex_str)
|
||||
{
|
||||
u32 length = (u32)strlen(hex_str);
|
||||
u32 length = (u32) strlen(hex_str);
|
||||
u64 tmp = 0;
|
||||
u64 result = 0;
|
||||
char c;
|
||||
@ -56,19 +74,19 @@ u64 hex_to_u64(const char* hex_str)
|
||||
return result;
|
||||
}
|
||||
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str)
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length)
|
||||
{
|
||||
u32 str_length = (u32)strlen(hex_str);
|
||||
u32 data_length = str_length / 2;
|
||||
u32 strn_length = (str_length > 0) ? str_length : (u32) strlen(hex_str);
|
||||
u32 data_length = strn_length / 2;
|
||||
char tmp_buf[3] = {0, 0, 0};
|
||||
|
||||
// Don't convert if the string length is odd.
|
||||
if (!(str_length % 2))
|
||||
if (!(strn_length % 2))
|
||||
{
|
||||
u8 *out = (u8 *) malloc (str_length * sizeof(u8));
|
||||
u8 *out = (u8 *)malloc(strn_length * sizeof(u8));
|
||||
u8 *pos = out;
|
||||
|
||||
while (str_length--)
|
||||
while (strn_length--)
|
||||
{
|
||||
tmp_buf[0] = *hex_str++;
|
||||
tmp_buf[1] = *hex_str++;
|
||||
@ -81,6 +99,23 @@ void hex_to_bytes(unsigned char *data, const char *hex_str)
|
||||
}
|
||||
}
|
||||
|
||||
bool is_hex(const char* hex_str, unsigned int str_length)
|
||||
{
|
||||
static const char hex_chars[] = "0123456789abcdefABCDEF";
|
||||
|
||||
if (hex_str == NULL)
|
||||
return false;
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < str_length; i++)
|
||||
{
|
||||
if (strchr(hex_chars, hex_str[i]) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
||||
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
|
||||
{
|
||||
@ -92,6 +127,16 @@ void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in,
|
||||
memset(iv, 0, 0x10);
|
||||
}
|
||||
|
||||
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
|
||||
{
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_crypt_cbc(&ctx, AES_ENCRYPT, len, iv, in, out);
|
||||
|
||||
// Reset the IV.
|
||||
memset(iv, 0, 0x10);
|
||||
}
|
||||
|
||||
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out)
|
||||
{
|
||||
aes_context ctx;
|
||||
@ -99,13 +144,13 @@ void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out
|
||||
aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out);
|
||||
}
|
||||
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
|
||||
{
|
||||
unsigned char *out = new unsigned char[key_len];
|
||||
|
||||
sha1_hmac(key, key_len, in, in_len, out);
|
||||
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
for (int i = 0; i < hash_len; i++)
|
||||
{
|
||||
if (out[i] != hash[i])
|
||||
{
|
||||
@ -119,7 +164,12 @@ bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
{
|
||||
sha1_hmac(key, key_len, in, in_len, hash);
|
||||
}
|
||||
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
|
||||
{
|
||||
unsigned char *out = new unsigned char[key_len];
|
||||
|
||||
@ -127,7 +177,7 @@ bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_cmac(&ctx, in_len, in, out);
|
||||
|
||||
for (int i = 0; i < key_len; i++)
|
||||
for (int i = 0; i < hash_len; i++)
|
||||
{
|
||||
if (out[i] != hash[i])
|
||||
{
|
||||
@ -141,9 +191,20 @@ bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "lz.h"
|
||||
// Reverse-engineered custom Lempel–Ziv–Markov based compression (unknown variant of LZRC).
|
||||
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
||||
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
{
|
||||
return decompress(out,in,size);
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_cmac(&ctx, in_len, in, hash);
|
||||
}
|
||||
|
||||
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH])
|
||||
{
|
||||
size_t file_path_len = strlen(file_path);
|
||||
const char* p = strrchr(file_path, '/');
|
||||
if (!p) p = strrchr(file_path, '\\');
|
||||
if (p) file_path_len = file_path + file_path_len - p - 1;
|
||||
strncpy(real_file_name, p ? (p + 1) : file_path, file_path_len + 1);
|
||||
|
||||
return real_file_name;
|
||||
}
|
@ -1,20 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
// Auxiliary functions (endian swap and xor).
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
#define MAX_PATH 4096
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "aes.h"
|
||||
#include "sha1.h"
|
||||
#include "lz.h"
|
||||
#include "ec.h"
|
||||
|
||||
// Auxiliary functions (endian swap, xor, prng and file name).
|
||||
u16 swap16(u16 i);
|
||||
u32 swap32(u32 i);
|
||||
u64 swap64(u64 i);
|
||||
void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size);
|
||||
void xor_key(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size);
|
||||
void prng(unsigned char *dest, int size);
|
||||
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH]);
|
||||
|
||||
// Hex string conversion auxiliary functions.
|
||||
u64 hex_to_u64(const char* hex_str);
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str);
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length);
|
||||
bool is_hex(const char* hex_str, unsigned int str_length);
|
||||
|
||||
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
||||
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len);
|
||||
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len);
|
||||
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out);
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
||||
|
||||
// Reverse-engineered custom Lempel–Ziv–Markov based compression (unknown variant of LZRC).
|
||||
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size);
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
|
||||
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
|
||||
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
@ -624,5 +624,9 @@ namespace PPU_instr
|
||||
bind_instr(g3f_0_list, MFFS, FRD, RC);
|
||||
bind_instr(g3f_0_list, MTFSF, FM, FRB, RC);
|
||||
|
||||
static auto LIS = std::bind(ADDIS, std::placeholders::_1, 0, std::placeholders::_2);
|
||||
static auto NOP = std::bind(ORI, 0, 0, 0);
|
||||
static auto BLR = std::bind(BCLR, 0x10 | 0x04, 0, 0, 0);
|
||||
|
||||
#undef bind_instr
|
||||
};
|
@ -59,12 +59,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ID
|
||||
class ID
|
||||
{
|
||||
std::string m_name;
|
||||
IDData* m_data;
|
||||
IDType m_type;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
ID(const std::string& name, T* data, const IDType type)
|
||||
: m_name(name)
|
||||
@ -96,6 +97,21 @@ struct ID
|
||||
{
|
||||
delete m_data;
|
||||
}
|
||||
|
||||
const std::string& GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
IDData* GetData() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
IDType GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
};
|
||||
|
||||
class IdManager
|
||||
@ -172,7 +188,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
result = f->second.m_data->get<T>();
|
||||
result = f->second.GetData()->get<T>();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -198,8 +214,8 @@ public:
|
||||
if (item == m_id_map.end()) {
|
||||
return false;
|
||||
}
|
||||
if (item->second.m_type < TYPE_OTHER) {
|
||||
m_types[item->second.m_type].erase(id);
|
||||
if (item->second.GetType() < TYPE_OTHER) {
|
||||
m_types[item->second.GetType()].erase(id);
|
||||
}
|
||||
|
||||
item->second.Kill();
|
||||
|
@ -108,9 +108,9 @@ void MemoryBase::Init(MemoryType type)
|
||||
memset(RawSPUMem, 0, sizeof(RawSPUMem));
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!m_base_addr)
|
||||
if (!g_base_addr)
|
||||
#else
|
||||
if ((s64)m_base_addr == (s64)-1)
|
||||
if ((s64)g_base_addr == (s64)-1)
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(MEMORY, "Initializing memory failed");
|
||||
@ -119,7 +119,7 @@ void MemoryBase::Init(MemoryType type)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_NOTICE(MEMORY, "Initializing memory: m_base_addr = 0x%llx", (u64)m_base_addr);
|
||||
LOG_NOTICE(MEMORY, "Initializing memory: m_base_addr = 0x%llx", (u64)g_base_addr);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
@ -204,7 +204,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
|
||||
if ((u32)addr != addr || (u64)addr + (u64)size > 0x100000000ull)
|
||||
if ((addr | (addr + size)) & ~0xFFFFFFFFull)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ using std::nullptr_t;
|
||||
#define safe_delete(x) do {delete (x);(x)=nullptr;} while(0)
|
||||
#define safe_free(x) do {free(x);(x)=nullptr;} while(0)
|
||||
|
||||
extern void* const m_base_addr;
|
||||
extern void* const g_base_addr;
|
||||
|
||||
enum MemoryType
|
||||
{
|
||||
@ -69,7 +69,7 @@ public:
|
||||
|
||||
static void* const GetBaseAddr()
|
||||
{
|
||||
return m_base_addr;
|
||||
return g_base_addr;
|
||||
}
|
||||
|
||||
__noinline void InvalidAddress(const char* func, const u64 addr);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
|
||||
void* const m_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||
void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
|
||||
@ -13,7 +13,7 @@ void* const m_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_N
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
void* const m_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
void* const g_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
#endif
|
||||
|
||||
namespace vm
|
||||
|
@ -10,7 +10,7 @@ namespace vm
|
||||
template<typename T>
|
||||
T* const get_ptr(u32 addr)
|
||||
{
|
||||
return (T*)((u8*)m_base_addr + addr);
|
||||
return (T*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -35,49 +35,29 @@ namespace vm
|
||||
{
|
||||
static u8 read8(u32 addr)
|
||||
{
|
||||
return *((u8*)m_base_addr + addr);
|
||||
}
|
||||
|
||||
static u8 read8(u64 addr)
|
||||
{
|
||||
return read8((u32)addr);
|
||||
return *((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write8(u32 addr, u8 value)
|
||||
{
|
||||
*((u8*)m_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static void write8(u64 addr, u8 value)
|
||||
{
|
||||
write8((u32)addr, value);
|
||||
*((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u16 read16(u32 addr)
|
||||
{
|
||||
return re16(*(u16*)((u8*)m_base_addr + addr));
|
||||
}
|
||||
|
||||
static u16 read16(u64 addr)
|
||||
{
|
||||
return read16((u32)addr);
|
||||
return re16(*(u16*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
|
||||
static void write16(u32 addr, u16 value)
|
||||
{
|
||||
*(u16*)((u8*)m_base_addr + addr) = re16(value);
|
||||
}
|
||||
|
||||
static void write16(u64 addr, u16 value)
|
||||
{
|
||||
write16((u32)addr, value);
|
||||
*(u16*)((u8*)g_base_addr + addr) = re16(value);
|
||||
}
|
||||
|
||||
static u32 read32(u32 addr)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET)
|
||||
{
|
||||
return re32(*(u32*)((u8*)m_base_addr + addr));
|
||||
return re32(*(u32*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -85,16 +65,11 @@ namespace vm
|
||||
}
|
||||
}
|
||||
|
||||
static u32 read32(u64 addr)
|
||||
{
|
||||
return read32((u32)addr);
|
||||
}
|
||||
|
||||
static void write32(u32 addr, u32 value)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET)
|
||||
{
|
||||
*(u32*)((u8*)m_base_addr + addr) = re32(value);
|
||||
*(u32*)((u8*)g_base_addr + addr) = re32(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -102,49 +77,24 @@ namespace vm
|
||||
}
|
||||
}
|
||||
|
||||
static void write32(u64 addr, u32 value)
|
||||
{
|
||||
write32((u32)addr, value);
|
||||
}
|
||||
|
||||
static u64 read64(u32 addr)
|
||||
{
|
||||
return re64(*(u64*)((u8*)m_base_addr + addr));
|
||||
}
|
||||
|
||||
static u64 read64(u64 addr)
|
||||
{
|
||||
return read64((u32)addr);
|
||||
return re64(*(u64*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
|
||||
static void write64(u32 addr, u64 value)
|
||||
{
|
||||
*(u64*)((u8*)m_base_addr + addr) = re64(value);
|
||||
}
|
||||
|
||||
static void write64(u64 addr, u64 value)
|
||||
{
|
||||
write64((u32)addr, value);
|
||||
*(u64*)((u8*)g_base_addr + addr) = re64(value);
|
||||
}
|
||||
|
||||
static u128 read128(u32 addr)
|
||||
{
|
||||
return re128(*(u128*)((u8*)m_base_addr + addr));
|
||||
}
|
||||
|
||||
static u128 read128(u64 addr)
|
||||
{
|
||||
return read128((u32)addr);
|
||||
return re128(*(u128*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
|
||||
static void write128(u32 addr, u128 value)
|
||||
{
|
||||
*(u128*)((u8*)m_base_addr + addr) = re128(value);
|
||||
}
|
||||
|
||||
static void write128(u64 addr, u128 value)
|
||||
{
|
||||
write128((u32)addr, value);
|
||||
*(u128*)((u8*)g_base_addr + addr) = re128(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,52 +102,52 @@ namespace vm
|
||||
{
|
||||
static u8 read8(u32 addr)
|
||||
{
|
||||
return *((u8*)m_base_addr + addr);
|
||||
return *((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write8(u32 addr, u8 value)
|
||||
{
|
||||
*((u8*)m_base_addr + addr) = value;
|
||||
*((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u16 read16(u32 addr)
|
||||
{
|
||||
return *(u16*)((u8*)m_base_addr + addr);
|
||||
return *(u16*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write16(u32 addr, u16 value)
|
||||
{
|
||||
*(u16*)((u8*)m_base_addr + addr) = value;
|
||||
*(u16*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u32 read32(u32 addr)
|
||||
{
|
||||
return *(u32*)((u8*)m_base_addr + addr);
|
||||
return *(u32*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write32(u32 addr, u32 value)
|
||||
{
|
||||
*(u32*)((u8*)m_base_addr + addr) = value;
|
||||
*(u32*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u64 read64(u32 addr)
|
||||
{
|
||||
return *(u64*)((u8*)m_base_addr + addr);
|
||||
return *(u64*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write64(u32 addr, u64 value)
|
||||
{
|
||||
*(u64*)((u8*)m_base_addr + addr) = value;
|
||||
*(u64*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u128 read128(u32 addr)
|
||||
{
|
||||
return *(u128*)((u8*)m_base_addr + addr);
|
||||
return *(u128*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write128(u32 addr, u128 value)
|
||||
{
|
||||
*(u128*)((u8*)m_base_addr + addr) = value;
|
||||
*(u128*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,14 +60,14 @@ namespace vm
|
||||
return make(m_addr - count * sizeof(AT));
|
||||
}
|
||||
|
||||
__forceinline _ptr_base<T, lvl - 1, AT>& operator *() const
|
||||
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator *() const
|
||||
{
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, AT>>(m_addr);
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr);
|
||||
}
|
||||
|
||||
__forceinline _ptr_base<T, lvl - 1, AT>& operator [](int index) const
|
||||
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator [](int index) const
|
||||
{
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, AT>>(m_addr + sizeof(AT) * index);
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr + sizeof(AT)* index);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
|
@ -1804,11 +1804,9 @@ void GLGSRender::ExecCMD()
|
||||
}
|
||||
}
|
||||
|
||||
if (m_set_two_side_light_enable)
|
||||
{
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
||||
checkForGlError("glLightModeli");
|
||||
}
|
||||
// TODO: Use other glLightModel functions?
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_set_two_side_light_enable ? GL_TRUE : GL_FALSE);
|
||||
checkForGlError("glLightModeli");
|
||||
|
||||
if(m_set_shade_mode)
|
||||
{
|
||||
|
@ -4,7 +4,9 @@
|
||||
extern void cellAdec_init(Module* pxThis);
|
||||
extern void cellAtrac_init(Module* pxThis);
|
||||
extern void cellAudio_init(Module* pxThis);
|
||||
extern void cellAvconfExt_init(Module* pxThis);
|
||||
extern void cellCamera_init(Module* pxThis);
|
||||
extern void cellCamera_unload();
|
||||
extern void cellDmux_init(Module *pxThis);
|
||||
extern void cellFiber_init(Module *pxThis);
|
||||
extern void cellFont_init(Module *pxThis);
|
||||
@ -18,10 +20,12 @@ extern void cellGcmSys_init(Module *pxThis);
|
||||
extern void cellGcmSys_load();
|
||||
extern void cellGcmSys_unload();
|
||||
extern void cellGem_init(Module *pxThis);
|
||||
extern void cellGem_unload();
|
||||
extern void cellJpgDec_init(Module *pxThis);
|
||||
extern void cellGifDec_init(Module *pxThis);
|
||||
extern void cellL10n_init(Module *pxThis);
|
||||
extern void cellNetCtl_init(Module *pxThis);
|
||||
extern void cellNetCtl_unload();
|
||||
extern void cellOvis_init(Module *pxThis);
|
||||
extern void cellPamf_init(Module *pxThis);
|
||||
extern void cellPngDec_init(Module *pxThis);
|
||||
@ -43,6 +47,7 @@ extern void cellVdec_init(Module *pxThis);
|
||||
extern void cellVpost_init(Module *pxThis);
|
||||
extern void libmixer_init(Module *pxThis);
|
||||
extern void sceNp_init(Module *pxThis);
|
||||
extern void sceNp_unload();
|
||||
extern void sceNpClans_init(Module *pxThis);
|
||||
extern void sceNpClans_unload();
|
||||
extern void sceNpCommerce2_init(Module *pxThis);
|
||||
@ -90,9 +95,9 @@ static const g_modules_list[] =
|
||||
{ 0x0011, "cellAudio", cellAudio_init, nullptr, nullptr },
|
||||
{ 0x0012, "cellPamf", cellPamf_init, nullptr, nullptr },
|
||||
{ 0x0013, "cellAtrac", cellAtrac_init, nullptr, nullptr },
|
||||
{ 0x0014, "cellNetCtl", cellNetCtl_init, nullptr, nullptr },
|
||||
{ 0x0014, "cellNetCtl", cellNetCtl_init, nullptr, cellNetCtl_unload },
|
||||
{ 0x0015, "cellSysutil", cellSysutil_init, cellSysutil_load, nullptr },
|
||||
{ 0x0016, "sceNp", sceNp_init, nullptr, nullptr },
|
||||
{ 0x0016, "sceNp", sceNp_init, nullptr, sceNp_unload },
|
||||
{ 0x0017, "sys_io", sys_io_init, nullptr, nullptr },
|
||||
{ 0x0018, "cellPngDec", cellPngDec_init, nullptr, nullptr },
|
||||
{ 0x0019, "cellFont", cellFont_init, cellFont_load, cellFont_unload },
|
||||
@ -105,7 +110,7 @@ static const g_modules_list[] =
|
||||
{ 0x0020, "cellDaisy", nullptr, nullptr, nullptr },
|
||||
{ 0x0021, "cellKey2char", nullptr, nullptr, nullptr },
|
||||
{ 0x0022, "cellMic", nullptr, nullptr, nullptr },
|
||||
{ 0x0023, "cellCamera", cellCamera_init, nullptr, nullptr },
|
||||
{ 0x0023, "cellCamera", cellCamera_init, nullptr, cellCamera_unload },
|
||||
{ 0x0024, "cellVdecMpeg2", nullptr, nullptr, nullptr },
|
||||
{ 0x0025, "cellVdecAvc", nullptr, nullptr, nullptr },
|
||||
{ 0x0026, "cellAdecLpcm", nullptr, nullptr, nullptr },
|
||||
@ -115,7 +120,7 @@ static const g_modules_list[] =
|
||||
{ 0x002a, "cellDmuxPamf", nullptr, nullptr, nullptr },
|
||||
{ 0x002e, "cellLv2dbg", nullptr, nullptr, nullptr },
|
||||
{ 0x0030, "cellUsbpspcm", nullptr, nullptr, nullptr },
|
||||
{ 0x0031, "cellAvconfExt", nullptr, nullptr, nullptr },
|
||||
{ 0x0031, "cellAvconfExt", cellAvconfExt_init, nullptr, nullptr },
|
||||
{ 0x0032, "cellUserInfo", cellUserInfo_init, nullptr, nullptr },
|
||||
{ 0x0033, "cellSysutilSavedata", nullptr, nullptr, nullptr },
|
||||
{ 0x0034, "cellSubdisplay", nullptr, nullptr, nullptr },
|
||||
@ -150,7 +155,7 @@ static const g_modules_list[] =
|
||||
{ 0x0056, "cellNpUtil", nullptr, nullptr, nullptr },
|
||||
{ 0x0057, "cellRudp", nullptr, nullptr, nullptr },
|
||||
{ 0x0059, "cellNpSns", sceNpSns_init, nullptr, sceNpSns_unload },
|
||||
{ 0x005a, "cellGem", cellGem_init, nullptr, nullptr },
|
||||
{ 0x005a, "cellGem", cellGem_init, nullptr, cellGem_unload },
|
||||
{ 0xf00a, "cellCelpEnc", nullptr, nullptr, nullptr },
|
||||
{ 0xf010, "cellGifDec", cellGifDec_init, nullptr, nullptr },
|
||||
{ 0xf019, "cellAdecCelp", nullptr, nullptr, nullptr },
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Emu/SysCalls/Static.h"
|
||||
#include "Crypto/sha1.h"
|
||||
#include "ModuleManager.h"
|
||||
#include "Emu/Cell/PPUInstrTable.h"
|
||||
|
||||
u32 getFunctionId(const char* name)
|
||||
{
|
||||
@ -89,10 +90,13 @@ void Module::UnLoad()
|
||||
|
||||
if(m_unload_func) m_unload_func();
|
||||
|
||||
for(u32 i=0; i<m_funcs_list.size(); ++i)
|
||||
{
|
||||
Emu.GetModuleManager().UnloadFunc(m_funcs_list[i]->id);
|
||||
}
|
||||
// TODO: Re-enable this when needed
|
||||
// This was disabled because some functions would get unloaded and
|
||||
// some games tried to use them, thus only printing a TODO message
|
||||
//for(u32 i=0; i<m_funcs_list.size(); ++i)
|
||||
//{
|
||||
// Emu.GetModuleManager().UnloadFunc(m_funcs_list[i]->id);
|
||||
//}
|
||||
|
||||
SetLoaded(false);
|
||||
}
|
||||
@ -146,12 +150,12 @@ void Module::SetName(const std::string& name)
|
||||
|
||||
bool Module::CheckID(u32 id) const
|
||||
{
|
||||
return Emu.GetIdManager().CheckID(id) && Emu.GetIdManager().GetID(id).m_name == GetName();
|
||||
return Emu.GetIdManager().CheckID(id) && Emu.GetIdManager().GetID(id).GetName() == GetName();
|
||||
}
|
||||
|
||||
bool Module::CheckID(u32 id, ID*& _id) const
|
||||
{
|
||||
return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->m_name == GetName();
|
||||
return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->GetName() == GetName();
|
||||
}
|
||||
|
||||
bool Module::RemoveId(u32 id)
|
||||
@ -171,12 +175,18 @@ void Module::PushNewFuncSub(SFunc* func)
|
||||
|
||||
void fix_import(Module* module, u32 func, u32 addr)
|
||||
{
|
||||
vm::write32(addr + 0x0, 0x3d600000 | (func >> 16)); /* lis r11, (func_id >> 16) */
|
||||
vm::write32(addr + 0x4, 0x616b0000 | (func & 0xffff)); /* ori r11, (func_id & 0xffff) */
|
||||
vm::write32(addr + 0x8, 0x60000000); /* nop */
|
||||
// leave rtoc saving at 0xC
|
||||
vm::write64(addr + 0x10, 0x440000024e800020ull); /* sc + blr */
|
||||
vm::write64(addr + 0x18, 0x6000000060000000ull); /* nop + nop */
|
||||
using namespace PPU_instr;
|
||||
|
||||
vm::ptr<u32>& ptr = (vm::ptr<u32>&)addr;
|
||||
|
||||
*ptr++ = LIS(11, func >> 16);
|
||||
*ptr++ = ORI(11, 11, func & 0xffff);
|
||||
*ptr++ = NOP();
|
||||
++ptr;
|
||||
*ptr++ = SC(2);
|
||||
*ptr++ = BLR();
|
||||
*ptr++ = NOP();
|
||||
*ptr++ = NOP();
|
||||
|
||||
module->Load(func);
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
|
||||
if(!CheckID(id, id_data)) return false;
|
||||
|
||||
data = id_data->m_data->get<T>();
|
||||
data = id_data->GetData()->get<T>();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -100,8 +100,8 @@ public:
|
||||
|
||||
if(!CheckID(id, id_data)) return false;
|
||||
|
||||
data = id_data->m_data->get<T>();
|
||||
type = id_data->m_type;
|
||||
data = id_data->GetData()->get<T>();
|
||||
type = id_data->GetType();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
60
rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp
Normal file
60
rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "stdafx.h"
|
||||
#include "Ini.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "Emu/RSX/sysutil_video.h"
|
||||
|
||||
Module *cellAvconfExt = nullptr;
|
||||
|
||||
int cellVideoOutConvertCursorColor()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellAvconfExt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize)
|
||||
{
|
||||
cellAvconfExt->Warning("cellVideoOutGetScreenSize(videoOut=%d, screenSize_addr=0x%x)", videoOut, screenSize.addr());
|
||||
|
||||
if (!videoOut == CELL_VIDEO_OUT_PRIMARY)
|
||||
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
|
||||
|
||||
#ifdef _WIN32
|
||||
HDC screen = GetDC(NULL);
|
||||
u32 diagonal = round(sqrt((pow(GetDeviceCaps(screen, HORZSIZE), 2) + pow(GetDeviceCaps(screen, VERTSIZE), 2))) * 0.0393);
|
||||
#else
|
||||
// TODO: Linux implementation, without using wx
|
||||
// u32 diagonal = round(sqrt((pow(wxGetDisplaySizeMM().GetWidth(), 2) + pow(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393);
|
||||
#endif
|
||||
|
||||
if (Ini.GS3DTV.GetValue())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
*screenSize = diagonal;
|
||||
#endif
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET;
|
||||
}
|
||||
|
||||
int cellVideoOutGetGamma()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellAvconfExt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellVideoOutSetGamma()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellAvconfExt);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellAvconfExt_init(Module *pxThis)
|
||||
{
|
||||
cellAvconfExt = pxThis;
|
||||
|
||||
cellAvconfExt->AddFunc(0x4ec8c141, cellVideoOutConvertCursorColor);
|
||||
cellAvconfExt->AddFunc(0xfaa275a4, cellVideoOutGetScreenSize);
|
||||
cellAvconfExt->AddFunc(0xc7020f62, cellVideoOutSetGamma);
|
||||
}
|
@ -221,6 +221,11 @@ int cellCameraRemoveNotifyEventQueue2()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellCamera_unload()
|
||||
{
|
||||
cellCameraInstance.m_bInitialized = false;
|
||||
}
|
||||
|
||||
void cellCamera_init(Module* pxThis)
|
||||
{
|
||||
cellCamera = pxThis;
|
||||
|
@ -251,6 +251,11 @@ int cellGemWriteExternalPort()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellGem_unload()
|
||||
{
|
||||
cellGemInstance.m_bInitialized = false;
|
||||
}
|
||||
|
||||
void cellGem_init(Module *pxThis)
|
||||
{
|
||||
cellGem = pxThis;
|
||||
|
@ -44,7 +44,7 @@ int cellNetCtlTerm()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellNetCtlGetState(vm::ptr<be_t<u32>> state)
|
||||
int cellNetCtlGetState(vm::ptr<u32> state)
|
||||
{
|
||||
cellNetCtl->Warning("cellNetCtlGetState(state_addr=0x%x)", state.addr());
|
||||
|
||||
@ -53,9 +53,9 @@ int cellNetCtlGetState(vm::ptr<be_t<u32>> state)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellNetCtlAddHandler(vm::ptr<cellNetCtlHandler> handler, vm::ptr<be_t<u32>> arg, s32 hid)
|
||||
int cellNetCtlAddHandler(vm::ptr<cellNetCtlHandler> handler, vm::ptr<void> arg, vm::ptr<s32> hid)
|
||||
{
|
||||
cellNetCtl->Todo("cellNetCtlAddHandler(handler_addr=0x%x, arg_addr=0x%x, hid=0x%x)", handler.addr(), arg.addr(), hid);
|
||||
cellNetCtl->Todo("cellNetCtlAddHandler(handler_addr=0x%x, arg_addr=0x%x, hid_addr=0x%x)", handler.addr(), arg.addr(), hid.addr());
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -111,6 +111,11 @@ int cellNetCtlGetNatInfo(vm::ptr<CellNetCtlNatInfo> natInfo)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellNetCtl_unload()
|
||||
{
|
||||
cellNetCtlInstance.m_bInitialized = false;
|
||||
}
|
||||
|
||||
void cellNetCtl_init(Module *pxThis)
|
||||
{
|
||||
cellNetCtl = pxThis;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
|
||||
Module *cellOvis = nullptr;
|
||||
@ -11,9 +12,9 @@ enum
|
||||
CELL_OVIS_ERROR_ALIGN = 0x80410410,
|
||||
};
|
||||
|
||||
int cellOvisGetOverlayTableSize()
|
||||
int cellOvisGetOverlayTableSize(vm::ptr<const char> elf)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellOvis);
|
||||
cellOvis->Todo("cellOvisGetOverlayTableSize(elf_addr=0x%x)", elf.addr());
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,40 @@ enum
|
||||
SCE_NP_ERROR_ALREADY_USED = 0x8002aa15,
|
||||
SCE_NP_ERROR_DIFFERENT_USER = 0x8002aa16,
|
||||
SCE_NP_ERROR_ALREADY_DONE = 0x8002aa17,
|
||||
// NP Basic Utility
|
||||
SCE_NP_BASIC_ERROR_ALREADY_INITIALIZED = 0x8002a661,
|
||||
SCE_NP_BASIC_ERROR_NOT_INITIALIZED = 0x8002a662,
|
||||
SCE_NP_BASIC_ERROR_NOT_SUPPORTED = 0x8002a663,
|
||||
SCE_NP_BASIC_ERROR_OUT_OF_MEMORY = 0x8002a664,
|
||||
SCE_NP_BASIC_ERROR_INVALID_ARGUMENT = 0x8002a665,
|
||||
SCE_NP_BASIC_ERROR_BAD_ID = 0x8002a666,
|
||||
SCE_NP_BASIC_ERROR_IDS_DIFFER = 0x8002a667,
|
||||
SCE_NP_BASIC_ERROR_PARSER_FAILED = 0x8002a668,
|
||||
SCE_NP_BASIC_ERROR_TIMEOUT = 0x8002a669,
|
||||
SCE_NP_BASIC_ERROR_NO_EVENT = 0x8002a66a,
|
||||
SCE_NP_BASIC_ERROR_EXCEEDS_MAX = 0x8002a66b,
|
||||
SCE_NP_BASIC_ERROR_INSUFFICIENT = 0x8002a66c,
|
||||
SCE_NP_BASIC_ERROR_NOT_REGISTERED = 0x8002a66d,
|
||||
SCE_NP_BASIC_ERROR_DATA_LOST = 0x8002a66e,
|
||||
SCE_NP_BASIC_ERROR_BUSY = 0x8002a66f,
|
||||
SCE_NP_BASIC_ERROR_STATUS = 0x8002a670,
|
||||
SCE_NP_BASIC_ERROR_CANCEL = 0x8002a671,
|
||||
SCE_NP_BASIC_ERROR_INVALID_MEMORY_CONTAINER = 0x8002a672,
|
||||
SCE_NP_BASIC_ERROR_INVALID_DATA_ID = 0x8002a673,
|
||||
SCE_NP_BASIC_ERROR_BROKEN_DATA = 0x8002a674,
|
||||
SCE_NP_BASIC_ERROR_BLOCKLIST_ADD_FAILED = 0x8002a675,
|
||||
SCE_NP_BASIC_ERROR_BLOCKLIST_IS_FULL = 0x8002a676,
|
||||
SCE_NP_BASIC_ERROR_SEND_FAILED = 0x8002a677,
|
||||
SCE_NP_BASIC_ERROR_NOT_CONNECTED = 0x8002a678,
|
||||
SCE_NP_BASIC_ERROR_INSUFFICIENT_DISK_SPACE = 0x8002a679,
|
||||
SCE_NP_BASIC_ERROR_INTERNAL_FAILURE = 0x8002a67a,
|
||||
SCE_NP_BASIC_ERROR_DOES_NOT_EXIST = 0x8002a67b,
|
||||
SCE_NP_BASIC_ERROR_INVALID = 0x8002a67c,
|
||||
SCE_NP_BASIC_ERROR_UNKNOWN = 0x8002a6bf,
|
||||
SCE_NP_EXT_ERROR_CONTEXT_DOES_NOT_EXIST = 0x8002a6a1,
|
||||
SCE_NP_EXT_ERROR_CONTEXT_ALREADY_EXISTS = 0x8002a6a2,
|
||||
SCE_NP_EXT_ERROR_NO_CONTEXT = 0x8002a6a3,
|
||||
SCE_NP_EXT_ERROR_NO_ORIGIN = 0x8002a6a4,
|
||||
// NP Community Utility
|
||||
SCE_NP_COMMUNITY_ERROR_ALREADY_INITIALIZED = 0x8002a101,
|
||||
SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED = 0x8002a102,
|
||||
@ -62,6 +96,8 @@ enum
|
||||
SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID = 0x8002a1b1,
|
||||
};
|
||||
|
||||
typedef int(*SceNpBasicEventHandler)(s32 event, s32 retCode, u32 reqId, vm::ptr<void> arg);
|
||||
|
||||
// NP Manager Utility statuses
|
||||
enum
|
||||
{
|
||||
@ -72,6 +108,38 @@ enum
|
||||
SCE_NP_MANAGER_STATUS_ONLINE = 3,
|
||||
};
|
||||
|
||||
// Event types
|
||||
enum
|
||||
{
|
||||
SCE_NP_BASIC_EVENT_UNKNOWN = -1,
|
||||
SCE_NP_BASIC_EVENT_OFFLINE = 0,
|
||||
SCE_NP_BASIC_EVENT_PRESENCE = 1,
|
||||
SCE_NP_BASIC_EVENT_MESSAGE = 2,
|
||||
SCE_NP_BASIC_EVENT_ADD_FRIEND_RESULT = 3,
|
||||
SCE_NP_BASIC_EVENT_INCOMING_ATTACHMENT = 4,
|
||||
SCE_NP_BASIC_EVENT_INCOMING_INVITATION = 5,
|
||||
SCE_NP_BASIC_EVENT_END_OF_INITIAL_PRESENCE = 6,
|
||||
SCE_NP_BASIC_EVENT_SEND_ATTACHMENT_RESULT = 7,
|
||||
SCE_NP_BASIC_EVENT_RECV_ATTACHMENT_RESULT = 8,
|
||||
SCE_NP_BASIC_EVENT_OUT_OF_CONTEXT = 9,
|
||||
SCE_NP_BASIC_EVENT_FRIEND_REMOVED = 10,
|
||||
SCE_NP_BASIC_EVENT_ADD_BLOCKLIST_RESULT = 11,
|
||||
SCE_NP_BASIC_EVENT_SEND_MESSAGE_RESULT = 12,
|
||||
SCE_NP_BASIC_EVENT_SEND_INVITATION_RESULT = 13,
|
||||
SCE_NP_BASIC_EVENT_RECV_INVITATION_RESULT = 14,
|
||||
SCE_NP_BASIC_EVENT_MESSAGE_MARKED_AS_USED_RESULT = 15,
|
||||
SCE_NP_BASIC_EVENT_INCOMING_CUSTOM_INVITATION = 16,
|
||||
SCE_NP_BASIC_EVENT_INCOMING_CLAN_MESSAGE = 17,
|
||||
SCE_NP_BASIC_EVENT_ADD_PLAYERS_HISTORY_RESULT = 18,
|
||||
SCE_NP_BASIC_EVENT_SEND_CUSTOM_DATA_RESULT = 19,
|
||||
SCE_NP_BASIC_EVENT_RECV_CUSTOM_DATA_RESULT = 20,
|
||||
SCE_NP_BASIC_EVENT_INCOMING_CUSTOM_DATA_MESSAGE = 21,
|
||||
SCE_NP_BASIC_EVENT_SEND_URL_ATTACHMENT_RESULT = 22,
|
||||
SCE_NP_BASIC_EVENT_INCOMING_BOOTABLE_INVITATION = 23,
|
||||
SCE_NP_BASIC_EVENT_BLOCKLIST_UPDATE = 24,
|
||||
SCE_NP_BASIC_EVENT_INCOMING_BOOTABLE_CUSTOM_DATA_MESSAGE = 25,
|
||||
};
|
||||
|
||||
// IDs for attachment data objects
|
||||
enum
|
||||
{
|
||||
|
@ -6,6 +6,18 @@
|
||||
|
||||
Module *sceNpCommerce2 = nullptr;
|
||||
|
||||
struct sceNpCommerce2Internal
|
||||
{
|
||||
bool m_bSceNpCommerce2Initialized;
|
||||
|
||||
sceNpCommerce2Internal()
|
||||
: m_bSceNpCommerce2Initialized(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
sceNpCommerce2Internal sceNpCommerce2Instance;
|
||||
|
||||
int sceNpCommerce2ExecuteStoreBrowse()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpCommerce2);
|
||||
@ -20,13 +32,25 @@ int sceNpCommerce2GetStoreBrowseUserdata()
|
||||
|
||||
int sceNpCommerce2Init()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpCommerce2);
|
||||
sceNpCommerce2->Warning("sceNpCommerce2Init()");
|
||||
|
||||
if (sceNpCommerce2Instance.m_bSceNpCommerce2Initialized)
|
||||
return SCE_NP_COMMERCE2_ERROR_ALREADY_INITIALIZED;
|
||||
|
||||
sceNpCommerce2Instance.m_bSceNpCommerce2Initialized = true;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sceNpCommerce2Term()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpCommerce2);
|
||||
sceNpCommerce2->Warning("sceNpCommerce2Term()");
|
||||
|
||||
if (!sceNpCommerce2Instance.m_bSceNpCommerce2Initialized)
|
||||
return SCE_NP_COMMERCE2_ERROR_NOT_INITIALIZED;
|
||||
|
||||
sceNpCommerce2Instance.m_bSceNpCommerce2Initialized = false;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -290,7 +314,7 @@ int sceNpCommerce2DestroyReq()
|
||||
|
||||
void sceNpCommerce2_unload()
|
||||
{
|
||||
// TODO: Unload SNS module
|
||||
sceNpCommerce2Instance.m_bSceNpCommerce2Initialized = false;
|
||||
}
|
||||
|
||||
void sceNpCommerce2_init(Module *pxThis)
|
||||
|
@ -67,19 +67,20 @@ struct sceNpTrophyInternal
|
||||
}
|
||||
};
|
||||
|
||||
sceNpTrophyInternal s_npTrophyInstance;
|
||||
sceNpTrophyInternal sceNpTrophyInstance;
|
||||
|
||||
// Functions
|
||||
int sceNpTrophyInit(u32 pool_addr, u32 poolSize, u32 containerId, u64 options)
|
||||
{
|
||||
sceNpTrophy->Log("sceNpTrophyInit(pool_addr=0x%x, poolSize=%d, containerId=%d, options=0x%llx)", pool_addr, poolSize, containerId, options);
|
||||
|
||||
if (s_npTrophyInstance.m_bInitialized)
|
||||
if (sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED;
|
||||
if (options)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
|
||||
|
||||
s_npTrophyInstance.m_bInitialized = true;
|
||||
sceNpTrophyInstance.m_bInitialized = true;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -88,7 +89,7 @@ int sceNpTrophyCreateContext(vm::ptr<be_t<u32>> context, vm::ptr<SceNpCommunicat
|
||||
sceNpTrophy->Warning("sceNpTrophyCreateContext(context_addr=0x%x, commID_addr=0x%x, commSign_addr=0x%x, options=0x%llx)",
|
||||
context.addr(), commID.addr(), commSign.addr(), options);
|
||||
|
||||
if (!s_npTrophyInstance.m_bInitialized)
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
if (options & (~(u64)1))
|
||||
return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
|
||||
@ -108,8 +109,8 @@ int sceNpTrophyCreateContext(vm::ptr<be_t<u32>> context, vm::ptr<SceNpCommunicat
|
||||
|
||||
if (stream && stream->IsOpened())
|
||||
{
|
||||
s_npTrophyInstance.contexts.emplace_back();
|
||||
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts.back();
|
||||
sceNpTrophyInstance.contexts.emplace_back();
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts.back();
|
||||
ctxt.trp_stream.reset(stream);
|
||||
ctxt.trp_name = entry->name;
|
||||
stream = nullptr;
|
||||
@ -125,7 +126,7 @@ int sceNpTrophyCreateHandle(vm::ptr<be_t<u32>> handle)
|
||||
{
|
||||
sceNpTrophy->Warning("sceNpTrophyCreateHandle(handle_addr=0x%x)", handle.addr());
|
||||
|
||||
if (!s_npTrophyInstance.m_bInitialized)
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
@ -139,15 +140,15 @@ int sceNpTrophyRegisterContext(u32 context, u32 handle, vm::ptr<SceNpTrophyStatu
|
||||
sceNpTrophy->Warning("sceNpTrophyRegisterContext(context=%d, handle=%d, statusCb_addr=0x%x, arg_addr=0x%x, options=0x%llx)",
|
||||
context, handle, statusCb.addr(), arg_addr, options);
|
||||
|
||||
if (!(s_npTrophyInstance.m_bInitialized))
|
||||
if (!(sceNpTrophyInstance.m_bInitialized))
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
if (options & (~(u64)1))
|
||||
return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
|
||||
if (context >= s_npTrophyInstance.contexts.size())
|
||||
if (context >= sceNpTrophyInstance.contexts.size())
|
||||
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
if (!ctxt.trp_stream)
|
||||
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
||||
|
||||
@ -216,13 +217,13 @@ int sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr<be_t<u64>>
|
||||
sceNpTrophy->Warning("sceNpTrophyGetRequiredDiskSpace(context=%d, handle=%d, reqspace_addr=0x%x, options=0x%llx)",
|
||||
context, handle, reqspace.addr(), options);
|
||||
|
||||
if (!s_npTrophyInstance.m_bInitialized)
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
if (context >= s_npTrophyInstance.contexts.size())
|
||||
if (context >= sceNpTrophyInstance.contexts.size())
|
||||
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
if (!ctxt.trp_stream)
|
||||
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
||||
|
||||
@ -236,9 +237,15 @@ int sceNpTrophyDestroyContext()
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sceNpTrophyAbortHandle()
|
||||
int sceNpTrophyAbortHandle(u32 handle)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
||||
sceNpTrophy->Todo("sceNpTrophyAbortHandle(handle=%d)", handle);
|
||||
|
||||
// TODO: ?
|
||||
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -247,13 +254,13 @@ int sceNpTrophyGetGameInfo(u32 context, u32 handle, vm::ptr<SceNpTrophyGameDetai
|
||||
sceNpTrophy->Warning("sceNpTrophyGetGameInfo(context=%d, handle=%d, details_addr=0x%x, data_addr=0x%x)",
|
||||
context, handle, details.addr(), data.addr());
|
||||
|
||||
if (!s_npTrophyInstance.m_bInitialized)
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
std::string path;
|
||||
rXmlDocument doc;
|
||||
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
Emu.GetVFS().GetDevice("/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name + "/TROPCONF.SFM", path); // TODO: Get the path of the current user
|
||||
doc.Load(path);
|
||||
|
||||
@ -305,11 +312,11 @@ int sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::ptr<be_t<
|
||||
sceNpTrophy->Warning("sceNpTrophyUnlockTrophy(context=%d, handle=%d, trophyId=%d, platinumId_addr=0x%x)",
|
||||
context, handle, trophyId, platinumId.addr());
|
||||
|
||||
if (!s_npTrophyInstance.m_bInitialized)
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
if (trophyId >= (s32)ctxt.tropusr->GetTrophiesCount())
|
||||
return SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID;
|
||||
if (ctxt.tropusr->GetTrophyUnlockState(trophyId))
|
||||
@ -327,7 +334,13 @@ int sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::ptr<be_t<
|
||||
|
||||
int sceNpTrophyTerm()
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sceNpTrophy);
|
||||
sceNpTrophy->Warning("sceNpTrophyTerm()");
|
||||
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
|
||||
sceNpTrophyInstance.m_bInitialized = false;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -336,11 +349,11 @@ int sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, vm::ptr<SceNpTrophy
|
||||
sceNpTrophy->Warning("sceNpTrophyGetTrophyUnlockState(context=%d, handle=%d, flags_addr=0x%x, count_addr=0x%x)",
|
||||
context, handle, flags.addr(), count.addr());
|
||||
|
||||
if (!s_npTrophyInstance.m_bInitialized)
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
*count = ctxt.tropusr->GetTrophiesCount();
|
||||
if (*count > 128)
|
||||
sceNpTrophy->Warning("sceNpTrophyGetTrophyUnlockState: More than 128 trophies detected!");
|
||||
@ -368,13 +381,13 @@ int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr<SceN
|
||||
sceNpTrophy->Warning("sceNpTrophyGetTrophyInfo(context=%u, handle=%u, trophyId=%d, details_addr=0x%x, data_addr=0x%x)",
|
||||
context, handle, trophyId, details.addr(), data.addr());
|
||||
|
||||
if (!s_npTrophyInstance.m_bInitialized)
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
std::string path;
|
||||
rXmlDocument doc;
|
||||
sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
Emu.GetVFS().GetDevice("/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name + "/TROPCONF.SFM", path); // TODO: Get the path of the current user
|
||||
doc.Load(path);
|
||||
|
||||
@ -420,7 +433,7 @@ int sceNpTrophyGetGameIcon()
|
||||
|
||||
void sceNpTrophy_unload()
|
||||
{
|
||||
s_npTrophyInstance.m_bInitialized = false;
|
||||
sceNpTrophyInstance.m_bInitialized = false;
|
||||
}
|
||||
|
||||
void sceNpTrophy_init(Module *pxThis)
|
||||
|
@ -82,7 +82,7 @@ s64 sys_prx_exitspawn_with_level()
|
||||
|
||||
int sys_spu_elf_get_information(u32 elf_img, vm::ptr<be_t<u32>> entry, vm::ptr<be_t<u32>> nseg)
|
||||
{
|
||||
sysPrxForUser->Todo("sys_spu_elf_get_information(elf_img=0x%x, entry_addr=0x%x, nseg_addr=0x%x", elf_img, entry.addr(), nseg.addr());
|
||||
sysPrxForUser->Todo("sys_spu_elf_get_information(elf_img=0x%x, entry_addr=0x%x, nseg_addr=0x%x)", elf_img, entry.addr(), nseg.addr());
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -137,14 +137,17 @@ int sys_raw_spu_image_load(int id, vm::ptr<sys_spu_image> img)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_get_random_number(u32 addr, u64 size)
|
||||
int sys_get_random_number(vm::ptr<u8> addr, u64 size)
|
||||
{
|
||||
sysPrxForUser->Warning("sys_get_random_number(addr=0x%x, size=%d)", addr, size);
|
||||
sysPrxForUser->Warning("sys_get_random_number(addr=0x%x, size=%d)", addr.addr(), size);
|
||||
|
||||
if (size > 4096)
|
||||
size = 4096;
|
||||
|
||||
vm::write32(addr, rand() % size);
|
||||
for (u64 i = 0; i < size - 1; i++)
|
||||
{
|
||||
addr[i] = rand() % 256;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
namespace detail{
|
||||
template<> bool CheckId(u32 id, ID*& _id,const std::string &name)
|
||||
{
|
||||
return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->m_name == name;
|
||||
return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->GetName() == name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace detail{
|
||||
{
|
||||
ID* id_data;
|
||||
if(!CheckId(id, id_data,name)) return false;
|
||||
data = id_data->m_data->get<T>();
|
||||
data = id_data->GetData()->get<T>();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public:
|
||||
|
||||
bool CheckId(u32 id) const
|
||||
{
|
||||
return GetIdManager().CheckID(id) && GetIdManager().GetID(id).m_name == GetName();
|
||||
return GetIdManager().CheckID(id) && GetIdManager().GetID(id).GetName() == GetName();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -406,6 +406,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
|
||||
wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write Depth Buffer");
|
||||
wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write Color Buffers");
|
||||
wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync");
|
||||
wxCheckBox* chbox_gs_3dmonitor = new wxCheckBox(p_graphics, wxID_ANY, "3D Monitor");
|
||||
wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file");
|
||||
wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit");
|
||||
wxCheckBox* chbox_hle_logging = new wxCheckBox(p_hle, wxID_ANY, "Log all SysCalls");
|
||||
@ -424,7 +425,11 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
|
||||
cbox_spu_decoder->Append("SPU Interpreter");
|
||||
cbox_spu_decoder->Append("SPU JIT (asmjit)");
|
||||
|
||||
for(int i=1; i<WXSIZEOF(ResolutionTable); ++i)
|
||||
cbox_gs_render->Append("Null");
|
||||
cbox_gs_render->Append("OpenGL");
|
||||
//cbox_gs_render->Append("Software");
|
||||
|
||||
for(int i = 1; i < WXSIZEOF(ResolutionTable); ++i)
|
||||
{
|
||||
cbox_gs_resolution->Append(wxString::Format("%dx%d", ResolutionTable[i].width.ToLE(), ResolutionTable[i].height.ToLE()));
|
||||
}
|
||||
@ -432,10 +437,6 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
|
||||
cbox_gs_aspect->Append("4:3");
|
||||
cbox_gs_aspect->Append("16:9");
|
||||
|
||||
cbox_gs_render->Append("Null");
|
||||
cbox_gs_render->Append("OpenGL");
|
||||
//cbox_gs_render->Append("Software");
|
||||
|
||||
cbox_pad_handler->Append("Null");
|
||||
cbox_pad_handler->Append("Windows");
|
||||
#if defined (_WIN32)
|
||||
@ -491,6 +492,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
|
||||
chbox_gs_dump_depth ->SetValue(Ini.GSDumpDepthBuffer.GetValue());
|
||||
chbox_gs_dump_color ->SetValue(Ini.GSDumpColorBuffers.GetValue());
|
||||
chbox_gs_vsync ->SetValue(Ini.GSVSyncEnable.GetValue());
|
||||
chbox_gs_3dmonitor ->SetValue(Ini.GS3DTV.GetValue());
|
||||
chbox_audio_dump ->SetValue(Ini.AudioDumpToFile.GetValue());
|
||||
chbox_audio_conv ->SetValue(Ini.AudioConvertToU16.GetValue());
|
||||
chbox_hle_logging ->SetValue(Ini.HLELogging.GetValue());
|
||||
@ -555,6 +557,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
|
||||
s_subpanel_graphics->Add(chbox_gs_dump_depth, wxSizerFlags().Border(wxALL, 5).Expand());
|
||||
s_subpanel_graphics->Add(chbox_gs_dump_color, wxSizerFlags().Border(wxALL, 5).Expand());
|
||||
s_subpanel_graphics->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5).Expand());
|
||||
s_subpanel_graphics->Add(chbox_gs_3dmonitor, wxSizerFlags().Border(wxALL, 5).Expand());
|
||||
|
||||
// Input - Output
|
||||
s_subpanel_io->Add(s_round_io_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand());
|
||||
@ -609,10 +612,11 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event))
|
||||
Ini.GSRenderMode.SetValue(cbox_gs_render->GetSelection());
|
||||
Ini.GSResolution.SetValue(ResolutionNumToId(cbox_gs_resolution->GetSelection() + 1));
|
||||
Ini.GSAspectRatio.SetValue(cbox_gs_aspect->GetSelection() + 1);
|
||||
Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue());
|
||||
Ini.GSLogPrograms.SetValue(chbox_gs_log_prog->GetValue());
|
||||
Ini.GSDumpDepthBuffer.SetValue(chbox_gs_dump_depth->GetValue());
|
||||
Ini.GSDumpColorBuffers.SetValue(chbox_gs_dump_color->GetValue());
|
||||
Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue());
|
||||
Ini.GS3DTV.SetValue(chbox_gs_3dmonitor->GetValue());
|
||||
Ini.PadHandlerMode.SetValue(cbox_pad_handler->GetSelection());
|
||||
Ini.KeyboardHandlerMode.SetValue(cbox_keyboard_handler->GetSelection());
|
||||
Ini.MouseHandlerMode.SetValue(cbox_mouse_handler->GetSelection());
|
||||
|
@ -492,23 +492,24 @@ void RSXDebugger::GetFlags()
|
||||
#define LIST_FLAGS_ADD(name, value) \
|
||||
m_list_flags->InsertItem(i, name); m_list_flags->SetItem(i, 1, value ? "Enabled" : "Disabled"); i++;
|
||||
|
||||
LIST_FLAGS_ADD("Alpha test", render.m_set_alpha_test);
|
||||
LIST_FLAGS_ADD("Blend", render.m_set_blend);
|
||||
LIST_FLAGS_ADD("Scissor", render.m_set_scissor_horizontal && render.m_set_scissor_vertical);
|
||||
LIST_FLAGS_ADD("Cull face", render.m_set_cull_face);
|
||||
LIST_FLAGS_ADD("Depth bounds test", render.m_set_depth_bounds_test);
|
||||
LIST_FLAGS_ADD("Depth test", render.m_set_depth_test);
|
||||
LIST_FLAGS_ADD("Dither", render.m_set_dither);
|
||||
LIST_FLAGS_ADD("Line smooth", render.m_set_line_smooth);
|
||||
LIST_FLAGS_ADD("Logic op", render.m_set_logic_op);
|
||||
LIST_FLAGS_ADD("Poly smooth", render.m_set_poly_smooth);
|
||||
LIST_FLAGS_ADD("Poly offset fill", render.m_set_poly_offset_fill);
|
||||
LIST_FLAGS_ADD("Poly offset line", render.m_set_poly_offset_line);
|
||||
LIST_FLAGS_ADD("Poly offset point", render.m_set_poly_offset_point);
|
||||
LIST_FLAGS_ADD("Stencil test", render.m_set_stencil_test);
|
||||
LIST_FLAGS_ADD("Primitive restart", render.m_set_restart_index);
|
||||
LIST_FLAGS_ADD("Point Sprite", render.m_set_point_sprite_control);
|
||||
LIST_FLAGS_ADD("Lighting ", render.m_set_specular);
|
||||
LIST_FLAGS_ADD("Alpha test", render.m_set_alpha_test);
|
||||
LIST_FLAGS_ADD("Blend", render.m_set_blend);
|
||||
LIST_FLAGS_ADD("Scissor", render.m_set_scissor_horizontal && render.m_set_scissor_vertical);
|
||||
LIST_FLAGS_ADD("Cull face", render.m_set_cull_face);
|
||||
LIST_FLAGS_ADD("Depth bounds test", render.m_set_depth_bounds_test);
|
||||
LIST_FLAGS_ADD("Depth test", render.m_set_depth_test);
|
||||
LIST_FLAGS_ADD("Dither", render.m_set_dither);
|
||||
LIST_FLAGS_ADD("Line smooth", render.m_set_line_smooth);
|
||||
LIST_FLAGS_ADD("Logic op", render.m_set_logic_op);
|
||||
LIST_FLAGS_ADD("Poly smooth", render.m_set_poly_smooth);
|
||||
LIST_FLAGS_ADD("Poly offset fill", render.m_set_poly_offset_fill);
|
||||
LIST_FLAGS_ADD("Poly offset line", render.m_set_poly_offset_line);
|
||||
LIST_FLAGS_ADD("Poly offset point", render.m_set_poly_offset_point);
|
||||
LIST_FLAGS_ADD("Stencil test", render.m_set_stencil_test);
|
||||
LIST_FLAGS_ADD("Primitive restart", render.m_set_restart_index);
|
||||
LIST_FLAGS_ADD("Two sided lighting", render.m_set_two_side_light_enable);
|
||||
LIST_FLAGS_ADD("Point Sprite", render.m_set_point_sprite_control);
|
||||
LIST_FLAGS_ADD("Lighting ", render.m_set_specular);
|
||||
|
||||
#undef LIST_FLAGS_ADD
|
||||
}
|
||||
|
12
rpcs3/Ini.h
12
rpcs3/Ini.h
@ -104,10 +104,11 @@ public:
|
||||
IniEntry<u8> GSRenderMode;
|
||||
IniEntry<u8> GSResolution;
|
||||
IniEntry<u8> GSAspectRatio;
|
||||
IniEntry<bool> GSVSyncEnable;
|
||||
IniEntry<bool> GSLogPrograms;
|
||||
IniEntry<bool> GSDumpColorBuffers;
|
||||
IniEntry<bool> GSDumpDepthBuffer;
|
||||
IniEntry<bool> GSVSyncEnable;
|
||||
IniEntry<bool> GS3DTV;
|
||||
|
||||
// Audio
|
||||
IniEntry<u8> AudioOutMode;
|
||||
@ -177,10 +178,11 @@ public:
|
||||
GSRenderMode.Init("GS_RenderMode", path);
|
||||
GSResolution.Init("GS_Resolution", path);
|
||||
GSAspectRatio.Init("GS_AspectRatio", path);
|
||||
GSVSyncEnable.Init("GS_VSyncEnable", path);
|
||||
GSLogPrograms.Init("GS_LogPrograms", path);
|
||||
GSDumpColorBuffers.Init("GS_DumpColorBuffers", path);
|
||||
GSDumpDepthBuffer.Init("GS_DumpDepthBuffer", path);
|
||||
GSVSyncEnable.Init("GS_VSyncEnable", path);
|
||||
GS3DTV.Init("GS_3DTV", path);
|
||||
|
||||
// Audio
|
||||
AudioOutMode.Init("Audio_AudioOutMode", path);
|
||||
@ -246,10 +248,11 @@ public:
|
||||
GSRenderMode.Load(1);
|
||||
GSResolution.Load(4);
|
||||
GSAspectRatio.Load(2);
|
||||
GSVSyncEnable.Load(false);
|
||||
GSLogPrograms.Load(false);
|
||||
GSDumpColorBuffers.Load(false);
|
||||
GSDumpDepthBuffer.Load(false);
|
||||
GSVSyncEnable.Load(false);
|
||||
GS3DTV.Load(false);
|
||||
|
||||
// Audio
|
||||
AudioOutMode.Load(1);
|
||||
@ -316,10 +319,11 @@ public:
|
||||
GSRenderMode.Save();
|
||||
GSResolution.Save();
|
||||
GSAspectRatio.Save();
|
||||
GSVSyncEnable.Save();
|
||||
GSLogPrograms.Save();
|
||||
GSDumpColorBuffers.Save();
|
||||
GSDumpDepthBuffer.Save();
|
||||
GSVSyncEnable.Save();
|
||||
GS3DTV.Save();
|
||||
|
||||
// Audio
|
||||
AudioOutMode.Save();
|
||||
|
@ -370,7 +370,7 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
||||
if(!phdr.p_filesz)
|
||||
break;
|
||||
|
||||
auto& proc_param = vm::get_ref<sys_process_param>(offset + phdr.p_vaddr);
|
||||
const sys_process_param& proc_param = vm::get_ref<sys_process_param>(offset + phdr.p_vaddr);
|
||||
|
||||
if (proc_param.size < sizeof(sys_process_param))
|
||||
{
|
||||
@ -400,7 +400,7 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
||||
if(!phdr.p_filesz)
|
||||
break;
|
||||
|
||||
sys_proc_prx_param proc_prx_param = vm::get_ref<sys_proc_prx_param>(offset + phdr.p_vaddr);
|
||||
const sys_proc_prx_param& proc_prx_param = vm::get_ref<sys_proc_prx_param>(offset + phdr.p_vaddr);
|
||||
|
||||
|
||||
#ifdef LOADER_DEBUG
|
||||
@ -414,21 +414,24 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
||||
LOG_NOTICE(LOADER, "*** ver: 0x%x", proc_prx_param.ver.ToLE());
|
||||
#endif
|
||||
|
||||
if (proc_prx_param.magic != 0x1b434cec) {
|
||||
if (proc_prx_param.magic != 0x1b434cec)
|
||||
{
|
||||
LOG_ERROR(LOADER, "Bad magic! (0x%x)", proc_prx_param.magic.ToLE());
|
||||
break;
|
||||
}
|
||||
|
||||
for(u32 s=proc_prx_param.libstubstart; s<proc_prx_param.libstubend; s+=sizeof(Elf64_StubHeader))
|
||||
for (u32 s = proc_prx_param.libstubstart; s < proc_prx_param.libstubend; s += sizeof(Elf64_StubHeader))
|
||||
{
|
||||
Elf64_StubHeader stub = vm::get_ref<Elf64_StubHeader>(offset + s);
|
||||
const Elf64_StubHeader& stub = vm::get_ref<Elf64_StubHeader>(offset + s);
|
||||
|
||||
const std::string module_name = vm::get_ptr<const char>(stub.s_modulename);
|
||||
Module* module = Emu.GetModuleManager().GetModuleByName(module_name);
|
||||
if (module) {
|
||||
if (module)
|
||||
{
|
||||
//module->SetLoaded();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
LOG_WARNING(LOADER, "Unknown module '%s'", module_name.c_str());
|
||||
}
|
||||
|
||||
@ -447,10 +450,10 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
||||
u64 tbl = Memory.MainMem.AllocAlign(stub.s_imports * 4 * 2);
|
||||
u64 dst = Memory.MainMem.AllocAlign(stub.s_imports * section);
|
||||
|
||||
for(u32 i=0; i<stub.s_imports; ++i)
|
||||
for (u32 i = 0; i < stub.s_imports; ++i)
|
||||
{
|
||||
const u32 nid = vm::read32(stub.s_nid + i*4);
|
||||
const u32 text = vm::read32(stub.s_text + i*4);
|
||||
const u32 nid = vm::read32(stub.s_nid + i * 4);
|
||||
const u32 text = vm::read32(stub.s_text + i * 4);
|
||||
|
||||
if (module && !module->Load(nid))
|
||||
{
|
||||
@ -471,10 +474,10 @@ bool ELF64Loader::LoadPhdrData(u64 offset)
|
||||
out_tbl[0] = (u32)dst + i*section;
|
||||
out_tbl[1] = Emu.GetModuleManager().GetFuncNumById(nid);
|
||||
|
||||
auto out_dst = vm::ptr<be_t<u32>>::make((u32)dst + i*section);
|
||||
auto out_dst = vm::ptr<be_t<u32>>::make((u32)dst + i * section);
|
||||
out_dst[0] = OR(11, 2, 2, 0);
|
||||
out_dst[1] = SC(2);
|
||||
out_dst[2] = BCLR(0x10 | 0x04, 0, 0, 0);
|
||||
out_dst[2] = BLR();
|
||||
}
|
||||
}
|
||||
#ifdef LOADER_DEBUG
|
||||
|
@ -39,6 +39,7 @@
|
||||
<ClCompile Include="..\Utilities\StrFmt.cpp" />
|
||||
<ClCompile Include="..\Utilities\Thread.cpp" />
|
||||
<ClCompile Include="Crypto\aes.cpp" />
|
||||
<ClCompile Include="Crypto\ec.cpp" />
|
||||
<ClCompile Include="Crypto\key_vault.cpp" />
|
||||
<ClCompile Include="Crypto\lz.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|Win32'">NotUsing</PrecompiledHeader>
|
||||
@ -128,6 +129,7 @@
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAdec.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAtrac.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAudio.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAvconfExt.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellBgdl.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellCamera.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellCelp8Enc.cpp" />
|
||||
@ -243,6 +245,7 @@
|
||||
<ClInclude Include="..\Utilities\Thread.h" />
|
||||
<ClInclude Include="..\Utilities\Timer.h" />
|
||||
<ClInclude Include="Crypto\aes.h" />
|
||||
<ClInclude Include="Crypto\ec.h" />
|
||||
<ClInclude Include="Crypto\key_vault.h" />
|
||||
<ClInclude Include="Crypto\lz.h" />
|
||||
<ClInclude Include="Crypto\sha1.h" />
|
||||
|
@ -131,6 +131,9 @@
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAudio.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAvconfExt.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellCamera.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
@ -347,6 +350,9 @@
|
||||
<ClCompile Include="Emu\Memory\Memory.cpp">
|
||||
<Filter>Emu\Memory</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Memory\vm.cpp">
|
||||
<Filter>Emu\Memory</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Loader\ELF.cpp">
|
||||
<Filter>Loader</Filter>
|
||||
</ClCompile>
|
||||
@ -617,8 +623,8 @@
|
||||
<ClCompile Include="..\Utilities\rXml.cpp">
|
||||
<Filter>Utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Memory\vm.cpp">
|
||||
<Filter>Emu\Memory</Filter>
|
||||
<ClCompile Include="Crypto\ec.cpp">
|
||||
<Filter>Crypto</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -724,6 +730,9 @@
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellPamf.h">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellPng.h">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellPngDec.h">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClInclude>
|
||||
@ -1210,9 +1219,6 @@
|
||||
<ClInclude Include="define_new_memleakdetect.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellPng.h">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\CB_FUNC.h">
|
||||
<Filter>Emu\SysCalls</Filter>
|
||||
</ClInclude>
|
||||
@ -1222,5 +1228,8 @@
|
||||
<ClInclude Include="Emu\Memory\atomic_type.h">
|
||||
<Filter>Emu\Memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Crypto\ec.h">
|
||||
<Filter>Crypto</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user