Skip to content

Instantly share code, notes, and snippets.

@simontime
Created June 20, 2020 15:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simontime/2148541141a6d91c0165b695b160d4d3 to your computer and use it in GitHub Desktop.
Save simontime/2148541141a6d91c0165b695b160d4d3 to your computer and use it in GitHub Desktop.
Scans through a ROM and decompresses all Yay0 data found inside.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef _MSC_VER
#define __builtin_bswap32(x) _byteswap_ulong(x)
#endif
typedef struct
{
uint32_t magic;
uint32_t uncompressedLength;
uint32_t opPtr;
uint32_t dataPtr;
} Yay0Header;
uint32_t Yay0Uncompress(uint8_t *src, uint8_t **dst)
{
uint8_t byte = 0, mask = 0;
uint8_t *ctrl, *ops, *data, *dstPtr;
uint16_t copy, op;
uint32_t written = 0, length;
Yay0Header *hdr;
hdr = (Yay0Header *)src;
length = __builtin_bswap32(hdr->uncompressedLength);
dstPtr = *dst = malloc(length);
ctrl = src + sizeof(Yay0Header);
ops = src + __builtin_bswap32(hdr->opPtr);
data = src + __builtin_bswap32(hdr->dataPtr);
while (written < length)
{
if ((mask >>= 1) == 0)
{
byte = *ctrl++;
mask = 0x80;
}
if (byte & mask)
{
*dstPtr++ = *data++;
written++;
}
else
{
op = (ops[0] << 8) | ops[1];
ops += 2;
written += copy = (op >> 12) ? (2 + (op >> 12)) : (18 + *data++);
while (copy--)
*dstPtr++ = dstPtr[-(op & 0xfff) - 1];
}
}
return written;
}
int main(int argc, char **argv)
{
char fn[256];
uint8_t *inBuf, *inStart, *inEnd, *outBuf;
FILE *in, *out;
long inLen, bufLen;
if (argc != 2)
{
printf("Usage: %s ROM\n", argv[0]);
return 0;
}
if ((in = fopen(argv[1], "rb")) == NULL)
{
perror("Error opening ROM");
return 1;
}
fseek(in, 0, SEEK_END);
inLen = ftell(in);
inStart = inBuf = malloc(inLen);
rewind(in);
fread(inBuf, 1, inLen, in);
fclose(in);
inEnd = inBuf + inLen;
while (inBuf < inEnd)
{
if (*(uint32_t *)inBuf == 0x30796159)
{
sprintf(fn, "%08x.bin", (uint32_t)(inBuf - inStart));
out = fopen(fn, "wb");
printf("Extracting %s...\n", fn);
bufLen = Yay0Uncompress(inBuf, &outBuf);
fwrite(outBuf, 1, bufLen, out);
fclose(out);
free(outBuf);
}
inBuf++;
}
free(inStart);
puts("\nDone!");
return 0;
}
@simontime
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment