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/bios/bios.c
|
||||
src/guest/bios/flash.c
|
||||
src/guest/bios/scramble.c
|
||||
src/guest/bios/syscalls.c
|
||||
src/guest/gdrom/cdi.c
|
||||
src/guest/gdrom/chd.c
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "guest/aica/aica.h"
|
||||
#include "guest/bios/bios.h"
|
||||
#include "guest/bios/flash.h"
|
||||
#include "guest/bios/scramble.h"
|
||||
#include "guest/bios/syscalls.h"
|
||||
#include "guest/dreamcast.h"
|
||||
#include "guest/gdrom/gdrom.h"
|
||||
|
@ -285,6 +286,18 @@ void bios_boot(struct bios *bios) {
|
|||
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);
|
||||
free(tmp);
|
||||
}
|
||||
|
@ -319,7 +332,7 @@ void bios_boot(struct bios *bios) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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/bios.h"
|
||||
#include "guest/bios/flash.h"
|
||||
#include "guest/bios/scramble.h"
|
||||
#include "guest/gdrom/gdrom.h"
|
||||
#include "guest/holly/holly.h"
|
||||
#include "guest/memory.h"
|
||||
|
@ -29,6 +30,7 @@ enum {
|
|||
|
||||
void bios_system_vector(struct bios *bios) {
|
||||
struct dreamcast *dc = bios->dc;
|
||||
struct gdrom *gd = dc->gdrom;
|
||||
struct sh4_context *ctx = &dc->sh4->ctx;
|
||||
|
||||
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) {
|
||||
struct dreamcast *dc = bios->dc;
|
||||
struct gdrom *gd = dc->gdrom;
|
||||
struct holly *hl = dc->holly;
|
||||
|
||||
if (bios->status != GDC_STATUS_ACTIVE) {
|
||||
return;
|
||||
|
@ -265,7 +268,8 @@ static void bios_gdrom_mainloop(struct bios *bios) {
|
|||
} break;
|
||||
|
||||
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;
|
||||
|
||||
case GDC_SEEK: {
|
||||
|
|
Loading…
Reference in New Issue