1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004-2006 Forgotten and the VBA development team
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #define FLASH_READ_ARRAY 0
30 #define FLASH_AUTOSELECT 3
34 #define FLASH_ERASE_COMPLETE 7
35 #define FLASH_PROGRAM 8
36 #define FLASH_SETBANK 9
38 u8 flashSaveMemory
[0x20000];
39 int flashState
= FLASH_READ_ARRAY
;
40 int flashReadState
= FLASH_READ_ARRAY
;
41 int flashSize
= 0x10000;
42 int flashDeviceID
= 0x1b;
43 int flashManufacturerID
= 0x32;
46 static variable_desc flashSaveData
[] = {
47 { &flashState
, sizeof(int) },
48 { &flashReadState
, sizeof(int) },
49 { &flashSaveMemory
[0], 0x10000 },
53 static variable_desc flashSaveData2
[] = {
54 { &flashState
, sizeof(int) },
55 { &flashReadState
, sizeof(int) },
56 { &flashSize
, sizeof(int) },
57 { &flashSaveMemory
[0], 0x20000 },
61 static variable_desc flashSaveData3
[] = {
62 { &flashState
, sizeof(int) },
63 { &flashReadState
, sizeof(int) },
64 { &flashSize
, sizeof(int) },
65 { &flashBank
, sizeof(int) },
66 { &flashSaveMemory
[0], 0x20000 },
72 memset(flashSaveMemory
, 0xff, sizeof(flashSaveMemory
));
77 flashState
= FLASH_READ_ARRAY
;
78 flashReadState
= FLASH_READ_ARRAY
;
82 void flashSaveGame(gzFile gzFile
)
84 utilWriteData(gzFile
, flashSaveData3
);
87 void flashReadGame(gzFile gzFile
, int version
)
89 if(version
< SAVE_GAME_VERSION_5
)
90 utilReadData(gzFile
, flashSaveData
);
91 else if(version
< SAVE_GAME_VERSION_7
) {
92 utilReadData(gzFile
, flashSaveData2
);
94 flashSetSize(flashSize
);
96 utilReadData(gzFile
, flashSaveData3
);
100 void flashSetSize(int size
)
102 // log("Setting flash size to %d\n", size);
103 if(size
== 0x10000) {
104 flashDeviceID
= 0x1b;
105 flashManufacturerID
= 0x32;
107 flashDeviceID
= 0x13; //0x09;
108 flashManufacturerID
= 0x62; //0xc2;
110 // Added to make 64k saves compatible with 128k ones
111 // (allow wrongfuly set 64k saves to work for Pokemon games)
112 if ((size
== 0x20000) && (flashSize
== 0x10000))
113 memcpy((u8
*)(flashSaveMemory
+0x10000), (u8
*)(flashSaveMemory
), 0x10000);
117 u8
flashRead(u32 address
)
119 // log("Reading %08x from %08x\n", address, reg[15].I);
120 // log("Current read state is %d\n", flashReadState);
123 switch(flashReadState
) {
124 case FLASH_READ_ARRAY
:
125 return flashSaveMemory
[(flashBank
<< 16) + address
];
126 case FLASH_AUTOSELECT
:
127 switch(address
& 0xFF) {
130 return flashManufacturerID
;
133 return flashDeviceID
;
136 case FLASH_ERASE_COMPLETE
:
137 flashState
= FLASH_READ_ARRAY
;
138 flashReadState
= FLASH_READ_ARRAY
;
144 void flashSaveDecide(u32 address
, u8 byte
)
146 // log("Deciding save type %08x\n", address);
147 if(address
== 0x0e005555) {
149 cpuSaveGameFunc
= flashWrite
;
152 cpuSaveGameFunc
= sramWrite
;
155 (*cpuSaveGameFunc
)(address
, byte
);
158 void flashDelayedWrite(u32 address
, u8 byte
)
161 cpuSaveGameFunc
= flashWrite
;
162 flashWrite(address
, byte
);
165 void flashWrite(u32 address
, u8 byte
)
167 // log("Writing %02x at %08x\n", byte, address);
168 // log("Current state is %d\n", flashState);
171 case FLASH_READ_ARRAY
:
172 if(address
== 0x5555 && byte
== 0xAA)
173 flashState
= FLASH_CMD_1
;
176 if(address
== 0x2AAA && byte
== 0x55)
177 flashState
= FLASH_CMD_2
;
179 flashState
= FLASH_READ_ARRAY
;
182 if(address
== 0x5555) {
184 flashState
= FLASH_AUTOSELECT
;
185 flashReadState
= FLASH_AUTOSELECT
;
186 } else if(byte
== 0x80) {
187 flashState
= FLASH_CMD_3
;
188 } else if(byte
== 0xF0) {
189 flashState
= FLASH_READ_ARRAY
;
190 flashReadState
= FLASH_READ_ARRAY
;
191 } else if(byte
== 0xA0) {
192 flashState
= FLASH_PROGRAM
;
193 } else if(byte
== 0xB0 && flashSize
== 0x20000) {
194 flashState
= FLASH_SETBANK
;
196 flashState
= FLASH_READ_ARRAY
;
197 flashReadState
= FLASH_READ_ARRAY
;
200 flashState
= FLASH_READ_ARRAY
;
201 flashReadState
= FLASH_READ_ARRAY
;
205 if(address
== 0x5555 && byte
== 0xAA) {
206 flashState
= FLASH_CMD_4
;
208 flashState
= FLASH_READ_ARRAY
;
209 flashReadState
= FLASH_READ_ARRAY
;
213 if(address
== 0x2AAA && byte
== 0x55) {
214 flashState
= FLASH_CMD_5
;
216 flashState
= FLASH_READ_ARRAY
;
217 flashReadState
= FLASH_READ_ARRAY
;
223 memset(&flashSaveMemory
[(flashBank
<< 16) + (address
& 0xF000)],
226 systemSaveUpdateCounter
= SYSTEM_SAVE_UPDATED
;
227 flashReadState
= FLASH_ERASE_COMPLETE
;
228 } else if(byte
== 0x10) {
230 memset(flashSaveMemory
, 0, flashSize
);
231 systemSaveUpdateCounter
= SYSTEM_SAVE_UPDATED
;
232 flashReadState
= FLASH_ERASE_COMPLETE
;
234 flashState
= FLASH_READ_ARRAY
;
235 flashReadState
= FLASH_READ_ARRAY
;
238 case FLASH_AUTOSELECT
:
240 flashState
= FLASH_READ_ARRAY
;
241 flashReadState
= FLASH_READ_ARRAY
;
242 } else if(address
== 0x5555 && byte
== 0xAA)
243 flashState
= FLASH_CMD_1
;
245 flashState
= FLASH_READ_ARRAY
;
246 flashReadState
= FLASH_READ_ARRAY
;
250 flashSaveMemory
[(flashBank
<<16)+address
] = byte
;
251 systemSaveUpdateCounter
= SYSTEM_SAVE_UPDATED
;
252 flashState
= FLASH_READ_ARRAY
;
253 flashReadState
= FLASH_READ_ARRAY
;
257 flashBank
= (byte
& 1);
259 flashState
= FLASH_READ_ARRAY
;
260 flashReadState
= FLASH_READ_ARRAY
;