1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - flashram.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 "flashram.h"
23 #include "pi_controller.h"
24
25 #include "../api/m64p_types.h"
26 #include "../api/callbacks.h"
27 #include "../memory/memory.h"
28 #include "../ri/ri_controller.h"
29
30 #include <string.h>
31
init_flashram(struct flashram * flashram,void * user_data,void (* save)(void *),uint8_t * data)32 void init_flashram(struct flashram* flashram,
33 void* user_data,
34 void (*save)(void*),
35 uint8_t* data)
36 {
37 flashram->user_data = user_data;
38 flashram->save = save;
39 flashram->data = data;
40 }
41
flashram_command(struct pi_controller * pi,uint32_t command)42 static void flashram_command(struct pi_controller *pi, uint32_t command)
43 {
44 unsigned int i;
45 struct flashram *flashram = &pi->flashram;
46 uint8_t *dram = (uint8_t*)pi->ri->rdram.dram;
47
48 switch (command & 0xff000000)
49 {
50 case 0x4b000000:
51 flashram->erase_offset = (command & 0xffff) * 128;
52 break;
53 case 0x78000000:
54 flashram->mode = FLASHRAM_MODE_ERASE;
55 flashram->status = 0x1111800800c20000LL;
56 break;
57 case 0xa5000000:
58 flashram->erase_offset = (command & 0xffff) * 128;
59 flashram->status = 0x1111800400c20000LL;
60 break;
61 case 0xb4000000:
62 flashram->mode = FLASHRAM_MODE_WRITE;
63 break;
64 case 0xd2000000: // execute
65 switch (flashram->mode)
66 {
67 case FLASHRAM_MODE_NOPES:
68 case FLASHRAM_MODE_READ:
69 break;
70 case FLASHRAM_MODE_ERASE:
71 {
72 for (i=flashram->erase_offset; i<(flashram->erase_offset+128); ++i)
73 flashram->data[i^S8] = 0xff;
74 flashram_save(flashram);
75 }
76 break;
77 case FLASHRAM_MODE_WRITE:
78 {
79 for(i = 0; i < 128; ++i)
80 flashram->data[(flashram->erase_offset+i)^S8]= dram[(flashram->write_pointer+i)^S8];
81 flashram_save(flashram);
82 }
83 break;
84 case FLASHRAM_MODE_STATUS:
85 break;
86 default:
87 DebugMessage(M64MSG_WARNING, "unknown flashram command with mode:%x", (int)flashram->mode);
88 break;
89 }
90 flashram->mode = FLASHRAM_MODE_NOPES;
91 break;
92 case 0xe1000000:
93 flashram->mode = FLASHRAM_MODE_STATUS;
94 flashram->status = 0x1111800100c20000LL;
95 break;
96 case 0xf0000000:
97 flashram->mode = FLASHRAM_MODE_READ;
98 flashram->status = 0x11118004f0000000LL;
99 break;
100 default:
101 DebugMessage(M64MSG_WARNING, "unknown flashram command: %x", (int)command);
102 break;
103 }
104 }
105
poweron_flashram(struct flashram * flashram)106 void poweron_flashram(struct flashram* flashram)
107 {
108 flashram->mode = FLASHRAM_MODE_NOPES;
109 flashram->status = 0;
110 flashram->erase_offset = 0;
111 flashram->write_pointer = 0;
112 }
113
flashram_save(struct flashram * flashram)114 void flashram_save(struct flashram* flashram)
115 {
116 flashram->save(flashram->user_data);
117 }
118
format_flashram(uint8_t * flash)119 void format_flashram(uint8_t* flash)
120 {
121 memset(flash, 0xff, FLASHRAM_SIZE);
122 }
123
read_flashram_status(void * opaque,uint32_t address,uint32_t * value)124 int read_flashram_status(void* opaque, uint32_t address, uint32_t* value)
125 {
126 struct pi_controller* pi = (struct pi_controller*)opaque;
127
128 if ((pi->use_flashram == -1) || ((address & 0xffff) != 0))
129 {
130 DebugMessage(M64MSG_ERROR, "unknown read in read_flashram_status()");
131 return -1;
132 }
133 pi->use_flashram = 1;
134 *value = pi->flashram.status >> 32;
135 return 0;
136 }
137
write_flashram_command(void * opaque,uint32_t address,uint32_t value,uint32_t mask)138 int write_flashram_command(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
139 {
140 struct pi_controller* pi = (struct pi_controller*)opaque;
141
142 if ((pi->use_flashram == -1) || ((address & 0xffff) != 0))
143 {
144 DebugMessage(M64MSG_ERROR, "unknown write in write_flashram_command()");
145 return -1;
146 }
147 pi->use_flashram = 1;
148 flashram_command(pi, value & mask);
149 return 0;
150 }
151
dma_read_flashram(struct pi_controller * pi)152 void dma_read_flashram(struct pi_controller *pi)
153 {
154 unsigned int dram_addr, cart_addr;
155 unsigned int i, length;
156 struct flashram* flashram = &pi->flashram;
157 uint32_t *dram = pi->ri->rdram.dram;
158 uint8_t *mem = flashram->data;
159
160 switch (flashram->mode)
161 {
162 case FLASHRAM_MODE_STATUS:
163 dram[pi->regs[PI_DRAM_ADDR_REG]/4] = (uint32_t)(flashram->status >> 32);
164 dram[pi->regs[PI_DRAM_ADDR_REG]/4+1] = (uint32_t)(flashram->status);
165 break;
166 case FLASHRAM_MODE_READ:
167 length = (pi->regs[PI_WR_LEN_REG] & 0xffffff) + 1;
168 dram_addr = pi->regs[PI_DRAM_ADDR_REG];
169 cart_addr = ((pi->regs[PI_CART_ADDR_REG]-0x08000000)&0xffff)*2;
170
171 for (i = 0; i < length; ++i)
172 ((uint8_t*)dram)[(dram_addr+i)^S8] = mem[(cart_addr+i)^S8];
173 break;
174 default:
175 DebugMessage(M64MSG_WARNING, "unknown dma_read_flashram: %x", flashram->mode);
176 break;
177 }
178 }
179
dma_write_flashram(struct pi_controller * pi)180 void dma_write_flashram(struct pi_controller *pi)
181 {
182 struct flashram *flashram = &pi->flashram;
183
184 switch (flashram->mode)
185 {
186 case FLASHRAM_MODE_WRITE:
187 flashram->write_pointer = pi->regs[PI_DRAM_ADDR_REG];
188 break;
189 default:
190 DebugMessage(M64MSG_ERROR, "unknown dma_write_flashram: %x", flashram->mode);
191 break;
192 }
193 }
194