1 #include <stdio.h>
2 #include <string.h>
3 #include <memory.h>
4 #include "GBA.h"
5 #include "Globals.h"
6 #include "Flash.h"
7 #include "Sram.h"
8 #include "../Util.h"
9
10 #define FLASH_READ_ARRAY 0
11 #define FLASH_CMD_1 1
12 #define FLASH_CMD_2 2
13 #define FLASH_AUTOSELECT 3
14 #define FLASH_CMD_3 4
15 #define FLASH_CMD_4 5
16 #define FLASH_CMD_5 6
17 #define FLASH_ERASE_COMPLETE 7
18 #define FLASH_PROGRAM 8
19 #define FLASH_SETBANK 9
20
21 #ifdef __LIBRETRO__
22 extern uint8_t libretro_save_buf[0x20000 + 0x2000];
23 uint8_t *flashSaveMemory = libretro_save_buf;
24 #else
25 uint8_t flashSaveMemory[FLASH_128K_SZ];
26 #endif
27
28 int flashState = FLASH_READ_ARRAY;
29 int flashReadState = FLASH_READ_ARRAY;
30 int flashSize = 0x10000;
31 int flashDeviceID = 0x1b;
32 int flashManufacturerID = 0x32;
33 int flashBank = 0;
34
35 static variable_desc flashSaveData[] = {
36 { &flashState, sizeof(int) },
37 { &flashReadState, sizeof(int) },
38 { &flashSaveMemory[0], 0x10000 },
39 { NULL, 0 }
40 };
41
42 static variable_desc flashSaveData2[] = {
43 { &flashState, sizeof(int) },
44 { &flashReadState, sizeof(int) },
45 { &flashSize, sizeof(int) },
46 { &flashSaveMemory[0], 0x20000 },
47 { NULL, 0 }
48 };
49
50 static variable_desc flashSaveData3[] = {
51 { &flashState, sizeof(int) },
52 { &flashReadState, sizeof(int) },
53 { &flashSize, sizeof(int) },
54 { &flashBank, sizeof(int) },
55 { &flashSaveMemory[0], 0x20000 },
56 { NULL, 0 }
57 };
58
flashInit()59 void flashInit()
60 {
61 #ifdef __LIBRETRO__
62 memset(flashSaveMemory, 0xff, 0x20000);
63 #else
64 memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
65 #endif
66 }
67
flashReset()68 void flashReset()
69 {
70 flashState = FLASH_READ_ARRAY;
71 flashReadState = FLASH_READ_ARRAY;
72 flashBank = 0;
73 }
74
75 #ifdef __LIBRETRO__
flashSaveGame(uint8_t * & data)76 void flashSaveGame(uint8_t *& data)
77 {
78 utilWriteDataMem(data, flashSaveData3);
79 }
80
flashReadGame(const uint8_t * & data,int)81 void flashReadGame(const uint8_t *& data, int)
82 {
83 utilReadDataMem(data, flashSaveData3);
84 }
85 #else
flashSaveGame(gzFile gzFile)86 void flashSaveGame(gzFile gzFile)
87 {
88 utilWriteData(gzFile, flashSaveData3);
89 }
90
flashReadGame(gzFile gzFile,int version)91 void flashReadGame(gzFile gzFile, int version)
92 {
93 if(version < SAVE_GAME_VERSION_5)
94 utilReadData(gzFile, flashSaveData);
95 else if(version < SAVE_GAME_VERSION_7) {
96 utilReadData(gzFile, flashSaveData2);
97 flashBank = 0;
98 flashSetSize(flashSize);
99 } else {
100 utilReadData(gzFile, flashSaveData3);
101 }
102 }
103
flashReadGameSkip(gzFile gzFile,int version)104 void flashReadGameSkip(gzFile gzFile, int version)
105 {
106 // skip the flash data in a save game
107 if(version < SAVE_GAME_VERSION_5)
108 utilReadDataSkip(gzFile, flashSaveData);
109 else if(version < SAVE_GAME_VERSION_7) {
110 utilReadDataSkip(gzFile, flashSaveData2);
111 } else {
112 utilReadDataSkip(gzFile, flashSaveData3);
113 }
114 }
115 #endif
116
117
flashSetSize(int size)118 void flashSetSize(int size)
119 {
120 // log("Setting flash size to %d\n", size);
121 if(size == 0x10000) {
122 flashDeviceID = 0x1b;
123 flashManufacturerID = 0x32;
124 } else {
125 flashDeviceID = 0x13; //0x09;
126 flashManufacturerID = 0x62; //0xc2;
127 }
128 // Added to make 64k saves compatible with 128k ones
129 // (allow wrongfuly set 64k saves to work for Pokemon games)
130 if ((size == 0x20000) && (flashSize == 0x10000))
131 memcpy((u8 *)(flashSaveMemory+0x10000), (u8 *)(flashSaveMemory), 0x10000);
132 flashSize = size;
133 }
134
flashRead(u32 address)135 u8 flashRead(u32 address)
136 {
137 // log("Reading %08x from %08x\n", address, reg[15].I);
138 // log("Current read state is %d\n", flashReadState);
139 address &= 0xFFFF;
140
141 switch(flashReadState) {
142 case FLASH_READ_ARRAY:
143 return flashSaveMemory[(flashBank << 16) + address];
144 case FLASH_AUTOSELECT:
145 switch(address & 0xFF) {
146 case 0:
147 // manufacturer ID
148 return flashManufacturerID;
149 case 1:
150 // device ID
151 return flashDeviceID;
152 }
153 break;
154 case FLASH_ERASE_COMPLETE:
155 flashState = FLASH_READ_ARRAY;
156 flashReadState = FLASH_READ_ARRAY;
157 return 0xFF;
158 };
159 return 0;
160 }
161
flashSaveDecide(u32 address,u8 byte)162 void flashSaveDecide(u32 address, u8 byte)
163 {
164 if (saveType == 1)
165 return;
166
167 // log("Deciding save type %08x\n", address);
168 if(address == 0x0e005555) {
169 saveType = 3;
170 cpuSaveGameFunc = flashWrite;
171 } else {
172 saveType = 2;
173 cpuSaveGameFunc = sramWrite;
174 }
175
176 (*cpuSaveGameFunc)(address, byte);
177 }
178
flashDelayedWrite(u32 address,u8 byte)179 void flashDelayedWrite(u32 address, u8 byte)
180 {
181 saveType = 3;
182 cpuSaveGameFunc = flashWrite;
183 flashWrite(address, byte);
184 }
185
flashWrite(u32 address,u8 byte)186 void flashWrite(u32 address, u8 byte)
187 {
188 // log("Writing %02x at %08x\n", byte, address);
189 // log("Current state is %d\n", flashState);
190 address &= 0xFFFF;
191 switch(flashState) {
192 case FLASH_READ_ARRAY:
193 if(address == 0x5555 && byte == 0xAA)
194 flashState = FLASH_CMD_1;
195 break;
196 case FLASH_CMD_1:
197 if(address == 0x2AAA && byte == 0x55)
198 flashState = FLASH_CMD_2;
199 else
200 flashState = FLASH_READ_ARRAY;
201 break;
202 case FLASH_CMD_2:
203 if(address == 0x5555) {
204 if(byte == 0x90) {
205 flashState = FLASH_AUTOSELECT;
206 flashReadState = FLASH_AUTOSELECT;
207 } else if(byte == 0x80) {
208 flashState = FLASH_CMD_3;
209 } else if(byte == 0xF0) {
210 flashState = FLASH_READ_ARRAY;
211 flashReadState = FLASH_READ_ARRAY;
212 } else if(byte == 0xA0) {
213 flashState = FLASH_PROGRAM;
214 } else if(byte == 0xB0 && flashSize == 0x20000) {
215 flashState = FLASH_SETBANK;
216 } else {
217 flashState = FLASH_READ_ARRAY;
218 flashReadState = FLASH_READ_ARRAY;
219 }
220 } else {
221 flashState = FLASH_READ_ARRAY;
222 flashReadState = FLASH_READ_ARRAY;
223 }
224 break;
225 case FLASH_CMD_3:
226 if(address == 0x5555 && byte == 0xAA) {
227 flashState = FLASH_CMD_4;
228 } else {
229 flashState = FLASH_READ_ARRAY;
230 flashReadState = FLASH_READ_ARRAY;
231 }
232 break;
233 case FLASH_CMD_4:
234 if(address == 0x2AAA && byte == 0x55) {
235 flashState = FLASH_CMD_5;
236 } else {
237 flashState = FLASH_READ_ARRAY;
238 flashReadState = FLASH_READ_ARRAY;
239 }
240 break;
241 case FLASH_CMD_5:
242 if(byte == 0x30) {
243 // SECTOR ERASE
244 memset(&flashSaveMemory[(flashBank << 16) + (address & 0xF000)],
245 0,
246 0x1000);
247 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
248 flashReadState = FLASH_ERASE_COMPLETE;
249 } else if(byte == 0x10) {
250 // CHIP ERASE
251 memset(flashSaveMemory, 0, flashSize);
252 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
253 flashReadState = FLASH_ERASE_COMPLETE;
254 } else {
255 flashState = FLASH_READ_ARRAY;
256 flashReadState = FLASH_READ_ARRAY;
257 }
258 break;
259 case FLASH_AUTOSELECT:
260 if(byte == 0xF0) {
261 flashState = FLASH_READ_ARRAY;
262 flashReadState = FLASH_READ_ARRAY;
263 } else if(address == 0x5555 && byte == 0xAA)
264 flashState = FLASH_CMD_1;
265 else {
266 flashState = FLASH_READ_ARRAY;
267 flashReadState = FLASH_READ_ARRAY;
268 }
269 break;
270 case FLASH_PROGRAM:
271 flashSaveMemory[(flashBank<<16)+address] = byte;
272 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
273 flashState = FLASH_READ_ARRAY;
274 flashReadState = FLASH_READ_ARRAY;
275 break;
276 case FLASH_SETBANK:
277 if(address == 0) {
278 flashBank = (byte & 1);
279 }
280 flashState = FLASH_READ_ARRAY;
281 flashReadState = FLASH_READ_ARRAY;
282 break;
283 }
284 }
285