diff options
Diffstat (limited to 'gba')
| -rw-r--r-- | gba/source/libSave.c | 596 | ||||
| -rw-r--r-- | gba/source/libSave.h | 27 | ||||
| -rw-r--r-- | gba/source/libpayload.c | 312 | ||||
| -rw-r--r-- | gba/source/libpayload.h | 160 | ||||
| -rw-r--r-- | gba/source/payload.c | 60 | ||||
| -rw-r--r-- | gba/source/payload.h | 1 | ||||
| -rw-r--r-- | gba/source/saveblocks.h | 338 | ||||
| -rw-r--r-- | gba/source/savestructs.h | 793 | 
8 files changed, 1656 insertions, 631 deletions
| diff --git a/gba/source/libSave.c b/gba/source/libSave.c deleted file mode 100644 index e3bda1d..0000000 --- a/gba/source/libSave.c +++ /dev/null | |||
| @@ -1,596 +0,0 @@ | |||
| 1 | /* | ||
| 2 | libSave | ||
| 3 | Cartridge backup memory save routines. To use, call the required | ||
| 4 | routine with a pointer to an appropriately sized array of data to | ||
| 5 | be read from or written to the cartridge. | ||
| 6 | Data types are from wintermute's gba_types.h libgba library. | ||
| 7 | Original file from SendSave by Chishm | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <stdio.h> | ||
| 11 | #include <stdlib.h> | ||
| 12 | #include <string.h> | ||
| 13 | #include <gba_dma.h> | ||
| 14 | |||
| 15 | #define EEPROM_ADDRESS (0xDFFFF00) | ||
| 16 | #define REG_EEPROM *(vu16 *)(EEPROM_ADDRESS) | ||
| 17 | #define REG_DMA3CNT_H *(vu16 *)(REG_BASE + 0x0de) | ||
| 18 | #define REG_WAITCNT *(vu16 *)(REG_BASE + 0x204) | ||
| 19 | |||
| 20 | //----------------------------------------------------------------------- | ||
| 21 | // Common EEPROM Routines | ||
| 22 | //----------------------------------------------------------------------- | ||
| 23 | |||
| 24 | void EEPROM_SendPacket( u16* packet, int size ) | ||
| 25 | { | ||
| 26 | REG_WAITCNT = (REG_WAITCNT & 0xF8FF) | 0x0300; | ||
| 27 | REG_DMA3SAD = (u32)packet; | ||
| 28 | REG_DMA3DAD = EEPROM_ADDRESS; | ||
| 29 | REG_DMA3CNT = 0x80000000 + size; | ||
| 30 | while((REG_DMA3CNT_H & 0x8000) != 0) ; | ||
| 31 | } | ||
| 32 | |||
| 33 | void EEPROM_ReceivePacket( u16* packet, int size ) | ||
| 34 | { | ||
| 35 | REG_WAITCNT = (REG_WAITCNT & 0xF8FF) | 0x0300; | ||
| 36 | REG_DMA3SAD = EEPROM_ADDRESS; | ||
| 37 | REG_DMA3DAD = (u32)packet; | ||
| 38 | REG_DMA3CNT = 0x80000000 + size; | ||
| 39 | while((REG_DMA3CNT_H & 0x8000) != 0) ; | ||
| 40 | } | ||
| 41 | |||
| 42 | //----------------------------------------------------------------------- | ||
| 43 | // Routines for 512B EEPROM | ||
| 44 | //----------------------------------------------------------------------- | ||
| 45 | |||
| 46 | void EEPROM_Read_512B( volatile u8 offset, u8* dest ) // dest must point to 8 bytes | ||
| 47 | { | ||
| 48 | u16 packet[68]; | ||
| 49 | u8* out_pos; | ||
| 50 | u16* in_pos; | ||
| 51 | u8 out_byte; | ||
| 52 | int byte, bit; | ||
| 53 | |||
| 54 | memset( packet, 0, 68*2 ); | ||
| 55 | |||
| 56 | // Read request | ||
| 57 | packet[0] = 1; | ||
| 58 | packet[1] = 1; | ||
| 59 | |||
| 60 | // 6 bits eeprom address (MSB first) | ||
| 61 | packet[2] = (offset>>5)&1; | ||
| 62 | packet[3] = (offset>>4)&1; | ||
| 63 | packet[4] = (offset>>3)&1; | ||
| 64 | packet[5] = (offset>>2)&1; | ||
| 65 | packet[6] = (offset>>1)&1; | ||
| 66 | packet[7] = (offset)&1; | ||
| 67 | |||
| 68 | // End of request | ||
| 69 | packet[8] = 0; | ||
| 70 | |||
| 71 | // Do transfers | ||
| 72 | EEPROM_SendPacket( packet, 9 ); | ||
| 73 | memset( packet, 0, 68*2 ); | ||
| 74 | EEPROM_ReceivePacket( packet, 68 ); | ||
| 75 | |||
| 76 | // Extract data | ||
| 77 | in_pos = &packet[4]; | ||
| 78 | out_pos = dest; | ||
| 79 | for( byte = 7; byte >= 0; --byte ) | ||
| 80 | { | ||
| 81 | out_byte = 0; | ||
| 82 | for( bit = 7; bit >= 0; --bit ) | ||
| 83 | { | ||
| 84 | // out_byte += (*in_pos++)<<bit; | ||
| 85 | out_byte += ((*in_pos++)&1)<<bit; | ||
| 86 | } | ||
| 87 | *out_pos++ = out_byte ; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | void EEPROM_Write_512B( volatile u8 offset, u8* source ) // source must point to 8 bytes | ||
| 92 | { | ||
| 93 | u16 packet[73]; | ||
| 94 | u8* in_pos; | ||
| 95 | u16* out_pos; | ||
| 96 | u8 in_byte; | ||
| 97 | int byte, bit; | ||
| 98 | |||
| 99 | memset( packet, 0, 73*2 ); | ||
| 100 | |||
| 101 | // Write request | ||
| 102 | packet[0] = 1; | ||
| 103 | packet[1] = 0; | ||
| 104 | |||
| 105 | // 6 bits eeprom address (MSB first) | ||
| 106 | packet[2] = (offset>>5)&1; | ||
| 107 | packet[3] = (offset>>4)&1; | ||
| 108 | packet[4] = (offset>>3)&1; | ||
| 109 | packet[5] = (offset>>2)&1; | ||
| 110 | packet[6] = (offset>>1)&1; | ||
| 111 | packet[7] = (offset)&1; | ||
| 112 | |||
| 113 | // Extract data | ||
| 114 | in_pos = source; | ||
| 115 | out_pos = &packet[8]; | ||
| 116 | for( byte = 7; byte >= 0; --byte ) | ||
| 117 | { | ||
| 118 | in_byte = *in_pos++; | ||
| 119 | for( bit = 7; bit >= 0; --bit ) | ||
| 120 | { | ||
| 121 | *out_pos++ = (in_byte>>bit)&1; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | // End of request | ||
| 126 | packet[72] = 0; | ||
| 127 | |||
| 128 | // Do transfers | ||
| 129 | EEPROM_SendPacket( packet, 73 ); | ||
| 130 | |||
| 131 | // Wait for EEPROM to finish (should timeout after 10 ms) | ||
| 132 | while( (REG_EEPROM & 1) == 0 ); | ||
| 133 | } | ||
| 134 | |||
| 135 | //--------------------------------------------------------------------------------- | ||
| 136 | void GetSave_EEPROM_512B(u8* data) | ||
| 137 | //--------------------------------------------------------------------------------- | ||
| 138 | { | ||
| 139 | volatile u8 x; | ||
| 140 | u32 sleep; | ||
| 141 | |||
| 142 | for (x=0;x<64;++x){ | ||
| 143 | EEPROM_Read_512B(x,&data[x*8]); | ||
| 144 | for(sleep=0;sleep<512000;sleep++); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | //--------------------------------------------------------------------------------- | ||
| 149 | void PutSave_EEPROM_512B(u8* data) | ||
| 150 | //--------------------------------------------------------------------------------- | ||
| 151 | { | ||
| 152 | volatile u8 x; | ||
| 153 | u32 sleep; | ||
| 154 | |||
| 155 | for (x=0;x<64;x++){ | ||
| 156 | EEPROM_Write_512B(x,&data[x*8]); | ||
| 157 | for(sleep=0;sleep<512000;sleep++); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | //----------------------------------------------------------------------- | ||
| 161 | // Routines for 8KB EEPROM | ||
| 162 | //----------------------------------------------------------------------- | ||
| 163 | |||
| 164 | void EEPROM_Read_8KB( volatile u16 offset, u8* dest ) // dest must point to 8 bytes | ||
| 165 | { | ||
| 166 | u16 packet[68]; | ||
| 167 | u8* out_pos; | ||
| 168 | u16* in_pos; | ||
| 169 | u8 out_byte; | ||
| 170 | int byte, bit; | ||
| 171 | |||
| 172 | memset( packet, 0, 68*2 ); | ||
| 173 | |||
| 174 | // Read request | ||
| 175 | packet[0] = 1; | ||
| 176 | packet[1] = 1; | ||
| 177 | |||
| 178 | // 14 bits eeprom address (MSB first) | ||
| 179 | packet[2] = (offset>>13)&1; | ||
| 180 | packet[3] = (offset>>12)&1; | ||
| 181 | packet[4] = (offset>>11)&1; | ||
| 182 | packet[5] = (offset>>10)&1; | ||
| 183 | packet[6] = (offset>>9)&1; | ||
| 184 | packet[7] = (offset>>8)&1; | ||
| 185 | packet[8] = (offset>>7)&1; | ||
| 186 | packet[9] = (offset>>6)&1; | ||
| 187 | packet[10] = (offset>>5)&1; | ||
| 188 | packet[11] = (offset>>4)&1; | ||
| 189 | packet[12] = (offset>>3)&1; | ||
| 190 | packet[13] = (offset>>2)&1; | ||
| 191 | packet[14] = (offset>>1)&1; | ||
| 192 | packet[15] = (offset)&1; | ||
| 193 | |||
| 194 | // End of request | ||
| 195 | packet[16] = 0; | ||
| 196 | |||
| 197 | // Do transfers | ||
| 198 | EEPROM_SendPacket( packet, 17 ); | ||
| 199 | memset( packet, 0, 68*2 ); | ||
| 200 | EEPROM_ReceivePacket( packet, 68 ); | ||
| 201 | |||
| 202 | // Extract data | ||
| 203 | in_pos = &packet[4]; | ||
| 204 | out_pos = dest; | ||
| 205 | for( byte = 7; byte >= 0; --byte ) | ||
| 206 | { | ||
| 207 | out_byte = 0; | ||
| 208 | for( bit = 7; bit >= 0; --bit ) | ||
| 209 | { | ||
| 210 | // out_byte += (*in_pos++)<<bit; | ||
| 211 | out_byte += ((*in_pos++)&1)<<bit; | ||
| 212 | } | ||
| 213 | *out_pos++ = out_byte; | ||
| 214 | } | ||
| 215 | |||
| 216 | } | ||
| 217 | |||
| 218 | void EEPROM_Write_8KB( volatile u16 offset, u8* source ) // source must point to 8 bytes | ||
| 219 | { | ||
| 220 | u16 packet[81]; | ||
| 221 | u8* in_pos; | ||
| 222 | u16* out_pos; | ||
| 223 | u8 in_byte; | ||
| 224 | int byte, bit; | ||
| 225 | |||
| 226 | memset( packet, 0, 81*2 ); | ||
| 227 | |||
| 228 | // Write request | ||
| 229 | packet[0] = 1; | ||
| 230 | packet[1] = 0; | ||
| 231 | |||
| 232 | // 14 bits eeprom address (MSB first) | ||
| 233 | packet[2] = (offset>>13)&1; | ||
| 234 | packet[3] = (offset>>12)&1; | ||
| 235 | packet[4] = (offset>>11)&1; | ||
| 236 | packet[5] = (offset>>10)&1; | ||
| 237 | packet[6] = (offset>>9)&1; | ||
| 238 | packet[7] = (offset>>8)&1; | ||
| 239 | packet[8] = (offset>>7)&1; | ||
| 240 | packet[9] = (offset>>6)&1; | ||
| 241 | packet[10] = (offset>>5)&1; | ||
| 242 | packet[11] = (offset>>4)&1; | ||
| 243 | packet[12] = (offset>>3)&1; | ||
| 244 | packet[13] = (offset>>2)&1; | ||
| 245 | packet[14] = (offset>>1)&1; | ||
| 246 | packet[15] = (offset)&1; | ||
| 247 | |||
| 248 | // Extract data | ||
| 249 | in_pos = source; | ||
| 250 | out_pos = &packet[16]; | ||
| 251 | for( byte = 7; byte >= 0; --byte ) | ||
| 252 | { | ||
| 253 | in_byte = *in_pos++; | ||
| 254 | for( bit = 7; bit >= 0; --bit ) | ||
| 255 | { | ||
| 256 | *out_pos++ = (in_byte>>bit)&1; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | // End of request | ||
| 261 | packet[80] = 0; | ||
| 262 | |||
| 263 | // Do transfers | ||
| 264 | EEPROM_SendPacket( packet, 81 ); | ||
| 265 | |||
| 266 | // Wait for EEPROM to finish (should timeout after 10 ms) | ||
| 267 | while( (REG_EEPROM & 1) == 0 ); | ||
| 268 | } | ||
| 269 | |||
| 270 | //--------------------------------------------------------------------------------- | ||
| 271 | void GetSave_EEPROM_8KB(u8* data) | ||
| 272 | //--------------------------------------------------------------------------------- | ||
| 273 | { | ||
| 274 | volatile u16 x; | ||
| 275 | u32 sleep; | ||
| 276 | |||
| 277 | for (x=0;x<1024;x++){ | ||
| 278 | EEPROM_Read_8KB(x,&data[x*8]); | ||
| 279 | for(sleep=0;sleep<512000;sleep++); | ||
| 280 | } | ||
| 281 | |||
| 282 | } | ||
| 283 | |||
| 284 | //--------------------------------------------------------------------------------- | ||
| 285 | void PutSave_EEPROM_8KB(u8* data) | ||
| 286 | //--------------------------------------------------------------------------------- | ||
| 287 | { | ||
| 288 | volatile u16 x; | ||
| 289 | u32 sleep; | ||
| 290 | |||
| 291 | for (x=0;x<1024;x++){ | ||
| 292 | EEPROM_Write_8KB(x,&data[x*8]); | ||
| 293 | for(sleep=0;sleep<512000;sleep++); | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | //--------------------------------------------------------------------------------- | ||
| 298 | void GetSave_SRAM_32KB(u8* data) | ||
| 299 | //--------------------------------------------------------------------------------- | ||
| 300 | { | ||
| 301 | volatile u8 *sram= (u8*) 0x0E000000; | ||
| 302 | volatile u16 x; | ||
| 303 | |||
| 304 | for (x = 0; x < 0x8000; ++x) | ||
| 305 | { | ||
| 306 | data[x] = sram[x]; | ||
| 307 | } | ||
| 308 | |||
| 309 | } | ||
| 310 | |||
| 311 | //--------------------------------------------------------------------------------- | ||
| 312 | void PutSave_SRAM_32KB(u8* data) | ||
| 313 | //--------------------------------------------------------------------------------- | ||
| 314 | { | ||
| 315 | volatile u8 *sram= (u8*) 0x0E000000; | ||
| 316 | volatile u16 x; | ||
| 317 | |||
| 318 | for (x = 0; x < 0x8000; ++x) | ||
| 319 | { | ||
| 320 | sram[x] = data[x]; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | //--------------------------------------------------------------------------------- | ||
| 325 | void GetSave_FLASH_64KB(u8* data) | ||
| 326 | //--------------------------------------------------------------------------------- | ||
| 327 | { | ||
| 328 | volatile u8 *sram= (u8*) 0x0E000000; | ||
| 329 | volatile u32 x; | ||
| 330 | |||
| 331 | for (x = 0; x < 0x10000; ++x) | ||
| 332 | { | ||
| 333 | data[x] = sram[x]; | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | //--------------------------------------------------------------------------------- | ||
| 338 | void PutSave_FLASH_64KB(u8* foo) | ||
| 339 | //--------------------------------------------------------------------------------- | ||
| 340 | { | ||
| 341 | volatile u8 *fctrl0 = (u8*) 0xE005555; | ||
| 342 | volatile u8 *fctrl1 = (u8*) 0xE002AAA; | ||
| 343 | volatile u8 *fctrl2 = (u8*) 0xE000000; | ||
| 344 | |||
| 345 | //init flash | ||
| 346 | *fctrl0 = 0xAA; | ||
| 347 | *fctrl1 = 0x55; | ||
| 348 | *fctrl0 = 0x90; | ||
| 349 | *fctrl2 = 0xF0; | ||
| 350 | |||
| 351 | //erase chip | ||
| 352 | *fctrl0 = 0xAA; | ||
| 353 | *fctrl1 = 0x55; | ||
| 354 | *fctrl0 = 0x80; | ||
| 355 | *fctrl0 = 0xAA; | ||
| 356 | *fctrl1 = 0x55; | ||
| 357 | *fctrl0 = 0x10; | ||
| 358 | |||
| 359 | //wait for erase done | ||
| 360 | u8 val1; | ||
| 361 | u8 val2; | ||
| 362 | val1 = *fctrl2; | ||
| 363 | val2 = *fctrl2; | ||
| 364 | while (val1 != val2) { | ||
| 365 | val1 = *fctrl2; | ||
| 366 | val2 = *fctrl2; | ||
| 367 | } | ||
| 368 | val1 = *fctrl2; | ||
| 369 | val2 = *fctrl2; | ||
| 370 | while (val1 != val2) { | ||
| 371 | val1 = *fctrl2; | ||
| 372 | val2 = *fctrl2; | ||
| 373 | } | ||
| 374 | |||
| 375 | volatile u8 *data = fctrl2; | ||
| 376 | u32 i; | ||
| 377 | //write data | ||
| 378 | for (i=0; i<65536; i++) { | ||
| 379 | *fctrl0 = 0xAA; | ||
| 380 | *fctrl1 = 0x55; | ||
| 381 | *fctrl0 = 0xA0; | ||
| 382 | data [i] = foo [ i ]; | ||
| 383 | val1 = data [ i ]; | ||
| 384 | val2 = data [ i ]; | ||
| 385 | |||
| 386 | while (val1 != val2) { | ||
| 387 | val1 = data [ i ]; | ||
| 388 | val2 = data [ i ]; | ||
| 389 | } | ||
| 390 | val1 = data [ i ]; | ||
| 391 | val2 = data [ i ]; | ||
| 392 | while (val1 != val2) { | ||
| 393 | val1 = data [ i ]; | ||
| 394 | val2 = data [ i ]; | ||
| 395 | } | ||
| 396 | val1 = data [ i ]; | ||
| 397 | val2 = data [ i ]; | ||
| 398 | while (val1 != val2) { | ||
| 399 | val1 = data [ i ]; | ||
| 400 | val2 = data [ i ]; | ||
| 401 | } | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | //--------------------------------------------------------------------------------- | ||
| 406 | void GetSave_FLASH_128KB(u8* data) | ||
| 407 | //--------------------------------------------------------------------------------- | ||
| 408 | { | ||
| 409 | const u32 size = 0x10000; | ||
| 410 | |||
| 411 | volatile u8 *fctrl0 = (u8*) 0xE005555; | ||
| 412 | volatile u8 *fctrl1 = (u8*) 0xE002AAA; | ||
| 413 | volatile u8 *fctrl2 = (u8*) 0xE000000; | ||
| 414 | volatile u32 i; | ||
| 415 | volatile u8 *sram= (u8*) 0x0E000000; | ||
| 416 | |||
| 417 | //init flash | ||
| 418 | *fctrl0 = 0xAA; | ||
| 419 | *fctrl1 = 0x55; | ||
| 420 | *fctrl0 = 0x90; | ||
| 421 | *fctrl2 = 0xF0; | ||
| 422 | |||
| 423 | // read first bank | ||
| 424 | *fctrl0 = 0xAA; | ||
| 425 | *fctrl1 = 0x55; | ||
| 426 | *fctrl0 = 0xB0; | ||
| 427 | *fctrl2 = 0x00; | ||
| 428 | |||
| 429 | for (i=0; i<size; i++){ | ||
| 430 | data[i] = sram[i]; | ||
| 431 | } | ||
| 432 | |||
| 433 | // read second bank | ||
| 434 | *fctrl0 = 0xAA; | ||
| 435 | *fctrl1 = 0x55; | ||
| 436 | *fctrl0 = 0xB0; | ||
| 437 | *fctrl2 = 0x01; | ||
| 438 | |||
| 439 | for (i=0; i<size; i++){ | ||
| 440 | data[i + size] = sram[i]; | ||
| 441 | } | ||
| 442 | |||
| 443 | } | ||
| 444 | |||
| 445 | //--------------------------------------------------------------------------------- | ||
| 446 | void PutSave_FLASH_128KB(u8* foo) | ||
| 447 | //--------------------------------------------------------------------------------- | ||
| 448 | { | ||
| 449 | volatile u8 *fctrl0 = (u8*) 0xE005555; | ||
| 450 | volatile u8 *fctrl1 = (u8*) 0xE002AAA; | ||
| 451 | volatile u8 *fctrl2 = (u8*) 0xE000000; | ||
| 452 | |||
| 453 | u8 val1; | ||
| 454 | u8 val2; | ||
| 455 | |||
| 456 | //init flash | ||
| 457 | *fctrl0 = 0xAA; | ||
| 458 | *fctrl1 = 0x55; | ||
| 459 | *fctrl0 = 0x90; | ||
| 460 | *fctrl2 = 0xF0; | ||
| 461 | |||
| 462 | //erase chip | ||
| 463 | *fctrl0 = 0xAA; | ||
| 464 | *fctrl1 = 0x55; | ||
| 465 | *fctrl0 = 0x80; | ||
| 466 | *fctrl0 = 0xAA; | ||
| 467 | *fctrl1 = 0x55; | ||
| 468 | *fctrl0 = 0x10; | ||
| 469 | |||
| 470 | //wait for erase done | ||
| 471 | val1 = *fctrl2; | ||
| 472 | val2 = *fctrl2; | ||
| 473 | while (val1 != val2) { | ||
| 474 | val1 = *fctrl2; | ||
| 475 | val2 = *fctrl2; | ||
| 476 | } | ||
| 477 | val1 = *fctrl2; | ||
| 478 | val2 = *fctrl2; | ||
| 479 | while (val1 != val2) { | ||
| 480 | val1 = *fctrl2; | ||
| 481 | val2 = *fctrl2; | ||
| 482 | } | ||
| 483 | |||
| 484 | volatile u8 *data = fctrl2; | ||
| 485 | volatile u32 i; | ||
| 486 | // change to bank 0 | ||
| 487 | *fctrl0 = 0xAA; | ||
| 488 | *fctrl1 = 0x55; | ||
| 489 | *fctrl0 = 0xB0; | ||
| 490 | *fctrl2 = 0x00; | ||
| 491 | |||
| 492 | //write data | ||
| 493 | for (i=0; i<65536; i++) { | ||
| 494 | *fctrl0 = 0xAA; | ||
| 495 | *fctrl1 = 0x55; | ||
| 496 | *fctrl0 = 0xA0; | ||
| 497 | data [i] = foo [ i ]; | ||
| 498 | val1 = data [ i ]; | ||
| 499 | val2 = data [ i ]; | ||
| 500 | |||
| 501 | while (val1 != val2) { | ||
| 502 | val1 = data [ i ]; | ||
| 503 | val2 = data [ i ]; | ||
| 504 | } | ||
| 505 | val1 = data [ i ]; | ||
| 506 | val2 = data [ i ]; | ||
| 507 | while (val1 != val2) { | ||
| 508 | val1 = data [ i ]; | ||
| 509 | val2 = data [ i ]; | ||
| 510 | } | ||
| 511 | val1 = data [ i ]; | ||
| 512 | val2 = data [ i ]; | ||
| 513 | while (val1 != val2) { | ||
| 514 | val1 = data [ i ]; | ||
| 515 | val2 = data [ i ]; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 519 | // Change to bank 1 | ||
| 520 | *fctrl0 = 0xAA; | ||
| 521 | *fctrl1 = 0x55; | ||
| 522 | *fctrl0 = 0xB0; | ||
| 523 | *fctrl2 = 0x01; | ||
| 524 | |||
| 525 | //write data | ||
| 526 | for (i=0; i<65536; i++) { | ||
| 527 | *fctrl0 = 0xAA; | ||
| 528 | *fctrl1 = 0x55; | ||
| 529 | *fctrl0 = 0xA0; | ||
| 530 | data [i] = foo [ i + 0x10000]; | ||
| 531 | val1 = data [ i ]; | ||
| 532 | val2 = data [ i ]; | ||
| 533 | |||
| 534 | while (val1 != val2) { | ||
| 535 | val1 = data [ i ]; | ||
| 536 | val2 = data [ i ]; | ||
| 537 | } | ||
| 538 | val1 = data [ i ]; | ||
| 539 | val2 = data [ i ]; | ||
| 540 | while (val1 != val2) { | ||
| 541 | val1 = data [ i ]; | ||
| 542 | val2 = data [ i ]; | ||
| 543 | } | ||
| 544 | val1 = data [ i ]; | ||
| 545 | val2 = data [ i ]; | ||
| 546 | while (val1 != val2) { | ||
| 547 | val1 = data [ i ]; | ||
| 548 | val2 = data [ i ]; | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 552 | } | ||
| 553 | |||
| 554 | //--------------------------------------------------------------------------------- | ||
| 555 | u32 SaveSize(u8* data, s32 gamesize) | ||
| 556 | //--------------------------------------------------------------------------------- | ||
| 557 | { | ||
| 558 | if(gamesize < 0) | ||
| 559 | return 0; | ||
| 560 | |||
| 561 | u32 *pak= ((u32*)0x08000000); | ||
| 562 | s32 x; | ||
| 563 | u16 i; | ||
| 564 | s32 size = gamesize/4; | ||
| 565 | |||
| 566 | |||
| 567 | for (x=size-1;x>=0;x--){ | ||
| 568 | switch (pak[x]) { | ||
| 569 | case 0x53414C46: | ||
| 570 | if (pak[x+1] == 0x5F4D3148){ | ||
| 571 | return 0x20000; // FLASH_128KB | ||
| 572 | } else if ((pak[x+1] & 0x0000FFFF) == 0x00005F48){ | ||
| 573 | return 0x10000; // FLASH_64KB | ||
| 574 | } else if (pak[x+1] == 0x32313548){ | ||
| 575 | return 0x10000; // FLASH_64KB | ||
| 576 | } | ||
| 577 | break; | ||
| 578 | case 0x52504545: | ||
| 579 | if ((pak[x+1] & 0x00FFFFFF) == 0x005F4D4F){ | ||
| 580 | GetSave_EEPROM_8KB(data); | ||
| 581 | for(i = 8; i < 0x800; i += 8) { | ||
| 582 | if(memcmp(data, data+i, 8) != 0) | ||
| 583 | return 0x2000; // EEPROM_8KB | ||
| 584 | } | ||
| 585 | return 0x200; // EEPROM_512B | ||
| 586 | } | ||
| 587 | break; | ||
| 588 | case 0x4D415253: | ||
| 589 | if ((pak[x+1] & 0x000000FF) == 0x0000005F){ | ||
| 590 | return 0x8000; // SRAM_32KB | ||
| 591 | } | ||
| 592 | } | ||
| 593 | } | ||
| 594 | return 0; | ||
| 595 | } | ||
| 596 | |||
| diff --git a/gba/source/libSave.h b/gba/source/libSave.h deleted file mode 100644 index 5ecf822..0000000 --- a/gba/source/libSave.h +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | |||
| 2 | |||
| 3 | //--------------------------------------------------------------------------------- | ||
| 4 | #ifdef __cplusplus | ||
| 5 | extern "C" { | ||
| 6 | #endif | ||
| 7 | //--------------------------------------------------------------------------------- | ||
| 8 | |||
| 9 | void GetSave_EEPROM_512B(u8* data); | ||
| 10 | void PutSave_EEPROM_512B(u8* data); | ||
| 11 | void GetSave_EEPROM_8KB(u8* data); | ||
| 12 | void PutSave_EEPROM_8KB(u8* data); | ||
| 13 | void GetSave_SRAM_32KB(u8* data); | ||
| 14 | void PutSave_SRAM_32KB(u8* data); | ||
| 15 | void GetSave_FLASH_64KB(u8* data); | ||
| 16 | void PutSave_FLASH_64KB(u8* foo); | ||
| 17 | void GetSave_FLASH_128KB(u8* data); | ||
| 18 | void PutSave_FLASH_128KB(u8* foo); | ||
| 19 | |||
| 20 | u32 SaveSize(u8* data, s32 gamesize); | ||
| 21 | |||
| 22 | |||
| 23 | //--------------------------------------------------------------------------------- | ||
| 24 | #ifdef __cplusplus | ||
| 25 | } // extern "C" | ||
| 26 | #endif | ||
| 27 | //--------------------------------------------------------------------------------- | ||
| diff --git a/gba/source/libpayload.c b/gba/source/libpayload.c new file mode 100644 index 0000000..f13a34f --- /dev/null +++ b/gba/source/libpayload.c | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | /* | ||
| 2 | * Example Gen3-multiboot payload by slipstream/RoL 2017. | ||
| 3 | * | ||
| 4 | * This software may be modified and distributed under the terms | ||
| 5 | * of the MIT license. See the LICENSE file for details. | ||
| 6 | * | ||
| 7 | * libpayload.c: contains helper functions for the payload | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <gba.h> | ||
| 11 | #include "payload.h" | ||
| 12 | |||
| 13 | // private functions | ||
| 14 | static void CryptBoxPokemon(struct BoxPokemon* pkm); | ||
| 15 | static u16 crc16(const u8* data, u16 len); | ||
| 16 | static u32 CalculateRamScriptDataChecksum(struct RamScriptData* ramScript); | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Decrypts the substructures of a Pokémon structure, so they can be viewed or modified easily. | ||
| 20 | * Remember to call EncryptPokemon() afterwards. | ||
| 21 | * @param struct Pokemon* pkm The Pokémon to decrypt the substructures of. | ||
| 22 | */ | ||
| 23 | void DecryptPokemon(struct Pokemon* pkm) { | ||
| 24 | struct BoxPokemon* boxMon = &(pkm->box); | ||
| 25 | CryptBoxPokemon(boxMon); | ||
| 26 | } | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Private function that does the actual work of crypting the substructures of a BoxPokemon. | ||
| 30 | * @param struct BoxPokemon* pkm The BoxPokemon whose substructures will be crypted. | ||
| 31 | */ | ||
| 32 | static void CryptBoxPokemon(struct BoxPokemon* pkm) { | ||
| 33 | for (u32 i = 0; i < 12; i++) { | ||
| 34 | pkm->secure.raw[i] ^= (pkm->otId ^ pkm->personality); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | /** | ||
| 39 | * Decrypts the substructures of a core Pokémon structure, so they can be viewed or modified easily. | ||
| 40 | * Used by DecryptPokemon(). | ||
| 41 | * Remember to call EncryptPokemon() afterwards. | ||
| 42 | * @param struct BoxPokemon* pkm The BoxPokemon to decrypt the substructures of. | ||
| 43 | */ | ||
| 44 | void DecryptBoxPokemon(struct BoxPokemon* pkm) { | ||
| 45 | CryptBoxPokemon(pkm); | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Encrypts the substructures of a Pokémon structure, and fixes the checksum. | ||
| 50 | * Must be used after DecryptPokemon() has been called, otherwise the Pokémon you decrypted and forgot to re-encrypt will become a Bad Egg. | ||
| 51 | * @param struct Pokemon* pkm The Pokémon to encrypt the substructures and fix the checksum of. | ||
| 52 | */ | ||
| 53 | void EncryptPokemon(struct Pokemon* pkm) { | ||
| 54 | struct BoxPokemon* boxMon = &(pkm->box); | ||
| 55 | EncryptBoxPokemon(boxMon); | ||
| 56 | } | ||
| 57 | |||
| 58 | /** | ||
| 59 | * Encrypts the substructures of a core Pokémon structure, and fixes the checksum. | ||
| 60 | * Must be used after DecryptBoxPokemon() has been called, otherwise the Pokémon you decrypted and forgot to re-encrypt will become a Bad Egg. | ||
| 61 | * @param struct BoxPokemon* pkm The BoxPokemon to encrypt the substructures and fix the checksum of. | ||
| 62 | */ | ||
| 63 | void EncryptBoxPokemon(struct BoxPokemon* pkm) { | ||
| 64 | FixBoxPokemonChecksum(pkm); | ||
| 65 | CryptBoxPokemon(pkm); | ||
| 66 | } | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Gets a substructure of a Pokémon structure. | ||
| 70 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 71 | * @param struct Pokemon* pkm The Pokemon to get a substructure of. | ||
| 72 | * @param u8 substructId The substructure to get. | ||
| 73 | * @return union PokemonSubstruct* The substructure. | ||
| 74 | */ | ||
| 75 | union PokemonSubstruct* GetPokemonSubstruct(struct Pokemon* pkm,u8 substructId) { | ||
| 76 | struct BoxPokemon* boxMon = &(pkm->box); | ||
| 77 | return GetBoxPokemonSubstruct(boxMon,substructId); | ||
| 78 | } | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Gets a substructure of a core Pokémon structure. | ||
| 82 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 83 | * @param struct Pokemon* pkm The Pokemon to get a substructure of. | ||
| 84 | * @param u8 substructId The substructure to get. | ||
| 85 | * @return union PokemonSubstruct* The substructure. | ||
| 86 | */ | ||
| 87 | union PokemonSubstruct* GetBoxPokemonSubstruct(struct BoxPokemon* pkm,u8 substructId) { | ||
| 88 | if (substructId > 3) return NULL; | ||
| 89 | u32 personality = pkm->personality; | ||
| 90 | // Staring at the substruct indexes, I noticed the last two columns are the reverse of the first two! | ||
| 91 | // that is, substructId==2 column is the reverse of substructId==1, substructId==3 is the reverse of substructId==0 | ||
| 92 | // At least that means there's no need to hardcode all four. | ||
| 93 | u8 substruct_idxes[2][24] = { | ||
| 94 | { 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3 }, | ||
| 95 | { 1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2 } | ||
| 96 | }; | ||
| 97 | u32 modulo = (personality % 24); | ||
| 98 | if (substructId < 2) { | ||
| 99 | return &( pkm->secure.substructs[ substruct_idxes[substructId][modulo] ] ); | ||
| 100 | } | ||
| 101 | return &( pkm->secure.substructs[ substruct_idxes[3 - substructId][23 - modulo] ] ); | ||
| 102 | } | ||
| 103 | |||
| 104 | /** | ||
| 105 | * Gets the checksum of a core Pokémon structure. | ||
| 106 | * @param struct BoxPokemon* pkm The BoxPokemon to calculate the checksum of. | ||
| 107 | * @return u16 The checksum. | ||
| 108 | */ | ||
| 109 | u16 CalculateBoxPokemonChecksum(struct BoxPokemon* pkm) { | ||
| 110 | u16 checksum = 0; | ||
| 111 | union PokemonSubstruct* substructs[4] = { | ||
| 112 | GetBoxPokemonSubstruct(pkm,0), | ||
| 113 | GetBoxPokemonSubstruct(pkm,1), | ||
| 114 | GetBoxPokemonSubstruct(pkm,2), | ||
| 115 | GetBoxPokemonSubstruct(pkm,3) | ||
| 116 | }; | ||
| 117 | |||
| 118 | for (int substruct = 0; substruct < 4; substruct++) { | ||
| 119 | for (int i = 0; i < 6; i++) { | ||
| 120 | checksum += substructs[substruct]->raw[i]; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | return checksum; | ||
| 124 | } | ||
| 125 | |||
| 126 | /** | ||
| 127 | * Fixes the checksum of a core Pokémon structure. | ||
| 128 | * @param struct BoxPokemon* pkm The BoxPokemon to fix the checksum of. | ||
| 129 | */ | ||
| 130 | void FixBoxPokemonChecksum(struct BoxPokemon* pkm) { | ||
| 131 | pkm->checksum = CalculateBoxPokemonChecksum(pkm); | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Gets the zeroth substructure ("Growth") of a Pokémon structure. | ||
| 136 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 137 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 138 | * @return struct PokemonSubstruct0* The substructure. | ||
| 139 | */ | ||
| 140 | struct PokemonSubstruct0* GetPokemonSubstruct0(struct Pokemon* pkm) { | ||
| 141 | struct BoxPokemon* boxMon = &(pkm->box); | ||
| 142 | return GetBoxPokemonSubstruct0(boxMon); | ||
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Gets the zeroth substructure ("Growth") of a core Pokémon structure. | ||
| 147 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 148 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 149 | * @return struct PokemonSubstruct0* The substructure. | ||
| 150 | */ | ||
| 151 | struct PokemonSubstruct0* GetBoxPokemonSubstruct0(struct BoxPokemon* pkm) { | ||
| 152 | return &( GetBoxPokemonSubstruct(pkm,0)->type0 ); | ||
| 153 | } | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Gets the first substructure ("Attacks") of a Pokémon structure. | ||
| 157 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 158 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 159 | * @return struct PokemonSubstruct0* The substructure. | ||
| 160 | */ | ||
| 161 | struct PokemonSubstruct1* GetPokemonSubstruct1(struct Pokemon* pkm) { | ||
| 162 | struct BoxPokemon* boxMon = &(pkm->box); | ||
| 163 | return GetBoxPokemonSubstruct1(boxMon); | ||
| 164 | } | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Gets the first substructure ("Attacks") of a core Pokémon structure. | ||
| 168 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 169 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 170 | * @return struct PokemonSubstruct1* The substructure. | ||
| 171 | */ | ||
| 172 | struct PokemonSubstruct1* GetBoxPokemonSubstruct1(struct BoxPokemon* pkm) { | ||
| 173 | return &( GetBoxPokemonSubstruct(pkm,1)->type1 ); | ||
| 174 | } | ||
| 175 | |||
| 176 | /** | ||
| 177 | * Gets the second substructure ("EVs & Condition") of a Pokémon structure. | ||
| 178 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 179 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 180 | * @return struct PokemonSubstruct0* The substructure. | ||
| 181 | */ | ||
| 182 | struct PokemonSubstruct2* GetPokemonSubstruct2(struct Pokemon* pkm) { | ||
| 183 | struct BoxPokemon* boxMon = &(pkm->box); | ||
| 184 | return GetBoxPokemonSubstruct2(boxMon); | ||
| 185 | } | ||
| 186 | |||
| 187 | /** | ||
| 188 | * Gets the second substructure ("EVs & Condition") of a core Pokémon structure. | ||
| 189 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 190 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 191 | * @return struct PokemonSubstruct2* The substructure. | ||
| 192 | */ | ||
| 193 | struct PokemonSubstruct2* GetBoxPokemonSubstruct2(struct BoxPokemon* pkm) { | ||
| 194 | return &( GetBoxPokemonSubstruct(pkm,2)->type2 ); | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 198 | * Gets the third substructure ("Miscellaneous") of a Pokémon structure. | ||
| 199 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 200 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 201 | * @return struct PokemonSubstruct0* The substructure. | ||
| 202 | */ | ||
| 203 | struct PokemonSubstruct3* GetPokemonSubstruct3(struct Pokemon* pkm) { | ||
| 204 | struct BoxPokemon* boxMon = &(pkm->box); | ||
| 205 | return GetBoxPokemonSubstruct3(boxMon); | ||
| 206 | } | ||
| 207 | |||
| 208 | /** | ||
| 209 | * Gets the third substructure ("Miscellaneous") of a core Pokémon structure. | ||
| 210 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 211 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 212 | * @return struct PokemonSubstruct3* The substructure. | ||
| 213 | */ | ||
| 214 | struct PokemonSubstruct3* GetBoxPokemonSubstruct3(struct BoxPokemon* pkm) { | ||
| 215 | return &( GetBoxPokemonSubstruct(pkm,3)->type3 ); | ||
| 216 | } | ||
| 217 | |||
| 218 | /** | ||
| 219 | * Calculates the checksum for an R/S-specific Enigma Berry structure in SaveBlock1. | ||
| 220 | * @param struct EnigmaBerry* enigmaBerry The R/S-specific Enigma Berry to calculate the checksum for. | ||
| 221 | * @return u32 The checksum. | ||
| 222 | */ | ||
| 223 | u32 CalculateEnigmaBerryChecksumRS(struct EnigmaBerry* enigmaBerry) { | ||
| 224 | if (!GAME_RS) return 0; // Enigma Berry structure changed in FR/LG, use CalculateEnigmaBerryChecksumFRLGE() instead. | ||
| 225 | u32 checksum = 0; | ||
| 226 | // Save off and zero out the original Enigma Berry description pointers. | ||
| 227 | const u8* description[2] = { enigmaBerry->berry.description1, enigmaBerry->berry.description2 }; | ||
| 228 | enigmaBerry->berry.description1 = enigmaBerry->berry.description2 = NULL; | ||
| 229 | u8* enigmaBerryBytes = (u8*)enigmaBerry; | ||
| 230 | // Calculate the checksum. | ||
| 231 | for (u32 i = 0; i < 1324; i++) { | ||
| 232 | checksum += enigmaBerryBytes[i]; | ||
| 233 | } | ||
| 234 | // Restore the saved description. | ||
| 235 | enigmaBerry->berry.description1 = description[0]; | ||
| 236 | enigmaBerry->berry.description2 = description[1]; | ||
| 237 | return checksum; | ||
| 238 | } | ||
| 239 | |||
| 240 | /** | ||
| 241 | * Calculates the checksum for an FR/LG/Emerald-specific Enigma Berry structure in SaveBlock1. | ||
| 242 | * @param struct EnigmaBerryFRLGE* enigmaBerry The FR/LG/Emerald-specific Enigma Berry to calculate the checksum for. | ||
| 243 | * @return u32 The checksum. | ||
| 244 | */ | ||
| 245 | u32 CalculateEnigmaBerryChecksumFRLGE(struct EnigmaBerryFRLGE* enigmaBerry) { | ||
| 246 | if (GAME_RS) return 0; // Enigma Berry structure is different in R/S, use CalculateEnigmaBerryChecksumRS() instead. | ||
| 247 | u32 checksum = 0; | ||
| 248 | u8* enigmaBerryBytes = (u8*)enigmaBerry; | ||
| 249 | for (int i = 0; i < 0x30; i++) { | ||
| 250 | checksum += enigmaBerryBytes[i]; | ||
| 251 | } | ||
| 252 | return checksum; | ||
| 253 | } | ||
| 254 | |||
| 255 | /** | ||
| 256 | * Calculates the checksum for an unspecified Enigma Berry structure in SaveBlock1. (detected by current game) | ||
| 257 | * @param void* enigmaBerry The Enigma Berry structure to calculate the checksum for. | ||
| 258 | * @return u32 The checksum. | ||
| 259 | */ | ||
| 260 | u32 CalculateEnigmaBerryChecksum(void* enigmaBerry) { | ||
| 261 | if (GAME_RS) return CalculateEnigmaBerryChecksumRS( (struct EnigmaBerry*) enigmaBerry ); | ||
| 262 | return CalculateEnigmaBerryChecksumFRLGE( (struct EnigmaBerryFRLGE*) enigmaBerry ); | ||
| 263 | } | ||
| 264 | |||
| 265 | /** | ||
| 266 | * Calculates the checksum for a RAM script structure in SaveBlock1. | ||
| 267 | * @param struct RamScript* ramScript The RAM script structure to calculate the checksum for. | ||
| 268 | * @return u32 The checksum. | ||
| 269 | */ | ||
| 270 | u32 CalculateRamScriptChecksum(struct RamScript* ramScript) { | ||
| 271 | asm(""); // make sure the call to CalculateRamScriptDataChecksum() is *not* inlined. | ||
| 272 | // For some reason, if it gets inlined, something happens, and the wrong length is used when checksumming... | ||
| 273 | return CalculateRamScriptDataChecksum(&ramScript->data); | ||
| 274 | } | ||
| 275 | |||
| 276 | /** | ||
| 277 | * Calculates the checksum for a RAM script structure in SaveBlock1. | ||
| 278 | * @param struct RamScript* ramScript The RAM script structure to calculate the checksum for. | ||
| 279 | * @return u32 The checksum. | ||
| 280 | */ | ||
| 281 | static __attribute__ ((noinline)) u32 CalculateRamScriptDataChecksum(struct RamScriptData* ramScript) { | ||
| 282 | u32 checksum = 0; | ||
| 283 | u32 i = 0; | ||
| 284 | u8* ramScriptBytes = (u8*)(ramScript); | ||
| 285 | if (GAME_RS) { | ||
| 286 | for (i = 0; i < sizeof(struct RamScriptData); i++) checksum += ramScriptBytes[i]; | ||
| 287 | return checksum; | ||
| 288 | } | ||
| 289 | |||
| 290 | return (u32)crc16(ramScriptBytes,sizeof(struct RamScriptData) + 1); | ||
| 291 | } | ||
| 292 | |||
| 293 | /** | ||
| 294 | * Private function to CRC-16, (used by FR/LG/Emerald ramscript checksum). Adapted from http://forums.glitchcity.info/index.php?topic=7114.0 | ||
| 295 | * @param u8* Data to checksum | ||
| 296 | * @param u16 Length of data | ||
| 297 | * @return u16 The checksum | ||
| 298 | */ | ||
| 299 | static u16 crc16(const u8* data, u16 len) { | ||
| 300 | u16 crc = 0x1121; | ||
| 301 | for (u16 i = 0; i < len; ++i) { | ||
| 302 | crc ^= data[i]; | ||
| 303 | for (u16 j = 0; j < 8; ++j) { | ||
| 304 | if(crc & 1) { | ||
| 305 | crc = (crc >> 1) ^ 0x8408; | ||
| 306 | } else { | ||
| 307 | crc >>= 1; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | } | ||
| 311 | return ~crc; | ||
| 312 | } \ No newline at end of file | ||
| diff --git a/gba/source/libpayload.h b/gba/source/libpayload.h new file mode 100644 index 0000000..4be6fb3 --- /dev/null +++ b/gba/source/libpayload.h | |||
| @@ -0,0 +1,160 @@ | |||
| 1 | /* | ||
| 2 | * Example Gen3-multiboot payload by slipstream/RoL 2017. | ||
| 3 | * | ||
| 4 | * This software may be modified and distributed under the terms | ||
| 5 | * of the MIT license. See the LICENSE file for details. | ||
| 6 | * | ||
| 7 | * libpayload.h: header for payload helper functions | ||
| 8 | */ | ||
| 9 | |||
| 10 | /** | ||
| 11 | * Decrypts the substructures of a Pokémon structure, so they can be viewed or modified easily. | ||
| 12 | * Remember to call EncryptPokemon() afterwards. | ||
| 13 | * @param struct Pokemon* pkm The Pokémon to decrypt the substructures of. | ||
| 14 | */ | ||
| 15 | void DecryptPokemon(struct Pokemon* pkm); | ||
| 16 | |||
| 17 | /** | ||
| 18 | * Decrypts the substructures of a core Pokémon structure, so they can be viewed or modified easily. | ||
| 19 | * Used by DecryptPokemon(). | ||
| 20 | * Remember to call EncryptPokemon() afterwards. | ||
| 21 | * @param struct BoxPokemon* pkm The BoxPokemon to decrypt the substructures of. | ||
| 22 | */ | ||
| 23 | void DecryptBoxPokemon(struct BoxPokemon* pkm); | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Encrypts the substructures of a Pokémon structure, and fixes the checksum. | ||
| 27 | * Must be used after DecryptPokemon() has been called, otherwise the Pokémon you decrypted and forgot to re-encrypt will become a Bad Egg. | ||
| 28 | * @param struct Pokemon* pkm The Pokémon to encrypt the substructures and fix the checksum of. | ||
| 29 | */ | ||
| 30 | void EncryptPokemon(struct Pokemon* pkm); | ||
| 31 | |||
| 32 | /** | ||
| 33 | * Encrypts the substructures of a core Pokémon structure, and fixes the checksum. | ||
| 34 | * Must be used after DecryptBoxPokemon() has been called, otherwise the Pokémon you decrypted and forgot to re-encrypt will become a Bad Egg. | ||
| 35 | * @param struct BoxPokemon* pkm The BoxPokemon to encrypt the substructures and fix the checksum of. | ||
| 36 | */ | ||
| 37 | void EncryptBoxPokemon(struct BoxPokemon* pkm); | ||
| 38 | |||
| 39 | /** | ||
| 40 | * Gets a substructure of a Pokémon structure. | ||
| 41 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 42 | * @param struct Pokemon* pkm The Pokemon to get a substructure of. | ||
| 43 | * @param u8 substructId The substructure to get. | ||
| 44 | * @return union PokemonSubstruct* The substructure. | ||
| 45 | */ | ||
| 46 | union PokemonSubstruct* GetPokemonSubstruct(struct Pokemon* pkm,u8 substructId); | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Gets a substructure of a core Pokémon structure. | ||
| 50 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 51 | * @param struct Pokemon* pkm The Pokemon to get a substructure of. | ||
| 52 | * @param u8 substructId The substructure to get. | ||
| 53 | * @return union PokemonSubstruct* The substructure. | ||
| 54 | */ | ||
| 55 | union PokemonSubstruct* GetBoxPokemonSubstruct(struct BoxPokemon* pkm,u8 substructId); | ||
| 56 | |||
| 57 | /** | ||
| 58 | * Gets the checksum of a core Pokémon structure. | ||
| 59 | * @param struct BoxPokemon* pkm The BoxPokemon to calculate the checksum of. | ||
| 60 | * @return u16 The checksum. | ||
| 61 | */ | ||
| 62 | u16 CalculateBoxPokemonChecksum(struct BoxPokemon* pkm); | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Fixes the checksum of a core Pokémon structure. | ||
| 66 | * @param struct BoxPokemon* pkm The BoxPokemon to fix the checksum of. | ||
| 67 | */ | ||
| 68 | void FixBoxPokemonChecksum(struct BoxPokemon* pkm); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Gets the zeroth substructure ("Growth") of a Pokémon structure. | ||
| 72 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 73 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 74 | * @return struct PokemonSubstruct0* The substructure. | ||
| 75 | */ | ||
| 76 | struct PokemonSubstruct0* GetPokemonSubstruct0(struct Pokemon* pkm); | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Gets the zeroth substructure ("Growth") of a core Pokémon structure. | ||
| 80 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 81 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 82 | * @return struct PokemonSubstruct0* The substructure. | ||
| 83 | */ | ||
| 84 | struct PokemonSubstruct0* GetBoxPokemonSubstruct0(struct BoxPokemon* pkm); | ||
| 85 | |||
| 86 | /** | ||
| 87 | * Gets the first substructure ("Attacks") of a Pokémon structure. | ||
| 88 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 89 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 90 | * @return struct PokemonSubstruct0* The substructure. | ||
| 91 | */ | ||
| 92 | struct PokemonSubstruct1* GetPokemonSubstruct1(struct Pokemon* pkm); | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Gets the first substructure ("Attacks") of a core Pokémon structure. | ||
| 96 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 97 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 98 | * @return struct PokemonSubstruct1* The substructure. | ||
| 99 | */ | ||
| 100 | struct PokemonSubstruct1* GetBoxPokemonSubstruct1(struct BoxPokemon* pkm); | ||
| 101 | |||
| 102 | /** | ||
| 103 | * Gets the second substructure ("EVs & Condition") of a Pokémon structure. | ||
| 104 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 105 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 106 | * @return struct PokemonSubstruct0* The substructure. | ||
| 107 | */ | ||
| 108 | struct PokemonSubstruct2* GetPokemonSubstruct2(struct Pokemon* pkm); | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Gets the second substructure ("EVs & Condition") of a core Pokémon structure. | ||
| 112 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 113 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 114 | * @return struct PokemonSubstruct2* The substructure. | ||
| 115 | */ | ||
| 116 | struct PokemonSubstruct2* GetBoxPokemonSubstruct2(struct BoxPokemon* pkm); | ||
| 117 | |||
| 118 | /** | ||
| 119 | * Gets the third substructure ("Miscellaneous") of a Pokémon structure. | ||
| 120 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
| 121 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
| 122 | * @return struct PokemonSubstruct0* The substructure. | ||
| 123 | */ | ||
| 124 | struct PokemonSubstruct3* GetPokemonSubstruct3(struct Pokemon* pkm); | ||
| 125 | |||
| 126 | /** | ||
| 127 | * Gets the third substructure ("Miscellaneous") of a core Pokémon structure. | ||
| 128 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
| 129 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
| 130 | * @return struct PokemonSubstruct3* The substructure. | ||
| 131 | */ | ||
| 132 | struct PokemonSubstruct3* GetBoxPokemonSubstruct3(struct BoxPokemon* pkm); | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Calculates the checksum for an R/S-specific Enigma Berry structure in SaveBlock1. | ||
| 136 | * @param struct EnigmaBerry* enigmaBerry The R/S-specific Enigma Berry to calculate the checksum for. | ||
| 137 | * @return u32 The checksum. | ||
| 138 | */ | ||
| 139 | u32 CalculateEnigmaBerryChecksumRS(struct EnigmaBerry* enigmaBerry); | ||
| 140 | |||
| 141 | /** | ||
| 142 | * Calculates the checksum for an FR/LG/Emerald-specific Enigma Berry structure in SaveBlock1. | ||
| 143 | * @param struct EnigmaBerryFRLGE* enigmaBerry The FR/LG/Emerald-specific Enigma Berry to calculate the checksum for. | ||
| 144 | * @return u32 The checksum. | ||
| 145 | */ | ||
| 146 | u32 CalculateEnigmaBerryChecksumFRLGE(struct EnigmaBerryFRLGE* enigmaBerry); | ||
| 147 | |||
| 148 | /** | ||
| 149 | * Calculates the checksum for an unspecified Enigma Berry structure in SaveBlock1. (detected by current game) | ||
| 150 | * @param void* enigmaBerry The Enigma Berry structure to calculate the checksum for. | ||
| 151 | * @return u32 The checksum. | ||
| 152 | */ | ||
| 153 | u32 CalculateEnigmaBerryChecksum(void* enigmaBerry); | ||
| 154 | |||
| 155 | /** | ||
| 156 | * Calculates the checksum for a RAM script structure in SaveBlock1. | ||
| 157 | * @param struct RamScript* ramScript The RAM script structure to calculate the checksum for. | ||
| 158 | * @return u32 The checksum. | ||
| 159 | */ | ||
| 160 | u32 CalculateRamScriptChecksum(struct RamScript* ramScript); \ No newline at end of file | ||
| diff --git a/gba/source/payload.c b/gba/source/payload.c index 7015774..665af70 100644 --- a/gba/source/payload.c +++ b/gba/source/payload.c | |||
| @@ -12,7 +12,61 @@ | |||
| 12 | 12 | ||
| 13 | // Your payload code should obviously go into the body of this, the payload function. | 13 | // Your payload code should obviously go into the body of this, the payload function. | 
| 14 | void payload(pSaveBlock1 SaveBlock1,pSaveBlock2 SaveBlock2,pSaveBlock3 SaveBlock3) { | 14 | void payload(pSaveBlock1 SaveBlock1,pSaveBlock2 SaveBlock2,pSaveBlock3 SaveBlock3) { | 
| 15 | // This example payload will modify the first character of the player's name. | 15 | // HoF-warp example payload! | 
| 16 | // It will change to 'z'. You can see the character encoding table here: http://bulbapedia.bulbagarden.net/wiki/Character_encoding_in_Generation_III | 16 | |
| 17 | SaveBlock2[0] = 0xee; // 'z' | 17 | // Structure offsets are different between R/S, FR/LG, and Emerald. | 
| 18 | // The beginning of the structures are the same but do NOT take shortcuts here, it's not good practise. | ||
| 19 | // If you want to support multiple games, make specific checks for games, use the right structure for each game. | ||
| 20 | SaveBlock1_RS* sb1rs = &SaveBlock1->rs; | ||
| 21 | SaveBlock1_FRLG* sb1frlg = &SaveBlock1->frlg; | ||
| 22 | SaveBlock1_E* sb1e = &SaveBlock1->e; | ||
| 23 | if (GAME_FRLG) { | ||
| 24 | sb1frlg->location.mapGroup = 1; // generic indoors? | ||
| 25 | sb1frlg->location.mapNum = 80; // Hall of Fame | ||
| 26 | // set coords to the same place that the champions' room script sets them to | ||
| 27 | sb1frlg->location.x = sb1frlg->pos.x = 5; | ||
| 28 | sb1frlg->location.y = sb1frlg->pos.y = 12; | ||
| 29 | sb1frlg->mapDataId = 0xDA; // from HoF map-header | ||
| 30 | sb1frlg->location.warpId = 0xff; | ||
| 31 | // make sure the HoF script doesn't crash, which it will do if 0 pokémon | ||
| 32 | if (sb1frlg->playerPartyCount == 0) { | ||
| 33 | sb1frlg->playerPartyCount = 1; | ||
| 34 | // this isn't enough, the heal animation recalculates the party count ignoring empty spots | ||
| 35 | // so let's hack together one. i don't care about it becoming a bad egg at all. | ||
| 36 | sb1frlg->playerParty[0].box.personality++; | ||
| 37 | } | ||
| 38 | return; | ||
| 39 | } else if (GAME_RS) { | ||
| 40 | sb1rs->location.mapGroup = 16; // Ever Grande City | ||
| 41 | sb1rs->location.mapNum = 11; // Hall of Fame | ||
| 42 | // set coords to the same place that the champions' room script sets them to | ||
| 43 | sb1rs->location.x = sb1rs->pos.x = 7; | ||
| 44 | sb1rs->location.y = sb1rs->pos.y = 16; | ||
| 45 | sb1rs->mapDataId = 299; // from HoF map-header | ||
| 46 | sb1rs->location.warpId = 0xff; | ||
| 47 | // make sure the HoF script doesn't crash, which it will do if 0 pokémon | ||
| 48 | if (sb1rs->playerPartyCount == 0) { | ||
| 49 | sb1rs->playerPartyCount = 1; | ||
| 50 | // this isn't enough, the heal animation recalculates the party count ignoring empty spots | ||
| 51 | // so let's hack together one. i don't care about it becoming a bad egg at all. | ||
| 52 | sb1rs->playerParty[0].box.personality++; | ||
| 53 | } | ||
| 54 | return; | ||
| 55 | } else if (GAME_EM) { | ||
| 56 | sb1e->location.mapGroup = 16; // Ever Grande City | ||
| 57 | sb1e->location.mapNum = 11; // Hall of Fame | ||
| 58 | // set coords to the same place that the champions' room script sets them to | ||
| 59 | sb1e->location.x = sb1e->pos.x = 7; | ||
| 60 | sb1e->location.y = sb1e->pos.y = 16; | ||
| 61 | sb1e->mapDataId = 298; // from HoF map-header | ||
| 62 | sb1e->location.warpId = 0xff; | ||
| 63 | // make sure the HoF script doesn't crash, which it will do if 0 pokémon | ||
| 64 | if (sb1e->playerPartyCount == 0) { | ||
| 65 | sb1e->playerPartyCount = 1; | ||
| 66 | // this isn't enough, the heal animation recalculates the party count ignoring empty spots | ||
| 67 | // so let's hack together one. i don't care about it becoming a bad egg at all. | ||
| 68 | sb1e->playerParty[0].box.personality++; | ||
| 69 | } | ||
| 70 | return; | ||
| 71 | } | ||
| 18 | } \ No newline at end of file | 72 | } \ No newline at end of file | 
| diff --git a/gba/source/payload.h b/gba/source/payload.h index d95476c..ea87200 100644 --- a/gba/source/payload.h +++ b/gba/source/payload.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | */ | 8 | */ | 
| 9 | 9 | ||
| 10 | #include "saveblocks.h" | 10 | #include "saveblocks.h" | 
| 11 | #include "libpayload.h" | ||
| 11 | 12 | ||
| 12 | #define GAME_RUBY (((*(u32*)(0x80000AC)) << 8) == 'VXA\x00') | 13 | #define GAME_RUBY (((*(u32*)(0x80000AC)) << 8) == 'VXA\x00') | 
| 13 | #define GAME_SAPP (((*(u32*)(0x80000AC)) << 8) == 'PXA\x00') | 14 | #define GAME_SAPP (((*(u32*)(0x80000AC)) << 8) == 'PXA\x00') | 
| diff --git a/gba/source/saveblocks.h b/gba/source/saveblocks.h index 45c127c..cf0a5c3 100644 --- a/gba/source/saveblocks.h +++ b/gba/source/saveblocks.h | |||
| @@ -7,9 +7,337 @@ | |||
| 7 | * saveblocks.h: describes saveblock structures for all of Gen 3 (yay!) | 7 | * saveblocks.h: describes saveblock structures for all of Gen 3 (yay!) | 
| 8 | */ | 8 | */ | 
| 9 | 9 | ||
| 10 | // TODO: this entire file. Placeholders for now, fill in later, if I can be bothered. | 10 | // Most of the structures come from pokeruby, FR/LG changes come from my own research / the firered IDB on pokecommunity | 
| 11 | // I don't really want to make a fork of pokeruby's headers for now... | 11 | #include "savestructs.h" | 
| 12 | 12 | ||
| 13 | typedef u8 SaveBlock1, *pSaveBlock1; | 13 | typedef struct | 
| 14 | typedef u8 SaveBlock2, *pSaveBlock2; | 14 | { | 
| 15 | typedef u8 SaveBlock3, *pSaveBlock3; \ No newline at end of file | 15 | /*0x00*/ struct Coords16 pos; | 
| 16 | /*0x04*/ struct WarpData location; | ||
| 17 | /*0x0C*/ struct WarpData warp[4]; | ||
| 18 | /*0x2C*/ u16 battleMusic; | ||
| 19 | /*0x2E*/ u8 weather; | ||
| 20 | /*0x2F*/ u8 filler_2F; | ||
| 21 | /*0x30*/ u8 flashUsed; | ||
| 22 | /*0x32*/ u16 mapDataId; | ||
| 23 | /*0x34*/ u16 mapView[0x100]; | ||
| 24 | /*0x234*/ u8 playerPartyCount; | ||
| 25 | /*0x238*/ struct Pokemon playerParty[6]; | ||
| 26 | /*0x490*/ u32 money; | ||
| 27 | /*0x494*/ u16 coins; | ||
| 28 | /*0x496*/ u16 registeredItem; // registered for use with SELECT button | ||
| 29 | /*0x498*/ struct ItemSlot pcItems[50]; | ||
| 30 | /*0x560*/ struct ItemSlot bagPocket_Items[20]; | ||
| 31 | /*0x5B0*/ struct ItemSlot bagPocket_KeyItems[20]; | ||
| 32 | /*0x600*/ struct ItemSlot bagPocket_PokeBalls[16]; | ||
| 33 | /*0x640*/ struct ItemSlot bagPocket_TMHM[64]; | ||
| 34 | /*0x740*/ struct ItemSlot bagPocket_Berries[46]; | ||
| 35 | /*0x7F8*/ struct Pokeblock pokeblocks[40]; | ||
| 36 | /*0x938*/ u8 unk938[52]; // pokedex related | ||
| 37 | /*0x96C*/ u16 berryBlenderRecords[3]; | ||
| 38 | /*0x972*/ u8 filler_972[0x6]; | ||
| 39 | /*0x978*/ u16 trainerRematchStepCounter; | ||
| 40 | /*0x97A*/ u8 trainerRematches[100]; | ||
| 41 | /*0x9E0*/ struct MapObject mapObjects[16]; | ||
| 42 | /*0xC20*/ struct MapObjectTemplate mapObjectTemplates[64]; | ||
| 43 | /*0x1220*/ u8 flags[0x120]; | ||
| 44 | /*0x1340*/ u16 vars[0x100]; | ||
| 45 | /*0x1540*/ u32 gameStats[50]; | ||
| 46 | /*0x1608*/ struct BerryTree berryTrees[128]; | ||
| 47 | /*0x1A08*/ struct SecretBaseRecord secretBases[20]; | ||
| 48 | /*0x2688*/ u8 playerRoomDecor[12]; | ||
| 49 | /*0x2694*/ u8 playerRoomDecorPos[12]; | ||
| 50 | /*0x26A0*/ u8 decorDesk[10]; | ||
| 51 | /*0x26AA*/ u8 decorChair[10]; | ||
| 52 | /*0x26B4*/ u8 decorPlant[10]; | ||
| 53 | /*0x26BE*/ u8 decorOrnament[30]; | ||
| 54 | /*0x26DC*/ u8 decorMat[30]; | ||
| 55 | /*0x26FA*/ u8 decorPoster[10]; | ||
| 56 | /*0x2704*/ u8 decorDoll[40]; | ||
| 57 | /*0x272C*/ u8 decorCushion[10]; | ||
| 58 | /*0x2736*/ u8 padding_2736[2]; | ||
| 59 | /*0x2738*/ TVShow tvShows[24]; | ||
| 60 | /*0x2A98*/ u8 filler_2A98[0x64]; | ||
| 61 | /*0x2AFC*/ u16 outbreakPokemonSpecies; | ||
| 62 | /*0x2AFE*/ u8 outbreakLocationMapNum; | ||
| 63 | /*0x2AFF*/ u8 outbreakLocationMapGroup; | ||
| 64 | /*0x2B00*/ u8 outbreakPokemonLevel; | ||
| 65 | /*0x2B01*/ u8 outbreakUnk1; | ||
| 66 | /*0x2B02*/ u16 outbreakUnk2; | ||
| 67 | /*0x2B04*/ u16 outbreakPokemonMoves[4]; | ||
| 68 | /*0x2B0C*/ u8 outbreakUnk4; | ||
| 69 | /*0x2B0D*/ u8 outbreakPokemonProbability; | ||
| 70 | /*0x2B0E*/ u16 outbreakUnk5; | ||
| 71 | /*0x2B10*/ u8 filler_2B0E[0xC]; | ||
| 72 | /*0x2B1C*/ u16 unk2B1C[4]; | ||
| 73 | /*0x2B24*/ u8 filler_2B24[0x28]; | ||
| 74 | /*0x2B4C*/ struct MailStruct mail[16]; | ||
| 75 | /*0x2D8C*/ u8 filler_2D8C[0x8]; | ||
| 76 | /*0x2D94*/ OldMan oldMan; | ||
| 77 | /*0x2DC0*/ u8 unk_2DC0[0x14]; | ||
| 78 | /*0x2DD4*/ struct EasyChatPair easyChatPairs[5]; //Dewford trend [0] and some other stuff | ||
| 79 | /*0x2DFC*/ u8 filler_2DFC[0x100]; | ||
| 80 | /*0x2EFC*/ struct SB1_2EFC_Struct sb1_2EFC_struct[5]; | ||
| 81 | /*0x2F9C*/ u8 filler_2F9C[0xA0]; | ||
| 82 | /*0x303C*/ u8 filler_303C[0x38]; | ||
| 83 | /*0x3074*/ u8 filler_3074[0x42]; | ||
| 84 | /*0x30B6*/ u8 filler_30B6; | ||
| 85 | /*0x30B7*/ u8 filler_30B7[0x59]; | ||
| 86 | /*0x3110*/ u8 giftRibbons[7]; | ||
| 87 | /*0x3117*/ u8 filler_311B[0x2D]; | ||
| 88 | /*0x3144*/ struct Roamer roamer; | ||
| 89 | /*0x3158*/ u8 filler_3158[0x8]; | ||
| 90 | /*0x3160*/ struct EnigmaBerry enigmaBerry; // this is actually offset by 0x98 ... | ||
| 91 | /*0x3690*/ struct RamScript ramScript; | ||
| 92 | /*0x3A7C*/ u8 filler_3A7C[0x10]; | ||
| 93 | /*0x3A8C*/ u8 unk3A8C[52]; //pokedex related | ||
| 94 | } SaveBlock1_RS; | ||
| 95 | |||
| 96 | typedef struct // Don't rely on the commented offsets, they'll be wrong due to elements removed in FR/LG... | ||
| 97 | { | ||
| 98 | /*0x00*/ struct Coords16 pos; | ||
| 99 | /*0x04*/ struct WarpData location; | ||
| 100 | /*0x0C*/ struct WarpData warp[4]; | ||
| 101 | /*0x2C*/ u16 battleMusic; | ||
| 102 | /*0x2E*/ u8 weather; | ||
| 103 | /*0x2F*/ u8 filler_2F; | ||
| 104 | /*0x30*/ u8 flashUsed; | ||
| 105 | /*0x32*/ u16 mapDataId; | ||
| 106 | // /*0x34*/ u16 mapView[0x100]; // Not in fr/lg | ||
| 107 | /*0x234*/ u8 playerPartyCount; | ||
| 108 | /*0x238*/ struct Pokemon playerParty[6]; | ||
| 109 | /*0x490*/ u32 money; | ||
| 110 | /*0x494*/ u16 coins; | ||
| 111 | /*0x496*/ u16 registeredItem; // registered for use with SELECT button | ||
| 112 | /*0x498*/ struct ItemSlot pcItems[30]; | ||
| 113 | /*0x560*/ struct ItemSlot bagPocket_Items[42]; | ||
| 114 | /*0x5B0*/ struct ItemSlot bagPocket_KeyItems[30]; | ||
| 115 | /*0x600*/ struct ItemSlot bagPocket_PokeBalls[13]; | ||
| 116 | /*0x640*/ struct ItemSlot bagPocket_TMHM[58]; | ||
| 117 | /*0x740*/ struct ItemSlot bagPocket_Berries[43]; | ||
| 118 | // /*0x7F8*/ struct Pokeblock pokeblocks[40]; // Not in fr/lg | ||
| 119 | /*0x938*/ u8 unk938[52]; // pokedex related | ||
| 120 | /*0x96C*/ u8 unk_62C[12]; | ||
| 121 | /*0x972*/ u8 filler_972[0x6]; | ||
| 122 | /*0x97A*/ u8 unk_63E[98]; | ||
| 123 | /*0x9E0*/ struct MapObject mapObjects[16]; | ||
| 124 | /*0xC20*/ struct MapObjectTemplate mapObjectTemplates[64]; | ||
| 125 | /*0x1220*/ u8 flags[0x120]; | ||
| 126 | /*0x1340*/ u16 vars[0x100]; | ||
| 127 | /*0x1540*/ u32 gameStats[64]; // encrypted with saveblock2 xor-key | ||
| 128 | struct QuestStory questlog[4]; | ||
| 129 | u8 messages[12][4]; | ||
| 130 | struct NPCState npc_states[0x10]; | ||
| 131 | u8 unk_2f10[112]; | ||
| 132 | struct DaycarePokemon daycare[2]; | ||
| 133 | u8 unk_3098[56]; | ||
| 134 | struct Roamer roamer; | ||
| 135 | u8 unk_30e4[8]; | ||
| 136 | /*0x3160*/ struct EnigmaBerryFRLGE enigmaBerry; | ||
| 137 | u8 unk_3120[0x1C0]; // 4 bytes of CRC16, then 444 bytes of unknown. Mystery Gift related. | ||
| 138 | u8 unk_32E0[0x150]; // 4 bytes of CRC16, then 332 bytes of unknown. Mystery Gift related. "mevent_buffer_1" | ||
| 139 | u8 unk_3430[0x150]; // 4 bytes of CRC16, then 332 bytes of unknown. Mystery Gift related. "mevent_buffer_2" | ||
| 140 | u8 unk_368C[0x9C]; // padding? doesn't seem to be actually used | ||
| 141 | struct RamScript ramScript; | ||
| 142 | u8 unk_3A07[17]; | ||
| 143 | u8 pokemon_flags_2[52]; | ||
| 144 | u8 rivalName[8]; | ||
| 145 | u8 unk_3a54[128]; | ||
| 146 | u8 words[21][10]; | ||
| 147 | u8 unk_3ba6[570]; | ||
| 148 | } __attribute__((aligned(1))) SaveBlock1_FRLG; | ||
| 149 | |||
| 150 | typedef struct // Don't rely on the commented offsets, they'll be wrong due to elements changed/added in Emerald... | ||
| 151 | { | ||
| 152 | /*0x00*/ struct Coords16 pos; | ||
| 153 | /*0x04*/ struct WarpData location; | ||
| 154 | /*0x0C*/ struct WarpData warp[4]; | ||
| 155 | /*0x2C*/ u16 battleMusic; | ||
| 156 | /*0x2E*/ u8 weather; | ||
| 157 | /*0x2F*/ u8 filler_2F; | ||
| 158 | /*0x30*/ u8 flashUsed; | ||
| 159 | /*0x32*/ u16 mapDataId; | ||
| 160 | /*0x34*/ u16 mapView[0x100]; | ||
| 161 | /*0x234*/ u8 playerPartyCount; | ||
| 162 | /*0x238*/ struct Pokemon playerParty[6]; | ||
| 163 | /*0x490*/ u32 money; | ||
| 164 | /*0x494*/ u16 coins; | ||
| 165 | /*0x496*/ u16 registeredItem; // registered for use with SELECT button | ||
| 166 | /*0x498*/ struct ItemSlot pcItems[50]; | ||
| 167 | /*0x560*/ struct ItemSlot bagPocket_Items[30]; | ||
| 168 | /*0x5D8*/ struct ItemSlot bagPocket_KeyItems[30]; | ||
| 169 | /*0x650*/ struct ItemSlot bagPocket_PokeBalls[16]; | ||
| 170 | /*0x690*/ struct ItemSlot bagPocket_TMHM[64]; | ||
| 171 | /*0x790*/ struct ItemSlot bagPocket_Berries[46]; | ||
| 172 | /*0x7F8*/ struct Pokeblock pokeblocks[40]; // every offset is shifted by 0x50 from here on thanks to changed bag-counts | ||
| 173 | /*0x938*/ u8 unk938[52]; // pokedex related | ||
| 174 | /*0x96C*/ u16 berryBlenderRecords[3]; | ||
| 175 | /*0x972*/ u8 filler_972[0x6]; | ||
| 176 | /*0x978*/ u16 trainerRematchStepCounter; | ||
| 177 | /*0x97A*/ u8 trainerRematches[100]; | ||
| 178 | /*0x9E0*/ struct MapObject mapObjects[16]; | ||
| 179 | /*0xC20*/ struct MapObjectTemplate mapObjectTemplates[64]; | ||
| 180 | /*0x1220*/ u8 flags[0x12C]; | ||
| 181 | /*0x1340*/ u16 vars[0x100]; // offsets shifted by 0x5C from here on thanks to added flags | ||
| 182 | /*0x1540*/ u32 gameStats[64]; // encrypted with saveblock2 xor-key | ||
| 183 | /*0x1608*/ struct BerryTree berryTrees[128]; // offsets shifted by 0x94 from here on thanks to added 14 gamestats | ||
| 184 | /*0x1A08*/ struct SecretBaseRecord secretBases[20]; | ||
| 185 | /*0x2688*/ u8 playerRoomDecor[12]; | ||
| 186 | /*0x2694*/ u8 playerRoomDecorPos[12]; | ||
| 187 | /*0x26A0*/ u8 decorDesk[10]; | ||
| 188 | /*0x26AA*/ u8 decorChair[10]; | ||
| 189 | /*0x26B4*/ u8 decorPlant[10]; | ||
| 190 | /*0x26BE*/ u8 decorOrnament[30]; | ||
| 191 | /*0x26DC*/ u8 decorMat[30]; | ||
| 192 | /*0x26FA*/ u8 decorPoster[10]; | ||
| 193 | /*0x2704*/ u8 decorDoll[40]; | ||
| 194 | /*0x272C*/ u8 decorCushion[10]; | ||
| 195 | // /*0x2736*/ u8 padding_2736[2]; | ||
| 196 | /*0x2738*/ TVShow tvShows[24]; | ||
| 197 | /*0x2A98*/ u8 filler_2A98[0x64]; | ||
| 198 | /*0x2AFC*/ u16 outbreakPokemonSpecies; // offset by 0x94 | ||
| 199 | /*0x2AFE*/ u8 outbreakLocationMapNum; | ||
| 200 | /*0x2AFF*/ u8 outbreakLocationMapGroup; | ||
| 201 | /*0x2B00*/ u8 outbreakPokemonLevel; | ||
| 202 | /*0x2B01*/ u8 outbreakUnk1; | ||
| 203 | /*0x2B02*/ u16 outbreakUnk2; | ||
| 204 | /*0x2B04*/ u16 outbreakPokemonMoves[4]; | ||
| 205 | /*0x2B0C*/ u8 outbreakUnk4; | ||
| 206 | /*0x2B0D*/ u8 outbreakPokemonProbability; | ||
| 207 | /*0x2B0E*/ u16 outbreakUnk5; | ||
| 208 | /*0x2B10*/ u8 filler_2B0E[0xC]; | ||
| 209 | /*0x2B1C*/ u16 unk2B1C[4]; | ||
| 210 | /*0x2B24*/ u8 filler_2B24[0x28]; | ||
| 211 | /*0x2B4C*/ struct MailStruct mail[16]; // offset by 0x94 | ||
| 212 | /*0x2D8C*/ u8 filler_2D8C[0x8]; | ||
| 213 | /*0x2D94*/ OldMan oldMan; | ||
| 214 | /*0x2DC0*/ u8 unk_2DC0[0x14]; | ||
| 215 | /*0x2DD4*/ struct EasyChatPair easyChatPairs[5]; //Dewford trend [0] and some other stuff | ||
| 216 | // /*0x2DFC*/ u8 filler_2DFC[0x100]; | ||
| 217 | /*0x2EFC*/ struct SB1_2EFC_Struct sb1_2EFC_struct[12]; | ||
| 218 | u8 unk_3010[0x198]; // no idea if any of this is actually used. | ||
| 219 | /*0x3110*/ u8 giftRibbons[7]; | ||
| 220 | /*0x3117*/ u8 filler_311B[0x2D]; | ||
| 221 | /*0x3144*/ struct Roamer roamer; | ||
| 222 | /*0x3158*/ u8 filler_3158[0x8]; | ||
| 223 | /*0x3160*/ struct EnigmaBerryFRLGE enigmaBerry; | ||
| 224 | u8 unk_322C[0x1C0]; // 4 bytes of CRC16, then 444 bytes of unknown. Mystery Gift related. | ||
| 225 | u8 unk_33EC[0x150]; // 4 bytes of CRC16, then 332 bytes of unknown. Mystery Gift related. "mevent_buffer_1" | ||
| 226 | u8 unk_353C[0x150]; // 4 bytes of CRC16, then 332 bytes of unknown. Mystery Gift related. "mevent_buffer_2" | ||
| 227 | u8 unk_368C[0x9C]; // padding? doesn't seem to be actually used | ||
| 228 | /*0x3690*/ struct RamScript ramScript; | ||
| 229 | /*0x3A7C*/ u8 filler_3A7C[0x10]; | ||
| 230 | /*0x3A8C*/ u8 unk3A8C[52]; //pokedex related | ||
| 231 | } SaveBlock1_E; | ||
| 232 | |||
| 233 | // --- | ||
| 234 | |||
| 235 | struct SaveBlock2_Sub | ||
| 236 | { | ||
| 237 | /*0x0000, 0x00A8*/ u8 filler_000[0x4AE]; | ||
| 238 | /*0x04AE, 0x0556*/ u8 var_4AE; | ||
| 239 | /*0x04AF, 0x0557*/ u8 var_4AF; | ||
| 240 | /*0x04B0, 0x0558*/ u16 var_4B0; | ||
| 241 | /*0x04B2, 0x055A*/ u16 var_4B2; | ||
| 242 | /*0x04B4, 0x055C*/ u16 var_4B4; | ||
| 243 | /*0x04B6, 0x055E*/ u16 var_4B6; | ||
| 244 | /*0x04B8, 0x0560*/ u8 filler_4B8[0x10]; | ||
| 245 | /*0x04C8, 0x0570*/ u16 var_4C8; | ||
| 246 | /*0x04CA, 0x0572*/ u16 var_4CA; | ||
| 247 | /*0x04CC, 0x0574*/ u8 filler_4CC[0x31C]; | ||
| 248 | }; | ||
| 249 | |||
| 250 | typedef struct | ||
| 251 | { | ||
| 252 | /*0x00*/ u8 playerName[8]; | ||
| 253 | /*0x08*/ u8 playerGender; // MALE, FEMALE | ||
| 254 | /*0x09*/ u8 specialSaveWarp; | ||
| 255 | /*0x0A*/ u8 playerTrainerId[4]; | ||
| 256 | /*0x0E*/ u16 playTimeHours; | ||
| 257 | /*0x10*/ u8 playTimeMinutes; | ||
| 258 | /*0x11*/ u8 playTimeSeconds; | ||
| 259 | /*0x12*/ u8 playTimeVBlanks; | ||
| 260 | /*0x13*/ u8 optionsButtonMode; // OPTIONS_BUTTON_MODE_[NORMAL/LR/L_EQUALS_A] | ||
| 261 | /*0x14*/ u16 optionsTextSpeed:3; // OPTIONS_TEXT_SPEED_[SLOW/MID/FAST] | ||
| 262 | u16 optionsWindowFrameType:5; // Specifies one of the 20 decorative borders for text boxes | ||
| 263 | u16 optionsSound:1; // OPTIONS_SOUND_[MONO/STEREO] | ||
| 264 | u16 optionsBattleStyle:1; // OPTIONS_BATTLE_STYLE_[SHIFT/SET] | ||
| 265 | u16 optionsBattleSceneOff:1; // whether battle animations are disabled | ||
| 266 | u16 regionMapZoom:1; // whether the map is zoomed in | ||
| 267 | /*0x18*/ struct Pokedex pokedex; | ||
| 268 | /*0x90*/ u8 filler_90[0x8]; | ||
| 269 | /*0x98*/ struct Time localTimeOffset; | ||
| 270 | /*0xA0*/ struct Time lastBerryTreeUpdate; | ||
| 271 | /*0xA8*/ struct SaveBlock2_Sub filler_A8; | ||
| 272 | } SaveBlock2_RS; | ||
| 273 | |||
| 274 | typedef struct | ||
| 275 | { | ||
| 276 | /*0x00*/ u8 playerName[8]; | ||
| 277 | /*0x08*/ u8 playerGender; // MALE, FEMALE | ||
| 278 | /*0x09*/ u8 specialSaveWarp; | ||
| 279 | /*0x0A*/ u8 playerTrainerId[4]; | ||
| 280 | /*0x0E*/ u16 playTimeHours; | ||
| 281 | /*0x10*/ u8 playTimeMinutes; | ||
| 282 | /*0x11*/ u8 playTimeSeconds; | ||
| 283 | /*0x12*/ u8 playTimeVBlanks; | ||
| 284 | /*0x13*/ u8 optionsButtonMode; // OPTIONS_BUTTON_MODE_[NORMAL/LR/L_EQUALS_A] | ||
| 285 | /*0x14*/ u16 optionsTextSpeed:3; // OPTIONS_TEXT_SPEED_[SLOW/MID/FAST] | ||
| 286 | u16 optionsWindowFrameType:5; // Specifies one of the 20 decorative borders for text boxes | ||
| 287 | u16 optionsSound:1; // OPTIONS_SOUND_[MONO/STEREO] | ||
| 288 | u16 optionsBattleStyle:1; // OPTIONS_BATTLE_STYLE_[SHIFT/SET] | ||
| 289 | u16 optionsBattleSceneOff:1; // whether battle animations are disabled | ||
| 290 | u16 regionMapZoom:1; // whether the map is zoomed in | ||
| 291 | /*0x18*/ struct Pokedex pokedex; | ||
| 292 | /*0x90*/ u8 filler_90[0x8]; | ||
| 293 | /*0x98*/ struct Time localTimeOffset; | ||
| 294 | /*0xA0*/ struct Time lastBerryTreeUpdate; | ||
| 295 | /*0xA8*/ struct SaveBlock2_Sub filler_A8; | ||
| 296 | /*0x890*/ u8 unk_890[8]; | ||
| 297 | /*0x898*/ u8 mapdata[0x258]; | ||
| 298 | /*0xaf0*/ u16 field_af0; | ||
| 299 | /*0xaf2*/ u16 field_af2; | ||
| 300 | /*0xaf4*/ u16 field_af4; | ||
| 301 | /*0xaf6*/ u16 field_af6; | ||
| 302 | /*0xaf8*/ u8 unk_af8[0x428]; | ||
| 303 | /*0xf20*/ u32 xor_key; | ||
| 304 | } SaveBlock2_FRLG; | ||
| 305 | |||
| 306 | typedef struct | ||
| 307 | { | ||
| 308 | /*0x00*/ u8 playerName[8]; | ||
| 309 | /*0x08*/ u8 playerGender; // MALE, FEMALE | ||
| 310 | /*0x09*/ u8 specialSaveWarp; | ||
| 311 | /*0x0A*/ u8 playerTrainerId[4]; | ||
| 312 | /*0x0E*/ u16 playTimeHours; | ||
| 313 | /*0x10*/ u8 playTimeMinutes; | ||
| 314 | /*0x11*/ u8 playTimeSeconds; | ||
| 315 | /*0x12*/ u8 playTimeVBlanks; | ||
| 316 | /*0x13*/ u8 optionsButtonMode; // OPTIONS_BUTTON_MODE_[NORMAL/LR/L_EQUALS_A] | ||
| 317 | /*0x14*/ u16 optionsTextSpeed:3; // OPTIONS_TEXT_SPEED_[SLOW/MID/FAST] | ||
| 318 | u16 optionsWindowFrameType:5; // Specifies one of the 20 decorative borders for text boxes | ||
| 319 | u16 optionsSound:1; // OPTIONS_SOUND_[MONO/STEREO] | ||
| 320 | u16 optionsBattleStyle:1; // OPTIONS_BATTLE_STYLE_[SHIFT/SET] | ||
| 321 | u16 optionsBattleSceneOff:1; // whether battle animations are disabled | ||
| 322 | u16 regionMapZoom:1; // whether the map is zoomed in | ||
| 323 | /*0x18*/ struct Pokedex pokedex; | ||
| 324 | /*0x90*/ u8 filler_90[0x8]; | ||
| 325 | /*0x98*/ struct Time localTimeOffset; | ||
| 326 | /*0xA0*/ struct Time lastBerryTreeUpdate; | ||
| 327 | /*0xA8*/ u32 xor_key; | ||
| 328 | /*0xAC*/ struct SaveBlock2_Sub filler_A8; | ||
| 329 | } SaveBlock2_E; | ||
| 330 | |||
| 331 | typedef union { | ||
| 332 | SaveBlock1_RS rs; | ||
| 333 | SaveBlock1_FRLG frlg; | ||
| 334 | SaveBlock1_E e; | ||
| 335 | } SaveBlock1, *pSaveBlock1; | ||
| 336 | |||
| 337 | typedef union { | ||
| 338 | SaveBlock2_RS rs; | ||
| 339 | SaveBlock2_FRLG frlg; | ||
| 340 | SaveBlock2_E e; | ||
| 341 | } SaveBlock2, *pSaveBlock2; | ||
| 342 | |||
| 343 | typedef struct PokemonStorage SaveBlock3, *pSaveBlock3; \ No newline at end of file | ||
| diff --git a/gba/source/savestructs.h b/gba/source/savestructs.h new file mode 100644 index 0000000..2bf4d4d --- /dev/null +++ b/gba/source/savestructs.h | |||
| @@ -0,0 +1,793 @@ | |||
| 1 | /* | ||
| 2 | * Example Gen3-multiboot payload by slipstream/RoL 2017. | ||
| 3 | * | ||
| 4 | * This software may be modified and distributed under the terms | ||
| 5 | * of the MIT license. See the LICENSE file for details. | ||
| 6 | * | ||
| 7 | * saveblocks.h: describes structures used by saveblocks for all of Gen 3 | ||
| 8 | */ | ||
| 9 | |||
| 10 | // Most of the structures come from pokeruby, FR/LG changes come from my own research / the firered IDB on pokecommunity | ||
| 11 | |||
| 12 | #define POKEMON_NAME_LENGTH 10 | ||
| 13 | #define OT_NAME_LENGTH 7 | ||
| 14 | #define TILE_SIZE_4BPP 32 | ||
| 15 | |||
| 16 | struct Coords16 | ||
| 17 | { | ||
| 18 | s16 x; | ||
| 19 | s16 y; | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct UCoords16 | ||
| 23 | { | ||
| 24 | u16 x; | ||
| 25 | u16 y; | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct SecretBaseRecord | ||
| 29 | { | ||
| 30 | u8 sbr_field_0; // ID? | ||
| 31 | u8 sbr_field_1_0:4; | ||
| 32 | u8 gender:1; | ||
| 33 | u8 sbr_field_1_5:1; | ||
| 34 | u8 sbr_field_2[7]; // 0xFF bytes? | ||
| 35 | u8 trainerId[4]; // byte 0 is used for determining trainer class | ||
| 36 | u16 sbr_field_e; | ||
| 37 | u8 sbr_field_10; | ||
| 38 | u8 sbr_field_11; | ||
| 39 | u8 decorations[16]; | ||
| 40 | u8 sbr_field_22[16]; | ||
| 41 | u32 partyPersonality[6]; | ||
| 42 | u16 partyMoves[6 * 4]; | ||
| 43 | u16 partySpecies[6]; | ||
| 44 | u16 partyHeldItems[6]; | ||
| 45 | u8 partyLevels[6]; | ||
| 46 | u8 partyEVs[6]; | ||
| 47 | }; | ||
| 48 | |||
| 49 | typedef void (*TilesetCB)(void); | ||
| 50 | |||
| 51 | struct Tileset | ||
| 52 | { | ||
| 53 | u8 isCompressed; | ||
| 54 | u8 isSecondary; | ||
| 55 | void *tiles; | ||
| 56 | void *palettes; | ||
| 57 | void *metatiles; | ||
| 58 | void *metatileAttributes; | ||
| 59 | TilesetCB callback; | ||
| 60 | }; | ||
| 61 | |||
| 62 | struct MapData | ||
| 63 | { | ||
| 64 | s32 width; | ||
| 65 | s32 height; | ||
| 66 | u16 *border; | ||
| 67 | u16 *map; | ||
| 68 | struct Tileset *primaryTileset; | ||
| 69 | struct Tileset *secondaryTileset; | ||
| 70 | }; | ||
| 71 | |||
| 72 | struct MapObjectTemplate | ||
| 73 | { | ||
| 74 | /*0x00*/ u8 localId; | ||
| 75 | /*0x01*/ u8 graphicsId; | ||
| 76 | /*0x02*/ u8 unk2; | ||
| 77 | /*0x04*/ s16 x; | ||
| 78 | /*0x06*/ s16 y; | ||
| 79 | /*0x08*/ u8 elevation; | ||
| 80 | /*0x09*/ u8 movementType; | ||
| 81 | /*0x0A*/ u8 unkA_0:4; | ||
| 82 | u8 unkA_4:4; | ||
| 83 | ///*0x0B*/ u8 fillerB[1]; | ||
| 84 | /*0x0C*/ u16 unkC; | ||
| 85 | /*0x0E*/ u16 unkE; | ||
| 86 | /*0x10*/ u8 *script; | ||
| 87 | /*0x14*/ u16 flagId; | ||
| 88 | /*0x16*/ u8 filler_16[2]; | ||
| 89 | }; /*size = 0x18*/ | ||
| 90 | |||
| 91 | struct WarpEvent | ||
| 92 | { | ||
| 93 | s16 x, y; | ||
| 94 | s8 warpId; | ||
| 95 | u8 mapGroup; | ||
| 96 | u8 mapNum; | ||
| 97 | u8 unk7; | ||
| 98 | }; | ||
| 99 | |||
| 100 | struct CoordEvent | ||
| 101 | { | ||
| 102 | s16 x, y; | ||
| 103 | u8 unk4; | ||
| 104 | u8 filler_5; | ||
| 105 | u16 trigger; | ||
| 106 | u16 index; | ||
| 107 | u8 filler_A[0x2]; | ||
| 108 | u8 *script; | ||
| 109 | }; | ||
| 110 | |||
| 111 | struct BgEvent | ||
| 112 | { | ||
| 113 | s16 x, y; | ||
| 114 | u8 unk4; | ||
| 115 | u8 kind; | ||
| 116 | s16 filler_6; | ||
| 117 | u8 *script; | ||
| 118 | }; | ||
| 119 | |||
| 120 | struct MapEvents | ||
| 121 | { | ||
| 122 | u8 mapObjectCount; | ||
| 123 | u8 warpCount; | ||
| 124 | u8 coordEventCount; | ||
| 125 | u8 bgEventCount; | ||
| 126 | |||
| 127 | struct MapObjectTemplate *mapObjects; | ||
| 128 | struct WarpEvent *warps; | ||
| 129 | struct CoordEvent *coordEvents; | ||
| 130 | struct BgEvent *bgEvents; | ||
| 131 | }; | ||
| 132 | |||
| 133 | struct MapConnection | ||
| 134 | { | ||
| 135 | u8 direction; | ||
| 136 | u32 offset; | ||
| 137 | u8 mapGroup; | ||
| 138 | u8 mapNum; | ||
| 139 | }; | ||
| 140 | |||
| 141 | struct MapConnections | ||
| 142 | { | ||
| 143 | s32 count; | ||
| 144 | struct MapConnection *connections; | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct MapHeader | ||
| 148 | { | ||
| 149 | struct MapData *mapData; | ||
| 150 | struct MapEvents *events; | ||
| 151 | u8 *mapScripts; | ||
| 152 | struct MapConnections *connections; | ||
| 153 | u16 music; | ||
| 154 | u16 mapDataId; | ||
| 155 | u8 name; | ||
| 156 | u8 cave; | ||
| 157 | u8 weather; | ||
| 158 | /* 0x17 */ u8 mapType; | ||
| 159 | u8 filler_18; | ||
| 160 | u8 escapeRope; | ||
| 161 | u8 flags; | ||
| 162 | u8 battleType; | ||
| 163 | }; | ||
| 164 | |||
| 165 | struct MapObject | ||
| 166 | { | ||
| 167 | /*0x00*/ u32 active:1; | ||
| 168 | u32 mapobj_bit_1:1; | ||
| 169 | u32 mapobj_bit_2:1; | ||
| 170 | u32 mapobj_bit_3:1; | ||
| 171 | u32 mapobj_bit_4:1; | ||
| 172 | u32 mapobj_bit_5:1; | ||
| 173 | u32 mapobj_bit_6:1; | ||
| 174 | u32 mapobj_bit_7:1; | ||
| 175 | /*0x01*/ u32 mapobj_bit_8:1; | ||
| 176 | u32 mapobj_bit_9:1; | ||
| 177 | u32 mapobj_bit_10:1; | ||
| 178 | u32 mapobj_bit_11:1; | ||
| 179 | u32 mapobj_bit_12:1; | ||
| 180 | u32 mapobj_bit_13:1; | ||
| 181 | u32 mapobj_bit_14:1; | ||
| 182 | u32 mapobj_bit_15:1; | ||
| 183 | /*0x02*/ u32 mapobj_bit_16:1; | ||
| 184 | u32 mapobj_bit_17:1; | ||
| 185 | u32 mapobj_bit_18:1; | ||
| 186 | u32 mapobj_bit_19:1; | ||
| 187 | u32 mapobj_bit_20:1; | ||
| 188 | u32 mapobj_bit_21:1; | ||
| 189 | u32 mapobj_bit_22:1; | ||
| 190 | u32 mapobj_bit_23:1; | ||
| 191 | /*0x03*/ u32 mapobj_bit_24:1; | ||
| 192 | u32 mapobj_bit_25:1; | ||
| 193 | u32 mapobj_bit_26:1; | ||
| 194 | u32 mapobj_bit_27:1; | ||
| 195 | u32 mapobj_bit_28:1; | ||
| 196 | u32 mapobj_bit_29:1; | ||
| 197 | u32 mapobj_bit_30:1; | ||
| 198 | u32 mapobj_bit_31:1; | ||
| 199 | /*0x04*/ u8 spriteId; | ||
| 200 | /*0x05*/ u8 graphicsId; | ||
| 201 | /*0x06*/ u8 animPattern; | ||
| 202 | /*0x07*/ u8 trainerType; | ||
| 203 | /*0x08*/ u8 localId; | ||
| 204 | /*0x09*/ u8 mapNum; | ||
| 205 | /*0x0A*/ u8 mapGroup; | ||
| 206 | /*0x0B*/ u8 mapobj_unk_0B_0:4; | ||
| 207 | u8 elevation:4; | ||
| 208 | /*0x0C*/ struct Coords16 coords1; | ||
| 209 | /*0x10*/ struct Coords16 coords2; | ||
| 210 | /*0x14*/ struct Coords16 coords3; | ||
| 211 | /*0x18*/ u8 mapobj_unk_18:4; //current direction? | ||
| 212 | /*0x18*/ u8 placeholder18:4; | ||
| 213 | /*0x19*/ u8 mapobj_unk_19; | ||
| 214 | /*0x1A*/ u8 mapobj_unk_1A; | ||
| 215 | /*0x1B*/ u8 mapobj_unk_1B; | ||
| 216 | /*0x1C*/ u8 mapobj_unk_1C; | ||
| 217 | /*0x1D*/ u8 trainerRange_berryTreeId; | ||
| 218 | /*0x1E*/ u8 mapobj_unk_1E; | ||
| 219 | /*0x1F*/ u8 mapobj_unk_1F; | ||
| 220 | /*0x20*/ u8 mapobj_unk_20; | ||
| 221 | /*0x21*/ u8 mapobj_unk_21; | ||
| 222 | /*0x22*/ u8 animId; | ||
| 223 | /*size = 0x24*/ | ||
| 224 | }; | ||
| 225 | |||
| 226 | struct Berry | ||
| 227 | { | ||
| 228 | const u8 name[7]; | ||
| 229 | u8 firmness; | ||
| 230 | u16 size; | ||
| 231 | u8 maxYield; | ||
| 232 | u8 minYield; | ||
| 233 | const u8 *description1; | ||
| 234 | const u8 *description2; | ||
| 235 | u8 stageDuration; | ||
| 236 | u8 spicy; | ||
| 237 | u8 dry; | ||
| 238 | u8 sweet; | ||
| 239 | u8 bitter; | ||
| 240 | u8 sour; | ||
| 241 | u8 smoothness; | ||
| 242 | }; | ||
| 243 | |||
| 244 | struct EnigmaBerry | ||
| 245 | { | ||
| 246 | struct Berry berry; | ||
| 247 | u8 pic[(6 * 6) * TILE_SIZE_4BPP]; | ||
| 248 | u16 palette[16]; | ||
| 249 | u8 description1[45]; | ||
| 250 | u8 description2[45]; | ||
| 251 | u8 itemEffect[18]; | ||
| 252 | u8 holdEffect; | ||
| 253 | u8 holdEffectParam; | ||
| 254 | u32 checksum; | ||
| 255 | }; | ||
| 256 | |||
| 257 | struct BattleEnigmaBerry | ||
| 258 | { | ||
| 259 | u8 name[7]; | ||
| 260 | u8 holdEffect; | ||
| 261 | u8 itemEffect[18]; | ||
| 262 | u8 holdEffectParam; | ||
| 263 | }; | ||
| 264 | |||
| 265 | struct EnigmaBerryFRLGE { | ||
| 266 | struct Berry berry; // 0x00 | ||
| 267 | u8 itemEffect[18]; // 0x1C | ||
| 268 | u8 holdEffect; // 0x2E | ||
| 269 | u8 holdEffectParam; // 0x2F | ||
| 270 | u32 checksum; // 0x30 | ||
| 271 | }; | ||
| 272 | |||
| 273 | struct __attribute__((aligned(4))) BerryTree | ||
| 274 | { | ||
| 275 | u8 berry; | ||
| 276 | u8 stage:7; | ||
| 277 | u8 growthSparkle:1; | ||
| 278 | u16 secondsUntilNextStage; | ||
| 279 | u8 berryYield; | ||
| 280 | u8 regrowthCount:4; | ||
| 281 | u8 watered1:1; | ||
| 282 | u8 watered2:1; | ||
| 283 | u8 watered3:1; | ||
| 284 | u8 watered4:1; | ||
| 285 | }; | ||
| 286 | |||
| 287 | struct PokemonSubstruct0 | ||
| 288 | { | ||
| 289 | u16 species; | ||
| 290 | u16 heldItem; | ||
| 291 | u32 experience; | ||
| 292 | u8 ppBonuses; | ||
| 293 | u8 friendship; | ||
| 294 | }; | ||
| 295 | |||
| 296 | struct PokemonSubstruct1 | ||
| 297 | { | ||
| 298 | u16 moves[4]; | ||
| 299 | u8 pp[4]; | ||
| 300 | }; | ||
| 301 | |||
| 302 | struct PokemonSubstruct2 | ||
| 303 | { | ||
| 304 | u8 hpEV; | ||
| 305 | u8 attackEV; | ||
| 306 | u8 defenseEV; | ||
| 307 | u8 speedEV; | ||
| 308 | u8 spAttackEV; | ||
| 309 | u8 spDefenseEV; | ||
| 310 | u8 cool; | ||
| 311 | u8 beauty; | ||
| 312 | u8 cute; | ||
| 313 | u8 smart; | ||
| 314 | u8 tough; | ||
| 315 | u8 sheen; | ||
| 316 | }; | ||
| 317 | |||
| 318 | struct PokemonSubstruct3 | ||
| 319 | { | ||
| 320 | /* 0x00 */ u8 pokerus; | ||
| 321 | /* 0x01 */ u8 metLocation; | ||
| 322 | |||
| 323 | /* 0x02 */ u16 metLevel:7; | ||
| 324 | /* 0x02 */ u16 metGame:4; | ||
| 325 | /* 0x03 */ u16 pokeball:4; | ||
| 326 | /* 0x03 */ u16 otGender:1; | ||
| 327 | |||
| 328 | /* 0x04 */ u32 hpIV:5; | ||
| 329 | /* 0x04 */ u32 attackIV:5; | ||
| 330 | /* 0x05 */ u32 defenseIV:5; | ||
| 331 | /* 0x05 */ u32 speedIV:5; | ||
| 332 | /* 0x05 */ u32 spAttackIV:5; | ||
| 333 | /* 0x06 */ u32 spDefenseIV:5; | ||
| 334 | /* 0x07 */ u32 isEgg:1; | ||
| 335 | /* 0x07 */ u32 altAbility:1; | ||
| 336 | |||
| 337 | /* 0x08 */ u32 coolRibbon:3; | ||
| 338 | /* 0x08 */ u32 beautyRibbon:3; | ||
| 339 | /* 0x08 */ u32 cuteRibbon:3; | ||
| 340 | /* 0x09 */ u32 smartRibbon:3; | ||
| 341 | /* 0x09 */ u32 toughRibbon:3; | ||
| 342 | /* 0x09 */ u32 championRibbon:1; | ||
| 343 | /* 0x0A */ u32 winningRibbon:1; | ||
| 344 | /* 0x0A */ u32 victoryRibbon:1; | ||
| 345 | /* 0x0A */ u32 artistRibbon:1; | ||
| 346 | /* 0x0A */ u32 effortRibbon:1; | ||
| 347 | /* 0x0A */ u32 giftRibbon1:1; | ||
| 348 | /* 0x0A */ u32 giftRibbon2:1; | ||
| 349 | /* 0x0A */ u32 giftRibbon3:1; | ||
| 350 | /* 0x0A */ u32 giftRibbon4:1; | ||
| 351 | /* 0x0B */ u32 giftRibbon5:1; | ||
| 352 | /* 0x0B */ u32 giftRibbon6:1; | ||
| 353 | /* 0x0B */ u32 giftRibbon7:1; | ||
| 354 | /* 0x0B */ u32 fatefulEncounter:5; // unused in Ruby/Sapphire, but the high bit must be set for Mew/Deoxys to obey in FR/LG/Emerald | ||
| 355 | }; | ||
| 356 | |||
| 357 | union PokemonSubstruct | ||
| 358 | { | ||
| 359 | struct PokemonSubstruct0 type0; | ||
| 360 | struct PokemonSubstruct1 type1; | ||
| 361 | struct PokemonSubstruct2 type2; | ||
| 362 | struct PokemonSubstruct3 type3; | ||
| 363 | u16 raw[6]; | ||
| 364 | }; | ||
| 365 | |||
| 366 | struct BoxPokemon | ||
| 367 | { | ||
| 368 | u32 personality; | ||
| 369 | u32 otId; | ||
| 370 | u8 nickname[POKEMON_NAME_LENGTH]; | ||
| 371 | u8 language; | ||
| 372 | u8 isBadEgg:1; | ||
| 373 | u8 hasSpecies:1; | ||
| 374 | u8 isEgg:1; | ||
| 375 | u8 unused:5; | ||
| 376 | u8 otName[OT_NAME_LENGTH]; | ||
| 377 | u8 markings; | ||
| 378 | u16 checksum; | ||
| 379 | u16 unknown; | ||
| 380 | |||
| 381 | union | ||
| 382 | { | ||
| 383 | u32 raw[12]; | ||
| 384 | union PokemonSubstruct substructs[4]; | ||
| 385 | } secure; | ||
| 386 | }; | ||
| 387 | |||
| 388 | struct Pokemon | ||
| 389 | { | ||
| 390 | struct BoxPokemon box; | ||
| 391 | u32 status; | ||
| 392 | u8 level; | ||
| 393 | u8 pokerus; | ||
| 394 | u16 hp; | ||
| 395 | u16 maxHP; | ||
| 396 | u16 attack; | ||
| 397 | u16 defense; | ||
| 398 | u16 speed; | ||
| 399 | u16 spAttack; | ||
| 400 | u16 spDefense; | ||
| 401 | }; | ||
| 402 | |||
| 403 | struct UnknownPokemonStruct | ||
| 404 | { | ||
| 405 | u16 species; | ||
| 406 | u16 heldItem; | ||
| 407 | u16 moves[4]; | ||
| 408 | u8 level; | ||
| 409 | u8 ppBonuses; | ||
| 410 | u8 hpEV; | ||
| 411 | u8 attackEV; | ||
| 412 | u8 defenseEV; | ||
| 413 | u8 speedEV; | ||
| 414 | u8 spAttackEV; | ||
| 415 | u8 spDefenseEV; | ||
| 416 | u32 otId; | ||
| 417 | u32 hpIV:5; | ||
| 418 | u32 attackIV:5; | ||
| 419 | u32 defenseIV:5; | ||
| 420 | u32 speedIV:5; | ||
| 421 | u32 spAttackIV:5; | ||
| 422 | u32 spDefenseIV:5; | ||
| 423 | u32 gap:1; | ||
| 424 | u32 altAbility:1; | ||
| 425 | u32 personality; | ||
| 426 | u8 nickname[POKEMON_NAME_LENGTH + 1]; | ||
| 427 | u8 friendship; | ||
| 428 | }; | ||
| 429 | |||
| 430 | struct BattlePokemon | ||
| 431 | { | ||
| 432 | /* 0x00 */ u16 species; | ||
| 433 | /* 0x02 */ u16 attack; | ||
| 434 | /* 0x04 */ u16 defense; | ||
| 435 | /* 0x06 */ u16 speed; | ||
| 436 | /* 0x08 */ u16 spAttack; | ||
| 437 | /* 0x0A */ u16 spDefense; | ||
| 438 | /* 0x0C */ u16 moves[4]; | ||
| 439 | /* 0x14 */ u32 hpIV:5; | ||
| 440 | /* 0x14 */ u32 attackIV:5; | ||
| 441 | /* 0x15 */ u32 defenseIV:5; | ||
| 442 | /* 0x15 */ u32 speedIV:5; | ||
| 443 | /* 0x16 */ u32 spAttackIV:5; | ||
| 444 | /* 0x17 */ u32 spDefenseIV:5; | ||
| 445 | /* 0x17 */ u32 isEgg:1; | ||
| 446 | /* 0x17 */ u32 altAbility:1; | ||
| 447 | /* 0x18 */ s8 statStages[8]; | ||
| 448 | /* 0x20 */ u8 ability; | ||
| 449 | /* 0x21 */ u8 type1; | ||
| 450 | /* 0x22 */ u8 type2; | ||
| 451 | /* 0x23 */ u8 unknown; | ||
| 452 | /* 0x24 */ u8 pp[4]; | ||
| 453 | /* 0x28 */ u16 hp; | ||
| 454 | /* 0x2A */ u8 level; | ||
| 455 | /* 0x2B */ u8 friendship; | ||
| 456 | /* 0x2C */ u16 maxHP; | ||
| 457 | /* 0x2E */ u16 item; | ||
| 458 | /* 0x30 */ u8 nickname[POKEMON_NAME_LENGTH + 1]; | ||
| 459 | /* 0x3B */ u8 ppBonuses; | ||
| 460 | /* 0x3C */ u8 otName[8]; | ||
| 461 | /* 0x44 */ u32 experience; | ||
| 462 | /* 0x48 */ u32 personality; | ||
| 463 | /* 0x4C */ u32 status1; | ||
| 464 | /* 0x50 */ u32 status2; | ||
| 465 | /* 0x54 */ u32 otId; | ||
| 466 | }; | ||
| 467 | |||
| 468 | struct BaseStats | ||
| 469 | { | ||
| 470 | /* 0x00 */ u8 baseHP; | ||
| 471 | /* 0x01 */ u8 baseAttack; | ||
| 472 | /* 0x02 */ u8 baseDefense; | ||
| 473 | /* 0x03 */ u8 baseSpeed; | ||
| 474 | /* 0x04 */ u8 baseSpAttack; | ||
| 475 | /* 0x05 */ u8 baseSpDefense; | ||
| 476 | /* 0x06 */ u8 type1; | ||
| 477 | /* 0x07 */ u8 type2; | ||
| 478 | /* 0x08 */ u8 catchRate; | ||
| 479 | /* 0x09 */ u8 expYield; | ||
| 480 | /* 0x0A */ u16 evYield_HP:2; | ||
| 481 | /* 0x0A */ u16 evYield_Attack:2; | ||
| 482 | /* 0x0A */ u16 evYield_Defense:2; | ||
| 483 | /* 0x0A */ u16 evYield_Speed:2; | ||
| 484 | /* 0x0B */ u16 evYield_SpAttack:2; | ||
| 485 | /* 0x0B */ u16 evYield_SpDefense:2; | ||
| 486 | /* 0x0C */ u16 item1; | ||
| 487 | /* 0x0E */ u16 item2; | ||
| 488 | /* 0x10 */ u8 genderRatio; | ||
| 489 | /* 0x11 */ u8 eggCycles; | ||
| 490 | /* 0x12 */ u8 friendship; | ||
| 491 | /* 0x13 */ u8 growthRate; | ||
| 492 | /* 0x14 */ u8 eggGroup1; | ||
| 493 | /* 0x15 */ u8 eggGroup2; | ||
| 494 | /* 0x16 */ u8 ability1; | ||
| 495 | /* 0x17 */ u8 ability2; | ||
| 496 | /* 0x18 */ u8 safariZoneFleeRate; | ||
| 497 | /* 0x19 */ u8 bodyColor; | ||
| 498 | }; | ||
| 499 | |||
| 500 | struct BattleMove | ||
| 501 | { | ||
| 502 | u8 effect; | ||
| 503 | u8 power; | ||
| 504 | u8 type; | ||
| 505 | u8 accuracy; | ||
| 506 | u8 pp; | ||
| 507 | u8 secondaryEffectChance; | ||
| 508 | u8 target; | ||
| 509 | u8 priority; | ||
| 510 | u32 flags; | ||
| 511 | }; | ||
| 512 | |||
| 513 | struct PokemonStorage | ||
| 514 | { | ||
| 515 | /* 0x00 */ u8 currentBox; | ||
| 516 | /* 0x01 */ struct BoxPokemon boxes[14][30]; | ||
| 517 | u8 boxNames[14][9]; | ||
| 518 | u8 boxBackground[14]; | ||
| 519 | }; | ||
| 520 | |||
| 521 | struct WarpData | ||
| 522 | { | ||
| 523 | s8 mapGroup; | ||
| 524 | s8 mapNum; | ||
| 525 | s8 warpId; | ||
| 526 | s16 x, y; | ||
| 527 | }; | ||
| 528 | |||
| 529 | struct ItemSlot | ||
| 530 | { | ||
| 531 | u16 itemId; | ||
| 532 | u16 quantity; | ||
| 533 | }; | ||
| 534 | |||
| 535 | struct __attribute__((aligned(2))) Pokeblock | ||
| 536 | { | ||
| 537 | u8 color; | ||
| 538 | u8 spicy; | ||
| 539 | u8 dry; | ||
| 540 | u8 sweet; | ||
| 541 | u8 bitter; | ||
| 542 | u8 sour; | ||
| 543 | u8 feel; | ||
| 544 | }; | ||
| 545 | |||
| 546 | struct Roamer | ||
| 547 | { | ||
| 548 | /*0x00*/ u32 ivs; | ||
| 549 | /*0x04*/ u32 personality; | ||
| 550 | /*0x08*/ u16 species; | ||
| 551 | /*0x0A*/ u16 hp; | ||
| 552 | /*0x0C*/ u8 level; | ||
| 553 | /*0x0D*/ u8 status; | ||
| 554 | /*0x0E*/ u8 cool; | ||
| 555 | /*0x0F*/ u8 beauty; | ||
| 556 | /*0x10*/ u8 cute; | ||
| 557 | /*0x11*/ u8 smart; | ||
| 558 | /*0x12*/ u8 tough; | ||
| 559 | /*0x13*/ u8 active; | ||
| 560 | }; | ||
| 561 | |||
| 562 | struct RamScriptData | ||
| 563 | { | ||
| 564 | u8 magic; | ||
| 565 | u8 mapGroup; | ||
| 566 | u8 mapNum; | ||
| 567 | u8 objectId; | ||
| 568 | u8 script[995]; | ||
| 569 | } __attribute__((aligned(1),packed)); | ||
| 570 | |||
| 571 | struct RamScript | ||
| 572 | { | ||
| 573 | u32 checksum; | ||
| 574 | struct RamScriptData data; | ||
| 575 | } __attribute__((aligned(1),packed)); | ||
| 576 | |||
| 577 | struct SB1_2EFC_Struct | ||
| 578 | { | ||
| 579 | u8 unknown[0x20]; | ||
| 580 | }; | ||
| 581 | |||
| 582 | struct EasyChatPair | ||
| 583 | { | ||
| 584 | u16 unk0_0:7; | ||
| 585 | u16 unk0_7:7; | ||
| 586 | u16 unk1_6:1; | ||
| 587 | u16 unk2; | ||
| 588 | u16 words[2]; | ||
| 589 | }; /*size = 0x8*/ | ||
| 590 | |||
| 591 | struct TVShowCommon { | ||
| 592 | /*0x00*/ u8 var00; | ||
| 593 | /*0x01*/ u8 var01; | ||
| 594 | }; | ||
| 595 | |||
| 596 | struct TVShowFanClubLetter { | ||
| 597 | /*0x00*/ u8 var00; | ||
| 598 | /*0x01*/ u8 var01; | ||
| 599 | /*0x02*/ u16 species; | ||
| 600 | u8 pad04[12]; | ||
| 601 | /*0x10*/ u8 playerName[8]; | ||
| 602 | /*0x18*/ u8 var18; | ||
| 603 | }; | ||
| 604 | |||
| 605 | struct TVShowRecentHappenings { | ||
| 606 | /*0x00*/ u8 var00; | ||
| 607 | /*0x01*/ u8 var01; | ||
| 608 | /*0x02*/ u16 var02; | ||
| 609 | u8 pad04[12]; | ||
| 610 | /*0x10*/ u8 var10[8]; | ||
| 611 | /*0x18*/ u8 var18; | ||
| 612 | u8 pad19[10]; | ||
| 613 | }; | ||
| 614 | |||
| 615 | struct TVShowFanclubOpinions { | ||
| 616 | /*0x00*/ u8 var00; | ||
| 617 | /*0x01*/ u8 var01; | ||
| 618 | /*0x02*/ u16 var02; | ||
| 619 | /*0x04*/ u8 var04A:4; | ||
| 620 | u8 var04B:4; | ||
| 621 | /*0x04*/ u8 var05[8]; | ||
| 622 | /*0x0D*/ u8 var0D; | ||
| 623 | /*0x0E*/ u8 var0E; | ||
| 624 | /*0x0F*/ u8 var0F; | ||
| 625 | /*0x10*/ u8 var10[8]; | ||
| 626 | }; | ||
| 627 | |||
| 628 | struct TVShowNameRaterShow { | ||
| 629 | /*0x00*/ u8 var00; | ||
| 630 | /*0x01*/ u8 var01; | ||
| 631 | /*0x02*/ u16 species; | ||
| 632 | /*0x04*/ u8 pokemonName[11]; | ||
| 633 | /*0x0F*/ u8 trainerName[11]; | ||
| 634 | /*0x1A*/ u8 random; | ||
| 635 | /*0x1B*/ u8 random2; | ||
| 636 | /*0x1C*/ u16 var1C; | ||
| 637 | /*0x1E*/ u8 language; | ||
| 638 | /*0x1F*/ u8 var1F; | ||
| 639 | }; | ||
| 640 | |||
| 641 | struct TVShowMassOutbreak { | ||
| 642 | /*0x00*/ u8 var00; | ||
| 643 | /*0x01*/ u8 var01; | ||
| 644 | /*0x02*/ u8 var02; | ||
| 645 | /*0x03*/ u8 var03; | ||
| 646 | /*0x04*/ u16 moves[4]; | ||
| 647 | /*0x0C*/ u16 species; | ||
| 648 | /*0x0E*/ u16 var0E; | ||
| 649 | /*0x10*/ u8 locationMapNum; | ||
| 650 | /*0x11*/ u8 locationMapGroup; | ||
| 651 | /*0x12*/ u8 var12; | ||
| 652 | /*0x13*/ u8 probability; | ||
| 653 | /*0x14*/ u8 level; | ||
| 654 | /*0x15*/ u8 var15; | ||
| 655 | /*0x16*/ u16 var16; | ||
| 656 | /*0x18*/ u8 var18; | ||
| 657 | u8 pad19[11]; | ||
| 658 | }; | ||
| 659 | |||
| 660 | typedef union TVShow { | ||
| 661 | struct TVShowCommon common; | ||
| 662 | struct TVShowFanClubLetter fanclubLetter; | ||
| 663 | struct TVShowRecentHappenings recentHappenings; | ||
| 664 | struct TVShowFanclubOpinions fanclubOpinions; | ||
| 665 | struct TVShowNameRaterShow nameRaterShow; | ||
| 666 | struct TVShowMassOutbreak massOutbreak; | ||
| 667 | } TVShow; | ||
| 668 | |||
| 669 | struct __attribute__((aligned(4))) MailStruct | ||
| 670 | { | ||
| 671 | /*0x00*/ u16 words[9]; | ||
| 672 | /*0x12*/ u8 playerName[8]; | ||
| 673 | /*0x1A*/ u8 trainerId[4]; | ||
| 674 | /*0x1E*/ u16 species; | ||
| 675 | /*0x20*/ u16 itemId; | ||
| 676 | }; | ||
| 677 | |||
| 678 | struct UnkMauvilleOldManStruct | ||
| 679 | { | ||
| 680 | u8 unk_2D94; | ||
| 681 | u8 unk_2D95; | ||
| 682 | /*0x2D96*/ u16 mauvilleOldMan_ecArray[6]; | ||
| 683 | /*0x2DA2*/ u16 mauvilleOldMan_ecArray2[6]; | ||
| 684 | /*0x2DAE*/ u8 playerName[8]; | ||
| 685 | /*0x2DB6*/ u8 filler_2DB6[0x3]; | ||
| 686 | /*0x2DB9*/ u8 playerTrainerId[4]; | ||
| 687 | u8 unk_2DBD; | ||
| 688 | /* size = 0x2C */ | ||
| 689 | }; | ||
| 690 | |||
| 691 | struct UnkMauvilleOldManStruct2 | ||
| 692 | { | ||
| 693 | u8 filler0; | ||
| 694 | u8 unk1; | ||
| 695 | u8 unk2; | ||
| 696 | u16 mauvilleOldMan_ecArray[10]; | ||
| 697 | u16 mauvilleOldMan_ecArray2[6]; | ||
| 698 | u8 fillerF[0x2]; | ||
| 699 | /* size = 0x2C */ | ||
| 700 | }; | ||
| 701 | |||
| 702 | typedef union OldMan { | ||
| 703 | struct UnkMauvilleOldManStruct oldMan1; | ||
| 704 | struct UnkMauvilleOldManStruct2 oldMan2; | ||
| 705 | } OldMan; | ||
| 706 | |||
| 707 | struct QuestStoryNPC { | ||
| 708 | u16 bitfield; | ||
| 709 | u8 direction; | ||
| 710 | u8 height; | ||
| 711 | u8 type_id; | ||
| 712 | u8 running_behaviour_or_picture_id; | ||
| 713 | u8 is_trainer; | ||
| 714 | u8 local_id; | ||
| 715 | u8 local_mapnumber; | ||
| 716 | u8 local_mapbank; | ||
| 717 | u16 x; | ||
| 718 | u16 y; | ||
| 719 | u8 sight_distance; | ||
| 720 | u8 role_from; | ||
| 721 | u8 unknown_decrement_on_step; | ||
| 722 | u8 unk_11; | ||
| 723 | u16 padding_12; | ||
| 724 | }; | ||
| 725 | |||
| 726 | struct QuestStory { | ||
| 727 | u8 active; | ||
| 728 | u8 bank; | ||
| 729 | u8 map; | ||
| 730 | u8 warpId; | ||
| 731 | u16 x; | ||
| 732 | u16 y; | ||
| 733 | struct QuestStoryNPC npc[0x10]; | ||
| 734 | u8 unk_148[0x51f]; | ||
| 735 | }; | ||
| 736 | |||
| 737 | struct NPCState { | ||
| 738 | u8 bitfield; | ||
| 739 | u8 obj_anim_and_vis_control; | ||
| 740 | u8 unk_2; | ||
| 741 | u8 unk_3; | ||
| 742 | u8 oamid; | ||
| 743 | u8 type_id; | ||
| 744 | u8 running_behaviour_or_picture_id; | ||
| 745 | u8 is_trainer; | ||
| 746 | u8 local_id; | ||
| 747 | u8 local_mapnumber; | ||
| 748 | u8 local_mapbank; | ||
| 749 | u8 height; | ||
| 750 | struct Coords16 stay_around; | ||
| 751 | struct Coords16 to; | ||
| 752 | struct Coords16 from; | ||
| 753 | u8 direction; | ||
| 754 | u8 movement_area; | ||
| 755 | u8 objid_surfing; | ||
| 756 | u8 objid_1B; | ||
| 757 | u8 idx_movement_behaviour; | ||
| 758 | u8 sight_distance; | ||
| 759 | u8 role_to; | ||
| 760 | u8 role_from; | ||
| 761 | u8 unk_20; | ||
| 762 | u8 unknown_decrement_on_step; | ||
| 763 | u8 unk_22; | ||
| 764 | u8 unk_23; | ||
| 765 | }; | ||
| 766 | |||
| 767 | struct DaycarePokemon { | ||
| 768 | struct BoxPokemon pokemon; | ||
| 769 | u8 unk_50[56]; | ||
| 770 | u32 steps; | ||
| 771 | }; | ||
| 772 | |||
| 773 | |||
| 774 | struct Time | ||
| 775 | { | ||
| 776 | /*0x00*/ s16 days; | ||
| 777 | /*0x02*/ s8 hours; | ||
| 778 | /*0x03*/ s8 minutes; | ||
| 779 | /*0x04*/ s8 seconds; | ||
| 780 | }; | ||
| 781 | |||
| 782 | struct Pokedex | ||
| 783 | { | ||
| 784 | /*0x00*/ u8 order; | ||
| 785 | /*0x01*/ u8 unknown1; | ||
| 786 | /*0x02*/ u8 nationalMagic; // must equal 0xDA in order to have National mode | ||
| 787 | /*0x03*/ u8 unknown2; | ||
| 788 | /*0x04*/ u32 unownPersonality; // set when you first see Unown | ||
| 789 | /*0x08*/ u32 spindaPersonality; // set when you first see Spinda | ||
| 790 | /*0x0C*/ u32 unknown3; | ||
| 791 | /*0x10*/ u8 owned[52]; | ||
| 792 | /*0x44*/ u8 seen[52]; | ||
| 793 | }; \ No newline at end of file | ||
