Last active
March 5, 2022 16:50
-
-
Save balika011/7a2443011c3a79ea53e0b98edb905a86 to your computer and use it in GitHub Desktop.
PS2/PSX OSDSYS and PS2LOGO decompressor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <elf.h> | |
#include <string.h> | |
uint8_t *findDataSegment(uint8_t *buf) | |
{ | |
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) buf; | |
Elf32_Shdr *shdr = (Elf32_Shdr *)&buf[ehdr->e_shoff]; | |
uint8_t *strtab = 0; | |
for (int i = 0; i < ehdr->e_shnum; i++) | |
{ | |
if (shdr[i].sh_type == SHT_STRTAB) | |
{ | |
strtab = &buf[shdr[i].sh_offset]; | |
break; | |
} | |
} | |
if (strtab) | |
{ | |
for (int i = 0; i < ehdr->e_shnum; i++) | |
{ | |
if (strcmp(".data", (char *) &strtab[shdr[i].sh_name]) == 0) | |
return &buf[shdr[i].sh_offset]; | |
} | |
} | |
return nullptr; | |
} | |
void lzDecompress(uint8_t *dest, uint8_t *source, uint32_t dest_size) | |
{ | |
uint8_t *ptr = dest; | |
uint32_t flag = 0, count = 0, mask = 0, shift = 0; | |
while(ptr - dest < dest_size) | |
{ | |
if (count == 0) | |
{ | |
count = 30; | |
flag = __builtin_bswap32(*(uint32_t *) source); | |
source += 4; | |
mask = 0x3fff >> (flag & 3); | |
shift = 14 - (flag & 3); | |
} | |
if (flag & 0x80000000) | |
{ | |
uint16_t off_size = __builtin_bswap16(*(uint16_t *) source); | |
source += 2; | |
uint16_t offset = (off_size & mask) + 1; | |
for (uint16_t i = (off_size >> shift) + 3; i > 0; i--) | |
*(ptr++) = *(ptr - offset); | |
} | |
else | |
*(ptr++) = *(source++); | |
count--; | |
flag <<= 1; | |
} | |
} | |
int main(int argc, char ** argv) | |
{ | |
if (argc != 3) | |
{ | |
printf("Usage: %s <OSDSYS> <output>\n", argv[0]); | |
return -1; | |
} | |
FILE *f = fopen(argv[1], "rb"); | |
fseek(f, 0, SEEK_END); | |
int len = ftell(f); | |
fseek(f, 0, SEEK_SET); | |
uint8_t *buf = new uint8_t[len]; | |
fread(buf, 1, len, f); | |
fclose(f); | |
uint8_t *data = findDataSegment(buf); | |
if (!data) | |
{ | |
printf(".data segment is not found!\n"); | |
return -1; | |
} | |
uint32_t uncompressed_len = *(uint32_t *) data; | |
uint8_t *unpacked = new uint8_t[uncompressed_len]; | |
lzDecompress(unpacked, &data[4], uncompressed_len); | |
delete [] buf; | |
FILE *fo = fopen(argv[2], "wb"); | |
fwrite(unpacked, 1, uncompressed_len, fo); | |
fclose(fo); | |
delete [] unpacked; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment