annotate src/gba/Flash.cpp @ 68:86093f2ce7d1

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