This is the code I modify to have it compile under windows with GCC 4.1.1
#define _LARGEFILE64_SOURCE
#define O_LARGEFILE 0100000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define OFFSET_PARTITION_1 0xFD90000ULL
#define OFFSET_FILENAME_1 (OFFSET_PARTITION_1 + 0x06AABECEAULL)
#define OFFSET_FILENAME_2 (OFFSET_PARTITION_1 + 0x06AABED06ULL)
#define OFFSET_FILENAME_3 (OFFSET_PARTITION_1 + 0x06AABED22ULL)
#define OFFSET_PAYLOAD_0 (OFFSET_PARTITION_1 + 0x087004800ULL)
#define OFFSET_SHADERS (OFFSET_PARTITION_1 + 0x09E8E8000ULL)
#define SWAP32(val) \
((unsigned int) ( \
(((unsigned int) (val) & (unsigned int) 0x000000ffU) << 24) | \
(((unsigned int) (val) & (unsigned int) 0x0000ff00U) << 8) | \
(((unsigned int) (val) & (unsigned int) 0x00ff0000U) >> 8) | \
(((unsigned int) (val) & (unsigned int) 0xff000000U) >> 24)))
void patch_filename(int fd, off64_t offset, char orig)
{
printf("patching filename at %llx...", (long long) offset); fflush(stdout);
if (lseek64(fd, offset, SEEK_SET) != offset)
{
fprintf(stderr, "seek failed: %m");
exit(1);
}
char r;
read(fd, &r, 1);
if (r != orig)
{
fprintf(stderr, "patch failed: expected %02x and found %02x\n", r, orig);
exit(1);
}
lseek64(fd, offset, SEEK_SET);
r++;
if (write(fd, &r, 1) != 1)
{
fprintf(stderr, "write failed: %m");
exit(1);
}
printf("done.\n");
}
struct bla {
unsigned char id[4];
int r0, num_files, num_shaders, nametable_off, other_off;
};
unsigned long ref[1024];
void patch_shader(int fd, off64_t offset)
{
struct bla hdr;
printf("patching shader at %llx...\n", (long long)offset);
FILE *f = fopen("shader.bin", "rb");
if (!f)
{
perror("shader.bin");
exit(1);
}
int shader_size = fread(ref, 1, 1024*4, f);
fclose(f);
printf("hack shader size: %d\n", shader_size);
if (lseek64(fd, offset, SEEK_SET) != offset)
{
fprintf(stderr, "seek failed - %m\n");
exit(1);
}
read(fd, &hdr, sizeof(hdr));
if (memcmp(hdr.id, "2BDS", 4))
{
fprintf(stderr, "incorrect shader database ID\n");
exit(1);
}
hdr.r0 = SWAP32(hdr.r0);//ntohl(hdr.r0);
hdr.num_files = SWAP32(hdr.num_files);//ntohl(hdr.num_files);
hdr.num_shaders = SWAP32(hdr.num_shaders);//ntohl(hdr.num_shaders);
hdr.nametable_off = SWAP32(hdr.nametable_off);//ntohl(hdr.nametable_off);
hdr.other_off = SWAP32(hdr.other_off);//ntohl(hdr.other_off);
lseek64(fd, offset + hdr.nametable_off, SEEK_SET);
int i;
if ((ref[0]&0xFFFFFF00) == 0x102a0e00)
for (i=0; i<shader_size/sizeof(*ref); ++i)
ref[i] = SWAP32(ref[i]);//htonl(ref[i]);
if ((ref[0]&0x00FFFFFF) != 0x000e2a10)
{
fprintf(stderr, "hack shader has wrong magic\n");
exit(1);
}
for (i=0; i<hdr.num_files; ++i)
{
struct file
{
char filename[0x3c];
int z0, z1, z2, z3, z4;
} file;
if (read(fd, &file, sizeof(file)) != sizeof(file))
break;
file.z4 = SWAP32(file.z4);//htonl(file.z4);
lseek64(fd, file.z4, SEEK_CUR);
}
lseek64(fd, offset + hdr.other_off, SEEK_SET);
printf("num shaders: %08x\n", hdr.num_shaders);
union entry_u
{
int array[9];
struct
{
int type, zero, v1, v2, v3, v4, v5, offset, len;
};
};
int shader_offset = 0, shader_len;
int shader_data[9];
int j;
for (j=0; j< hdr.num_shaders; ++j)
{
union entry_u entry;
if (read(fd, &entry, sizeof(entry)) != sizeof(entry))
break;
memcpy(shader_data, &entry, sizeof(entry));
for (i=0; i<9; ++i)
entry.array[i] = SWAP32(entry.array[i]);//ntohl(entry.array[i]);
off64_t x = lseek64(fd, 0, SEEK_CUR);
lseek64(fd, offset + entry.offset, SEEK_SET);
unsigned char hexdump[16];
read(fd, hexdump, 16);
if (entry.type == 1)
{
int l1, l2;
l1 = SWAP32(*(long*)hexdump);//htonl(*(long*)hexdump);
l2 = SWAP32(*(long*)(hexdump + 4));//htonl(*(long*)(hexdump + 4));
printf("%08x %08x\n", l1, l2);
if ((l1 >= shader_size) && (l2 >= shader_size))
{
lseek64(fd, offset + entry.offset + 8, SEEK_SET);
read(fd, hexdump, 4);
if (memcmp(hexdump, "\x10\x2A\x0E\x01", 4))
{
printf("!!! does not fit\n");
exit(1);
}
lseek64(fd, offset + entry.offset + 8 + l1, SEEK_SET);
read(fd, hexdump, 4);
if (memcmp(hexdump, "\x10\x2A\x0E\x01", 4))
{
printf("!!! does not fit\n");
exit(1);
}
if (j < 100)
{
printf("patch nr %d (%08x %08x %08x)\n", j, l1, l2, shader_size);
lseek64(fd, offset + entry.offset + 8, SEEK_SET);
write(fd, ref, shader_size);
}
shader_offset = entry.offset;
shader_len = entry.len;
}
}
lseek64(fd, x, SEEK_SET);
}
if (!shader_offset)
{
fprintf(stderr, "ouch. no suitable shader found\n");
exit(1);
}
}
int main(int argc, char **argv)
{
int fd;
if (argc != 2)
{
fprintf(stderr, "usage: %s <kk.000>\n", *argv);
return 1;
}
fd = open(argv[1], O_RDWR | O_LARGEFILE );
if (fd < 0)
{
perror(argv[1]);
return 2;
}
patch_filename(fd, OFFSET_FILENAME_1, 'U');
patch_filename(fd, OFFSET_FILENAME_2, 'U');
patch_filename(fd, OFFSET_FILENAME_3, 'W');
patch_shader(fd, OFFSET_SHADERS);
close(fd);
printf("patch ok.\n");
return 0;
}
The code compiles ok, and it should work.
I'm still not 100% sure about ntohl and htonl functions, I read the documentation and only seems to swap the bit order, so I have SWAP32 macro included as ntohl nor htonl compile under GCC for me.
Any suggestion will be appreciated.
warpjavier