RICE: OOT Fix from mupen64plus-ae team
[mupen64plus-pandora.git] / source / mupen64plus-core / src / memory / dma.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - dma.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2002 Hacktarux *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25
26#include "api/m64p_types.h"
27
28#include "dma.h"
29#include "memory.h"
30#include "pif.h"
31#include "flashram.h"
32
33#include "r4300/r4300.h"
34#include "r4300/interupt.h"
35#include "r4300/macros.h"
36#include "r4300/ops.h"
37#include "../r4300/new_dynarec/new_dynarec.h"
38
39#define M64P_CORE_PROTOTYPES 1
40#include "api/m64p_config.h"
41#include "api/config.h"
42#include "api/callbacks.h"
43#include "main/main.h"
44#include "main/rom.h"
45#include "main/util.h"
46
47static unsigned char sram[0x8000];
48
49static char *get_sram_path(void)
50{
51 return formatstr("%s%s.sra", get_savesrampath(), ROM_SETTINGS.goodname);
52}
53
54static void sram_format(void)
55{
56 memset(sram, 0, sizeof(sram));
57}
58
59static void sram_read_file(void)
60{
61 char *filename = get_sram_path();
62
63 sram_format();
64 switch (read_from_file(filename, sram, sizeof(sram)))
65 {
66 case file_open_error:
67 DebugMessage(M64MSG_VERBOSE, "couldn't open sram file '%s' for reading", filename);
68 sram_format();
69 break;
70 case file_read_error:
71 DebugMessage(M64MSG_WARNING, "fread() failed on 32kb read from sram file '%s'", filename);
72 sram_format();
73 break;
74 default: break;
75 }
76
77 free(filename);
78}
79
80static void sram_write_file(void)
81{
82 char *filename = get_sram_path();
83
84 switch (write_to_file(filename, sram, sizeof(sram)))
85 {
86 case file_open_error:
87 DebugMessage(M64MSG_WARNING, "couldn't open sram file '%s' for writing.", filename);
88 break;
89 case file_write_error:
90 DebugMessage(M64MSG_WARNING, "fwrite() failed on 32kb write to sram file '%s'", filename);
91 break;
92 default: break;
93 }
94
95 free(filename);
96}
97
98void dma_pi_read(void)
99{
100 unsigned int i;
101
102 if (pi_register.pi_cart_addr_reg >= 0x08000000
103 && pi_register.pi_cart_addr_reg < 0x08010000)
104 {
105 if (flashram_info.use_flashram != 1)
106 {
107 sram_read_file();
108
109 for (i=0; i < (pi_register.pi_rd_len_reg & 0xFFFFFF)+1; i++)
110 {
111 sram[((pi_register.pi_cart_addr_reg-0x08000000)+i)^S8] =
112 ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8];
113 }
114
115 sram_write_file();
116
117 flashram_info.use_flashram = -1;
118 }
119 else
120 {
121 dma_write_flashram();
122 }
123 }
124 else
125 {
126 DebugMessage(M64MSG_WARNING, "Unknown dma read in dma_pi_read()");
127 }
128
129 pi_register.read_pi_status_reg |= 1;
130 update_count();
131 add_interupt_event(PI_INT, 0x1000/*pi_register.pi_rd_len_reg*/);
132}
133
134void dma_pi_write(void)
135{
136 unsigned int longueur;
137 int i;
138
139 if (pi_register.pi_cart_addr_reg < 0x10000000)
140 {
141 if (pi_register.pi_cart_addr_reg >= 0x08000000
142 && pi_register.pi_cart_addr_reg < 0x08010000)
143 {
144 if (flashram_info.use_flashram != 1)
145 {
146 int i;
147
148 sram_read_file();
149
150 for (i=0; i<(int)(pi_register.pi_wr_len_reg & 0xFFFFFF)+1; i++)
151 {
152 ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
153 sram[(((pi_register.pi_cart_addr_reg-0x08000000)&0xFFFF)+i)^S8];
154 }
155
156 flashram_info.use_flashram = -1;
157 }
158 else
159 {
160 dma_read_flashram();
161 }
162 }
163 else if (pi_register.pi_cart_addr_reg >= 0x06000000
164 && pi_register.pi_cart_addr_reg < 0x08000000)
165 {
166 }
167 else
168 {
169 DebugMessage(M64MSG_WARNING, "Unknown dma write 0x%x in dma_pi_write()", (int)pi_register.pi_cart_addr_reg);
170 }
171
172 pi_register.read_pi_status_reg |= 1;
173 update_count();
174 add_interupt_event(PI_INT, /*pi_register.pi_wr_len_reg*/0x1000);
175
176 return;
177 }
178
179 if (pi_register.pi_cart_addr_reg >= 0x1fc00000) // for paper mario
180 {
181 pi_register.read_pi_status_reg |= 1;
182 update_count();
183 add_interupt_event(PI_INT, 0x1000);
184
185 return;
186 }
187
188 longueur = (pi_register.pi_wr_len_reg & 0xFFFFFF)+1;
189 i = (pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF;
190 longueur = (i + (int) longueur) > rom_size ?
191 (rom_size - i) : longueur;
192 longueur = (pi_register.pi_dram_addr_reg + longueur) > 0x7FFFFF ?
193 (0x7FFFFF - pi_register.pi_dram_addr_reg) : longueur;
194
195 if (i>rom_size || pi_register.pi_dram_addr_reg > 0x7FFFFF)
196 {
197 pi_register.read_pi_status_reg |= 3;
198 update_count();
199 add_interupt_event(PI_INT, longueur/8);
200
201 return;
202 }
203
204 if (r4300emu != CORE_PURE_INTERPRETER)
205 {
206 for (i=0; i<(int)longueur; i++)
207 {
208 unsigned long rdram_address1 = pi_register.pi_dram_addr_reg+i+0x80000000;
209 unsigned long rdram_address2 = pi_register.pi_dram_addr_reg+i+0xa0000000;
210 ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
211 rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
212
213 if (!invalid_code[rdram_address1>>12])
214 {
215 if (!blocks[rdram_address1>>12] ||
216 blocks[rdram_address1>>12]->block[(rdram_address1&0xFFF)/4].ops !=
217 current_instruction_table.NOTCOMPILED)
218 {
219 invalid_code[rdram_address1>>12] = 1;
220 }
221#ifdef NEW_DYNAREC
222 invalidate_block(rdram_address1>>12);
223#endif
224 }
225 if (!invalid_code[rdram_address2>>12])
226 {
227 if (!blocks[rdram_address1>>12] ||
228 blocks[rdram_address2>>12]->block[(rdram_address2&0xFFF)/4].ops !=
229 current_instruction_table.NOTCOMPILED)
230 {
231 invalid_code[rdram_address2>>12] = 1;
232 }
233 }
234 }
235 }
236 else
237 {
238 for (i=0; i<(int)longueur; i++)
239 {
240 ((unsigned char*)rdram)[(pi_register.pi_dram_addr_reg+i)^S8]=
241 rom[(((pi_register.pi_cart_addr_reg-0x10000000)&0x3FFFFFF)+i)^S8];
242 }
243 }
244
245 // Set the RDRAM memory size when copying main ROM code
246 // (This is just a convenient way to run this code once at the beginning)
247 if (pi_register.pi_cart_addr_reg == 0x10001000)
248 {
249 switch (CIC_Chip)
250 {
251 case 1:
252 case 2:
253 case 3:
254 case 6:
255 {
256 if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
257 {
258 rdram[0x318/4] = 0x400000;
259 }
260 else
261 {
262 rdram[0x318/4] = 0x800000;
263 }
264 break;
265 }
266 case 5:
267 {
268 if (ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"))
269 {
270 rdram[0x3F0/4] = 0x400000;
271 }
272 else
273 {
274 rdram[0x3F0/4] = 0x800000;
275 }
276 break;
277 }
278 }
279 }
280
281 pi_register.read_pi_status_reg |= 3;
282 update_count();
283 add_interupt_event(PI_INT, longueur/8);
284
285 return;
286}
287
288void dma_sp_write(void)
289{
290 unsigned int i,j;
291
292 unsigned int l = sp_register.sp_rd_len_reg;
293
294 unsigned int length = ((l & 0xfff) | 7) + 1;
295 unsigned int count = ((l >> 12) & 0xff) + 1;
296 unsigned int skip = ((l >> 20) & 0xfff);
297
298 unsigned int memaddr = sp_register.sp_mem_addr_reg & 0xfff;
299 unsigned int dramaddr = sp_register.sp_dram_addr_reg & 0xffffff;
300
301 unsigned char *spmem = ((sp_register.sp_mem_addr_reg & 0x1000) != 0) ? (unsigned char*)SP_IMEM : (unsigned char*)SP_DMEM;
302 unsigned char *dram = (unsigned char*)rdram;
303
304 for(j=0; j<count; j++) {
305 for(i=0; i<length; i++) {
306 spmem[memaddr^S8] = dram[dramaddr^S8];
307 memaddr++;
308 dramaddr++;
309 }
310 dramaddr+=skip;
311 }
312}
313
314void dma_sp_read(void)
315{
316 unsigned int i,j;
317
318 unsigned int l = sp_register.sp_wr_len_reg;
319
320 unsigned int length = ((l & 0xfff) | 7) + 1;
321 unsigned int count = ((l >> 12) & 0xff) + 1;
322 unsigned int skip = ((l >> 20) & 0xfff);
323
324 unsigned int memaddr = sp_register.sp_mem_addr_reg & 0xfff;
325 unsigned int dramaddr = sp_register.sp_dram_addr_reg & 0xffffff;
326
327 unsigned char *spmem = ((sp_register.sp_mem_addr_reg & 0x1000) != 0) ? (unsigned char*)SP_IMEM : (unsigned char*)SP_DMEM;
328 unsigned char *dram = (unsigned char*)rdram;
329
330 for(j=0; j<count; j++) {
331 for(i=0; i<length; i++) {
332 dram[dramaddr^S8] = spmem[memaddr^S8];
333 memaddr++;
334 dramaddr++;
335 }
336 dramaddr+=skip;
337 }
338}
339
340void dma_si_write(void)
341{
342 int i;
343
344 if (si_register.si_pif_addr_wr64b != 0x1FC007C0)
345 {
346 DebugMessage(M64MSG_ERROR, "dma_si_write(): unknown SI use");
347 stop=1;
348 }
349
350 for (i=0; i<(64/4); i++)
351 {
352 PIF_RAM[i] = sl(rdram[si_register.si_dram_addr/4+i]);
353 }
354
355 update_pif_write();
356 update_count();
357 add_interupt_event(SI_INT, /*0x100*/0x900);
358}
359
360void dma_si_read(void)
361{
362 int i;
363
364 if (si_register.si_pif_addr_rd64b != 0x1FC007C0)
365 {
366 DebugMessage(M64MSG_ERROR, "dma_si_read(): unknown SI use");
367 stop=1;
368 }
369
370 update_pif_read();
371
372 for (i=0; i<(64/4); i++)
373 {
374 rdram[si_register.si_dram_addr/4+i] = sl(PIF_RAM[i]);
375 }
376
377 update_count();
378 add_interupt_event(SI_INT, /*0x100*/0x900);
379}
380