Automatically seed the PIF RAM based on CIC type.

This commit is contained in:
Tyler Stachecki 2015-01-01 14:22:43 -05:00
parent 0524573137
commit 40ff6bd9ac
5 changed files with 122 additions and 9 deletions

View file

@ -74,7 +74,7 @@ struct cen64_device *device_create(struct cen64_device *device,
}
// Initialize the SI.
if (si_init(&device->si, &device->bus, pifrom->ptr) < 0) {
if (si_init(&device->si, &device->bus, pifrom->ptr, cart->ptr) < 0) {
printf("create_device: Failed to initialize the SI.\n");
return NULL;
}

86
si/cic.c Normal file
View file

@ -0,0 +1,86 @@
//
// si/cic.c: PIF CIC security/lock out algorithms.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#include "common.h"
#include "si/cic.h"
#define CIC_SEED_NUS_6101 0x00063F3FU
#define CIC_SEED_NUS_6102 0x00023F3FU
#define CIC_SEED_NUS_6103 0x0002783FU
#define CIC_SEED_NUS_6105 0x0002913FU
#define CIC_SEED_NUS_6106 0x0002853FU
#define CRC_NUS_6101 0x6170A4A1U
#define CRC_NUS_6102 0x90BB6CB5U
#define CRC_NUS_6103 0x0B050EE0U
#define CRC_NUS_6105 0x98BC2C86U
#define CRC_NUS_6106 0xACC8580AU
cen64_cold static uint32_t si_crc32(const uint8_t *data, size_t size);
// Determines the CIC seed for a cart, given the ROM data.
int get_cic_seed(const uint8_t *rom_data, uint32_t *cic_seed) {
uint32_t crc = si_crc32(rom_data + 0x40, 0x1000 - 0x40);
switch (crc) {
case CRC_NUS_6101:
*cic_seed = CIC_SEED_NUS_6101;
break;
case CRC_NUS_6102:
*cic_seed = CIC_SEED_NUS_6102;
break;
case CRC_NUS_6103:
*cic_seed = CIC_SEED_NUS_6103;
break;
case CRC_NUS_6105:
*cic_seed = CIC_SEED_NUS_6105;
break;
case CRC_NUS_6106:
*cic_seed = CIC_SEED_NUS_6106;
break;
default:
*cic_seed = 0;
return 1;
}
return 0;
}
uint32_t si_crc32(const uint8_t *data, size_t size) {
uint32_t table[256];
unsigned n, k;
uint32_t c;
for (n = 0; n < 256; n++) {
c = (uint32_t) n;
for (k = 0; k < 8; k++) {
if (c & 1)
c = 0xEDB88320L ^ (c >> 1);
else
c = c >> 1;
}
table[n] = c;
}
c = 0L ^ 0xFFFFFFFF;
for (n = 0; n < size; n++)
c = table[(c ^ data[n]) & 0xFF] ^ (c >> 8);
return c ^ 0xFFFFFFFF;
}

17
si/cic.h Normal file
View file

@ -0,0 +1,17 @@
//
// si/cic.h: PIF CIC security/lock out algorithms.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef __si_cic_h__
#define __si_cic_h__
int get_cic_seed(const uint8_t *rom_data, uint32_t *cic_seed);
#endif

View file

@ -13,6 +13,7 @@
#include "bus/controller.h"
#include "os/main.h"
#include "ri/controller.h"
#include "si/cic.h"
#include "si/controller.h"
#include "vi/controller.h"
#include "vr4300/interface.h"
@ -31,13 +32,22 @@ static int pif_perform_command(struct si_controller *si, unsigned channel,
uint8_t *send_buf, uint8_t send_bytes, uint8_t *recv_buf, uint8_t recv_bytes);
// Initializes the SI.
int si_init(struct si_controller *si,
struct bus_controller *bus, const uint8_t *rom) {
si->bus = bus;
si->rom = rom;
int si_init(struct si_controller *si, struct bus_controller *bus,
const uint8_t *pif_rom, const uint8_t *cart_rom) {
uint32_t cic_seed;
si->ram[0x26] = 0x3F;
si->ram[0x27] = 0x3F;
si->bus = bus;
si->rom = pif_rom;
if (get_cic_seed(cart_rom, &cic_seed)) {
printf("Unknown CIC type; is this a byte-swapped ROM?\n");
return 1;
}
si->ram[0x24] = cic_seed >> 24;
si->ram[0x25] = cic_seed >> 16;
si->ram[0x26] = cic_seed >> 8;
si->ram[0x27] = cic_seed >> 0;
// Specify 8MiB RDRAM for 6102/6105 carts.
if (si->ram[0x26] == 0x3F && si->ram[0x27] == 0x3F)

View file

@ -36,8 +36,8 @@ struct si_controller {
uint8_t input[4];
};
cen64_cold int si_init(struct si_controller *si,
struct bus_controller *bus, const uint8_t *rom);
cen64_cold int si_init(struct si_controller *si, struct bus_controller *bus,
const uint8_t *pif_rom, const uint8_t *cart_rom);
int read_pif_ram(void *opaque, uint32_t address, uint32_t *word);
int read_pif_rom(void *opaque, uint32_t address, uint32_t *word);