31
31
#include <string.h>
32
32
33
33
#define RDRAM_BCAST_ADDRESS_MASK UINT32_C(0x00080000)
34
-
34
+ #define RDRAM_MODE_CE_MASK UINT32_C(0x80000000)
35
35
36
36
/* XXX: deduce # of RDRAM modules from it's total size
37
37
* Assume only 2Mo RDRAM modules.
@@ -59,19 +59,32 @@ static osal_inline uint16_t idfield_value(uint32_t device_id)
59
59
{
60
60
return ((((device_id >> 26 ) & 0x3f ) << 0 )
61
61
| (((device_id >> 23 ) & 0x01 ) << 6 )
62
- | (((device_id >> 16 ) & 0xff ) << 7 )
62
+ | (((device_id >> 8 ) & 0xff ) << 7 )
63
63
| (((device_id >> 7 ) & 0x01 ) << 15 ));
64
64
}
65
65
66
+ static osal_inline uint8_t swapfield_value (uint32_t address_select )
67
+ {
68
+ return ((((address_select >> 25 ) & 0x7F ) << 0 )
69
+ | (((address_select >> 15 ) & 0x01 ) << 7 ));
70
+ }
71
+
72
+ static osal_inline uint16_t ri_address_to_idfield (uint32_t address , uint8_t swapfield )
73
+ {
74
+ /* https://n64brew.dev/wiki/RDRAM#RDRAM_addressing */
75
+ return (((swapfield & ((address >> 11 ) & 0x1FF )))
76
+ | ((~swapfield & ((address >> 20 ) & 0x1FF )))); /* AdrS[28:20] */
77
+ }
78
+
66
79
static size_t get_module (const struct rdram * rdram , uint32_t address )
67
80
{
68
81
size_t module ;
69
82
size_t modules = get_modules_count (rdram );
70
- uint16_t id_field = ri_address_to_id_field (address );
71
-
83
+ uint16_t id_field ;
72
84
73
85
for (module = 0 ; module < modules ; ++ module ) {
74
- if (id_field == idfield_value (rdram -> regs [module ][RDRAM_DEVICE_ID_REG ])) {
86
+ id_field = ri_address_to_idfield (ri_address (address ), swapfield_value (rdram -> regs [module ][RDRAM_ADDR_SELECT_REG ]));
87
+ if ((id_field & 0xFFFE ) == (idfield_value (rdram -> regs [module ][RDRAM_DEVICE_ID_REG ]) & 0xFFFE )) {
75
88
return module ;
76
89
}
77
90
}
@@ -87,8 +100,6 @@ static void read_rdram_dram_corrupted(void* opaque, uint32_t address, uint32_t*
87
100
uint32_t addr = rdram_dram_address (address );
88
101
size_t module ;
89
102
90
- * value = rdram -> dram [addr ];
91
-
92
103
module = get_module (rdram , address );
93
104
if (module == RDRAM_MAX_MODULES_COUNT ) {
94
105
* value = 0 ;
@@ -97,7 +108,14 @@ static void read_rdram_dram_corrupted(void* opaque, uint32_t address, uint32_t*
97
108
98
109
/* corrupt read value if CC value is not calibrated */
99
110
uint32_t mode = rdram -> regs [module ][RDRAM_MODE_REG ] ^ UINT32_C (0xc0c0c0c0 );
100
- if ((mode & 0x80000000 ) && (cc_value (mode ) == 0 )) {
111
+ if ((mode & RDRAM_MODE_CE_MASK ) && (cc_value (mode ) == 0 )) {
112
+ * value = 0 ;
113
+ return ;
114
+ }
115
+
116
+ if (address < rdram -> dram_size ) {
117
+ * value = rdram -> dram [addr ];
118
+ } else {
101
119
* value = 0 ;
102
120
}
103
121
}
@@ -131,6 +149,7 @@ void init_rdram(struct rdram* rdram,
131
149
rdram -> dram = dram ;
132
150
rdram -> dram_size = dram_size ;
133
151
rdram -> r4300 = r4300 ;
152
+ rdram -> corrupted_handler = 0 ;
134
153
}
135
154
136
155
void poweron_rdram (struct rdram * rdram )
@@ -185,33 +204,11 @@ void write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t m
185
204
{
186
205
struct rdram * rdram = (struct rdram * )opaque ;
187
206
uint32_t reg = rdram_reg (address );
207
+ uint32_t mode ;
208
+ uint8_t corrupted_handler = 0 ;
188
209
size_t module ;
189
210
size_t modules = get_modules_count (rdram );
190
211
191
- /* HACK: Detect when current Control calibration is about to start,
192
- * so we can set corrupted rdram_dram handler
193
- */
194
- if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_DELAY_REG ) {
195
- map_corrupt_rdram (rdram , 1 );
196
- }
197
-
198
- /* HACK: Detect when current Control calibration is over,
199
- * so we can restore the original rdram_dram handler
200
- * and let dynarec have it's fast_memory enabled.
201
- */
202
- if (address & RDRAM_BCAST_ADDRESS_MASK && reg == RDRAM_MODE_REG ) {
203
- map_corrupt_rdram (rdram , 0 );
204
-
205
- /* HACK: In the IPL3 procedure, at this point,
206
- * the amount of detected memory can be found in s4 */
207
- size_t ipl3_rdram_size = r4300_regs (rdram -> r4300 )[20 ] & UINT32_C (0x0fffffff );
208
- if (ipl3_rdram_size != rdram -> dram_size ) {
209
- DebugMessage (M64MSG_WARNING , "IPL3 detected %u MB of RDRAM != %u MB" ,
210
- (uint32_t ) ipl3_rdram_size / (1024 * 1024 ), (uint32_t ) rdram -> dram_size / (1024 * 1024 ));
211
- }
212
- }
213
-
214
-
215
212
if (address & RDRAM_BCAST_ADDRESS_MASK ) {
216
213
for (module = 0 ; module < modules ; ++ module ) {
217
214
masked_write (& rdram -> regs [module ][reg ], value , mask );
@@ -223,6 +220,19 @@ void write_rdram_regs(void* opaque, uint32_t address, uint32_t value, uint32_t m
223
220
masked_write (& rdram -> regs [module ][reg ], value , mask );
224
221
}
225
222
}
223
+
224
+ /* toggle corrupt handler based on CC value for all modules,
225
+ * only check values when writing to the mode register */
226
+ if (reg == RDRAM_MODE_REG ) {
227
+ for (module = 0 ; module < modules ; ++ module ) {
228
+ mode = rdram -> regs [module ][RDRAM_MODE_REG ] ^ UINT32_C (0xc0c0c0c0 );
229
+ corrupted_handler |= ((mode & RDRAM_MODE_CE_MASK ) && (cc_value (mode ) == 0 ));
230
+ }
231
+ if (rdram -> corrupted_handler != corrupted_handler ) {
232
+ map_corrupt_rdram (rdram , corrupted_handler );
233
+ rdram -> corrupted_handler = corrupted_handler ;
234
+ }
235
+ }
226
236
}
227
237
228
238
0 commit comments