1 /*
2 Copyright (C) 2009-2015 DeSmuME Team
3
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with the this software. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "firmware.h"
19
20 #include "NDSSystem.h"
21 #include "MMU.h"
22 #include "path.h"
23 #include "encrypt.h"
24 #include "wifi.h"
25
26 #define DFC_ID_CODE "DeSmuME Firmware User Settings"
27 #define DFC_ID_SIZE sizeof(DFC_ID_CODE)
28 #define USER_SETTINGS_SIZE 0x100
29 #define WIFI_SETTINGS_SIZE 0x1D5
30 #define WIFI_AP_SETTINGS_SIZE 0x300
31 #define SETTINGS_SIZE (USER_SETTINGS_SIZE + WIFI_SETTINGS_SIZE + WIFI_AP_SETTINGS_SIZE)
32 #define DFC_FILE_SIZE (SETTINGS_SIZE + DFC_ID_SIZE)
33 #define WIFI_SETTINGS_OFF 0x0000002A
34 #define WIFI_AP_SETTINGS_OFF 0x0003FA00
35
36 static _KEY1 enc(&MMU.ARM7_BIOS[0x0030]);
37
getBootCodeCRC16()38 u16 CFIRMWARE::getBootCodeCRC16()
39 {
40 unsigned int i, j;
41 u32 crc = 0xFFFF;
42 const u16 val[8] = {0xC0C1, 0xC181, 0xC301, 0xC601, 0xCC01, 0xD801, 0xF001, 0xA001};
43
44 for(i = 0; i < size9; i++)
45 {
46 crc = (crc ^ tmp_data9[i]);
47
48 for(j = 0; j < 8; j++)
49 {
50 if(crc & 0x0001)
51 crc = ((crc >> 1) ^ (val[j] << (7-j)));
52 else
53 crc = (crc >> 1);
54 }
55 }
56
57 for(i = 0; i < size7; i++)
58 {
59 crc = (crc ^ tmp_data7[i]);
60
61 for(j = 0; j < 8; j++)
62 {
63 if(crc & 0x0001)
64 crc = ((crc >> 1) ^ (val[j] << (7-j)));
65 else
66 crc = (crc >> 1);
67 }
68 }
69
70 return (crc & 0xFFFF);
71 }
72
decrypt(const u8 * in,u8 * & out)73 u32 CFIRMWARE::decrypt(const u8 *in, u8* &out)
74 {
75 u32 curBlock[2] = { 0 };
76 u32 blockSize = 0;
77 u32 xLen = 0;
78
79 u32 i = 0, j = 0;
80 u32 xIn = 4, xOut = 0;
81 u32 len = 0;
82 u32 offset = 0;
83 u32 windowOffset = 0;
84 u8 d = 0;
85 u16 data = 0;
86
87 memcpy(curBlock, in, 8);
88 enc.decrypt(curBlock);
89 blockSize = (curBlock[0] >> 8);
90
91 if (blockSize == 0) return (0);
92
93 out = new u8 [blockSize];
94 if (!out ) return (0);
95 memset(out, 0xFF, blockSize);
96
97 xLen = blockSize;
98 while(xLen > 0)
99 {
100 d = T1ReadByte((u8*)curBlock, (xIn % 8));
101 xIn++;
102 if((xIn % 8) == 0)
103 {
104 memcpy(curBlock, in + xIn, 8);
105 enc.decrypt(curBlock);
106 }
107
108 for(i = 0; i < 8; i++)
109 {
110 if(d & 0x80)
111 {
112 data = (T1ReadByte((u8*)curBlock, (xIn % 8)) << 8);
113 xIn++;
114 if((xIn % 8) == 0)
115 {
116 memcpy(curBlock, in + xIn, 8);
117 enc.decrypt(curBlock);
118 }
119 data |= T1ReadByte((u8*)curBlock, (xIn % 8));
120 xIn++;
121 if((xIn % 8) == 0)
122 {
123 memcpy(curBlock, in + xIn, 8);
124 enc.decrypt(curBlock);
125 }
126
127 len = (data >> 12) + 3;
128 offset = (data & 0xFFF);
129 windowOffset = (xOut - offset - 1);
130
131 for(j = 0; j < len; j++)
132 {
133 T1WriteByte(out, xOut, T1ReadByte(out, windowOffset));
134 xOut++;
135 windowOffset++;
136
137 xLen--;
138 if(xLen == 0) return (blockSize);
139 }
140 }
141 else
142 {
143 T1WriteByte(out, xOut, T1ReadByte((u8*)curBlock, (xIn % 8)));
144 xOut++;
145 xIn++;
146 if((xIn % 8) == 0)
147 {
148 memcpy(curBlock, in + xIn, 8);
149 enc.decrypt(curBlock);
150 }
151
152 xLen--;
153 if(xLen == 0) return (blockSize);
154 }
155
156 d = ((d << 1) & 0xFF);
157 }
158 }
159
160 return (blockSize);
161 }
162
decompress(const u8 * in,u8 * & out)163 u32 CFIRMWARE::decompress(const u8 *in, u8* &out)
164 {
165 u32 curBlock[2] = { 0 };
166 u32 blockSize = 0;
167 u32 xLen = 0;
168
169 u32 i = 0, j = 0;
170 u32 xIn = 4, xOut = 0;
171 u32 len = 0;
172 u32 offset = 0;
173 u32 windowOffset = 0;
174 u8 d = 0;
175 u16 data = 0;
176
177 memcpy(curBlock, in, 8);
178 blockSize = (curBlock[0] >> 8);
179
180 if (blockSize == 0) return (0);
181
182 out = new u8 [blockSize];
183 if (!out ) return (0);
184 memset(out, 0xFF, blockSize);
185
186 xLen = blockSize;
187 while(xLen > 0)
188 {
189 d = T1ReadByte((u8*)curBlock, (xIn % 8));
190 xIn++;
191 if((xIn % 8) == 0)
192 {
193 memcpy(curBlock, in + xIn, 8);
194 }
195
196 for(i = 0; i < 8; i++)
197 {
198 if(d & 0x80)
199 {
200 data = (T1ReadByte((u8*)curBlock, (xIn % 8)) << 8);
201 xIn++;
202 if((xIn % 8) == 0)
203 {
204 memcpy(curBlock, in + xIn, 8);
205 }
206 data |= T1ReadByte((u8*)curBlock, (xIn % 8));
207 xIn++;
208 if((xIn % 8) == 0)
209 {
210 memcpy(curBlock, in + xIn, 8);
211 }
212
213 len = (data >> 12) + 3;
214 offset = (data & 0xFFF);
215 windowOffset = (xOut - offset - 1);
216
217 for(j = 0; j < len; j++)
218 {
219 T1WriteByte(out, xOut, T1ReadByte(out, windowOffset));
220 xOut++;
221 windowOffset++;
222
223 xLen--;
224 if(xLen == 0) return (blockSize);
225 }
226 }
227 else
228 {
229 T1WriteByte(out, xOut, T1ReadByte((u8*)curBlock, (xIn % 8)));
230 xOut++;
231 xIn++;
232 if((xIn % 8) == 0)
233 {
234 memcpy(curBlock, in + xIn, 8);
235 }
236
237 xLen--;
238 if(xLen == 0) return (blockSize);
239 }
240
241 d = ((d << 1) & 0xFF);
242 }
243 }
244
245 return (blockSize);
246 }
247 //================================================================================
load()248 bool CFIRMWARE::load()
249 {
250 u32 size = 0;
251 u8 *data = NULL;
252
253 if (CommonSettings.UseExtFirmware == false)
254 return false;
255 if (strlen(CommonSettings.Firmware) == 0)
256 return false;
257
258 FILE *fp = fopen(CommonSettings.Firmware, "rb");
259 if (!fp)
260 return false;
261 fseek(fp, 0, SEEK_END);
262 size = ftell(fp);
263 fseek(fp, 0, SEEK_SET);
264 if( (size != NDS_FW_SIZE_V1) && (size != NDS_FW_SIZE_V2) )
265 {
266 fclose(fp);
267 return false;
268 }
269
270 data = new u8 [size];
271 if (!data)
272 {
273 fclose(fp);
274 return false;
275 }
276
277 if (fread(data, 1, size, fp) != size)
278 {
279 delete [] data;
280 data = NULL;
281 fclose(fp);
282 return false;
283 }
284
285 memcpy(&header, data, sizeof(header));
286 if ((header.fw_identifier & 0x00FFFFFF) != 0x0043414D)
287 {
288 delete [] data;
289 data = NULL;
290 fclose(fp);
291 return false;
292 }
293 fclose(fp);
294
295 if (MMU.fw.size != size) // reallocate
296 mc_alloc(&MMU.fw, size);
297
298 userDataAddr = T1ReadWord(data, 0x20) * 8;
299
300 // fix bad dump of firmware? (wrong DS type)
301 // fix mario kart touch screen calibration
302 if ((T1ReadWord(data, 0x1E) != 0xFFFF) && data[0x1D] == 0x63)
303 {
304 data[0x1D] = NDS_CONSOLE_TYPE_FAT;
305 data[0x1E] = 0xFF;
306 data[0x1F] = 0xFF;
307 }
308
309 memcpy(MMU.fw.data, data, size);
310
311 delete [] data;
312 data = NULL;
313
314 // Generate the path for the external firmware config file.
315 std::string extFilePath = CFIRMWARE::GetExternalFilePath();
316 strncpy(MMU.fw.userfile, extFilePath.c_str(), PATH_MAX_LENGTH);
317
318 successLoad = true;
319 return true;
320 }
321
unpack()322 bool CFIRMWARE::unpack()
323 {
324 u32 src = 0;
325 u16 shift1 = 0, shift2 = 0, shift3 = 0, shift4 = 0;
326 u32 part1addr = 0, part2addr = 0, part3addr = 0, part4addr = 0, part5addr = 0;
327 u32 part1ram = 0, part2ram = 0;
328 u32 size = MMU.fw.size;
329
330 if (size == 512*1024)
331 {
332 #ifdef DEBUG
333 INFO("ERROR: 32Mbit (512Kb) firmware not supported\n");
334 #endif
335 return false;
336 }
337
338 u8 *data = new u8 [size];
339 if (!data)
340 return false;
341
342 memcpy(data, MMU.fw.data, size);
343
344 shift1 = ((header.shift_amounts >> 0) & 0x07);
345 shift2 = ((header.shift_amounts >> 3) & 0x07);
346 shift3 = ((header.shift_amounts >> 6) & 0x07);
347 shift4 = ((header.shift_amounts >> 9) & 0x07);
348
349 // todo - add support for 512Kb
350 part1addr = (header.part1_rom_boot9_addr << (2 + shift1));
351 part1ram = (0x02800000 - (header.part1_ram_boot9_addr << (2+shift2)));
352 part2addr = (header.part2_rom_boot7_addr << (2+shift3));
353 part2ram = (0x03810000 - (header.part2_ram_boot7_addr << (2+shift4)));
354 part3addr = (header.part3_rom_gui9_addr << 3);
355 part4addr = (header.part4_rom_wifi7_addr << 3);
356 part5addr = (header.part5_data_gfx_addr << 3);
357
358 ARM9bootAddr = part1ram;
359 ARM7bootAddr = part2ram;
360
361 enc.init(header.fw_identifier, 1, 0xC);
362
363 #if 0
364 enc.applyKeycode((u32*)&data[0x18]);
365 #else
366 // fix touch coords
367 data[0x18] = 0x00;
368 data[0x19] = 0x00;
369 data[0x1A] = 0x00;
370 data[0x1B] = 0x00;
371
372 data[0x1C] = 0x00;
373 data[0x1D] = 0xFF;
374 data[0x1E] = 0x00;
375 data[0x1F] = 0x00;
376 #endif
377
378 enc.init(header.fw_identifier, 2, 0xC);
379
380 size9 = decrypt(data + part1addr, tmp_data9);
381 if (!tmp_data9)
382 {
383 delete [] data; data = NULL;
384 return false;
385 }
386
387 size7 = decrypt(data + part2addr, tmp_data7);
388 if (!tmp_data7)
389 {
390 delete [] tmp_data9;
391 delete [] data; data = NULL;
392 return false;
393 }
394
395 u16 crc16_mine = getBootCodeCRC16();
396
397 if (crc16_mine != header.part12_boot_crc16)
398 {
399 #ifdef DEBUG
400 INFO("Firmware: ERROR: the boot code CRC16 (0x%04X) doesn't match the value in the firmware header (0x%04X)", crc16_mine, header.part12_boot_crc16);
401 #endif
402 delete [] tmp_data9;
403 delete [] tmp_data7;
404 delete [] data; data = NULL;
405 return false;
406 }
407
408 // Copy firmware boot codes to their respective locations
409 src = 0;
410 for(u32 i = 0; i < (size9 >> 2); i++)
411 {
412 _MMU_write32<ARMCPU_ARM9>(part1ram, T1ReadLong(tmp_data9, src));
413 src += 4; part1ram += 4;
414 }
415
416 src = 0;
417 for(u32 i = 0; i < (size7 >> 2); i++)
418 {
419 _MMU_write32<ARMCPU_ARM7>(part2ram, T1ReadLong(tmp_data7, src));
420 src += 4; part2ram += 4;
421 }
422 delete [] tmp_data7;
423 delete [] tmp_data9;
424
425 patched = false;
426 if (data[0x17C] != 0xFF)
427 patched = true;
428
429 #ifdef DEBUG
430 INFO("Firmware:\n");
431 INFO("- path: %s\n", CommonSettings.Firmware);
432 INFO("- size: %i bytes (%i Mbit)\n", size, size/1024/8);
433 INFO("- CRC : 0x%04X\n", header.part12_boot_crc16);
434 INFO("- header: \n");
435 INFO(" * size firmware %i\n", ((header.shift_amounts >> 12) & 0xF) * 128 * 1024);
436 INFO(" * ARM9 boot code address: 0x%08X\n", part1addr);
437 INFO(" * ARM9 boot code RAM address: 0x%08X\n", ARM9bootAddr);
438 INFO(" * ARM9 unpacked size: 0x%08X (%i) bytes\n", size9, size9);
439 INFO(" * ARM9 GUI code address: 0x%08X\n", part3addr);
440 INFO("\n");
441 INFO(" * ARM7 boot code address: 0x%08X\n", part2addr);
442 INFO(" * ARM7 boot code RAM address: 0x%08X\n", ARM7bootAddr);
443 INFO(" * ARM7 WiFi code address: 0x%08X\n", part4addr);
444 INFO(" * ARM7 unpacked size: 0x%08X (%i) bytes\n", size7, size7);
445 INFO("\n");
446 INFO(" * Data/GFX address: 0x%08X\n", part5addr);
447 #endif
448
449 if (patched)
450 {
451 u32 patch_offset = 0x3FC80;
452 if (data[0x17C] > 1)
453 patch_offset = 0x3F680;
454
455 memcpy(&header, data + patch_offset, sizeof(header));
456
457 shift1 = ((header.shift_amounts >> 0) & 0x07);
458 shift2 = ((header.shift_amounts >> 3) & 0x07);
459 shift3 = ((header.shift_amounts >> 6) & 0x07);
460 shift4 = ((header.shift_amounts >> 9) & 0x07);
461
462 // todo - add support for 512Kb
463 part1addr = (header.part1_rom_boot9_addr << (2 + shift1));
464 part1ram = (0x02800000 - (header.part1_ram_boot9_addr << (2+shift2)));
465 part2addr = (header.part2_rom_boot7_addr << (2+shift3));
466 part2ram = (0x03810000 - (header.part2_ram_boot7_addr << (2+shift4)));
467
468 ARM9bootAddr = part1ram;
469 ARM7bootAddr = part2ram;
470
471 size9 = decompress(data + part1addr, tmp_data9);
472 if (!tmp_data9)
473 {
474 delete [] data;
475 return false;
476 }
477
478 size7 = decompress(data + part2addr, tmp_data7);
479 if (!tmp_data7)
480 {
481 delete [] tmp_data9;
482 delete [] data;
483 return false;
484 };
485 // Copy firmware boot codes to their respective locations
486 src = 0;
487 for(u32 i = 0; i < (size9 >> 2); i++)
488 {
489 _MMU_write32<ARMCPU_ARM9>(part1ram, T1ReadLong(tmp_data9, src));
490 src += 4; part1ram += 4;
491 }
492
493 src = 0;
494 for(u32 i = 0; i < (size7 >> 2); i++)
495 {
496 _MMU_write32<ARMCPU_ARM7>(part2ram, T1ReadLong(tmp_data7, src));
497 src += 4; part2ram += 4;
498 }
499 delete [] tmp_data7;
500 delete [] tmp_data9;
501
502 #ifdef DEBUG
503 INFO("\nFlashme:\n");
504 INFO("- header: \n");
505 INFO(" * ARM9 boot code address: 0x%08X\n", part1addr);
506 INFO(" * ARM9 boot code RAM address: 0x%08X\n", ARM9bootAddr);
507 INFO(" * ARM9 unpacked size: 0x%08X (%i) bytes\n", size9, size9);
508 INFO("\n");
509 INFO(" * ARM7 boot code address: 0x%08X\n", part2addr);
510 INFO(" * ARM7 boot code RAM address: 0x%08X\n", ARM7bootAddr);
511 INFO(" * ARM7 unpacked size: 0x%08X (%i) bytes\n", size7, size7);
512 #endif
513 }
514
515 memcpy(MMU.fw.data, data, size);
516 MMU.fw.fp = NULL;
517
518 delete [] data; data = NULL;
519 return true;
520 }
521
loadSettings()522 bool CFIRMWARE::loadSettings()
523 {
524 if (!CommonSettings.UseExtFirmware) return false;
525 if (!CommonSettings.UseExtFirmwareSettings) return false;
526
527 FILE *fp = fopen(MMU.fw.userfile, "rb");
528 if (fp)
529 {
530 fseek(fp, 0, SEEK_END);
531 if (ftell(fp) == DFC_FILE_SIZE)
532 {
533 fseek(fp, 0, SEEK_SET);
534 u8 *usr = new u8[SETTINGS_SIZE];
535 if (usr)
536 {
537 if (fread(usr, 1, DFC_ID_SIZE, fp) == DFC_ID_SIZE)
538 {
539 if (memcmp(usr, DFC_ID_CODE, DFC_ID_SIZE) == 0)
540 {
541 if (fread(usr, 1, SETTINGS_SIZE, fp) == SETTINGS_SIZE)
542 {
543 memcpy(&MMU.fw.data[userDataAddr], usr, USER_SETTINGS_SIZE);
544 memcpy(&MMU.fw.data[userDataAddr + 0x100], usr, USER_SETTINGS_SIZE);
545 memcpy(&MMU.fw.data[WIFI_SETTINGS_OFF], usr + USER_SETTINGS_SIZE, WIFI_SETTINGS_SIZE);
546 memcpy(&MMU.fw.data[WIFI_AP_SETTINGS_OFF], usr + USER_SETTINGS_SIZE + WIFI_SETTINGS_SIZE, WIFI_AP_SETTINGS_SIZE);
547 printf("Loaded user settings from %s\n", MMU.fw.userfile);
548 }
549 }
550 }
551 delete [] usr;
552 usr = NULL;
553 }
554 }
555 else
556 printf("Failed loading firmware config from %s (wrong file size)\n", MMU.fw.userfile);
557
558 fclose(fp);
559 }
560
561 return false;
562 }
563
saveSettings()564 bool CFIRMWARE::saveSettings()
565 {
566 if (!CommonSettings.UseExtFirmware) return false;
567 if (!CommonSettings.UseExtFirmwareSettings) return false;
568
569 u8 *data = &MMU.fw.data[userDataAddr];
570 u8 counter0 = data[0x070];
571 u8 counter1 = data[0x170];
572
573 if (counter1 == ((counter0 + 1) & 0x7F))
574 {
575 // copy User Settings 1 to User Settings 0 area
576 memcpy(data, data + 0x100, 0x100);
577 }
578 else
579 {
580 // copy User Settings 0 to User Settings 1 area
581 memcpy(data + 0x100, data, 0x100);
582 }
583
584 printf("Firmware: saving config");
585 FILE *fp = fopen(MMU.fw.userfile, "wb");
586 if (fp)
587 {
588 u8 *usr = new u8[DFC_FILE_SIZE];
589 if (usr)
590 {
591 memcpy(usr, DFC_ID_CODE, DFC_ID_SIZE);
592 memcpy(usr + DFC_ID_SIZE, data, USER_SETTINGS_SIZE);
593 memcpy(usr + DFC_ID_SIZE + USER_SETTINGS_SIZE, &MMU.fw.data[WIFI_SETTINGS_OFF], WIFI_SETTINGS_SIZE);
594 memcpy(usr + DFC_ID_SIZE + USER_SETTINGS_SIZE + WIFI_SETTINGS_SIZE, &MMU.fw.data[WIFI_AP_SETTINGS_OFF], WIFI_AP_SETTINGS_SIZE);
595 if (fwrite(usr, 1, DFC_FILE_SIZE, fp) == DFC_FILE_SIZE)
596 printf(" - done\n");
597 else
598 printf(" - failed\n");
599
600 delete [] usr;
601 }
602 fclose(fp);
603 }
604 else
605 printf(" - failed\n");
606
607 return true;
608 }
609
GetExternalFilePath()610 std::string CFIRMWARE::GetExternalFilePath()
611 {
612 std::string fwPath = CommonSettings.Firmware;
613 std::string fwFileName = Path::GetFileNameFromPathWithoutExt(fwPath);
614 char configPath[PATH_MAX_LENGTH] = {0};
615 path.getpath(path.BATTERY, configPath);
616 if (configPath[strlen(configPath)-1] == DIRECTORY_DELIMITER_CHAR)
617 configPath[strlen(configPath)-1] = 0;
618 std::string finalPath = std::string(configPath) + DIRECTORY_DELIMITER_CHAR + fwFileName + FILE_EXT_DELIMITER_CHAR + FW_CONFIG_FILE_EXT;
619
620 return finalPath;
621 }
622
getTouchCalibrate()623 void *CFIRMWARE::getTouchCalibrate()
624 {
625 static TSCalInfo cal = {0};
626
627 if (!successLoad || !CommonSettings.UseExtFirmware || !successLoad)
628 {
629 cal.adc.x1 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x58) & 0x1FFF;
630 cal.adc.y1 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x5A) & 0x1FFF;
631 cal.scr.x1 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x5C);
632 cal.scr.y1 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x5D);
633 cal.adc.x2 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x5E) & 0x1FFF;
634 cal.adc.y2 = _MMU_read16<ARMCPU_ARM7>(0x027FFC80 + 0x60) & 0x1FFF;
635 cal.scr.x2 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x62);
636 cal.scr.y2 = _MMU_read08<ARMCPU_ARM7>(0x027FFC80 + 0x63);
637 }
638 else
639 {
640 cal.adc.x1 = T1ReadWord(MMU.fw.data, userDataAddr + 0x58) & 0x1FFF;
641 cal.adc.y1 = T1ReadWord(MMU.fw.data, userDataAddr + 0x5A) & 0x1FFF;
642 cal.scr.x1 = T1ReadByte(MMU.fw.data, userDataAddr + 0x5C);
643 cal.scr.y1 = T1ReadByte(MMU.fw.data, userDataAddr + 0x5D);
644 cal.adc.x2 = T1ReadWord(MMU.fw.data, userDataAddr + 0x5E) & 0x1FFF;
645 cal.adc.y2 = T1ReadWord(MMU.fw.data, userDataAddr + 0x60) & 0x1FFF;
646 cal.scr.x2 = T1ReadByte(MMU.fw.data, userDataAddr + 0x62);
647 cal.scr.y2 = T1ReadByte(MMU.fw.data, userDataAddr + 0x63);
648 }
649
650 cal.adc.width = (cal.adc.x2 - cal.adc.x1);
651 cal.adc.height = (cal.adc.y2 - cal.adc.y1);
652 cal.scr.width = (cal.scr.x2 - cal.scr.x1);
653 cal.scr.height = (cal.scr.y2 - cal.scr.y1);
654
655 return (void*)&cal;
656 }
657
658 //=====================================================================================================
659 static u32
calc_CRC16(u32 start,const u8 * data,int count)660 calc_CRC16( u32 start, const u8 *data, int count) {
661 int i,j;
662 u32 crc = start & 0xffff;
663 const u16 val[8] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 };
664 for(i = 0; i < count; i++)
665 {
666 crc = crc ^ data[i];
667
668 for(j = 0; j < 8; j++) {
669 int do_bit = 0;
670
671 if ( crc & 0x1)
672 do_bit = 1;
673
674 crc = crc >> 1;
675
676 if ( do_bit) {
677 crc = crc ^ (val[j] << (7-j));
678 }
679 }
680 }
681 return crc;
682 }
683
copy_firmware_user_data(u8 * dest_buffer,const u8 * fw_data)684 int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data)
685 {
686 /*
687 * Determine which of the two user settings in the firmware is the current
688 * and valid one and then copy this into the destination buffer.
689 *
690 * The current setting will have a greater count.
691 * Settings are only valid if its CRC16 is correct.
692 */
693 int user1_valid = 0;
694 int user2_valid = 0;
695 u32 user_settings_offset;
696 u32 fw_crc;
697 u32 crc;
698 int copy_good = 0;
699
700 user_settings_offset = fw_data[0x20];
701 user_settings_offset |= fw_data[0x21] << 8;
702 user_settings_offset <<= 3;
703
704 if ( user_settings_offset <= 0x3FE00) {
705 s32 copy_settings_offset = -1;
706
707 crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset],
708 NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
709 fw_crc = fw_data[user_settings_offset + 0x72];
710 fw_crc |= fw_data[user_settings_offset + 0x73] << 8;
711 if ( crc == fw_crc) {
712 user1_valid = 1;
713 }
714
715 crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100],
716 NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
717 fw_crc = fw_data[user_settings_offset + 0x100 + 0x72];
718 fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8;
719 if ( crc == fw_crc) {
720 user2_valid = 1;
721 }
722
723 if ( user1_valid) {
724 if ( user2_valid) {
725 u16 count1, count2;
726
727 count1 = fw_data[user_settings_offset + 0x70];
728 count1 |= fw_data[user_settings_offset + 0x71] << 8;
729
730 count2 = fw_data[user_settings_offset + 0x100 + 0x70];
731 count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8;
732
733 if ( count2 > count1) {
734 copy_settings_offset = user_settings_offset + 0x100;
735 }
736 else {
737 copy_settings_offset = user_settings_offset;
738 }
739 }
740 else {
741 copy_settings_offset = user_settings_offset;
742 }
743 }
744 else if ( user2_valid) {
745 /* copy the second user settings */
746 copy_settings_offset = user_settings_offset + 0x100;
747 }
748
749 if ( copy_settings_offset > 0) {
750 memcpy( dest_buffer, &fw_data[copy_settings_offset],
751 NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT);
752 copy_good = 1;
753 }
754 }
755
756 return copy_good;
757 }
758
fill_user_data_area(struct NDS_fw_config_data * user_settings,u8 * data,int count)759 static void fill_user_data_area( struct NDS_fw_config_data *user_settings,u8 *data, int count)
760 {
761 u32 crc;
762 int i;
763 u8 *ts_cal_data_area;
764
765 memset( data, 0, 0x100);
766
767 // version
768 data[0x00] = 5;
769 data[0x01] = 0;
770
771 // colour
772 data[0x02] = user_settings->fav_colour;
773
774 // birthday month and day
775 data[0x03] = user_settings->birth_month;
776 data[0x04] = user_settings->birth_day;
777
778 //nickname and length
779 for ( i = 0; i < MAX_FW_NICKNAME_LENGTH; i++) {
780 data[0x06 + (i * 2)] = user_settings->nickname[i] & 0xff;
781 data[0x06 + (i * 2) + 1] = (user_settings->nickname[i] >> 8) & 0xff;
782 }
783
784 data[0x1a] = user_settings->nickname_len;
785
786 //Message
787 for ( i = 0; i < MAX_FW_MESSAGE_LENGTH; i++) {
788 data[0x1c + (i * 2)] = user_settings->message[i] & 0xff;
789 data[0x1c + (i * 2) + 1] = (user_settings->message[i] >> 8) & 0xff;
790 }
791
792 data[0x50] = user_settings->message_len;
793
794 //touch screen calibration
795 ts_cal_data_area = &data[0x58];
796 for ( i = 0; i < 2; i++) {
797 // ADC x y
798 *ts_cal_data_area++ = user_settings->touch_cal[i].adc_x & 0xff;
799 *ts_cal_data_area++ = (user_settings->touch_cal[i].adc_x >> 8) & 0xff;
800 *ts_cal_data_area++ = user_settings->touch_cal[i].adc_y & 0xff;
801 *ts_cal_data_area++ = (user_settings->touch_cal[i].adc_y >> 8) & 0xff;
802
803 //screen x y
804 *ts_cal_data_area++ = user_settings->touch_cal[i].screen_x;
805 *ts_cal_data_area++ = user_settings->touch_cal[i].screen_y;
806 }
807
808 //language and flags
809 data[0x64] = user_settings->language;
810 data[0x65] = 0xfc;
811
812 //update count and crc
813 data[0x70] = count & 0xff;
814 data[0x71] = (count >> 8) & 0xff;
815
816 crc = calc_CRC16( 0xffff, data, 0x70);
817 data[0x72] = crc & 0xff;
818 data[0x73] = (crc >> 8) & 0xff;
819
820 memset( &data[0x74], 0xff, 0x100 - 0x74);
821 }
822
823 // creates an firmware flash image, which contains all needed info to initiate a wifi connection
NDS_CreateDummyFirmware(NDS_fw_config_data * user_settings)824 int NDS_CreateDummyFirmware(NDS_fw_config_data *user_settings)
825 {
826 //Create the firmware header
827
828 memset( MMU.fw.data, 0, 0x40000);
829
830 //firmware identifier
831 MMU.fw.data[0x8] = 'M';
832 MMU.fw.data[0x8 + 1] = 'A';
833 MMU.fw.data[0x8 + 2] = 'C';
834 MMU.fw.data[0x8 + 3] = 'P';
835
836 // DS type
837 if ( user_settings->ds_type == NDS_CONSOLE_TYPE_DSI)
838 MMU.fw.data[0x1d] = 0xFF;
839 else
840 MMU.fw.data[0x1d] = user_settings->ds_type;
841
842 //User Settings offset 0x3fe00 / 8
843 MMU.fw.data[0x20] = 0xc0;
844 MMU.fw.data[0x21] = 0x7f;
845
846
847 //User settings (at 0x3FE00 and 0x3FF00)
848
849 fill_user_data_area( user_settings, &MMU.fw.data[ 0x3FE00], 0);
850 fill_user_data_area( user_settings, &MMU.fw.data[ 0x3FF00], 1);
851
852 // Wifi config length
853 MMU.fw.data[0x2C] = 0x38;
854 MMU.fw.data[0x2D] = 0x01;
855
856 MMU.fw.data[0x2E] = 0x00;
857
858 //Wifi version
859 MMU.fw.data[0x2F] = 0x00;
860
861 //MAC address
862 memcpy((MMU.fw.data + 0x36), FW_Mac, sizeof(FW_Mac));
863
864 //Enabled channels
865 MMU.fw.data[0x3C] = 0xFE;
866 MMU.fw.data[0x3D] = 0x3F;
867
868 MMU.fw.data[0x3E] = 0xFF;
869 MMU.fw.data[0x3F] = 0xFF;
870
871 //RF related
872 MMU.fw.data[0x40] = 0x02;
873 MMU.fw.data[0x41] = 0x18;
874 MMU.fw.data[0x42] = 0x0C;
875
876 MMU.fw.data[0x43] = 0x01;
877
878 //Wifi I/O init values
879 memcpy((MMU.fw.data + 0x44), FW_WIFIInit, sizeof(FW_WIFIInit));
880
881 //Wifi BB init values
882 memcpy((MMU.fw.data + 0x64), FW_BBInit, sizeof(FW_BBInit));
883
884 //Wifi RF init values
885 memcpy((MMU.fw.data + 0xCE), FW_RFInit, sizeof(FW_RFInit));
886
887 //Wifi channel-related init values
888 memcpy((MMU.fw.data + 0xF2), FW_RFChannel, sizeof(FW_RFChannel));
889 memcpy((MMU.fw.data + 0x146), FW_BBChannel, sizeof(FW_BBChannel));
890 memset((MMU.fw.data + 0x154), 0x10, 0xE);
891
892 //WFC profiles
893 memcpy((MMU.fw.data + 0x3FA40), &FW_WFCProfile1, sizeof(FW_WFCProfile));
894 memcpy((MMU.fw.data + 0x3FB40), &FW_WFCProfile2, sizeof(FW_WFCProfile));
895 memcpy((MMU.fw.data + 0x3FC40), &FW_WFCProfile3, sizeof(FW_WFCProfile));
896 (*(u16*)(MMU.fw.data + 0x3FAFE)) = (u16)calc_CRC16(0, (MMU.fw.data + 0x3FA00), 0xFE);
897 (*(u16*)(MMU.fw.data + 0x3FBFE)) = (u16)calc_CRC16(0, (MMU.fw.data + 0x3FB00), 0xFE);
898 (*(u16*)(MMU.fw.data + 0x3FCFE)) = (u16)calc_CRC16(0, (MMU.fw.data + 0x3FC00), 0xFE);
899
900
901 MMU.fw.data[0x162] = 0x19;
902 memset((MMU.fw.data + 0x163), 0xFF, 0x9D);
903
904 //Wifi settings CRC16
905 (*(u16*)(MMU.fw.data + 0x2A)) = calc_CRC16(0, (MMU.fw.data + 0x2C), 0x138);
906
907 if (&CommonSettings.fw_config != user_settings)
908 memcpy(&CommonSettings.fw_config, user_settings, sizeof(NDS_fw_config_data));
909
910 return TRUE ;
911 }
912
NDS_FillDefaultFirmwareConfigData(NDS_fw_config_data * fw_config)913 void NDS_FillDefaultFirmwareConfigData(NDS_fw_config_data *fw_config) {
914 const char *default_nickname = "DeSmuME";
915 const char *default_message = "DeSmuME makes you happy!";
916 int i;
917 int str_length;
918
919 memset( fw_config, 0, sizeof(NDS_fw_config_data));
920 fw_config->ds_type = NDS_CONSOLE_TYPE_FAT;
921
922 fw_config->fav_colour = 7;
923
924 fw_config->birth_day = 23;
925 fw_config->birth_month = 6;
926
927 str_length = strlen( default_nickname);
928 for ( i = 0; i < str_length; i++) {
929 fw_config->nickname[i] = default_nickname[i];
930 }
931 fw_config->nickname_len = str_length;
932
933 str_length = strlen( default_message);
934 for ( i = 0; i < str_length; i++) {
935 fw_config->message[i] = default_message[i];
936 }
937 fw_config->message_len = str_length;
938
939 //default to English
940 fw_config->language = 1;
941
942 // default touchscreen calibration
943
944 //ANCIENT DESMUME VALUES
945 fw_config->touch_cal[0].adc_x = 0x200;
946 fw_config->touch_cal[0].adc_y = 0x200;
947 fw_config->touch_cal[0].screen_x = 0x20 + 1; // calibration screen coords are 1-based,
948 fw_config->touch_cal[0].screen_y = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong.
949 //VALUES FROM NOCASH
950 //fw_config->touch_cal[0].adc_x = 0x02DF;
951 //fw_config->touch_cal[0].adc_y = 0x032C;
952 //fw_config->touch_cal[0].screen_x = 0x20;
953 //fw_config->touch_cal[0].screen_y = 0x20;
954
955 //ANCIENT DESMUME VALUES
956 fw_config->touch_cal[1].adc_x = 0xe00;
957 fw_config->touch_cal[1].adc_y = 0x800;
958 fw_config->touch_cal[1].screen_x = 0xe0 + 1;
959 fw_config->touch_cal[1].screen_y = 0x80 + 1;
960 //VALUES FROM NOCASH
961 //fw_config->touch_cal[1].adc_x = 0x0D3B;
962 //fw_config->touch_cal[1].adc_y = 0x0CE7;
963 //fw_config->touch_cal[1].screen_x = 0xE0;
964 //fw_config->touch_cal[1].screen_y = 0xA0;
965 }
966
NDS_PatchFirmwareMAC()967 void NDS_PatchFirmwareMAC()
968 {
969 memcpy((MMU.fw.data + 0x36), FW_Mac, sizeof(FW_Mac));
970 (*(u16*)(MMU.fw.data + 0x2A)) = calc_CRC16(0, (MMU.fw.data + 0x2C), 0x138);
971 }
972
973 //=========================
974 //- firmware SPI chip interface -
975 //the original intention was for this code to have similarity to the AUXSPI backup memory devices.
976 //however, that got overgrown, and this stuff stayed pretty simple.
977 //perhaps it can be re-defined in terms of a simpler AUXSPI device after the AUXSPI devices are re-designed.
978
979 #define FW_CMD_READ 0x03
980 #define FW_CMD_WRITEDISABLE 0x04
981 #define FW_CMD_READSTATUS 0x05
982 #define FW_CMD_WRITEENABLE 0x06
983 #define FW_CMD_PAGEWRITE 0x0A
984 #define FW_CMD_READ_ID 0x9F
985
fw_reset_com(fw_memory_chip * mc)986 void fw_reset_com(fw_memory_chip *mc)
987 {
988 if(mc->com == FW_CMD_PAGEWRITE)
989 {
990 if (mc->fp)
991 {
992 fseek(mc->fp, 0, SEEK_SET);
993 fwrite(mc->data, mc->size, 1, mc->fp);
994 }
995
996 if (mc->isFirmware && CommonSettings.UseExtFirmware && CommonSettings.UseExtFirmwareSettings && firmware)
997 {
998 firmware->saveSettings();
999 }
1000 mc->write_enable = FALSE;
1001 }
1002
1003 mc->com = 0;
1004 }
1005
fw_transfer(fw_memory_chip * mc,u8 data)1006 u8 fw_transfer(fw_memory_chip *mc, u8 data)
1007 {
1008 if(mc->com == FW_CMD_READ || mc->com == FW_CMD_PAGEWRITE) /* check if we are in a command that needs 3 bytes address */
1009 {
1010 if(mc->addr_shift > 0) /* if we got a complete address */
1011 {
1012 mc->addr_shift--;
1013 mc->addr |= data << (mc->addr_shift * 8); /* argument is a byte of address */
1014 }
1015 else /* if we have received 3 bytes of address, proceed command */
1016 {
1017 switch(mc->com)
1018 {
1019 case FW_CMD_READ:
1020 if(mc->addr < mc->size) /* check if we can read */
1021 {
1022 data = mc->data[mc->addr]; /* return byte */
1023 mc->addr++; /* then increment address */
1024 }
1025 break;
1026
1027 case FW_CMD_PAGEWRITE:
1028 if(mc->addr < mc->size)
1029 {
1030 mc->data[mc->addr] = data; /* write byte */
1031 mc->addr++;
1032 }
1033 break;
1034 }
1035
1036 }
1037 }
1038 else if(mc->com == FW_CMD_READ_ID)
1039 {
1040 switch(mc->addr)
1041 {
1042 //here is an ID string measured from an old ds fat: 62 16 00 (0x62=sanyo)
1043 //but we chose to use an ST from martin's ds fat string so programs might have a clue as to the firmware size:
1044 //20 40 12
1045 case 0:
1046 data = 0x20;
1047 mc->addr=1;
1048 break;
1049 case 1:
1050 data = 0x40; //according to gbatek this is the device ID for the flash on someone's ds fat
1051 mc->addr=2;
1052 break;
1053 case 2:
1054 data = 0x12;
1055 mc->addr = 0;
1056 break;
1057 }
1058 }
1059 else if(mc->com == FW_CMD_READSTATUS)
1060 {
1061 return (mc->write_enable ? 0x02 : 0x00);
1062 }
1063 else //finally, check if it's a new command
1064 {
1065 switch(data)
1066 {
1067 case 0: break; //nothing
1068
1069 case FW_CMD_READ_ID:
1070 mc->addr = 0;
1071 mc->com = FW_CMD_READ_ID;
1072 break;
1073
1074 case FW_CMD_READ: //read command
1075 mc->addr = 0;
1076 mc->addr_shift = 3;
1077 mc->com = FW_CMD_READ;
1078 break;
1079
1080 case FW_CMD_WRITEENABLE: //enable writing
1081 if(mc->writeable_buffer) { mc->write_enable = TRUE; }
1082 break;
1083
1084 case FW_CMD_WRITEDISABLE: //disable writing
1085 mc->write_enable = FALSE;
1086 break;
1087
1088 case FW_CMD_PAGEWRITE: //write command
1089 if(mc->write_enable)
1090 {
1091 mc->addr = 0;
1092 mc->addr_shift = 3;
1093 mc->com = FW_CMD_PAGEWRITE;
1094 }
1095 else { data = 0; }
1096 break;
1097
1098 case FW_CMD_READSTATUS: //status register command
1099 mc->com = FW_CMD_READSTATUS;
1100 break;
1101
1102 default:
1103 printf("Unhandled FW command: %02X\n", data);
1104 break;
1105 }
1106 }
1107
1108 return data;
1109 }
1110
1111
mc_init(fw_memory_chip * mc,int type)1112 void mc_init(fw_memory_chip *mc, int type)
1113 {
1114 mc->com = 0;
1115 mc->addr = 0;
1116 mc->addr_shift = 0;
1117 mc->data = NULL;
1118 mc->size = 0;
1119 mc->write_enable = FALSE;
1120 mc->writeable_buffer = FALSE;
1121 mc->type = type;
1122
1123 switch(mc->type)
1124 {
1125 case MC_TYPE_EEPROM1:
1126 mc->addr_size = 1;
1127 break;
1128 case MC_TYPE_EEPROM2:
1129 case MC_TYPE_FRAM:
1130 mc->addr_size = 2;
1131 break;
1132 case MC_TYPE_FLASH:
1133 mc->addr_size = 3;
1134 break;
1135 default: break;
1136 }
1137 }
1138
mc_alloc(fw_memory_chip * mc,u32 size)1139 u8 *mc_alloc(fw_memory_chip *mc, u32 size)
1140 {
1141 u8 *buffer = NULL;
1142 buffer = new u8[size];
1143 if(!buffer) { return NULL; }
1144 memset(buffer,0,size);
1145
1146 if (mc->data) delete [] mc->data;
1147 mc->data = buffer;
1148 mc->size = size;
1149 mc->writeable_buffer = TRUE;
1150
1151 return buffer;
1152 }
1153
mc_free(fw_memory_chip * mc)1154 void mc_free(fw_memory_chip *mc)
1155 {
1156 if(mc->data) delete[] mc->data;
1157 mc_init(mc, 0);
1158 }
1159