mirror of https://github.com/inolen/redream.git
unscramble bootfile of CD-ROM XA discs during HLE bootstrap
This commit is contained in:
parent
b7cb524c02
commit
c618cd595c
|
@ -207,6 +207,7 @@ set(RELIB_SOURCES
|
||||||
src/guest/arm7/arm7.c
|
src/guest/arm7/arm7.c
|
||||||
src/guest/bios/bios.c
|
src/guest/bios/bios.c
|
||||||
src/guest/bios/flash.c
|
src/guest/bios/flash.c
|
||||||
|
src/guest/bios/scramble.c
|
||||||
src/guest/bios/syscalls.c
|
src/guest/bios/syscalls.c
|
||||||
src/guest/gdrom/cdi.c
|
src/guest/gdrom/cdi.c
|
||||||
src/guest/gdrom/chd.c
|
src/guest/gdrom/chd.c
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "guest/aica/aica.h"
|
#include "guest/aica/aica.h"
|
||||||
#include "guest/bios/bios.h"
|
#include "guest/bios/bios.h"
|
||||||
#include "guest/bios/flash.h"
|
#include "guest/bios/flash.h"
|
||||||
|
#include "guest/bios/scramble.h"
|
||||||
#include "guest/bios/syscalls.h"
|
#include "guest/bios/syscalls.h"
|
||||||
#include "guest/dreamcast.h"
|
#include "guest/dreamcast.h"
|
||||||
#include "guest/gdrom/gdrom.h"
|
#include "guest/gdrom/gdrom.h"
|
||||||
|
@ -285,6 +286,18 @@ void bios_boot(struct bios *bios) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CD-ROM XA discs have their binary scrambled. the bios descrambles this
|
||||||
|
later on in the boot, but it should be fine to descramble now */
|
||||||
|
struct gd_status_info stat;
|
||||||
|
gdrom_get_status(gd, &stat);
|
||||||
|
|
||||||
|
if (stat.format == GD_DISC_CDROM_XA) {
|
||||||
|
uint8_t *tmp2 = malloc(len);
|
||||||
|
descramble(tmp2, tmp, len);
|
||||||
|
free(tmp);
|
||||||
|
tmp = tmp2;
|
||||||
|
}
|
||||||
|
|
||||||
sh4_memcpy_to_guest(dc->mem, BOOT2_ADDR, tmp, read);
|
sh4_memcpy_to_guest(dc->mem, BOOT2_ADDR, tmp, read);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
@ -319,7 +332,7 @@ void bios_boot(struct bios *bios) {
|
||||||
sh4_write32(dc->mem, VECTOR_SYSTEM, SYSCALL_SYSTEM);
|
sh4_write32(dc->mem, VECTOR_SYSTEM, SYSCALL_SYSTEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start executing at license screen code inside of ip.bin */
|
/* start executing at license screen code inside of IP.BIN */
|
||||||
ctx->pc = 0xac008300;
|
ctx->pc = 0xac008300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
#include "guest/bios/scramble.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
|
||||||
|
#define MIN_CHUNK_SIZE 32
|
||||||
|
#define MAX_CHUNK_SIZE (2048 * 1024)
|
||||||
|
|
||||||
|
#define MAX_SLICES (MAX_CHUNK_SIZE / MIN_CHUNK_SIZE)
|
||||||
|
|
||||||
|
static int scramble_init(int n) {
|
||||||
|
return n & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scramble_next(int *seed, int i) {
|
||||||
|
unsigned key;
|
||||||
|
*seed = (*seed * 2109 + 9273) & 0x7fff;
|
||||||
|
key = (*seed + 0xc000) & 0xffff;
|
||||||
|
return ((unsigned)i * (unsigned)key) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void descramble_chunk(int *seed, uint8_t *dst, const uint8_t *src,
|
||||||
|
int size) {
|
||||||
|
CHECK((size % MIN_CHUNK_SIZE) == 0 && size <= MAX_CHUNK_SIZE);
|
||||||
|
|
||||||
|
/* descramble each chunk in MIN_CHUNK_SIZE slices */
|
||||||
|
size /= MIN_CHUNK_SIZE;
|
||||||
|
|
||||||
|
/* lookup table maps scrambled slice index to descrambled index */
|
||||||
|
int table[MAX_SLICES];
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
table[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = size - 1; i >= 0; i--) {
|
||||||
|
int x = scramble_next(seed, i);
|
||||||
|
|
||||||
|
/* swap table index */
|
||||||
|
int tmp = table[i];
|
||||||
|
table[i] = table[x];
|
||||||
|
table[x] = tmp;
|
||||||
|
|
||||||
|
/* write slice out to descrambled index */
|
||||||
|
memcpy(dst + MIN_CHUNK_SIZE * table[i], src, MIN_CHUNK_SIZE);
|
||||||
|
src += MIN_CHUNK_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void descramble(uint8_t *dst, const uint8_t *src, int size) {
|
||||||
|
int seed = scramble_init(size);
|
||||||
|
|
||||||
|
/* descramble the data starting with the largest chunk size (2mb) */
|
||||||
|
int chunk_size = MAX_CHUNK_SIZE;
|
||||||
|
|
||||||
|
while (chunk_size >= MIN_CHUNK_SIZE) {
|
||||||
|
/* continue descrambling with the current chunk size until the remaining
|
||||||
|
data is too small */
|
||||||
|
while (size >= chunk_size) {
|
||||||
|
descramble_chunk(&seed, dst, src, chunk_size);
|
||||||
|
size -= chunk_size;
|
||||||
|
dst += chunk_size;
|
||||||
|
src += chunk_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to use the the next smallest chunk size */
|
||||||
|
chunk_size >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* any remaining data isn't scrambled, just copy it */
|
||||||
|
if (size) {
|
||||||
|
memcpy(dst, src, size);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef SCRAMBLE_H
|
||||||
|
#define SCRAMBLE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void descramble(uint8_t *dst, const uint8_t *src, int size);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,6 +1,7 @@
|
||||||
#include "guest/bios/syscalls.h"
|
#include "guest/bios/syscalls.h"
|
||||||
#include "guest/bios/bios.h"
|
#include "guest/bios/bios.h"
|
||||||
#include "guest/bios/flash.h"
|
#include "guest/bios/flash.h"
|
||||||
|
#include "guest/bios/scramble.h"
|
||||||
#include "guest/gdrom/gdrom.h"
|
#include "guest/gdrom/gdrom.h"
|
||||||
#include "guest/holly/holly.h"
|
#include "guest/holly/holly.h"
|
||||||
#include "guest/memory.h"
|
#include "guest/memory.h"
|
||||||
|
@ -29,6 +30,7 @@ enum {
|
||||||
|
|
||||||
void bios_system_vector(struct bios *bios) {
|
void bios_system_vector(struct bios *bios) {
|
||||||
struct dreamcast *dc = bios->dc;
|
struct dreamcast *dc = bios->dc;
|
||||||
|
struct gdrom *gd = dc->gdrom;
|
||||||
struct sh4_context *ctx = &dc->sh4->ctx;
|
struct sh4_context *ctx = &dc->sh4->ctx;
|
||||||
|
|
||||||
uint32_t fn = ctx->r[4];
|
uint32_t fn = ctx->r[4];
|
||||||
|
@ -138,6 +140,7 @@ static uint32_t bios_gdrom_send_cmd(struct bios *bios, uint32_t cmd_code,
|
||||||
static void bios_gdrom_mainloop(struct bios *bios) {
|
static void bios_gdrom_mainloop(struct bios *bios) {
|
||||||
struct dreamcast *dc = bios->dc;
|
struct dreamcast *dc = bios->dc;
|
||||||
struct gdrom *gd = dc->gdrom;
|
struct gdrom *gd = dc->gdrom;
|
||||||
|
struct holly *hl = dc->holly;
|
||||||
|
|
||||||
if (bios->status != GDC_STATUS_ACTIVE) {
|
if (bios->status != GDC_STATUS_ACTIVE) {
|
||||||
return;
|
return;
|
||||||
|
@ -265,7 +268,8 @@ static void bios_gdrom_mainloop(struct bios *bios) {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GDC_INIT: {
|
case GDC_INIT: {
|
||||||
/* this seems to always immediately follow GDROM_INIT */
|
/* sanity check in case dma transfers are made async in the future */
|
||||||
|
CHECK_EQ(*hl->SB_GDST, 0);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GDC_SEEK: {
|
case GDC_SEEK: {
|
||||||
|
|
Loading…
Reference in New Issue