diff --git a/desmume/src/firmware.cpp b/desmume/src/firmware.cpp index f337ed4d8..2d5d4d5f4 100644 --- a/desmume/src/firmware.cpp +++ b/desmume/src/firmware.cpp @@ -246,53 +246,24 @@ u32 CFIRMWARE::_decompress(const u8 *in, u8* &out) //================================================================================ bool CFIRMWARE::load() { - u32 size = 0; - if (!CommonSettings.UseExtFirmware) 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 != NDS_FW_SIZE_V1) && (size != NDS_FW_SIZE_V2) ) - { - fclose(fp); - return false; - } - + size_t fileSize = 0; NDSFirmwareData newFirmwareData; - if (fread(&newFirmwareData._raw[0], 1, 12, fp) == 12) + bool isFirmwareFileRead = NDS_ReadFirmwareDataFromFile(CommonSettings.Firmware, &newFirmwareData, &fileSize, NULL, NULL); + if (!isFirmwareFileRead) { - if ((newFirmwareData.header.identifierValue & 0x00FFFFFF) != 0x0043414D) - { - fclose(fp); - return false; - } - } - else - { - fclose(fp); return false; } - if (fread(&newFirmwareData._raw[12], 1, size - 12, fp) != (size - 12)) - { - fclose(fp); - return false; - } - - fclose(fp); - this->_header = newFirmwareData.header; - if (MMU.fw.size != size) // reallocate - mc_alloc(&MMU.fw, size); + if (MMU.fw.size != fileSize) // reallocate + mc_alloc(&MMU.fw, fileSize); this->_userDataAddr = LE_TO_LOCAL_16(newFirmwareData.header.userSettingsOffset) * 8; @@ -304,7 +275,7 @@ bool CFIRMWARE::load() newFirmwareData.header.key.unused = 0xFFFF; } - memcpy(&MMU.fw.data, &newFirmwareData, size); + memcpy(&MMU.fw.data, &newFirmwareData, fileSize); // Generate the path for the external firmware config file. std::string extFilePath = CFIRMWARE::GetExternalFilePath(); @@ -367,13 +338,13 @@ bool CFIRMWARE::unpack() u32 arm7Size = 0; arm9Size = this->_decrypt((u8 *)&workingFirmwareData + part1addr, tmp_data9); - if (!tmp_data9) + if (tmp_data9 == NULL) { return false; } arm7Size = this->_decrypt((u8 *)&workingFirmwareData + part2addr, tmp_data7); - if (!tmp_data7) + if (tmp_data7 == NULL) { delete [] tmp_data9; return false; @@ -403,10 +374,14 @@ bool CFIRMWARE::unpack() _MMU_write32(part2ram, T1ReadLong(tmp_data7, src)); src += 4; part2ram += 4; } + delete [] tmp_data7; + tmp_data7 = NULL; + delete [] tmp_data9; - - bool isPatched = (workingFirmwareData._raw[0x17C] != 0xFF); + tmp_data9 = NULL; + + const bool isPatched = (workingFirmwareData._raw[0x17C] != 0xFF); INFO("Firmware:\n"); INFO("- path: %s\n", CommonSettings.Firmware); @@ -449,13 +424,13 @@ bool CFIRMWARE::unpack() ARM7bootAddr = part2ram; arm9Size = this->_decompress(&workingFirmwareData._raw[part1addr], tmp_data9); - if (!tmp_data9) + if (tmp_data9 == NULL) { return false; } arm7Size = this->_decompress(&workingFirmwareData._raw[part2addr], tmp_data7); - if (!tmp_data7) + if (tmp_data7 == NULL) { delete [] tmp_data9; return false; @@ -1050,6 +1025,120 @@ void NDS_OverrideFirmwareMAC(const u8 inMAC[6]) fw.wifiInfo.crc16 = calc_CRC16(0, &fw.wifiInfo.length, fw.wifiInfo.length); } +bool NDS_ReadFirmwareDataFromFile(const char *fileName, NDSFirmwareData *outFirmwareData, size_t *outFileSize, int *outConsoleType, u8 *outMACAddr) +{ + bool result = false; + + if (fileName == NULL) + { + return result; + } + + // Open the file. + FILE *fp = fopen(fileName, "rb"); + if (fp == NULL) + { + return result; + } + + // Do some basic validation of the firmware file. + fseek(fp, 0, SEEK_END); + const size_t fileSize = ftell(fp); + if (outFileSize != NULL) + { + *outFileSize = fileSize; + } + + if ( (fileSize != NDS_FW_SIZE_V1) && (fileSize != NDS_FW_SIZE_V2) ) + { + fclose(fp); + return result; + } + + size_t readBytes = 0; + u32 identifierValue = 0; + + fseek(fp, offsetof(FWHeader, identifierValue), SEEK_SET); + readBytes = fread(&identifierValue, 1, sizeof(u32), fp); + + if ( (readBytes != sizeof(u32)) || ((identifierValue & 0x00FFFFFF) != 0x0043414D) ) + { + fclose(fp); + return result; + } + + // Now that the firmware file has been validated, let's start reading the individual + // pieces of data that the caller has requested. + result = true; + + if (outFirmwareData != NULL) + { + fseek(fp, 0, SEEK_SET); + readBytes = fread(outFirmwareData, 1, sizeof(NDSFirmwareData), fp); + + if ( readBytes == sizeof(NDSFirmwareData) ) + { + if (outConsoleType != NULL) + { + *outConsoleType = (int)outFirmwareData->header.key.consoleType; + } + + if (outMACAddr != NULL) + { + outMACAddr[0] = outFirmwareData->wifiInfo.MACAddr[0]; + outMACAddr[1] = outFirmwareData->wifiInfo.MACAddr[1]; + outMACAddr[2] = outFirmwareData->wifiInfo.MACAddr[2]; + outMACAddr[3] = outFirmwareData->wifiInfo.MACAddr[3]; + outMACAddr[4] = outFirmwareData->wifiInfo.MACAddr[4]; + outMACAddr[5] = outFirmwareData->wifiInfo.MACAddr[5]; + } + } + else + { + printf("Ext. Firmware: Failed to read the firmware data. (%lu out of %lu bytes read.)\n", (unsigned long)readBytes, sizeof(NDSFirmwareData)); + result = false; + } + } + else + { + if (outConsoleType != NULL) + { + FW_HEADER_KEY fpKey; + fpKey.consoleType = NDS_CONSOLE_TYPE_FAT; + + fseek(fp, offsetof(FWHeader, key), SEEK_SET); + readBytes = fread(&fpKey, 1, sizeof(FW_HEADER_KEY), fp); + + if (readBytes == sizeof(FW_HEADER_KEY)) + { + *outConsoleType = (int)fpKey.consoleType; + } + else + { + printf("Ext. Firmware: Failed to read the console type. (%lu out of %lu bytes read.)\n", (unsigned long)readBytes, sizeof(FW_HEADER_KEY)); + result = false; + } + } + + if (outMACAddr != NULL) + { + fseek(fp, sizeof(FWHeader) + offsetof(FWWifiInfo, MACAddr), SEEK_SET); + readBytes = fread(outMACAddr, 1, 6, fp); + + if (readBytes != 6) + { + printf("Ext. Firmware: Failed to read the MAC address. (%lu out of %lu bytes read.)\n", (unsigned long)readBytes, sizeof(u8) * 6); + result = false; + } + } + } + + // Close the file. + fclose(fp); + + return result; +} + //========================= //- firmware SPI chip interface - //the original intention was for this code to have similarity to the AUXSPI backup memory devices. diff --git a/desmume/src/firmware.h b/desmume/src/firmware.h index f161e0595..110b85b1b 100644 --- a/desmume/src/firmware.h +++ b/desmume/src/firmware.h @@ -428,6 +428,7 @@ int copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data); void NDS_GetDefaultFirmwareConfig(FirmwareConfig &outConfig); void NDS_InitFirmwareWithConfig(const FirmwareConfig &inConfig); void NDS_OverrideFirmwareMAC(const u8 inMAC[6]); +bool NDS_ReadFirmwareDataFromFile(const char *fileName, NDSFirmwareData *outFirmwareData, size_t *outFileSize, int *outConsoleType, u8 *outMACAddr); struct fw_memory_chip { diff --git a/desmume/src/frontend/cocoa/cocoa_core.h b/desmume/src/frontend/cocoa/cocoa_core.h index 1351d9bf3..2af1e615f 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.h +++ b/desmume/src/frontend/cocoa/cocoa_core.h @@ -61,6 +61,7 @@ typedef struct NSString *frameStatus; NSString *executionSpeedStatus; NSString *errorStatus; + NSString *extFirmwareMACAddressString; NSString *firmwareMACAddressSelectionString; NSString *currentSessionMACAddressString; @@ -117,6 +118,7 @@ typedef struct @property (copy) NSURL *firmwareImageURL; @property (copy) NSURL *slot1R4URL; +@property (retain) NSString *extFirmwareMACAddressString; @property (retain) NSString *firmwareMACAddressSelectionString; @property (retain) NSString *currentSessionMACAddressString; diff --git a/desmume/src/frontend/cocoa/cocoa_core.mm b/desmume/src/frontend/cocoa/cocoa_core.mm index 2c8cd271c..a71b37b4c 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.mm +++ b/desmume/src/frontend/cocoa/cocoa_core.mm @@ -84,6 +84,7 @@ volatile bool execute = true; @synthesize frameStatus; @synthesize executionSpeedStatus; @synthesize errorStatus; +@synthesize extFirmwareMACAddressString; @synthesize firmwareMACAddressSelectionString; @synthesize currentSessionMACAddressString; @@ -172,6 +173,7 @@ volatile bool execute = true; executionSpeedStatus = @"1.00x"; errorStatus = @""; slot1StatusText = NSSTRING_STATUS_EMULATION_NOT_RUNNING; + extFirmwareMACAddressString = @"Invalid MAC!"; firmwareMACAddressSelectionString = @"Firmware 00:09:BF:FF:FF:FF"; currentSessionMACAddressString = NSSTRING_STATUS_NO_ROM_LOADED; @@ -191,6 +193,7 @@ volatile bool execute = true; [self setCdsGPU:nil]; [self setCdsOutputList:nil]; [self setErrorStatus:nil]; + [self setExtFirmwareMACAddressString:nil]; [self setFirmwareMACAddressSelectionString:nil]; [self setCurrentSessionMACAddressString:nil]; @@ -478,6 +481,25 @@ volatile bool execute = true; - (void) setEmuFlagUseExternalFirmware:(BOOL)enable { execControl->SetEnableExternalFirmware((enable) ? true : false); + + if (enable) + { + uint8_t MACAddr[6] = {0x00, 0x09, 0xBF, 0xFF, 0xFF, 0xFF}; + const char *extFirmwareFileName = execControl->GetFirmwareImagePath(); + bool isFirmwareFileRead = NDS_ReadFirmwareDataFromFile(extFirmwareFileName, NULL, NULL, NULL, MACAddr); + + if (isFirmwareFileRead) + { + NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[5]]; + [self setExtFirmwareMACAddressString:macAddressString]; + } + else + { + [self setExtFirmwareMACAddressString:@"Invalid MAC!"]; + } + } + + [self updateFirmwareMACAddressString]; } - (BOOL) emuFlagUseExternalFirmware @@ -721,7 +743,14 @@ volatile bool execute = true; - (void) updateFirmwareMACAddressString { - [self setFirmwareMACAddressSelectionString:[NSString stringWithFormat:@"Firmware %@", [[self cdsFirmware] MACAddressString]]]; + if ([self emuFlagUseExternalFirmware]) + { + [self setFirmwareMACAddressSelectionString:[NSString stringWithFormat:@"Ext. Firmware %@", [self extFirmwareMACAddressString]]]; + } + else + { + [self setFirmwareMACAddressSelectionString:[NSString stringWithFormat:@"Firmware %@", [[self cdsFirmware] MACAddressString]]]; + } } - (void) updateCurrentSessionMACAddressString:(BOOL)isRomLoaded