Skip to content

Instantly share code, notes, and snippets.

@balika011
Last active March 5, 2022 16:50
Show Gist options
  • Save balika011/7a2443011c3a79ea53e0b98edb905a86 to your computer and use it in GitHub Desktop.
Save balika011/7a2443011c3a79ea53e0b98edb905a86 to your computer and use it in GitHub Desktop.
PS2/PSX OSDSYS and PS2LOGO decompressor
#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