How Microsoft attempted to make the Xbox 360 dashboard load faster

Eaton •

Discussion links: Hacker News

Since 2005, the Xbox 360 dashboard has resided on the flash chip soldered onto the motherboard. In most consoles it is a 16 MB flash chip (Hynix HY27US08281A). Some consoles have a larger flash of 256 MB or 512 MB gamers can use as extra storage space. All of the essential system files are on the nand file system, meaning the console can boot to dash successfully without a hard-drive. The Xbox 360 hard-drive has always been an optional accessory, but as the console generation progressed, having a hard-drive became increasingly necessary as the number of games and downloadable content increased.

On November 19, 2008, Microsoft released the NXE (New Xbox Experience) update (v7357). It was a huge update that brought avatars, a redesigned dash UI, and much more. In particular, it brought support for 2 new partitions on the hard-drive. They are called the System Auxiliary and System Extended partitions. The NXE update brought so many features that they could not all fit on the 16 MB nand file system. The 2 new partitions gave Microsoft 350 MB more space to play with – more than enough for the initial NXE update, and future expansion. This has a caveat where the hard-drive is needed to get the full experience. For example, if the hard-drive is not connected, the console will still function since all the essential system files are still on the nand, but all the extra goodies, such as avatars, will not work, since those files are on the hard-drive.

October 2012 Update

4 years later, someone at Microsoft realized they may be able to speed up the dash by moving it to one of the new hard-drive partitions. The v16197 update brought a lot of features, but one small feature no noticed was how the dash executable was moved to the hard-drive’s System Extended partition. A new function was added to the Xbox Application Manager (xam) named CXamTitleLoader::GetFastestDashLoadPath. Here’s what it looks like in IDA:

The decompiled version:

What it does is check if “fast extended storage” is connected (this means a hard-drive is connected with a valid System Extended partition), and will override the dash load path, which by default is the dash that is on the nand. The dash is still on the nand as a fallback in case a hard-drive is not connected.

Another change was made to the dash executable itself: it is now uncompressed. Xbox 360 executables can be LZX-compressed and/or AES-encrypted. The dash being uncompressed means the system won’t have as much to do when the data is loaded into memory from disk. This will make the dash load faster, as long as the disk read completes in the same time (or less) as the nand flash read.

Performance Testing

The hard-drive installed in my console is a WD Black 2.5″ 7200rpm HDD, Model WD5000LPLX (500 GB).

Based on the function name “GetFastestDashLoadPath” and what it does, it is clear that Microsoft developers believe the hard-drive is faster than the nand flash. Are they right? To get a general idea, I used the stopwatch app on my phone to test loading the latest dash (v17559) on the nand vs hard-drive. I could not find any noticeable difference. Both load in about 2.3 seconds. Time was measured from the instant the dash started being loaded (black screen) to when the black screen started to fade. This test shows the performance benefits aren’t as noticeable as expected, but that doesn’t mean they are nonexistent.

For the second test, I wrote a rudimentary benchmark in C++ to run on the console itself:

//https://eaton-works.com/2023/01/09/how-microsoft-attempted-to-make-the-xbox-360-dashboard-load-faster/
DbgPrint("[Benchmark] Benchmark begin.\n");
//Use a 1 MB buffer. This results in the best performance for both devices.
DWORD readBufferSize = 1048576;
//FLASH symbolically linked to: \\Device\\Flash
HANDLE hFlash = CreateFile("FLASH:\\dash.xex", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//HDDSYSEXT symbolically linked to: \\Device\\Harddisk0\\SystemExtPartition
HANDLE hExt = CreateFile("HDDSYSEXT:\\20449700\\dash.xex", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFlash == INVALID_HANDLE_VALUE || hExt == INVALID_HANDLE_VALUE)
{
DbgPrint("[Benchmark] A CreateFile failed with error %d.\n", GetLastError());
return;
}
LARGE_INTEGER flashDashSize;
LARGE_INTEGER extDashSize;
if (!GetFileSizeEx(hFlash, &flashDashSize) || !GetFileSizeEx(hExt, &extDashSize))
{
DbgPrint("[Benchmark] A GetFileSizeEx failed with error %d.\n", GetLastError());
return;
}
PVOID readBuffer = malloc(readBufferSize);
if (readBuffer == NULL)
{
DbgPrint("[Benchmark] No memory available for read buffer.\n");
return;
}
LARGE_INTEGER counterFreq;
LARGE_INTEGER counterStart;
LARGE_INTEGER counterEnd;
//Let's be fancy and use these APIs. Note that using GetTickCount also produces the same end results.
QueryPerformanceFrequency(&counterFreq);
QueryPerformanceCounter(&counterStart);
DWORD numRead;
while (flashDashSize.QuadPart > 0)
{
if (!ReadFile(hFlash, readBuffer, readBufferSize, &numRead, NULL))
{
DbgPrint("[Benchmark] ReadFile (flash) failed with error %d.\n", GetLastError());
return;
}
flashDashSize.QuadPart -= numRead;
}
QueryPerformanceCounter(&counterEnd);
DWORD flashTimeMs = ((counterEnd.QuadPart – counterStart.QuadPart) * 1000) / counterFreq.QuadPart;
QueryPerformanceCounter(&counterStart);
while (extDashSize.QuadPart > 0)
{
if (!ReadFile(hExt, readBuffer, readBufferSize, &numRead, NULL))
{
DbgPrint("[Benchmark] ReadFile (ext) failed with error %d.\n", GetLastError());
return;
}
extDashSize.QuadPart -= numRead;
}
QueryPerformanceCounter(&counterEnd);
DWORD extTimeMs = ((counterEnd.QuadPart – counterStart.QuadPart) * 1000) / counterFreq.QuadPart;
DbgPrint("[Benchmark] Benchmark concluded. Results with buffer size of %d: Nand=%dms, HDD=%dms\n", readBufferSize, flashTimeMs, extTimeMs);
return;

Here are the results:

There is indeed a performance benefit to loading the dash from the hard-drive, but it’s measured in milliseconds. That is better than nothing, and concludes that moving the dash to the hard-drive is (slightly) beneficial to the user experience. Given how important and widely used the dash is, any speed boost is appreciated by gamers.

August 2013 Update

On August 26, 2013, Microsoft released the v16537 update. CXamTitleLoader::GetFastestDashLoadPath was renamed to CXamTitleLoader::GetDefaultTitleImage. The function works the same, but has new “data center” functionality. When the console is in data center mode, it’ll download a “data center dashboard” from Xbox Live to use instead. Data center mode is a mystery and is presumably an internal service, perhaps related to an early experiment with cloud gaming.

Subscribe to new posts

Get an email notification every time something new is published.
📧