/* Copyright (C) 2009-2011 DeSmuME Team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the this software. If not, see . */ #include "firmware.h" #include "NDSSystem.h" #include "path.h" //#define DWNUM(i) ((i) >> 2) static inline uint32_t DWNUM(uint32_t i) { return i >> 2; } bool CFIRMWARE::getKeyBuf() { FILE *file = fopen(CommonSettings.ARM7BIOS, "rb"); if (!file) return false; fseek(file, 0x30, SEEK_SET); size_t res = fread(keyBuf, 4, 0x412, file); fclose(file); return res == 0x412; } void CFIRMWARE::crypt64BitUp(uint32_t *ptr) { uint32_t Y = ptr[0]; uint32_t X = ptr[1]; for(uint32_t i = 0x00; i <= 0x0F; i++) { uint32_t Z = (keyBuf[i] ^ X); X = keyBuf[DWNUM(0x048 + (((Z >> 24) & 0xFF) << 2))]; X = (keyBuf[DWNUM(0x448 + (((Z >> 16) & 0xFF) << 2))] + X); X = (keyBuf[DWNUM(0x848 + (((Z >> 8) & 0xFF) << 2))] ^ X); X = (keyBuf[DWNUM(0xC48 + ((Z & 0xFF) << 2))] + X); X = (Y ^ X); Y = Z; } ptr[0] = (X ^ keyBuf[DWNUM(0x40)]); ptr[1] = (Y ^ keyBuf[DWNUM(0x44)]); } void CFIRMWARE::crypt64BitDown(uint32_t *ptr) { uint32_t Y = ptr[0]; uint32_t X = ptr[1]; for(uint32_t i = 0x11; i >= 0x02; i--) { uint32_t Z = (keyBuf[i] ^ X); X = keyBuf[DWNUM(0x048 + (((Z >> 24) & 0xFF) << 2))]; X = (keyBuf[DWNUM(0x448 + (((Z >> 16) & 0xFF) << 2))] + X); X = (keyBuf[DWNUM(0x848 + (((Z >> 8) & 0xFF) << 2))] ^ X); X = (keyBuf[DWNUM(0xC48 + ((Z & 0xFF) << 2))] + X); X = (Y ^ X); Y = Z; } ptr[0] = (X ^ keyBuf[DWNUM(0x04)]); ptr[1] = (Y ^ keyBuf[DWNUM(0x00)]); } //#define bswap32(val) (((val & 0x000000FF) << 24) | ((val & 0x0000FF00) << 8) | ((val & 0x00FF0000) >> 8) | ((val & 0xFF000000) >> 24)) static inline uint32_t bswap32(uint32_t val) { return ((val & 0x000000FF) << 24) | ((val & 0x0000FF00) << 8) | ((val & 0x00FF0000) >> 8) | ((val & 0xFF000000) >> 24); } void CFIRMWARE::applyKeycode(uint32_t modulo) { crypt64BitUp(&keyCode[1]); crypt64BitUp(&keyCode[0]); uint32_t scratch[2] = {0x00000000, 0x00000000}; for(uint32_t i = 0; i <= 0x44; i += 4) { keyBuf[DWNUM(i)] = (keyBuf[DWNUM(i)] ^ bswap32(keyCode[DWNUM(i % modulo)])); } for(uint32_t i = 0; i <= 0x1040; i += 8) { crypt64BitUp(scratch); keyBuf[DWNUM(i)] = scratch[1]; keyBuf[DWNUM(i+4)] = scratch[0]; } } //#undef bswap32 bool CFIRMWARE::initKeycode(uint32_t idCode, int level, uint32_t modulo) { if(getKeyBuf() == false) return false; keyCode[0] = idCode; keyCode[1] = (idCode >> 1); keyCode[2] = (idCode << 1); if(level >= 1) applyKeycode(modulo); if(level >= 2) applyKeycode(modulo); keyCode[1] <<= 1; keyCode[2] >>= 1; if(level >= 3) applyKeycode(modulo); return true; } uint16_t CFIRMWARE::getBootCodeCRC16() { unsigned int i, j; uint32_t crc = 0xFFFF; const uint16_t val[8] = {0xC0C1, 0xC181, 0xC301, 0xC601, 0xCC01, 0xD801, 0xF001, 0xA001}; for(i = 0; i < size9; i++) { crc = (crc ^ tmp_data9[i]); for(j = 0; j < 8; j++) { if(crc & 0x0001) crc = ((crc >> 1) ^ (val[j] << (7-j))); else crc = (crc >> 1); } } for(i = 0; i < size7; i++) { crc = (crc ^ tmp_data7[i]); for(j = 0; j < 8; j++) { if(crc & 0x0001) crc = ((crc >> 1) ^ (val[j] << (7-j))); else crc = (crc >> 1); } } return crc & 0xFFFF; } uint32_t CFIRMWARE::decrypt(const uint8_t *in, uint8_t* &out) { uint32_t curBlock[2] = { 0 }; uint32_t blockSize = 0; uint32_t xLen = 0; uint32_t i = 0, j = 0; uint32_t xIn = 4, xOut = 0; uint32_t len = 0; uint32_t offset = 0; uint32_t windowOffset = 0; uint8_t d = 0; uint16_t data = 0; memcpy(curBlock, in, 8); crypt64BitDown(curBlock); blockSize = (curBlock[0] >> 8); if (blockSize == 0) return 0; out = new uint8_t [blockSize]; if (!out ) return 0; memset(out, 0xFF, blockSize); xLen = blockSize; while(xLen > 0) { d = T1ReadByte((uint8_t*)curBlock, (xIn % 8)); xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); crypt64BitDown(curBlock); } for(i = 0; i < 8; i++) { if(d & 0x80) { data = (T1ReadByte((uint8_t*)curBlock, (xIn % 8)) << 8); xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); crypt64BitDown(curBlock); } data |= T1ReadByte((uint8_t*)curBlock, (xIn % 8)); xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); crypt64BitDown(curBlock); } len = (data >> 12) + 3; offset = (data & 0xFFF); windowOffset = (xOut - offset - 1); for(j = 0; j < len; j++) { T1WriteByte(out, xOut, T1ReadByte(out, windowOffset)); xOut++; windowOffset++; xLen--; if(xLen == 0) return blockSize; } } else { T1WriteByte(out, xOut, T1ReadByte((uint8_t*)curBlock, (xIn % 8))); xOut++; xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); crypt64BitDown(curBlock); } xLen--; if(xLen == 0) return blockSize; } d = ((d << 1) & 0xFF); } } return blockSize; } uint32_t CFIRMWARE::decompress(const uint8_t *in, uint8_t* &out) { uint32_t curBlock[2] = { 0 }; uint32_t blockSize = 0; uint32_t xLen = 0; uint32_t i = 0, j = 0; uint32_t xIn = 4, xOut = 0; uint32_t len = 0; uint32_t offset = 0; uint32_t windowOffset = 0; uint8_t d = 0; uint16_t data = 0; memcpy(curBlock, in, 8); blockSize = (curBlock[0] >> 8); if (blockSize == 0) return 0; out = new uint8_t [blockSize]; if (!out ) return 0; memset(out, 0xFF, blockSize); xLen = blockSize; while(xLen > 0) { d = T1ReadByte((uint8_t*)curBlock, (xIn % 8)); xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); } for(i = 0; i < 8; i++) { if(d & 0x80) { data = (T1ReadByte((uint8_t*)curBlock, (xIn % 8)) << 8); xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); } data |= T1ReadByte((uint8_t*)curBlock, (xIn % 8)); xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); } len = (data >> 12) + 3; offset = (data & 0xFFF); windowOffset = (xOut - offset - 1); for(j = 0; j < len; j++) { T1WriteByte(out, xOut, T1ReadByte(out, windowOffset)); xOut++; windowOffset++; xLen--; if(xLen == 0) return blockSize; } } else { T1WriteByte(out, xOut, T1ReadByte((uint8_t*)curBlock, (xIn % 8))); xOut++; xIn++; if((xIn % 8) == 0) { memcpy(curBlock, in + xIn, 8); } xLen--; if(xLen == 0) return blockSize; } d = ((d << 1) & 0xFF); } } return blockSize; } //================================================================================ bool CFIRMWARE::load() { uint32_t size = 0; uint8_t *data = NULL; uint16_t shift1 = 0, shift2 = 0, shift3 = 0, shift4 = 0; uint32_t part1addr = 0, part2addr = 0/*, part3addr = 0, part4addr = 0, part5addr = 0*/; uint32_t part1ram = 0, part2ram = 0; uint32_t src = 0; if (CommonSettings.UseExtFirmware == false) return false; if (strlen(CommonSettings.Firmware) == 0) return false; FILE *fp = fopen(CommonSettings.Firmware, "rb"); if (!fp) return false; fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); if( (size != 256*1024) && (size != 512*1024) ) { fclose(fp); return false; } #if 1 if (size == 512*1024) { //INFO("ERROR: 32Mbit (512Kb) firmware not supported\n"); fclose(fp); return false; } #endif data = new uint8_t [size]; if (!data) { fclose(fp); return false; } if (fread(data, 1, size, fp) != size) { delete [] data; fclose(fp); return false; } memcpy(&header, data, sizeof(header)); if ((header.fw_identifier[0] != 'M') || (header.fw_identifier[1] != 'A') || (header.fw_identifier[2] != 'C')) { delete [] data; fclose(fp); return false; } shift1 = ((header.shift_amounts >> 0) & 0x07); shift2 = ((header.shift_amounts >> 3) & 0x07); shift3 = ((header.shift_amounts >> 6) & 0x07); shift4 = ((header.shift_amounts >> 9) & 0x07); // todo - add support for 512Kb part1addr = (header.part1_rom_boot9_addr << (2 + shift1)); part1ram = (0x02800000 - (header.part1_ram_boot9_addr << (2+shift2))); part2addr = (header.part2_rom_boot7_addr << (2+shift3)); part2ram = (0x03810000 - (header.part2_ram_boot7_addr << (2+shift4))); //part3addr = (header.part3_rom_gui9_addr << 3); //part4addr = (header.part4_rom_wifi7_addr << 3); //part5addr = (header.part5_data_gfx_addr << 3); ARM9bootAddr = part1ram; ARM7bootAddr = part2ram; if(initKeycode(T1ReadLong(data, 0x08), 1, 0xC) == false) { delete [] data; fclose(fp); return false; } #if 0 crypt64BitDown((uint32_t*)&data[0x18]); #else // fix touch coords data[0x18] = 0x00; data[0x19] = 0x00; data[0x1A] = 0x00; data[0x1B] = 0x00; data[0x1C] = 0x00; data[0x1D] = 0xFF; data[0x1E] = 0x00; data[0x1F] = 0x00; #endif if(initKeycode(T1ReadLong(data, 0x08), 2, 0xC) == false) { delete [] data; fclose(fp); return false; } size9 = decrypt(data + part1addr, tmp_data9); if (!tmp_data9) { delete [] data; fclose(fp); return false; } size7 = decrypt(data + part2addr, tmp_data7); if (!tmp_data7) { delete [] tmp_data9; delete [] data; fclose(fp); return false; } uint16_t crc16_mine = getBootCodeCRC16(); if (crc16_mine != header.part12_boot_crc16) { //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); delete [] tmp_data9; delete [] tmp_data7; delete [] data; fclose(fp); return false; } // Copy firmware boot codes to their respective locations src = 0; for(uint32_t i = 0; i < (size9 >> 2); i++) { _MMU_write32(part1ram, T1ReadLong(tmp_data9, src)); src += 4; part1ram += 4; } src = 0; for(uint32_t i = 0; i < (size7 >> 2); i++) { _MMU_write32(part2ram, T1ReadLong(tmp_data7, src)); src += 4; part2ram += 4; } delete [] tmp_data7; delete [] tmp_data9; patched = false; if (data[0x17C] != 0xFF) patched = true; //INFO("Firmware:\n"); //INFO("- path: %s\n", CommonSettings.Firmware); //INFO("- size: %i bytes (%i Mbit)\n", size, size/1024/8); //INFO("- CRC : 0x%04X\n", header.part12_boot_crc16); //INFO("- header: \n"); //INFO(" * size firmware %i\n", ((header.shift_amounts >> 12) & 0xF) * 128 * 1024); //INFO(" * ARM9 boot code address: 0x%08X\n", part1addr); //INFO(" * ARM9 boot code RAM address: 0x%08X\n", ARM9bootAddr); //INFO(" * ARM9 unpacked size: 0x%08X (%i) bytes\n", size9, size9); //INFO(" * ARM9 GUI code address: 0x%08X\n", part3addr); //INFO("\n"); //INFO(" * ARM7 boot code address: 0x%08X\n", part2addr); //INFO(" * ARM7 boot code RAM address: 0x%08X\n", ARM7bootAddr); //INFO(" * ARM7 WiFi code address: 0x%08X\n", part4addr); //INFO(" * ARM7 unpacked size: 0x%08X (%i) bytes\n", size7, size7); //INFO("\n"); //INFO(" * Data/GFX address: 0x%08X\n", part5addr); if (patched) { uint32_t patch_offset = 0x3FC80; if (data[0x17C] > 1) patch_offset = 0x3F680; memcpy(&header, data + patch_offset, sizeof(header)); shift1 = ((header.shift_amounts >> 0) & 0x07); shift2 = ((header.shift_amounts >> 3) & 0x07); shift3 = ((header.shift_amounts >> 6) & 0x07); shift4 = ((header.shift_amounts >> 9) & 0x07); // todo - add support for 512Kb part1addr = (header.part1_rom_boot9_addr << (2 + shift1)); part1ram = (0x02800000 - (header.part1_ram_boot9_addr << (2+shift2))); part2addr = (header.part2_rom_boot7_addr << (2+shift3)); part2ram = (0x03810000 - (header.part2_ram_boot7_addr << (2+shift4))); ARM9bootAddr = part1ram; ARM7bootAddr = part2ram; size9 = decompress(data + part1addr, tmp_data9); if (!tmp_data9) { delete [] data; fclose(fp); return false; } size7 = decompress(data + part2addr, tmp_data7); if (!tmp_data7) { delete [] tmp_data9; delete [] data; fclose(fp); return false; }; // Copy firmware boot codes to their respective locations src = 0; for(uint32_t i = 0; i < (size9 >> 2); i++) { _MMU_write32(part1ram, T1ReadLong(tmp_data9, src)); src += 4; part1ram += 4; } src = 0; for(uint32_t i = 0; i < (size7 >> 2); i++) { _MMU_write32(part2ram, T1ReadLong(tmp_data7, src)); src += 4; part2ram += 4; } delete [] tmp_data7; delete [] tmp_data9; //INFO("\nFlashme:\n"); //INFO("- header: \n"); //INFO(" * ARM9 boot code address: 0x%08X\n", part1addr); //INFO(" * ARM9 boot code RAM address: 0x%08X\n", ARM9bootAddr); //INFO(" * ARM9 unpacked size: 0x%08X (%i) bytes\n", size9, size9); //INFO("\n"); //INFO(" * ARM7 boot code address: 0x%08X\n", part2addr); //INFO(" * ARM7 boot code RAM address: 0x%08X\n", ARM7bootAddr); //INFO(" * ARM7 unpacked size: 0x%08X (%i) bytes\n", size7, size7); } // Generate the path for the external firmware config file. std::string extFilePath = CFIRMWARE::GetExternalFilePath(); strncpy(MMU.fw.userfile, extFilePath.c_str(), MAX_PATH); fclose(fp); fp = fopen(MMU.fw.userfile, "rb"); if (fp) { char buf[0x300]; memset(buf, 0, 0x300); if (fread(buf, 1, 0x100, fp) == 0x100) { printf("- loaded from %s:\n", MMU.fw.userfile); memcpy(&data[0x3FE00], &buf[0], 0x100); memcpy(&data[0x3FF00], &buf[0], 0x100); printf(" * User settings\n"); memset(buf, 0, 0x100); if (fread(buf, 1, 0x1D6, fp) == 0x1D6) { memcpy(&data[0x002A], &buf[0], 0x1D6); printf(" * WiFi settings\n"); memset(buf, 0, 0x1D6); if (fread(buf, 1, 0x300, fp) == 0x300) { memcpy(&data[0x3FA00], &buf[0], 0x300); printf(" * WiFi AP settings\n"); } } } fclose(fp); } printf("\n"); // TODO: add 512Kb support memcpy(&MMU.fw.data[0], data, 256*1024); MMU.fw.fp = NULL; delete [] data; data = NULL; return true; } std::string CFIRMWARE::GetExternalFilePath() { std::string fwPath = CommonSettings.Firmware; std::string fwFileName = Path::GetFileNameFromPathWithoutExt(fwPath); std::string configPath = path.pathToBattery; std::string finalPath = configPath + DIRECTORY_DELIMITER_CHAR + fwFileName + FILE_EXT_DELIMITER_CHAR + FW_CONFIG_FILE_EXT; return finalPath; } //===================================================================================================== static uint32_t calc_CRC16( uint32_t start, const uint8_t *data, int count) { int i,j; uint32_t crc = start & 0xffff; const uint16_t val[8] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; for(i = 0; i < count; i++) { crc = crc ^ data[i]; for(j = 0; j < 8; j++) { int do_bit = 0; if ( crc & 0x1) do_bit = 1; crc = crc >> 1; if ( do_bit) { crc = crc ^ (val[j] << (7-j)); } } } return crc; } int copy_firmware_user_data( uint8_t *dest_buffer, const uint8_t *fw_data) { /* * Determine which of the two user settings in the firmware is the current * and valid one and then copy this into the destination buffer. * * The current setting will have a greater count. * Settings are only valid if its CRC16 is correct. */ int user1_valid = 0; int user2_valid = 0; uint32_t user_settings_offset; uint32_t fw_crc; uint32_t crc; int copy_good = 0; user_settings_offset = fw_data[0x20]; user_settings_offset |= fw_data[0x21] << 8; user_settings_offset <<= 3; if ( user_settings_offset <= 0x3FE00) { int32_t copy_settings_offset = -1; crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset], NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); fw_crc = fw_data[user_settings_offset + 0x72]; fw_crc |= fw_data[user_settings_offset + 0x73] << 8; if ( crc == fw_crc) { user1_valid = 1; } crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100], NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); fw_crc = fw_data[user_settings_offset + 0x100 + 0x72]; fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8; if ( crc == fw_crc) { user2_valid = 1; } if ( user1_valid) { if ( user2_valid) { uint16_t count1, count2; count1 = fw_data[user_settings_offset + 0x70]; count1 |= fw_data[user_settings_offset + 0x71] << 8; count2 = fw_data[user_settings_offset + 0x100 + 0x70]; count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8; if ( count2 > count1) { copy_settings_offset = user_settings_offset + 0x100; } else { copy_settings_offset = user_settings_offset; } } else { copy_settings_offset = user_settings_offset; } } else if ( user2_valid) { /* copy the second user settings */ copy_settings_offset = user_settings_offset + 0x100; } if ( copy_settings_offset > 0) { memcpy( dest_buffer, &fw_data[copy_settings_offset], NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); copy_good = 1; } } return copy_good; } /*static void fill_user_data_area( struct NDS_fw_config_data *user_settings,uint8_t *data, int count) { uint32_t crc; int i; //uint8_t *ts_cal_data_area; memset( data, 0, 0x100); // version data[0x00] = 5; data[0x01] = 0; // colour data[0x02] = user_settings->fav_colour; // birthday month and day data[0x03] = user_settings->birth_month; data[0x04] = user_settings->birth_day; //nickname and length for ( i = 0; i < MAX_FW_NICKNAME_LENGTH; i++) { data[0x06 + (i * 2)] = user_settings->nickname[i] & 0xff; data[0x06 + (i * 2) + 1] = (user_settings->nickname[i] >> 8) & 0xff; } data[0x1a] = user_settings->nickname_len; //Message for ( i = 0; i < MAX_FW_MESSAGE_LENGTH; i++) { data[0x1c + (i * 2)] = user_settings->message[i] & 0xff; data[0x1c + (i * 2) + 1] = (user_settings->message[i] >> 8) & 0xff; } data[0x50] = user_settings->message_len;*/ //touch screen calibration /*ts_cal_data_area = &data[0x58]; for ( i = 0; i < 2; i++) { // ADC x y *ts_cal_data_area++ = user_settings->touch_cal[i].adc_x & 0xff; *ts_cal_data_area++ = (user_settings->touch_cal[i].adc_x >> 8) & 0xff; *ts_cal_data_area++ = user_settings->touch_cal[i].adc_y & 0xff; *ts_cal_data_area++ = (user_settings->touch_cal[i].adc_y >> 8) & 0xff; //screen x y *ts_cal_data_area++ = user_settings->touch_cal[i].screen_x; *ts_cal_data_area++ = user_settings->touch_cal[i].screen_y; }*/ //language and flags /*data[0x64] = user_settings->language; data[0x65] = 0xfc; //update count and crc data[0x70] = count & 0xff; data[0x71] = (count >> 8) & 0xff; crc = calc_CRC16( 0xffff, data, 0x70); data[0x72] = crc & 0xff; data[0x73] = (crc >> 8) & 0xff; memset( &data[0x74], 0xff, 0x100 - 0x74); }*/ // creates an firmware flash image, which contains all needed info to initiate a wifi connection /*int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings) { //Create the firmware header memset(&MMU.fw.data[0], 0, 0x40000); //firmware identifier MMU.fw.data[0x8] = 'M'; MMU.fw.data[0x8 + 1] = 'A'; MMU.fw.data[0x8 + 2] = 'C'; MMU.fw.data[0x8 + 3] = 'P'; // DS type if ( user_settings->ds_type == NDS_FW_DS_TYPE_LITE) MMU.fw.data[0x1d] = 0x20; else MMU.fw.data[0x1d] = 0xff; //User Settings offset 0x3fe00 / 8 MMU.fw.data[0x20] = 0xc0; MMU.fw.data[0x21] = 0x7f; //User settings (at 0x3FE00 and 0x3FF00) fill_user_data_area( user_settings, &MMU.fw.data[ 0x3FE00], 0); fill_user_data_area( user_settings, &MMU.fw.data[ 0x3FF00], 1); // Wifi config length //MMU.fw.data[0x2C] = 0x38; //MMU.fw.data[0x2D] = 0x01; //MMU.fw.data[0x2E] = 0x00; //Wifi version //MMU.fw.data[0x2F] = 0x00; //MAC address //memcpy((MMU.fw.data + 0x36), FW_Mac, sizeof(FW_Mac)); //Enabled channels MMU.fw.data[0x3C] = 0xFE; MMU.fw.data[0x3D] = 0x3F; MMU.fw.data[0x3E] = 0xFF; MMU.fw.data[0x3F] = 0xFF; //RF related MMU.fw.data[0x40] = 0x02; MMU.fw.data[0x41] = 0x18; MMU.fw.data[0x42] = 0x0C; MMU.fw.data[0x43] = 0x01; //Wifi I/O init values //memcpy((MMU.fw.data + 0x44), FW_WIFIInit, sizeof(FW_WIFIInit)); //Wifi BB init values //memcpy((MMU.fw.data + 0x64), FW_BBInit, sizeof(FW_BBInit)); //Wifi RF init values //memcpy((MMU.fw.data + 0xCE), FW_RFInit, sizeof(FW_RFInit)); //Wifi channel-related init values //memcpy((MMU.fw.data + 0xF2), FW_RFChannel, sizeof(FW_RFChannel)); //memcpy((MMU.fw.data + 0x146), FW_BBChannel, sizeof(FW_BBChannel)); memset(&MMU.fw.data[0x154], 0x10, 0xE);*/ //WFC profiles /*memcpy((MMU.fw.data + 0x3FA40), &FW_WFCProfile1, sizeof(FW_WFCProfile)); memcpy((MMU.fw.data + 0x3FB40), &FW_WFCProfile2, sizeof(FW_WFCProfile)); memcpy((MMU.fw.data + 0x3FC40), &FW_WFCProfile3, sizeof(FW_WFCProfile)); (*(uint16_t*)(MMU.fw.data + 0x3FAFE)) = (uint16_t)calc_CRC16(0, (MMU.fw.data + 0x3FA00), 0xFE); (*(uint16_t*)(MMU.fw.data + 0x3FBFE)) = (uint16_t)calc_CRC16(0, (MMU.fw.data + 0x3FB00), 0xFE); (*(uint16_t*)(MMU.fw.data + 0x3FCFE)) = (uint16_t)calc_CRC16(0, (MMU.fw.data + 0x3FC00), 0xFE);*/ /*MMU.fw.data[0x162] = 0x19; memset(&MMU.fw.data[0x163], 0xFF, 0x9D); //Wifi settings CRC16 (*(uint16_t*)(&MMU.fw.data[0x2A])) = calc_CRC16(0, &MMU.fw.data[0x2C], 0x138); if (&CommonSettings.InternalFirmConf != user_settings) memcpy(&CommonSettings.InternalFirmConf, user_settings, sizeof(struct NDS_fw_config_data)); return true ; }*/ void NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config) { const char *default_nickname = "DeSmuME"; const char *default_message = "DeSmuME makes you happy!"; int i; int str_length; memset( fw_config, 0, sizeof( struct NDS_fw_config_data)); fw_config->ds_type = NDS_CONSOLE_TYPE_FAT; fw_config->fav_colour = 7; fw_config->birth_day = 23; fw_config->birth_month = 6; str_length = strlen( default_nickname); for ( i = 0; i < str_length; i++) { fw_config->nickname[i] = default_nickname[i]; } fw_config->nickname_len = str_length; str_length = strlen( default_message); for ( i = 0; i < str_length; i++) { fw_config->message[i] = default_message[i]; } fw_config->message_len = str_length; /* default to English */ fw_config->language = 1; /* default touchscreen calibration */ //fw_config->touch_cal[0].adc_x = 0x200; //fw_config->touch_cal[0].adc_y = 0x200; //fw_config->touch_cal[0].screen_x = 0x20 + 1; // calibration screen coords are 1-based, //fw_config->touch_cal[0].screen_y = 0x20 + 1; // either that or NDS_getADCTouchPosX/Y are wrong. //fw_config->touch_cal[1].adc_x = 0xe00; //fw_config->touch_cal[1].adc_y = 0x800; //fw_config->touch_cal[1].screen_x = 0xe0 + 1; //fw_config->touch_cal[1].screen_y = 0x80 + 1; } /*void NDS_PatchFirmwareMAC() { //memcpy((MMU.fw.data + 0x36), FW_Mac, sizeof(FW_Mac)); //(*(uint16_t*)(MMU.fw.data + 0x2A)) = calc_CRC16(0, (MMU.fw.data + 0x2C), 0x138); }*/