Skip to content

Commit

Permalink
WIP RDRAM initialization patch
Browse files Browse the repository at this point in the history
  • Loading branch information
Rosalie241 committed Jan 15, 2025
1 parent 817ef45 commit 2cbfff4
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 32 deletions.
12 changes: 12 additions & 0 deletions Source/3rdParty/mupen64plus-core/src/device/rcp/ri/ri_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ static osal_inline uint32_t ri_reg(uint32_t address)
return (address & 0xffff) >> 2;
}

static osal_inline uint32_t ri_address(uint32_t address)
{
/* https://n64brew.dev/wiki/RDRAM_Interface#Memory_addressing */
return (((address >> 20) == 0x03f)
? (((address & 0x3FF))) | /* Adr[10:0] */
(((address >> 10) & 0x1FF) << 11) | /* Adr[19:11] */
(((address >> 10) & 0x1FF) << 20) /* Adr[28:20] */
: (((address & 0x7FF))) | /* Adr[10:0] */
(((address >> 11) & 0x1FF) << 11) | /* Adr[19:11] */
(((address >> 20) & 0x3F) << 20)); /* Adr[28:20] */
}

static osal_inline uint16_t ri_address_to_id_field(uint32_t address)
{
/* XXX: pure guessing, need harware test */
Expand Down
74 changes: 42 additions & 32 deletions Source/3rdParty/mupen64plus-core/src/device/rdram/rdram.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <string.h>

#define RDRAM_BCAST_ADDRESS_MASK UINT32_C(0x00080000)

#define RDRAM_MODE_CE_MASK UINT32_C(0x80000000)

/* XXX: deduce # of RDRAM modules from it's total size
* Assume only 2Mo RDRAM modules.
Expand Down Expand Up @@ -59,19 +59,32 @@ static osal_inline uint16_t idfield_value(uint32_t device_id)
{
return ((((device_id >> 26) & 0x3f) << 0)
| (((device_id >> 23) & 0x01) << 6)
| (((device_id >> 16) & 0xff) << 7)
| (((device_id >> 8) & 0xff) << 7)
| (((device_id >> 7) & 0x01) << 15));
}

static osal_inline uint8_t swapfield_value(uint32_t address_select)
{
return ((((address_select >> 25) & 0x7F) << 0)
| (((address_select >> 15) & 0x01) << 7));
}

static osal_inline uint16_t ri_address_to_idfield(uint32_t address, uint8_t swapfield)
{
/* https://n64brew.dev/wiki/RDRAM#RDRAM_addressing */
return (((swapfield & ((address >> 11) & 0x1FF)))
| ((~swapfield & ((address >> 20) & 0x1FF)))); /* AdrS[28:20] */
}

static size_t get_module(const struct rdram* rdram, uint32_t address)
{
size_t module;
size_t modules = get_modules_count(rdram);
uint16_t id_field = ri_address_to_id_field(address);

uint16_t id_field;

for (module = 0; module < modules; ++module) {
if (id_field == idfield_value(rdram->regs[module][RDRAM_DEVICE_ID_REG])) {
id_field = ri_address_to_idfield(ri_address(address), swapfield_value(rdram->regs[module][RDRAM_ADDR_SELECT_REG]));
if ((id_field & 0xFFFE) == (idfield_value(rdram->regs[module][RDRAM_DEVICE_ID_REG]) & 0xFFFE)) {
return module;
}
}
Expand All @@ -87,8 +100,6 @@ static void read_rdram_dram_corrupted(void* opaque, uint32_t address, uint32_t*
uint32_t addr = rdram_dram_address(address);
size_t module;

*value = rdram->dram[addr];

module = get_module(rdram, address);
if (module == RDRAM_MAX_MODULES_COUNT) {
*value = 0;
Expand All @@ -97,7 +108,14 @@ static void read_rdram_dram_corrupted(void* opaque, uint32_t address, uint32_t*

/* corrupt read value if CC value is not calibrated */
uint32_t mode = rdram->regs[module][RDRAM_MODE_REG] ^ UINT32_C(0xc0c0c0c0);
if ((mode & 0x80000000) && (cc_value(mode) == 0)) {
if ((mode & RDRAM_MODE_CE_MASK) && (cc_value(mode) == 0)) {
*value = 0;
return;
}

if (address < rdram->dram_size) {
*value = rdram->dram[addr];
} else {
*value = 0;
}
}
Expand Down Expand Up @@ -131,6 +149,7 @@ void init_rdram(struct rdram* rdram,
rdram->dram = dram;
rdram->dram_size = dram_size;
rdram->r4300 = r4300;
rdram->corrupted_handler = 0;
}

void poweron_rdram(struct rdram* rdram)
Expand Down Expand Up @@ -185,33 +204,11 @@ void write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t m
{
struct rdram* rdram = (struct rdram*)opaque;
uint32_t reg = rdram_reg(address);
uint32_t mode;
uint8_t corrupted_handler = 0;
size_t module;
size_t modules = get_modules_count(rdram);

/* HACK: Detect when current Control calibration is about to start,
* so we can set corrupted rdram_dram handler
*/
if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_DELAY_REG) {
map_corrupt_rdram(rdram, 1);
}

/* HACK: Detect when current Control calibration is over,
* so we can restore the original rdram_dram handler
* and let dynarec have it's fast_memory enabled.
*/
if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_MODE_REG) {
map_corrupt_rdram(rdram, 0);

/* HACK: In the IPL3 procedure, at this point,
* the amount of detected memory can be found in s4 */
size_t ipl3_rdram_size = r4300_regs(rdram->r4300)[20] & UINT32_C(0x0fffffff);
if (ipl3_rdram_size != rdram->dram_size) {
DebugMessage(M64MSG_WARNING, "IPL3 detected %u MB of RDRAM != %u MB",
(uint32_t) ipl3_rdram_size / (1024*1024), (uint32_t) rdram->dram_size / (1024*1024));
}
}


if (address & RDRAM_BCAST_ADDRESS_MASK) {
for (module = 0; module < modules; ++module) {
masked_write(&rdram->regs[module][reg], value, mask);
Expand All @@ -223,6 +220,19 @@ void write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t m
masked_write(&rdram->regs[module][reg], value, mask);
}
}

/* toggle corrupt handler based on CC value for all modules,
* only check values when writing to the mode register */
if (reg == RDRAM_MODE_REG) {
for (module = 0; module < modules; ++module) {
mode = rdram->regs[module][RDRAM_MODE_REG] ^ UINT32_C(0xc0c0c0c0);
corrupted_handler |= ((mode & RDRAM_MODE_CE_MASK) && (cc_value(mode) == 0));
}
if (rdram->corrupted_handler != corrupted_handler) {
map_corrupt_rdram(rdram, corrupted_handler);
rdram->corrupted_handler = corrupted_handler;
}
}
}


Expand Down
2 changes: 2 additions & 0 deletions Source/3rdParty/mupen64plus-core/src/device/rdram/rdram.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ struct rdram
uint32_t* dram;
size_t dram_size;

uint8_t corrupted_handler;

struct r4300_core* r4300;
};

Expand Down

0 comments on commit 2cbfff4

Please sign in to comment.