https://www.3dbrew.org/w/api.php?action=feedcontributions&user=Subv&feedformat=atom3dbrew - User contributions [en]2024-03-29T11:44:36ZUser contributionsMediaWiki 1.35.8https://www.3dbrew.org/w/index.php?title=NIM_Services&diff=20489NIM Services2017-12-10T15:04:47Z<p>Subv: /* NIM user service "nim:u" */</p>
<hr />
<div>[[Category:Services]]<br />
= NIM user service "nim:u" =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| Related to starting a sysupdate?<br />
|-<br />
| 0x00020000<br />
| [[NIMU:GetUpdateDownloadProgress|GetUpdateDownloadProgress]]<br />
|-<br />
| 0x0003....<br />
| ?<br />
|-<br />
| 0x00040000<br />
| [[NIMU:FinishTitlesInstall|FinishTitlesInstall]]<br />
|-<br />
| 0x00050000<br />
| This obtains an event handle. Home Menu will check whether a system update is available when this event is triggered.<br />
|-<br />
| 0x0006....<br />
| ?<br />
|-<br />
| 0x0007....<br />
| This deletes and recreates the system save data 0x0001002C (NIM System SaveData)<br />
|-<br />
| 0x0008....<br />
| ?<br />
|-<br />
| 0x00090000<br />
| [[NIMU:CheckSysupdateAvailable|CheckSysupdateAvailable]]<br />
|-<br />
| 0x000A0000<br />
| GetState<br />
|-<br />
| 0x000B0000<br />
| [[NIMU:GetSystemTitleHash|GetSystemTitleHash]]<br />
|-<br />
| 0x000C0082<br />
| ?<br />
|-<br />
| 0x000E0080<br />
| ?<br />
|-<br />
| 0x000F0042<br />
| ?<br />
|-<br />
| 0x00110000<br />
| ?<br />
|-<br />
| 0x00130000<br />
| ?<br />
|-<br />
| 0x00140000<br />
| ?<br />
|-<br />
| 0x00150000<br />
| ?<br />
|-<br />
| 0x00170042<br />
| ?<br />
|-<br />
| 0x00180080<br />
| ?<br />
|-<br />
| 0x00250000<br />
| ?<br />
|-<br />
| 0x00260200<br />
| ?<br />
|-<br />
| 0x00270000<br />
| ?<br />
|-<br />
| 0x00280000<br />
| ?<br />
|-<br />
| 0x00290246<br />
| ?<br />
|-<br />
| 0x002A0000<br />
| ?<br />
|-<br />
| 0x002B0000<br />
| ?<br />
|-<br />
| 0x002C0000<br />
| ?<br />
|-<br />
| 0x002D00C0<br />
| ?<br />
|-<br />
| 0x00480002<br />
| ?<br />
|}<br />
<br />
= NIM server service "nim:s" =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010200<br />
| [[NIMS:StartDownloadSimple|StartDownloadSimple]]<br />
|-<br />
| 0x00020000<br />
| [[NIMS:CancelDownload|CancelDownload]]<br />
|-<br />
| 0x00030000<br />
| [[NIMS:GetProgress|GetProgress]]<br />
|-<br />
| 0x00050082<br />
| [[NIMS:UnregisterTask|UnregisterTask]]<br />
|-<br />
| 0x00060080<br />
| [[NIMS:IsTaskRegistered|IsTaskRegistered]]<br />
|-<br />
| 0x000A0000<br />
| [[NIMS:CheckSysupdateAvailableSOAP|CheckSysupdateAvailableSOAP]]<br />
|-<br />
| 0x000B0084<br />
| [[NIMS:SetAttribute|SetAttribute]]<br />
|-<br />
| 0x0016020A<br />
| [[NIMS:ListTitles|ListTitles]]<br />
|-<br />
| 0x00220080<br />
| AccountDeleteTitleETicketsSOAP. The SOAP request is sent only after the ticket for the specified titleID has been successfully deleted.<br />
|-<br />
| 0x00290000<br />
| [[NIMS:AccountCheckBalanceSOAP|AccountCheckBalanceSOAP]]<br />
|-<br />
| 0x002D0042<br />
| [[NIMS:DownloadTickets|DownloadTickets]]<br />
|-<br />
| 0x003C0002<br />
| [[NIMS:RegisterSelf|RegisterSelf]]<br />
|-<br />
| 0x003F0000<br />
| GetInitializeResult. Checks whether nim is properly initialized or not. If it is not, the result code returned is non-zero.<br />
|-<br />
| 0x00420240<br />
| [[NIMS:StartDownload|StartDownload]]<br />
|-<br />
| 0x00550246<br />
| [[NIMS:RegisterTask|RegisterTask]]<br />
|-<br />
| 0x00570082<br />
| [[NIMS:ConnectNoTicketDownload|ConnectNoTicketDownload]]<br />
|}<br />
<br />
= NIM server service "nim:aoc" =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00030042<br />
| SetApplicationId<br />
|-<br />
| 0x00040042<br />
| SetTin<br />
|-<br />
| 0x000902D0<br />
| ListContentSetsEx<br />
|-<br />
| 0x00180000<br />
| GetBalance<br />
|-<br />
| 0x001D0000<br />
| GetCustomerSupportCode<br />
|-<br />
| 0x00210000<br />
| Initialize<br />
|-<br />
| 0x00240282<br />
| CalculateContentsRequiredSize<br />
|-<br />
| 0x00250000<br />
| RefreshServerTime<br />
|}<br />
<br />
= NIM service "nim:ndm" =<br />
<br />
= kagiya server =<br />
The nim system module communicates with a server called kagiya (kagiya-ctr.cdn.nintendo.net or kagiya-dev-ctr.cdn.nintendo.net for development units). It provides the 9.6 crypto seed in binary form for any given title ID under (HTTPS) kagiya-ctr.cdn.nintendo.net/title/0x%16llx/ext_key?country=%s, where %16llx is the title ID and %s is a country code as used in the [[EShop|eShop]].<br />
<br />
=New3DS=<br />
NIM module only uses [[PTMSYSM:CheckNew3DS|CheckNew3DS]] for determining what heap sizes to use, in two functions. One is for the size of the 0x08000000 vmem heap, the other is probably for some buffer allocated on that heap. The New3DS version of these sizes are 0x1C000-bytes larger than the Old3DS sizes here.<br />
<br />
=HTTPS requests=<br />
<br />
==Trusted RootCAs==<br />
During startup NIM-module creates two RootCertChains with [[HTTP_Services|HTTPC]]. Both of these only contain the same [[HTTPC:RootCertChainAddDefaultCert|default]] cert with ID 0x3. The first RootCertChain is used with NetUpdateSOAP. Requests such as the "notifications.json" page don't use these RootCertChains(in this case just [[HTTPC:AddDefaultCert|default]] certID 0xB is used).<br />
<br />
==SOAP==<br />
<br />
===NetUpdateSOAP===<br />
There are exactly 3 types of network SOAP requests used with [https://nus.c.shop.nintendowifi.net/nus/services/NetUpdateSOAP NetUpdateSOAP] by NIM module, described below. This URL contained in NIM module itself is only used with GetSystemTitleHash. The other requests use an identical URL loaded from an ECommerceSOAP response instead.<br />
<br />
See also [https://github.com/yellows8/ninupdates here].<br />
<br />
====GetSystemUpdate====<br />
Returns the current sysupdate title-listing. This also contains the SystemTitleHash returned by GetSystemTitleHash.<br />
<br />
====GetSystemTitleHash====<br />
Returns the current SystemTitleHash for the current sysupdate title-listing.<br />
<br />
====GetSystemCommonETicket====<br />
Returns the Base64-encoded cetk for each specified TitleId entry.<br />
<br />
This is only used when installing new titles. This means with CDN system-updates, tickets are never installed except when a title is being installed for the first time. For example, a system on the latest system-version that was only ever updated via CDN has the same NATIVE_FIRM ticket installed from the factory.<br />
<br />
=Sysupdate checking process=<br />
This section describes the process used when checking whether a sysupdate is required.<br />
<br />
First the GetSystemTitleHash SOAP request is done. Then the SystemTitleHash in savedata hash.dat is compared with the received one. If they match and the SystemTitleHash flag is set to value 0x03, it will immediately return that no sysupdate is required. Otherwise it will start the GetSystemUpdate SOAP request handling.<br />
<br />
The GetSystemUpdate SOAP request contains a titlelist of all NAND system-titles. For GetSystemUpdate response parsing, it compares each SOAP title_entry with the NAND system titlelist. If a SOAP titleID isn't found in the NAND titlelist, this means NAND is missing a new title and hence a sysupdate is required for installing that title. If a NAND title_entry-version is less than the SOAP title_entry-version, this means the title needs updated and hence a sysupdate is required.<br />
<br />
At least one <TitleVersion> entry with valid data in the GetSystemUpdate response is required.<br />
<br />
The titleIDs sent in the GetSystemUpdate SOAP request are decimal, while the titleIDs in the response are hex.<br />
<br />
=NIM [[System_SaveData]]=<br />
==hash.dat==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x60<br />
| 0x1<br />
| u8 flag used with the SystemTitleHash. 0x01 = latest sysupdate isn't installed as of last SOAP requests, 0x03 = latest sysupdate is installed as of last SOAP requests.<br />
|-<br />
| 0x61<br />
| 0x21<br />
| ASCII hex SystemTitleHash, including NUL-terminator. This is the latest SystemTitleHash which NIM module received from SOAP.<br />
|}<br />
<br />
=Types=<br />
==InstallationMode==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| Initial installation<br />
|-<br />
| 1<br />
| Unknown<br />
|-<br />
| 2<br />
| Unknown<br />
|-<br />
| 3<br />
| Reinstallation<br />
|}<br />
==DownloadState==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| Not initialized<br />
|-<br />
| 1<br />
| Download initialized<br />
|-<br />
| 2<br />
| Downloading, verifying and installing TMD<br />
|-<br />
| 3<br />
| Initializing save data<br />
|-<br />
| 4<br />
| Downloading and installing contents<br />
|-<br />
| 5<br />
| Waiting before calling [[AM:CommitImportPrograms]]<br />
|-<br />
| 6<br />
| Running [[AM:CommitImportPrograms]]<br />
|-<br />
| 7<br />
| Title installation finished<br />
|-<br />
| 8<br />
| Unknown error regarding title version<br />
|-<br />
| 9<br />
| Creating the .ctx file (or error doing so)?<br />
|-<br />
| 10<br />
| Irrecoverable error encountered<br />
|}<br />
==TitleConfig==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Length<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| Title ID<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Title version<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown (always 0)<br />
|-<br />
| 0x10<br />
| 0x1<br />
| Age rating for the HOME Menu parental controls<br />
|-<br />
| 0x11<br />
| 0x1<br />
| [[Filesystem_services#MediaType|Media Type]]<br />
|-<br />
| 0x12<br />
| 0x2<br />
| Padding<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Unknown (always 0?)<br />
|}<br />
==TitleProgress==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Length<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| [[#DownloadState|Download State]]<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Last result code in NIM related to the installation<br />
|-<br />
| 0x8<br />
| 0x8<br />
| Amount of bytes that have been downloaded<br />
|-<br />
| 0x10<br />
| 0x8<br />
| Total bytes that need to be downloaded<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=Filesystem_services&diff=20487Filesystem services2017-12-09T17:01:20Z<p>Subv: /* Filesystem service "fs:USER" */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
= Services =<br />
== Filesystem service "fs:USER" ==<br />
You can at most have 32 FS archive handles.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version <br />
! Description<br />
! scope="col" width="400" | Required [[NCCH/Extended_Header|exheader]] access info bitmask<br />
|-<br />
| 0x000100C6<br />
|?<br />
| [[FS:Dummy1|Dummy1]]<br />
| None<br />
|-<br />
| 0x040100C4<br />
|?<br />
| [[FS:Control|Control]]<br />
| None<br />
|-<br />
| 0x08010002<br />
|?<br />
| [[FS:Initialize|Initialize]]<br />
| None<br />
|-<br />
| 0x080201C2<br />
|?<br />
| [[FS:OpenFile|OpenFile]]<br />
| None<br />
|-<br />
| 0x08030204<br />
|?<br />
| [[FS:OpenFileDirectly|OpenFileDirectly]]<br />
| None<br />
|-<br />
| 0x08040142<br />
|?<br />
| [[FS:DeleteFile|DeleteFile]]<br />
| None<br />
|-<br />
| 0x08050244<br />
|?<br />
| [[FS:RenameFile|RenameFile]]<br />
| None<br />
|-<br />
| 0x08060142<br />
|?<br />
| [[FS:DeleteDirectory|DeleteDirectory]]<br />
| None<br />
|-<br />
| 0x08070142<br />
|?<br />
| [[FS:DeleteDirectoryRecursively|DeleteDirectoryRecursively]]<br />
| None<br />
|-<br />
| 0x08080202<br />
|?<br />
| [[FS:CreateFile|CreateFile]]<br />
| None<br />
|-<br />
| 0x08090182<br />
|?<br />
| [[FS:CreateDirectory|CreateDirectory]]<br />
| None<br />
|-<br />
| 0x080A0244<br />
|?<br />
| [[FS:RenameDirectory|RenameDirectory]]<br />
| None<br />
|-<br />
| 0x080B0102<br />
|?<br />
| [[FS:OpenDirectory|OpenDirectory]]<br />
| None<br />
|-<br />
| 0x080C00C2<br />
|?<br />
| [[FS:OpenArchive|OpenArchive]]<br />
| Each archive ID code has separate access info bitmasks, if it has any<br />
|-<br />
| 0x080D0144<br />
|?<br />
| [[FS:ControlArchive|ControlArchive]]<br />
| None<br />
|-<br />
| 0x080E0080<br />
|?<br />
| [[FS:CloseArchive|CloseArchive]]<br />
| None<br />
|-<br />
| 0x080F0180<br />
|?<br />
| [[FS:Obsoleted_2_0_FormatThisUserSaveData|Obsoleted_2_0_FormatThisUserSaveData]]<br />
| None<br />
|-<br />
| 0x08100200<br />
|?<br />
| [[FS:Obsoleted_3_0_CreateSystemSaveData|Obsoleted_3_0_CreateSystemSaveData]]<br />
| 0x4, for when the input saveID doesn't match the exheader saveID<br />
|-<br />
| 0x08110040<br />
|?<br />
| [[FS:Obsoleted_3_0_DeleteSystemSaveData|Obsoleted_3_0_DeleteSystemSaveData]]<br />
| 0x1004, for when the input saveID doesn't match the exheader saveID<br />
|-<br />
| 0x08120080<br />
|?<br />
| [[FS:GetFreeBytes|GetFreeBytes]]<br />
| None<br />
|-<br />
| 0x08130000<br />
|?<br />
| [[FS:GetCardType|GetCardType]]<br />
| 0x1017<br />
|-<br />
| 0x08140000<br />
|?<br />
| [[FS:GetSdmcArchiveResource|GetSdmcArchiveResource]]<br />
| None<br />
|-<br />
| 0x08150000<br />
|?<br />
| [[FS:GetNandArchiveResource|GetNandArchiveResource]]<br />
| 0x1007<br />
|-<br />
| 0x08160000<br />
|?<br />
| [[FS:GetSdmcFatfsError|GetSdmcFatfsError]]<br />
| 0x2<br />
|-<br />
| 0x08170000<br />
|?<br />
| [[FS:IsSdmcDetected|IsSdmcDetected]]<br />
| None<br />
|-<br />
| 0x08180000<br />
|?<br />
| [[FS:IsSdmcWritable|IsSdmcWritable]]<br />
| None<br />
|-<br />
| 0x08190042<br />
|?<br />
| [[FS:GetSdmcCid|GetSdmcCid]]<br />
| 0x2<br />
|-<br />
| 0x081A0042<br />
|?<br />
| [[FS:GetNandCid|GetNandCid]]<br />
| 0x2<br />
|-<br />
| 0x081B0000<br />
|?<br />
| [[FS:GetSdmcSpeedInfo|GetSdmcSpeedInfo]]<br />
| 0x2<br />
|-<br />
| 0x081C0000<br />
|?<br />
| [[FS:GetNandSpeedInfo|GetNandSpeedInfo]]<br />
| 0x2<br />
|-<br />
| 0x081D0042<br />
|?<br />
| [[FS:GetSdmcLog|GetSdmcLog]]<br />
| 0x2<br />
|-<br />
| 0x081E0042<br />
|?<br />
| [[FS:GetNandLog|GetNandLog]]<br />
| 0x2<br />
|-<br />
| 0x081F0000<br />
|?<br />
| [[FS:ClearSdmcLog|ClearSdmcLog]]<br />
| 0x2<br />
|-<br />
| 0x08200000<br />
|?<br />
| [[FS:ClearNandLog|ClearNandLog]]<br />
| 0x2<br />
|-<br />
| 0x08210000<br />
|?<br />
| [[FS:CardSlotIsInserted|CardSlotIsInserted]]<br />
| 0x1017<br />
|-<br />
| 0x08220000<br />
|?<br />
| [[FS:CardSlotPowerOn|CardSlotPowerOn]]<br />
| 0x2<br />
|-<br />
| 0x08230000<br />
|?<br />
| [[FS:CardSlotPowerOff|CardSlotPowerOff]]<br />
| 0x2<br />
|-<br />
| 0x08240000<br />
|?<br />
| [[FS:CardSlotGetCardIFPowerStatus|CardSlotGetCardIFPowerStatus]]<br />
| 0x2<br />
|-<br />
| 0x08250040<br />
|?<br />
| [[FS:CardNorDirectCommand|CardNorDirectCommand]]<br />
| 0x2<br />
|-<br />
| 0x08260080<br />
|?<br />
| [[FS:CardNorDirectCommandWithAddress|CardNorDirectCommandWithAddress]]<br />
| 0x2<br />
|-<br />
| 0x08270082<br />
|?<br />
| [[FS:CardNorDirectRead|CardNorDirectRead]]<br />
| 0x2<br />
|-<br />
| 0x082800C2<br />
|?<br />
| [[FS:CardNorDirectReadWithAddress|CardNorDirectReadWithAddress]]<br />
| 0x2<br />
|-<br />
| 0x08290082<br />
|?<br />
| [[FS:CardNorDirectWrite|CardNorDirectWrite]]<br />
| 0x2<br />
|-<br />
| 0x082A00C2<br />
|?<br />
| [[FS:CardNorDirectWriteWithAddress|CardNorDirectWriteWithAddress]]<br />
| 0x2<br />
|-<br />
| 0x082B00C2<br />
|?<br />
| [[FS:CardNorDirectRead_4xIO|CardNorDirectRead_4xIO]]<br />
| 0x2<br />
|-<br />
| 0x082C0082<br />
|?<br />
| [[FS:CardNorDirectCpuWriteWithoutVerify|CardNorDirectCpuWriteWithoutVerify]]<br />
| 0x2<br />
|-<br />
| 0x082D0040<br />
|?<br />
| [[FS:CardNorDirectSectorEraseWithoutVerify|CardNorDirectSectorEraseWithoutVerify]]<br />
| 0x2<br />
|-<br />
| 0x082E0040<br />
|?<br />
| [[FS:GetProductInfo|GetProductInfo]]<br />
| 0x1005<br />
|-<br />
| 0x082F0040<br />
|?<br />
| [[FS:GetProgramLaunchInfo|GetProgramLaunchInfo]]<br />
| 0x1005<br />
|-<br />
| 0x08300182<br />
|?<br />
| [[FS:Obsoleted_3_0_CreateExtSaveData|Obsoleted_3_0_CreateExtSaveData]]<br />
| 0xC, for when the input extdataID doesn't match the exheader extdataID<br />
|-<br />
| 0x08310180<br />
|?<br />
| [[FS:Obsoleted_3_0_CreateSharedExtSaveData|Obsoleted_3_0_CreateSharedExtSaveData]]<br />
| 0x1005<br />
|-<br />
| 0x08320102<br />
|?<br />
| [[FS:Obsoleted_3_0_ReadExtSaveDataIcon|Obsoleted_3_0_ReadExtSaveDataIcon]]<br />
| 0x100D, for when the input extdataID doesn't match the exheader extdataID<br />
|-<br />
| 0x08330082<br />
|?<br />
| [[FS:Obsoleted_3_0_EnumerateExtSaveData|Obsoleted_3_0_EnumerateExtSaveData]]<br />
| 0x1005<br />
|-<br />
| 0x08340082<br />
|?<br />
| [[FS:Obsoleted_3_0_EnumerateSharedExtSaveData|Obsoleted_3_0_EnumerateSharedExtSaveData]]<br />
| 0x1005<br />
|-<br />
| 0x08350080<br />
|?<br />
| [[FS:Obsoleted_3_0_DeleteExtSaveData|Obsoleted_3_0_DeleteExtSaveData]]<br />
| 0x100D, for when the input extdataID doesn't match the exheader extdataID<br />
|-<br />
| 0x08360080<br />
|?<br />
| [[FS:Obsoleted_3_0_DeleteSharedExtSaveData|Obsoleted_3_0_DeleteSharedExtSaveData]]<br />
| 0x1005<br />
|-<br />
| 0x08370040<br />
|?<br />
| [[FS:SetCardSpiBaudRate|SetCardSpiBaudRate]]<br />
| 0x2<br />
|-<br />
| 0x08380040<br />
|?<br />
| [[FS:SetCardSpiBusMode|SetCardSpiBusMode]]<br />
| 0x2<br />
|-<br />
| 0x08390000<br />
|?<br />
| [[FS:SendInitializeInfoTo9|SendInitializeInfoTo9]]<br />
| None<br />
|-<br />
| 0x083A0100<br />
|?<br />
| [[FS:GetSpecialContentIndex|GetSpecialContentIndex]]<br />
| 0x1005<br />
|-<br />
| 0x083B00C2<br />
|?<br />
| [[FS:GetLegacyRomHeader|GetLegacyRomHeader]]<br />
| 0x1015<br />
|-<br />
| 0x083C00C2<br />
|?<br />
| [[FS:GetLegacyBannerData|GetLegacyBannerData]]<br />
| 0x1015<br />
|-<br />
| 0x083D0100<br />
|?<br />
| [[FS:CheckAuthorityToAccessExtSaveData|CheckAuthorityToAccessExtSaveData]]<br />
| 0x44<br />
|-<br />
| 0x083E00C2<br />
|?<br />
| [[FS:QueryTotalQuotaSize|QueryTotalQuotaSize]]<br />
| None<br />
|-<br />
| 0x083F00C0<br />
|?<br />
| [[FS:Obsoleted_3_0_GetExtDataBlockSize|Obsoleted_3_0_GetExtDataBlockSize]]<br />
| None<br />
|-<br />
| 0x08400040<br />
|?<br />
| [[FS:AbnegateAccessRight|AbnegateAccessRight]]<br />
|?<br />
|-<br />
| 0x08410000<br />
|?<br />
| [[FS:DeleteSdmcRoot|DeleteSdmcRoot]]<br />
| 0x1005<br />
|-<br />
| 0x08420040<br />
|?<br />
| [[FS:DeleteAllExtSaveDataOnNand|DeleteAllExtSaveDataOnNand]]<br />
| 0x1005<br />
|-<br />
| 0x08430000<br />
|?<br />
| [[FS:InitializeCtrFileSystem|InitializeCtrFileSystem]]<br />
| None<br />
|-<br />
| 0x08440000<br />
|?<br />
| [[FS:CreateSeed|CreateSeed]]<br />
| 0x2<br />
|-<br />
| 0x084500C2<br />
|?<br />
| [[FS:GetFormatInfo|GetFormatInfo]]<br />
|?<br />
|-<br />
| 0x08460102<br />
|?<br />
| [[FS:GetLegacyRomHeader2|GetLegacyRomHeader2]]<br />
| 0x1015<br />
|-<br />
| 0x08470180<br />
|?<br />
| [[FS:Obsoleted_2_0_FormatCtrCardUserSaveData|Obsoleted_2_0_FormatCtrCardUserSaveData]]<br />
| 0x6<br />
|-<br />
| 0x08480042<br />
|?<br />
| [[FS:GetSdmcCtrRootPath|GetSdmcCtrRootPath]]<br />
| 0x100D<br />
|-<br />
| 0x08490040<br />
|?<br />
| [[FS:GetArchiveResource|GetArchiveResource]]<br />
|?<br />
|-<br />
| 0x084A0002<br />
|?<br />
| [[FS:ExportIntegrityVerificationSeed|ExportIntegrityVerificationSeed]]<br />
| 0x4000<br />
|-<br />
| 0x084B0002<br />
|?<br />
| [[FS:ImportIntegrityVerificationSeed|ImportIntegrityVerificationSeed]]<br />
| 0x4000<br />
|-<br />
| 0x084C0242<br />
|?<br />
| [[FS:FormatSaveData|FormatSaveData]]<br />
| 0x6, in some cases this write isn't needed however<br />
|-<br />
| 0x084D0102<br />
|?<br />
| [[FS:GetLegacySubBannerData|GetLegacySubBannerData]]<br />
| 0x1015<br />
|-<br />
| 0x084E0342<br />
|?<br />
| [[FS:UpdateSha256Context|UpdateSha256Context]]<br />
| 0x5<br />
|-<br />
| 0x084F0102<br />
|?<br />
| [[FS:ReadSpecialFile|ReadSpecialFile]]<br />
| None<br />
|-<br />
| 0x08500040<br />
|?<br />
| [[FS:GetSpecialFileSize|GetSpecialFileSize]]<br />
| None<br />
|-<br />
| 0x08510242<br />
| [[3.0.0-5]]<br />
| [[FS:CreateExtSaveData|CreateExtSaveData]]<br />
| Shared extdata: 0x101005. Regular extdata in certain cases: 0xC<br />
|-<br />
| 0x08520100<br />
| [[3.0.0-5]]<br />
| [[FS:DeleteExtSaveData|DeleteExtSaveData]]<br />
| Shared extdata: 0x101005. Regular extdata in certain cases: 0x10100D<br />
|-<br />
| 0x08530142<br />
| [[3.0.0-5]]<br />
| [[FS:ReadExtSaveDataIcon|ReadExtSaveDataIcon]]<br />
| 0x10100D (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x085400C0<br />
| [[3.0.0-5]]<br />
| [[FS:GetExtDataBlockSize|GetExtDataBlockSize]]<br />
| 0x10100D (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x08550102<br />
| [[3.0.0-5]]<br />
| [[FS:EnumerateExtSaveData|EnumerateExtSaveData]]<br />
| 0x101005<br />
|-<br />
| 0x08560240<br />
| [[3.0.0-5]]<br />
| [[FS:CreateSystemSaveData|CreateSystemSaveData]]<br />
| 0x4 (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x08570080<br />
| [[3.0.0-5]]<br />
| [[FS:DeleteSystemSaveData|DeleteSystemSaveData]]<br />
| 0x1004 (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x08580000<br />
| [[3.0.0-5]]<br />
| [[FS:StartDeviceMoveAsSource|StartDeviceMoveAsSource]]<br />
| 0x2004<br />
|-<br />
| 0x08590200<br />
| [[3.0.0-5]]<br />
| [[FS:StartDeviceMoveAsDestination|StartDeviceMoveAsDestination]]<br />
| 0x2004<br />
|-<br />
| 0x085A00C0<br />
| [[3.0.0-5]]<br />
| [[FS:SetArchivePriority|SetArchivePriority]]<br />
| None<br />
|-<br />
| 0x085B0080<br />
| [[3.0.0-5]]<br />
| [[FS:GetArchivePriority|GetArchivePriority]]<br />
| None<br />
|-<br />
| 0x085C00C0<br />
| [[3.0.0-5]]<br />
| [[FS:SetCtrCardLatencyParameter|SetCtrCardLatencyParameter]]<br />
| 0xE<br />
|-<br />
| 0x085D01C0<br />
| [[3.0.0-5]]<br />
| [[FS:SetFsCompatibilityInfo|SetFsCompatibilityInfo]]<br />
| 0x100001<br />
|-<br />
| 0x085E0040<br />
| [[3.0.0-5]]<br />
| [[FS:ResetCardCompatibilityParameter|ResetCardCompatibilityParameter]]<br />
| 0xE<br />
|-<br />
| 0x085F0040<br />
| [[3.0.0-5]]<br />
| [[FS:SwitchCleanupInvalidSaveData|SwitchCleanupInvalidSaveData]]<br />
| 0x12004<br />
|-<br />
| 0x08600042<br />
| [[3.0.0-5]]<br />
| [[FS:EnumerateSystemSaveData|EnumerateSystemSaveData]]<br />
| 0x2004<br />
|-<br />
| 0x08610042<br />
| [[3.0.0-5]]<br />
| [[FS:InitializeWithSdkVersion|InitializeWithSdkVersion]]<br />
| None<br />
|-<br />
| 0x08620040<br />
| [[3.0.0-5]]<br />
| [[FS:SetPriority|SetPriority]]<br />
| None<br />
|-<br />
| 0x08630000<br />
| [[3.0.0-5]]<br />
| [[FS:GetPriority|GetPriority]]<br />
| None<br />
|-<br />
| 0x08640000<br />
| [[3.0.0-5]]<br />
| [[FS:Obsoleted_4_0_GetNandInfo|Obsoleted_4_0_GetNandInfo]]<br />
| Stubbed, this returns an error<br />
|-<br />
| 0x08650140<br />
| [[4.0.0-7]]<br />
| [[FS:SetSaveDataSecureValue|SetSaveDataSecureValue]]<br />
| 0x121004 (in certain cases this doesn't apply, however)<br />
|-<br />
| 0x086600C0<br />
| [[4.0.0-7]]<br />
| [[FS:GetSaveDataSecureValue|GetSaveDataSecureValue]]<br />
| 0x121004 (in certain cases this doesn't apply, however)<br />
|-<br />
| 0x086700C4<br />
| [[4.0.0-7]]<br />
| [[FS:ControlSecureSave|ControlSecureSave]]<br />
| 0x121004<br />
|-<br />
| 0x08680000<br />
| [[4.0.0-7]]<br />
| [[FS:GetMediaType|GetMediaType]]<br />
| None<br />
|-<br />
| 0x08690000<br />
| [[4.0.0-7]]<br />
| [[FS:Obsoleted_4_0_GetNandEraseCount|Obsoleted_4_0_GetNandEraseCount]]<br />
| Stubbed, this returns an error.<br />
|-<br />
| 0x086A0082<br />
| [[4.0.0-7]]<br />
| [[FS:ReadNandReport|ReadNandReport]]<br />
| None<br />
|-<br />
| 0x086B00C2<br />
|?<br />
|?<br />
| 00121004<br />
|-<br />
| 0x086C00C2<br />
|?<br />
|?<br />
| 00121004<br />
|-<br />
| 0x086D0040<br />
|?<br />
|?<br />
| 00020004<br />
|-<br />
| 0x086E00C0<br />
|Related to Secure Value? Used in Pokemon Sun/Moon.<br />
|?<br />
|None?<br />
|-<br />
| 0x086F0040<br />
|Related to Secure Value? Used in Pokemon Sun/Moon.<br />
|?<br />
| 0xE<br />
|-<br />
| 0x087000C2<br />
|?<br />
|?<br />
|None?<br />
|-<br />
| 0x08710100<br />
|?<br />
|?<br />
| 0xC<br />
|-<br />
| 0x087201C0<br />
|?<br />
|?<br />
| 00080004<br />
|-<br />
| 0x087300C0<br />
|?<br />
|?<br />
| 00080004<br />
|-<br />
| 0x08740000<br />
|?<br />
|?<br />
| 00080004<br />
|-<br />
| 0x08750140<br />
|?<br />
|?<br />
|None?<br />
|-<br />
| 0x087600C0<br />
|?<br />
|?<br />
|None?<br />
|-<br />
| 0x08770100<br />
|?<br />
|?<br />
|?<br />
|-<br />
| 0x087800C0<br />
|?<br />
|?<br />
|?<br />
|-<br />
| 0x087900C2<br />
| ?<br />
| Same as GetLegacyBannerData, except for the last parameter this passes u8 value 0x1 instead of 0x0, for the FSPXI command.<br />
| 0x00101015<br />
|-<br />
| 0x087A0180<br />
| [[9.6.0-24|9.6.0-X]]<br />
| [[FS:AddSeed|AddSeed]]<br />
| 0x00200000<br />
|-<br />
| 0x087B....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Wrapper for the code internally used for command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x087C....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x087D0000<br />
| [[9.6.0-24|9.6.0-X]]<br />
| GetNumSeeds. Writes the number of seeds to cmdreply[2]<br />
| 0x00200000<br />
|-<br />
| 0x087E0042<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>. Writes a list of titleIDs to the outbuf, this is for titles with content-lock-seed(s) stored in SEEDDB. (u32 total_titleids_probably, ((Size<<4) <nowiki>|</nowiki> 12), outbufptr)<br />
| 0x00200000<br />
|-<br />
| 0x087F....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| ?<br />
| 0x00200000<br />
|-<br />
| 0x0880....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x0881....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x0882....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x08830000<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Writes an output value to cmdreply[2].<br />
| 0x00200000<br />
|-<br />
| 0x08840042<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x0885....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| ?<br />
| 0x00200000<br />
|-<br />
| 0x088600C0<br />
| [[11.1.0-34|11.1.0-X]]<br />
| [[FS:CheckUpdatedDat|CheckUpdatedDat]]<br />
| 0x00080000<br />
|}<br />
<br />
Note: The question marks from Dummy1 to GetSpecialFileSize on the "available since system version" field are mainly there because I think that most of these are necessary for the main system to function, so theoretically that would mean that since the creation of the 3DS these were available, or since launch if that makes more sense. But because of the peculiar nature of some of the functions, they will remain question marks until they can be confirmed 100%.<br />
<br />
When access rights are required for a command, at least one of the bits in the process access info specified in the above table for the command must be set. Error 0xD9004676 is returned when a process attempts to use a command which it doesn't have access rights for the command. The exheader access info field is all zero's for most applications. Note that the permissions listed in the above table is for system-version v2.x, therefore permission bit(s) added with newer FIRM may be missing from this.<br />
<br />
Each session for fs:USER has separate permissions, initially these are set to all zero's for new fs:USER sessions. The permissions/etc for fs:USER sessions are initialized via [[FS:Initialize]](loaded from the user process exheader).<br />
<br />
== Filesystem service "fs:LDR" ==<br />
This service is identical to fs:USER, except [[FS:OpenArchive]] archive 0x2345678E can only be accessed with fs:LDR.<br />
<br />
== ProgramRegistry service "fs:REG" ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x000100C6<br />
| [[FSReg:Dummy1|Dummy1]]<br />
|-<br />
| 0x040103C0<br />
| [[FSReg:Register|Register]]<br />
|-<br />
| 0x04020040<br />
| [[FSReg:Unregister|Unregister]]<br />
|-<br />
| 0x040300C0<br />
| [[FSReg:GetProgramInfo|GetProgramInfo]]<br />
|-<br />
| 0x04040100<br />
| [[FSReg:LoadProgram|LoadProgram]]<br />
|-<br />
| 0x04050080<br />
| [[FSReg:UnloadProgram|UnloadProgram]]<br />
|-<br />
| 0x04060080<br />
| [[FSReg:CheckHostLoadId|CheckHostLoadId]]<br />
|}<br />
<br />
Only two sessions can be opened for this service at a time, hence no other processes can use this due to [[Process_Manager_Services|pm-module]] and [[Loader_Services|loader]] using this.<br />
<br />
=File and directory access=<br />
==Files==<br />
File session handles obtained via [[FS:OpenFile]] et al can be used to access files through a service-like interface, despite not being an actual service registered using [[SRV:RegisterService]].<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x000100C6<br />
| [[FSFile:Dummy1|Dummy1]]<br />
|-<br />
| 0x040100C4<br />
| [[FSFile:Control|Control]]<br />
|-<br />
| 0x08010100<br />
| [[FSFile:OpenSubFile|OpenSubFile]]<br />
|-<br />
| 0x080200C2<br />
| [[FSFile:Read|Read]]<br />
|-<br />
| 0x08030102<br />
| [[FSFile:Write|Write]]<br />
|-<br />
| 0x08040000<br />
| [[FSFile:GetSize|GetSize]]<br />
|-<br />
| 0x08050080<br />
| [[FSFile:SetSize|SetSize]]<br />
|-<br />
| 0x08060000<br />
| [[FSFile:GetAttributes|GetAttributes]]<br />
|-<br />
| 0x08070040<br />
| [[FSFile:SetAttributes|SetAttributes]]<br />
|-<br />
| 0x08080000<br />
| [[FSFile:Close|Close]]<br />
|-<br />
| 0x08090000<br />
| [[FSFile:Flush|Flush]]<br />
|-<br />
| 0x080A0040<br />
| [[FSFile:SetPriority|SetPriority]]<br />
|-<br />
| 0x080B0000<br />
| [[FSFile:GetPriority|GetPriority]]<br />
|-<br />
| 0x080C0000<br />
| [[FSFile:OpenLinkFile|OpenLinkFile]]<br />
|-<br />
| 0x0C010100<br />
| [[FSFile:GetAvailable|GetAvailable]]<br />
|}<br />
<br />
==Directories==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x000100C6<br />
| [[1.0.0-0]]<br />
| [[FSDir:Dummy1|Dummy1]]<br />
|-<br />
| 0x040100C4<br />
| [[1.0.0-0]]<br />
| [[FSDir:Control|Control]]<br />
|-<br />
| 0x08010042<br />
| [[1.0.0-0]]<br />
| [[FSDir:Read|Read]]<br />
|-<br />
| 0x08020000<br />
| [[1.0.0-0]]<br />
| [[FSDir:Close|Close]]<br />
|-<br />
| 0x08030040<br />
| ?<br />
| [[FSDir:SetPriority|SetPriority]]<br />
|-<br />
| 0x08040000<br />
| ?<br />
| [[FSDir:GetPriority|GetPriority]]<br />
|}<br />
<br />
= Archives =<br />
{| class="wikitable" border="1"<br />
|-<br />
! ArchiveId<br />
! Description<br />
! Accessible via [[Filesystem_services|FS]]<br />
! Accessible via [[Filesystem_services_PXI|FSPXI]]<br />
! Only accessible by Process9 internally<br />
! Requires binary [[FS:OpenFile|Lowpath]]<br />
! Required exheader FS access info bitmask<br />
|-<br />
| 0x00000003<br />
| SelfNCCH (including [[#RomFS|RomFS]])<br />
| Yes<br />
| No<br />
| No<br />
| No<br />
| None<br />
|-<br />
| 0x00000004<br />
| SaveData (the saveID/mediatype for this is loaded from data originally from the user process' exheader)<br />
| Yes<br />
| No<br />
| No<br />
| No<br />
| None<br />
|-<br />
| 0x00000006<br />
| ExtSaveData<br />
| Yes<br />
| No<br />
| No<br />
| Yes<br />
| 0x100D, when the input extdataID isn't listed in the exheader.<br />
|-<br />
| 0x00000007<br />
| Shared ExtSaveData<br />
| Yes<br />
| No<br />
| No<br />
| Yes<br />
| None<br />
|-<br />
| 0x00000008<br />
| SystemSaveData<br />
| Yes<br />
| No<br />
| No<br />
| Yes<br />
| 0x4, when the input saveID doesn't match the exheader system-saveID.<br />
|-<br />
| 0x00000009<br />
| SDMC<br />
| Yes<br />
| Yes<br />
| No<br />
| No<br />
| 0x8E<br />
|-<br />
| 0x0000000A<br />
| SDMC Write-Only<br />
| Yes<br />
| No<br />
| No<br />
| No<br />
| 0x808E<br />
|-<br />
| 0x12345678<br />
| ExtSaveData for BOSS<br />
| Yes<br />
| No<br />
| No<br />
| Yes<br />
| 0x44<br />
|-<br />
| 0x12345679<br />
| CARD SPI FS<br />
| Yes<br />
| Yes<br />
| No<br />
| No<br />
| 0x16<br />
|-<br />
| 0x1234567B<br />
| ExtSaveData, and ExtSaveData for BOSS<br />
| No<br />
| Yes<br />
| No<br />
| Yes<br />
| <br />
|-<br />
| 0x1234567C<br />
| SystemSaveData<br />
| No<br />
| Yes<br />
| No<br />
| Yes<br />
| <br />
|-<br />
| 0x1234567D<br />
| NAND RW<br />
| Yes<br />
| Yes<br />
| No<br />
| No<br />
| 0x800<br />
|-<br />
| 0x1234567E<br />
| NAND RO<br />
| Yes<br />
| Yes<br />
| No<br />
| No<br />
| 0x200<br />
|-<br />
| 0x1234567F<br />
| NAND RO Write FS<br />
| No<br />
| Yes<br />
| No<br />
| No<br />
| ?<br />
|-<br />
| 0x12345680<br />
| Unknown. There's code for this in spider v9.9, but that code isn't actually used.<br />
| Yes<br />
| ?<br />
| No<br />
| Yes<br />
| ?<br />
|-<br />
| 0x12345681<br />
| Unknown. Accessed by FS service.<br />
| ?<br />
| ?<br />
| No<br />
| ?<br />
| ?<br />
|-<br />
| 0x12345682<br />
| Unknown. There's code for this in spider v9.9, but that code isn't actually used.<br />
| Yes<br />
| ?<br />
| No<br />
| Yes<br />
| ?<br />
|-<br />
| 0x2345678A<br />
| Used for accessing general NCCH data. With FSPXI this also allows savedata access.<br />
| Yes<br />
| Yes<br />
| No<br />
| Yes<br />
| 0x1005<br />
|-<br />
| 0x2345678B<br />
| ?<br />
| No<br />
| No<br />
| Yes<br />
| Yes<br />
| <br />
|-<br />
| 0x2345678C<br />
| Used internally to access [[Title_Database|/dbs]] files?<br />
| No<br />
| No<br />
| Yes<br />
| Yes<br />
| <br />
|-<br />
| 0x2345678D<br />
| ?<br />
| No<br />
| No<br />
| Yes<br />
| No<br />
| <br />
|-<br />
| 0x2345678E<br />
| FSPXI: Similar to archive 0x2345678A. For fs:LDR(used by the "loader" FIRM ARM11-process), only ExeFS. Not accessible with fs:USER.<br />
| Yes<br />
| Yes<br />
| No<br />
| Yes<br />
| None, see description.<br />
|-<br />
| 0x567890AB<br />
| NAND CTR FS<br />
| No<br />
| Yes<br />
| No<br />
| No<br />
| ?<br />
|-<br />
| 0x567890AC<br />
| TWL PHOTO<br />
| Yes<br />
| Yes<br />
| No<br />
| No<br />
| ?<br />
|-<br />
| 0x567890AD<br />
| TWLS (DSi Sound stores recordings here). This is mapped to the FAT12 image stored in the file at [[Twln/shared2/0000]].<br />
| No<br />
| Yes<br />
| No<br />
| No<br />
| ?<br />
|-<br />
| 0x567890AE<br />
| NAND TWL FS<br />
| Yes<br />
| Yes<br />
| No<br />
| No<br />
| 0x100<br />
|-<br />
| 0x567890AF<br />
| NAND W FS<br />
| Yes<br />
| Yes<br />
| No<br />
| No<br />
| 0x100<br />
|-<br />
| 0x567890B0<br />
| ?<br />
| No<br />
| Yes<br />
| No<br />
| No<br />
| <br />
|-<br />
| 0x567890B1<br />
| Gamecard SaveData (for check). This is a wrapper for UserSaveDataForCheck: the OpenArchive code for that is called with archive-lowpath TID=0/mediatype=2(gamecard).<br />
| Yes<br />
| No<br />
| No<br />
| No<br />
| 0x6<br />
|-<br />
| 0x567890B2<br />
| UserSaveData (for check). This is the same as the regular SaveData archive, except with this the savedata ID and mediatype is loaded from the input archive lowpath.<br />
| Yes<br />
| No<br />
| No<br />
| Yes<br />
| 0x6<br />
|-<br />
| 0x567890B4<br />
| Similar to 0x567890B2 but can only access Accessible Save specified in [[NCCH/Extended_Header#Storage_Info|exheader]]?<br />
| Yes<br />
| No<br />
| No<br />
| Yes<br />
| ?<br />
|}<br />
<br />
Archives listed as not requiring a binary lowpath, use lowpath type [[FS:OpenFile|empty]].<br />
<br />
The above permission bitmasks are from v2.x, see the above Services section for how these are handled.<br />
<br />
Archives CTR NAND, NAND RO Write FS, TWL NAND, NAND W FS, and CARD SPI FS require the corresponding process exheader access control mount flag to be set, in the exheader for any of the currently running ARM11 processes, for [[Filesystem_services_PXI|FSPXI]]. The access rights checked by [[Filesystem services|FS]] module for archive mounting with fs:USER, are stored in the process' exheader accessinfo.<br />
<br />
The CARDSPI archive allows access to the gamecard CARD1 raw savedata flash(aka "cardspi:/" in [[FIRM|Process9]]), the file lowpath must be WCHAR "/". The "NAND W FS" archive allows access to the raw NAND image(aka "wnand:/" in Process9), the file lowpath must be WCHAR "/".<br />
<br />
= Filenames and Paths =<br />
PathType:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| -1<br />
| Returned internally by Process9, when errors occur it seems(in particular when no nul-terminator was found in the input path). The data ptr is set to NULL.<br />
|-<br />
| 0x0<br />
| INVALID - Specifies an invalid path<br />
|-<br />
| 0x1<br />
| EMPTY - Specifies an empty path<br />
|-<br />
| 0x2<br />
| BINARY - Non-text based path. Meaning is per-archive<br />
|-<br />
| 0x3<br />
| ASCII - Text-based path with 7-bit ASCII characters padded to 8-bits each (signed char)<br />
|-<br />
| 0x4<br />
| UTF16 - Text-based path with UTF-16 characters<br />
|}<br />
<br />
In IPC requests, sizes of ASCII and UTF16 paths must include space for the null-terminator. <br />
<br />
== Binary LowPath ==<br />
The format of the data that a binary LowPath points to is custom per archive.<br />
<br />
=== SelfNCCH File Path Data Format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0 <br />
| Type:<br />
* 0x0: RomFS<br />
* 0x1: error 0xD9004676<br />
* 0x2: ExeFS<br />
* 0x3: Error 0xE0E046BE.<br />
* 0x4: FS-module crashes on this<br />
* 0x5: Update RomFS?<br />
|-<br />
| 1-2<br />
| File name for ExeFS ("icon"/"banner"/"logo"). ".code" is not allowed<br />
|}<br />
<br />
Note that ExeFS files only support reading from offset=0 and with size=file_size. <br />
<br />
=== SystemSaveData Archive Path Data Format ===<br />
==== FS ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0 <br />
| [[Mediatypes|Mediatype]] (must be zero for NAND)<br />
|-<br />
| 1<br />
| saveid<br />
|}<br />
The file/directory lowpath is a text lowpath in the [[Savegames|savegame]] filesystem.<br />
<br />
==== FSPXI ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0 <br />
| u8 [[Mediatypes|Mediatype]] (must be zero for NAND)<br />
|}<br />
The file lowpath is a binary lowpath containing the u64 saveid, however the high word of the saveid is always zero. The mounted file is the cleartext savegame image. Up to 32 SystemSaveData image files can be opened under a single mounted FSPXI archive.<br />
<br />
=== UserSaveDataForCheck Archive Path Data Format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0 <br />
| [[Mediatypes|Mediatype]] (must be non-zero)<br />
|-<br />
| 1<br />
| Lower word saveid<br />
|-<br />
| 2<br />
| Upper word saveid<br />
|}<br />
The file/directory lowpath for this FS archive is a text path in the [[Savegames|savegame]] filesystem.<br />
<br />
=== 0x567890B4 Archive Path Data Format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0 <br />
| [[Mediatypes|Mediatype]]<br />
|-<br />
| 1<br />
| <code><nowiki>Lower_word_saveid >> 8</nowiki></code> ?<br />
|-<br />
| 2<br />
| Unknown. Game calculate this using formula <code><nowiki>(unknown_a & 0xFFFFFF00) | unknown_b</nowiki></code><br />
|}<br />
<br />
=== ExtSaveData Archive Path Data Format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0 <br />
| [[Mediatypes|Mediatype]]<br />
|-<br />
| 1<br />
| Lower word saveid<br />
|-<br />
| 2<br />
| Upper word saveid<br />
|}<br />
For FS, the file/directory lowpath is a text path in the [[extdata]] filesystem. For FSPXI, the file lowpath is a text path relative to the "/extdata/<ExtdataIDHigh>/<ExtdataIDLow>" directory on SD/NAND, for the cleartext extdata image to mount.<br />
<br />
=== 0x2345678A Archive Path Data Format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0<br />
| Lower word programID<br />
|-<br />
| 1<br />
| Upper word programID<br />
|-<br />
| 2 <br />
| ([[Mediatypes|Mediatype]] & 0xFF) | (uninitialized_data? & 0xFFFFFF00)<br />
|-<br />
| 3<br />
| Number of something? Hardcoded per-archive, 0 for ExeFS, 200 for area:, 100 for rate:, 40 for eula:, etc.<br />
|}<br />
<br />
File lowpath:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0<br />
| 0 for NCCH data, 1 for savedata. The latter is only valid for FSPXI. Value 2 is allowed via archive 0x3, it's unknown what this is.<br />
|-<br />
| 1<br />
| TMD content index / NCSD partition index.<br />
|-<br />
| 2<br />
| Type: 0=romfs(0 for non-NCCH as well), 1=exefs ".code"(?), 2=exefs "icon"/"banner"/"logo", 3=unknown, 4=unknown, 5=unknown.<br />
|-<br />
| 3-4<br />
| Filename for ExeFS.<br />
|}<br />
<br />
The 0x14-byte lowpath is all-zero for accessing the title's main RomFS.<br />
<br />
=== [[RomFS]] ===<br />
<br />
Archives 0x3 and 0x2345678E both allow for accessing the [[RomFS#Level_3_Format|level-3 IVFC images]] for RomFS access. The main CXI RomFS is accessible via an all-zero 0xc-byte binary file-lowpath. The update RomFS can be accessed with the first u32 in the binary file-lowpath being set to 0x5. The user must handle parsing the filesystem used in the exposed image itself.<br />
<br />
With FSPXI the returned data for RomFS is the entire RomFS section from the NCCH, starting at the IVFC header.<br />
<br />
The 0x3 archive is an interface for the 0x2345678E archive with the current process programID+mediatype. The file lowpath is 3-words. These words are written to 0x2345678E-archive file_lowpath+0, with the rest of that lowpath set to all-zero(lowpath is different from archive 0x2345678A). File lowpath:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index word<br />
! Description<br />
|-<br />
| 0<br />
| See above. The only values which FS-module doesn't allow to be used here are:<br />
* 0x1: Error 0xE0E046BE.<br />
* 0x3: Error 0xE0E046BE.<br />
* 0x4: FS-module executes svcBreak when using this.<br />
|-<br />
| 1-2<br />
| See above. Not validated by FS-module.<br />
|}<br />
<br />
=SEEDDB=<br />
With [[9.6.0-24|9.6.0-X]] new [[System_SaveData]] with saveID 0001000F was added, this seems to be handled by FS-module itself, probably via the new service-cmds added to fsuser. [[Home Menu]] and [[NIM_Services|NIM]] module have access to those commands.<br />
<br />
The SEEDDB savedata contains the title-unique seed-data used for the new [[NCCH]] keyY generation added with FIRM [[9.6.0-24|9.6.0-X]].<br />
<br />
= Common Types =<br />
== MediaType ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| NAND<br />
|-<br />
| 1<br />
| SD<br />
|-<br />
| 2<br />
| Game Card<br />
|}<br />
<br />
== SystemMediaType ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| CTR NAND<br />
|-<br />
| 1<br />
| TWL NAND<br />
|-<br />
| 2<br />
| SD<br />
|-<br />
| 2<br />
| TWL Photo<br />
|}<br />
<br />
== OpenFlags ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Read<br />
|-<br />
| 1<br />
| Write<br />
|-<br />
| 2<br />
| Create<br />
|}<br />
<br />
== Attributes ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1<br />
| Is Directory<br />
|-<br />
| 0x1<br />
| 0x1<br />
| Is Hidden<br />
|-<br />
| 0x2<br />
| 0x1<br />
| Is Archive<br />
|-<br />
| 0x3<br />
| 0x1<br />
| Is Read-Only<br />
|}<br />
<br />
== WriteOption ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1<br />
| Flush<br />
|-<br />
| 0x1<br />
| 0x1<br />
| Update Time Stamp<br />
|-<br />
| 0x2<br />
| 0x1<br />
| Reserved<br />
|-<br />
| 0x3<br />
| 0x1<br />
| Reserved<br />
|}<br />
<br />
== DirectoryEntry ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x20C<br />
| UTF-16 Entry Name<br />
|-<br />
| 0x20C<br />
| 0xA<br />
| 8.3 short filename name<br />
|-<br />
| 0x216<br />
| 0x4<br />
| 8.3 short filename extension<br />
|-<br />
| 0x21A<br />
| 0x1<br />
| Always 1<br />
|-<br />
| 0x21B<br />
| 0x1<br />
| Reserved<br />
|-<br />
| 0x21C<br />
| 0x4<br />
| [[Filesystem_services#Attributes|Attributes]]<br />
|-<br />
| 0x220<br />
| 0x8<br />
| Entry Size<br />
|}<br />
<br />
== ArchiveResource ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Sector byte-size<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Cluster byte-size<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Partition capacity in clusters<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Available free space in clusters<br />
|}<br />
<br />
== ProgramInfo ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| Program ID<br />
|-<br />
| 0x8<br />
| 0x1<br />
| [[Filesystem_services#MediaType|Media Type]]<br />
|-<br />
| 0x9<br />
| 0x7<br />
| Padding<br />
|}<br />
<br />
== ProductInfo ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| Product Code<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Company Code<br />
|-<br />
| 0x12<br />
| 0x2<br />
| Remaster Version<br />
|}<br />
<br />
== IntegrityVerificationSeed ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| AES-CBC MAC over a SHA256 hash, which hashes the first 0x110-bytes of the cleartext SEED.<br />
|-<br />
| 0x10<br />
| 0x120<br />
| The [[nand/private/movable.sed]], encrypted with AES-CTR using the above MAC for the counter.<br />
|}<br />
<br />
== ExtSaveDataInfo ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1<br />
| [[Filesystem_services#MediaType|Media Type]]<br />
|-<br />
| 0x1<br />
| 0x1<br />
| Unknown<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Reserved<br />
|-<br />
| 0x4<br />
| 0x8<br />
| Save ID<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Reserved<br />
|}<br />
<br />
== SystemSaveDataInfo ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1<br />
| [[Filesystem_services#MediaType|Media Type]]<br />
|-<br />
| 0x1<br />
| 0x1<br />
| Unknown<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Reserved<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Save ID<br />
|}<br />
<br />
== SecureValueSlot ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0x1000<br />
| SD Application<br />
|}<br />
<br />
== CardSpiBaudRate ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0x0<br />
| 512KHz<br />
|-<br />
| 0x1<br />
| 1MHz<br />
|-<br />
| 0x2<br />
| 2MHz<br />
|-<br />
| 0x3<br />
| 4MHz<br />
|-<br />
| 0x4<br />
| 8MHz<br />
|-<br />
| 0x5<br />
| 16MHz<br />
|}<br />
<br />
== CardSpiBusMode ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0x0<br />
| 1-bit<br />
|-<br />
| 0x1<br />
| 4-bit<br />
|}<br />
<br />
== SpecialContentType ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0x1<br />
| Update<br />
|-<br />
| 0x2<br />
| Manual<br />
|-<br />
| 0x3<br />
| DLP Child<br />
|}<br />
<br />
== DeviceMoveContext ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| IVs<br />
|-<br />
| 0x10<br />
| 0x10<br />
| Encrypt Parameter<br />
|}<br />
<br />
=Errors=<br />
See [[Filesystem_services_PXI]].</div>Subvhttps://www.3dbrew.org/w/index.php?title=WIFI_Registers&diff=20486WIFI Registers2017-12-06T21:48:27Z<p>Subv: </p>
<hr />
<div>These registers are used to control the WiFi card via the SDIO protocol.<br />
<br />
=Registers=<br />
<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Address<br />
! Width<br />
|-<br />
| WIFI_CMD<br />
| 0x10122000<br />
| 2<br />
|-<br />
| ?<br />
| 0x10006002<br />
| 2<br />
|-<br />
| WIFI_CMDARG0<br />
| 0x10122004<br />
| 2<br />
|-<br />
| WIFI_CMDARG1<br />
| 0x10122006<br />
| 2<br />
|-<br />
| WIFI_BLKCOUNT<br />
| 0x1012200a<br />
| 2<br />
|-<br />
| WIFI_CLKCTL<br />
| 0x10122024<br />
| 2<br />
|-<br />
| WIFI_BLKLEN<br />
| 0x10122026<br />
| 2<br />
|-<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=WIFI_Registers&diff=20485WIFI Registers2017-12-06T21:47:27Z<p>Subv: Created page with "These registers are used to control the WiFi card via the SDIO protocol. =Registers= {| class="wikitable" border="1" ! Name ! Address ! Width |- | WIFI_CMD | 0x10006000 |..."</p>
<hr />
<div>These registers are used to control the WiFi card via the SDIO protocol.<br />
<br />
=Registers=<br />
<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Address<br />
! Width<br />
|-<br />
| WIFI_CMD<br />
| 0x10006000<br />
| 2<br />
|-<br />
| ?<br />
| 0x10006002<br />
| 2<br />
|-<br />
| WIFI_CMDARG0<br />
| 0x10006004<br />
| 2<br />
|-<br />
| WIFI_CMDARG1<br />
| 0x10006006<br />
| 2<br />
|-<br />
| WIFI_BLKCOUNT<br />
| 0x1000600a<br />
| 2<br />
|-<br />
| WIFI_CLKCTL<br />
| 0x10006024<br />
| 2<br />
|-<br />
| WIFI_BLKLEN<br />
| 0x10006026<br />
| 2<br />
|-<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20429NWM Services2017-10-31T15:13:00Z<p>Subv: /* Network structure */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
[There does not appear to be an association request frame sent by the client to the server, it is however possible that it was sent and just not captured by the test equipment]<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is connected to the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 ([[NWM_Services#EAPoL-Start frame|EAPoL-Start]])<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202([[NWM_Services#EAPoL-Logoff frame|EAPoL-Logoff]])<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D ([[NWM_Services#SecureData NWM header|SecureData]])]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
Application data packets are sent to the host using 802.11 unicast, which then acts as a router and forwards the packet to the right destination node id based on the SecureData header using either broadcast or unicast, it is not yet known how it chooses which to use.<br />
<br />
==Special data channels==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Channel<br />
! Description<br />
|-<br />
| 0x101<br />
| Used when broadcasting the updated node information after a new client connects.<br />
|-<br />
| 0x103<br />
| Used when sending what appears to be "ping" or "null" frames.<br />
|-<br />
| 0x104<br />
| Used to signal the ejection of all spectators in the network.<br />
|}<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Association id of the sending client in big-endian.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Number of times the network structure hash was updated.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0xD<br />
| ?<br />
|-<br />
| 0x2B<br />
| 0x14<br />
| SHA1 hash of the network structure, starting at the OUI field (offset 0xC) and spanning SizeOfAppData + 0x34. The unused space of the app data buffer is not hashed.<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=SVC&diff=20369SVC2017-10-02T04:34:24Z<p>Subv: /* GetProcessInfo */</p>
<hr />
<div>= System calls =<br />
'''Note: The argument-lists here apply to the official syscall wrapper-functions that are found in userland processes. The actual ordering passed to the kernel via the SVC instruction is documented in [[Kernel_ABI|Kernel ABI]].'''<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Id<br />
! NF ARM11<br />
! NF ARM9<br />
! TF ARM11<br />
! Description<br />
! scope="col" width="200" | Notes<br />
|-<br />
| 0x01 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Memory Management|ControlMemory]](u32* outaddr, u32 addr0, u32 addr1, u32 size, [[Memory Management#enum_MemoryOperation|MemoryOperation]] operation, [[Memory Management#enum_MemoryPermission|MemoryPermission]] permissions)<br />
| Outaddr is usually the same as the input addr0.<br />
|-<br />
| 0x02 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Memory Management|QueryMemory]]([[Memory Management#struct MemoryInfo|MemoryInfo]]* info, [[Memory Management#struct PageInfo|PageInfo]]* out, u32 Addr)<br />
|<br />
|-<br />
| 0x03 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| void ExitProcess(void)<br />
|<br />
|-<br />
| 0x04 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetProcessAffinityMask(u8* affinitymask, Handle process, s32 processorcount)<br />
|<br />
|-<br />
| 0x05 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SetProcessAffinityMask(Handle process, u8* affinitymask, s32 processorcount)<br />
|<br />
|-<br />
| 0x06 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetProcessIdealProcessor(s32 *idealprocessor, Handle process)<br />
|<br />
|-<br />
| 0x07 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SetProcessIdealProcessor(Handle process, s32 idealprocessor)<br />
|<br />
|-<br />
| 0x08 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#CreateThread|CreateThread]](Handle* thread, func entrypoint, u32 arg, u32 stacktop, s32 threadpriority, s32 processorid)<br />
|<br />
|-<br />
| 0x09 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| void [[Multi-threading#ExitThread|ExitThread]](void)<br />
|<br />
|-<br />
| 0x0A <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| void [[Multi-threading#SleepThread|SleepThread]](s64 nanoseconds)<br />
|<br />
|-<br />
| 0x0B <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#GetThreadPriority|GetThreadPriority]](s32* priority, Handle thread)<br />
|<br />
|-<br />
| 0x0C <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#SetThreadPriority|SetThreadPriority]](Handle thread, s32 priority)<br />
|<br />
|-<br />
| 0x0D <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#GetThreadAffinityMask|GetThreadAffinityMask]](u8* affinitymask, Handle thread, s32 processorcount)<br />
|<br />
|-<br />
| 0x0E <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#SetThreadAffinityMask|SetThreadAffinityMask]](Handle thread, u8* affinitymask, s32 processorcount)<br />
| Replaced with a stub in ARM11 NATIVE_FIRM kernel beginning with [[8.0.0-18]].<br />
|-<br />
| 0x0F <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#GetThreadIdealProcessor|GetThreadIdealProcessor]](s32* processorid, Handle thread)<br />
|<br />
|-<br />
| 0x10 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#SetThreadIdealProcessor|SetThreadIdealProcessor]](Handle thread, s32 processorid)<br />
| Replaced with a stub in ARM11 NATIVE_FIRM kernel beginning with [[8.0.0-18]].<br />
|-<br />
| 0x11 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| s32 GetCurrentProcessorNumber(void)<br />
|<br />
|-<br />
| 0x12 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#Run|Run]](Handle process, StartupInfo* info)<br />
| This starts the main() thread. Buf+0 is main-thread priority, Buf+4 is main-thread stack-size.<br />
|-<br />
| 0x13 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#CreateMutex|CreateMutex]](Handle* mutex, bool initialLocked)<br />
|<br />
|-<br />
| 0x14 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#ReleaseMutex|ReleaseMutex]](Handle mutex)<br />
|<br />
|-<br />
| 0x15 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#CreateSemaphore|CreateSemaphore]](Handle* semaphore, s32 initialCount, s32 maxCount)<br />
|<br />
|-<br />
| 0x16 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#ReleaseSemaphore|ReleaseSemaphore]](s32* count, Handle semaphore, s32 releaseCount)<br />
|<br />
|-<br />
| 0x17 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#CreateEvent|CreateEvent]](Handle* event, ResetType resettype)<br />
|<br />
|-<br />
| 0x18 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#SignalEvent|SignalEvent]](Handle event)<br />
|<br />
|-<br />
| 0x19 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#ClearEvent|ClearEvent]](Handle event)<br />
|<br />
|-<br />
| 0x1A <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result CreateTimer(Handle* timer, ResetType resettype)<br />
|<br />
|-<br />
| 0x1B <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result SetTimer(Handle timer, s64 initial_nanoseconds, s64 interval)<br />
|<br />
|-<br />
| 0x1C <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result CancelTimer(Handle timer)<br />
|<br />
|-<br />
| 0x1D <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result ClearTimer(Handle timer)<br />
|<br />
|-<br />
| 0x1E <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Memory Management|CreateMemoryBlock]](Handle* memblock, u32 addr, u32 size, [[Memory Management#enum_MemoryPermission|MemoryPermission]] mypermission, [[Memory Management#enum_MemoryPermission|MemoryPermission]] otherpermission)<br />
|<br />
|-<br />
| 0x1F <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Memory Management|MapMemoryBlock]](Handle memblock, u32 addr, [[Memory Management#enum_MemoryPermission|MemoryPermission]] mypermissions, [[Memory Management#enum_MemoryPermission|MemoryPermission]] otherpermission)<br />
|<br />
|-<br />
| 0x20 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Memory Management|UnmapMemoryBlock]](Handle memblock, u32 addr)<br />
|<br />
|-<br />
| 0x21 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#Address_Arbiters|CreateAddressArbiter]](Handle* arbiter)<br />
|<br />
|-<br />
| 0x22 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#Address_Arbiters|ArbitrateAddress]](Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds)<br />
|<br />
|-<br />
| 0x23 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result CloseHandle(Handle handle)<br />
|<br />
|-<br />
| 0x24 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result WaitSynchronization1(Handle handle, s64 timeout_nanoseconds)<br />
|<br />
|-<br />
| 0x25 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result WaitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 timeout_nanoseconds)<br />
|<br />
|-<br />
| 0x26 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SignalAndWait(s32* out, Handle signal, Handle* handles, s32 handleCount, bool waitAll, s64 nanoseconds)<br />
| Stubbed<br />
|-<br />
| 0x27 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result DuplicateHandle(Handle* out, Handle original)<br />
|<br />
|-<br />
| 0x28 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| s64 GetSystemTick(void) (This returns the total CPU ticks elapsed since the CPU was powered-on)<br />
|<br />
|-<br />
| 0x29 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetHandleInfo(s64* out, Handle handle, HandleInfoType type)<br />
|<br />
|-<br />
| 0x2A <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result GetSystemInfo(s64* out, SystemInfoType type, s32 param)<br />
|<br />
|-<br />
| 0x2B <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type)<br />
|<br />
|-<br />
| 0x2C <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#GetThreadInfo|GetThreadInfo]](s64* out, Handle thread, ThreadInfoType type)<br />
|<br />
|-<br />
| 0x2D <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[IPC|ConnectToPort]](Handle* out, const char* portName)<br />
|<br />
|-<br />
| 0x2E <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SendSyncRequest1(Handle session)<br />
| Stubbed<br />
|<br />
|-<br />
| 0x2F <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SendSyncRequest2(Handle session)<br />
| Stubbed<br />
|<br />
|-<br />
| 0x30 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SendSyncRequest3(Handle session)<br />
| Stubbed<br />
|<br />
|-<br />
| 0x31 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SendSyncRequest4(Handle session)<br />
| Stubbed<br />
|<br />
|-<br />
| 0x32 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[IPC|SendSyncRequest]](Handle session)<br />
|<br />
|-<br />
| 0x33 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result OpenProcess(Handle* process, u32 processId)<br />
|<br />
|-<br />
| 0x34 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#OpenThread|OpenThread]](Handle* thread, Handle process, u32 threadId)<br />
|<br />
|-<br />
| 0x35 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: green" | Yes<br />
| Result GetProcessId(u32* processId, Handle process)<br />
|<br />
|-<br />
| 0x36 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#GetProcessIdOfThread|GetProcessIdOfThread]](u32* processId, Handle thread)<br />
|<br />
|-<br />
| 0x37 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Multi-threading#GetThreadId|GetThreadId]](u32* threadId, Handle thread)<br />
|<br />
|-<br />
| 0x38 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetResourceLimit(Handle* resourceLimit, Handle process)<br />
|<br />
|-<br />
| 0x39 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetResourceLimitLimitValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount)<br />
|<br />
|-<br />
| 0x3A <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetResourceLimitCurrentValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount)<br />
|<br />
|-<br />
| 0x3B <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#GetThreadContext|GetThreadContext]](ThreadContext* context, Handle thread)<br />
| Stubbed<br />
|-<br />
| 0x3C <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Break(BreakReason reason)<br />
Break(BreakReason debugReason, const void* croInfo, u32 croInfoSize)<br />
|<br />
|-<br />
| 0x3D <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| OutputDebugString(void const, int)<br />
| Does nothing on non-debug units.<br />
|-<br />
| 0x3E <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| ControlPerformanceCounter(unsigned long long, int, unsigned int, unsigned long long)<br />
|<br />
|- style="border-top: double"<br />
| 0x47 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[IPC|CreatePort]](Handle* portServer, Handle* portClient, const char* name, s16 maxSessions)<br />
| Setting name=NULL creates a private port not accessible from svcConnectToPort.<br />
|-<br />
| 0x48 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[IPC|CreateSessionToPort]](Handle* session, Handle port)<br />
|<br />
|-<br />
| 0x49 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[IPC|CreateSession]](Handle* sessionServer, Handle* sessionClient)<br />
|<br />
|-<br />
| 0x4A <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[IPC|AcceptSession]](Handle* session, Handle port)<br />
|<br />
|-<br />
| 0x4B <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result ReplyAndReceive1(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)<br />
| Stubbed.<br />
|-<br />
| 0x4C <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result ReplyAndReceive2(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)<br />
| Stubbed.<br />
|-<br />
| 0x4D <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result ReplyAndReceive3(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)<br />
| Stubbed.<br />
|-<br />
| 0x4E <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result ReplyAndReceive4(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)<br />
| Stubbed.<br />
|-<br />
| 0x4F <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[IPC#svcReplyAndReceive|ReplyAndReceive]](s32* index, Handle* handles, s32 handleCount, Handle replyTarget)<br />
|<br />
|-<br />
| 0x50 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[#Interrupt Handling|BindInterrupt]](Interrupt name, Handle eventOrSemaphore, s32 priority, bool isLevelHighActive)<br />
|<br />
|-<br />
| 0x51 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result UnbindInterrupt(Interrupt name, Handle eventOrSemaphore)<br />
|<br />
|-<br />
| 0x52 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result InvalidateProcessDataCache(Handle process, void* addr, u32 size)<br />
|<br />
|-<br />
| 0x53 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result StoreProcessDataCache(Handle process, void const* addr, u32 size)<br />
|<br />
|-<br />
| 0x54 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result FlushProcessDataCache(Handle process, void const* addr, u32 size)<br />
|<br />
|-<br />
| 0x55 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result [[Corelink DMA Engines|StartInterProcessDma]](Handle* dma, Handle dstProcess, void* dst, Handle srcProcess, const void* src, u32 size, const DmaConfig* config)<br />
|<br />
|-<br />
| 0x56 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result StopDma(Handle dma)<br />
|<br />
|-<br />
| 0x57 <br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Result GetDmaState(DmaState* state, Handle dma)<br />
|<br />
|-<br />
| 0x58<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| RestartDma(Handle, void *, void const*, unsigned int, signed char)<br />
|<br />
|-<br />
| 0x59<br />
| style="background: green" | Yes<br />
| style="background: red" | No?<br />
| style="background: red" | No<br />
| SetGpuProt(s8 input_flag). Implemented with [[11.3.0-36|11.3.0-X]], see below.<br />
|-<br />
| 0x5A<br />
| style="background: green" | Yes<br />
| style="background: red" | No?<br />
| style="background: red" | No<br />
| SetWifiEnabled(s0 input_flag). Implemented with [[11.4.0-37|11.4.0-X]], see below.<br />
|- style="border-top: double"<br />
| 0x60 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result DebugActiveProcess(Handle* debug, u32 processID)<br />
|<br />
|-<br />
| 0x61 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result BreakDebugProcess(Handle debug)<br />
|<br />
|-<br />
| 0x62 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result TerminateDebugProcess(Handle debug)<br />
|<br />
|-<br />
| 0x63 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetProcessDebugEvent(DebugEventInfo* info, Handle debug)<br />
|<br />
|-<br />
| 0x64 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result ContinueDebugEvent(Handle debug, u32 flags)<br />
|<br />
|-<br />
| 0x65 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount)<br />
|<br />
|-<br />
| 0x66 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetThreadList(s32* threadCount, u32* threadIds, s32 threadIdMaxCount, Handle domain)<br />
|<br />
|-<br />
| 0x67 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result GetDebugThreadContext(ThreadContext* context, Handle debug, u32 threadId, u32 controlFlags)<br />
|<br />
|-<br />
| 0x68 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SetDebugThreadContext(Handle debug, u32 threadId, const ThreadContext* context, u32 controlFlags)<br />
|<br />
|-<br />
| 0x69 <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result QueryDebugProcessMemory(MemoryInfo* blockInfo, PageInfo* pageInfo, Handle debug, u32 addr)<br />
|<br />
|-<br />
| 0x6A <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result ReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size)<br />
|<br />
|-<br />
| 0x6B <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result WriteProcessMemory(Handle debug, void const* buffer, u32 addr, u32 size)<br />
|<br />
|-<br />
| 0x6C <br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SetHardwareBreakPoint(s32 registerId, u32 control, u32 value)<br />
|<br />
|-<br />
| 0x6D<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| [[Multi-threading#GetDebugThreadParam|GetDebugThreadParam]](s64* unused, u32* out, Handle kdebug, u32 threadId, DebugThreadParameter param)<br />
| <br />
|- style="border-top: double"<br />
| 0x70<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result ControlProcessMemory(Handle KProcess, unsigned int Addr0, unsigned int Addr1, unsigned int Size, unsigned int Type, unsigned int Permissions)<br />
|<br />
|-<br />
| 0x71<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Memory Management#Memory_Mapping|MapProcessMemory]](Handle process, u32 startAddr, u32 size)<br />
|<br />
|-<br />
| 0x72<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Memory Management#Memory_Mapping|UnmapProcessMemory]](Handle process, u32 startAddr, u32 size)<br />
|<br />
|-<br />
| 0x73<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#CreateCodeSet|CreateCodeSet]](Handle* handle_out, struct CodeSetInfo, u32 code_ptr, u32 ro_ptr, u32 data_ptr)<br />
|<br />
|-<br />
| 0x74<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result RandomStub()<br />
| Stubbed<br />
|-<br />
| 0x75<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result [[Multi-threading#CreateProcess|CreateProcess]](Handle* handle_out, Handle codeset_handle, u32 [[NCCH/Extended_Header#ARM11_Kernel_Capabilities|arm11kernelcaps_ptr]], u32 arm11kernelcaps_num)<br />
|<br />
|-<br />
| 0x76<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| TerminateProcess(Handle)<br />
|<br />
|-<br />
| 0x77<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SetProcessResourceLimits(Handle KProcess, Handle KResourceLimit)<br />
| <br />
|-<br />
| 0x78<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result CreateResourceLimit(Handle *KResourceLimit)<br />
|<br />
|-<br />
| 0x79<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result SetResourceLimitValues(Handle res_limit, LimitableResource* resource_type_list, s64* resource_list, u32 count)<br />
|<br />
|-<br />
| 0x7A<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: green" | Yes<br />
| AddCodeSegment (unsigned int Addr, unsigned int Size)<br />
| Stubbed on NATIVE_FIRM beginning with [[2.0.0-2]]. Used during TWL_FIRM boot.<br />
|-<br />
| 0x7B<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| Backdoor(unsigned int CodeAddress)<br />
| This is used on ARM9 NATIVE_FIRM. <br />
No ARM11 processes have access to it without some form of kernelhax, and this was removed on [[11.0.0-33]] (for ARM11).<br />
<br />
|-<br />
| 0x7C<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| KernelSetState(unsigned int Type, ...)<br />
| The type determines the args to be passed<br />
|-<br />
| 0x7D<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result QueryProcessMemory(MemInfo *Info, unsigned int *Out, Handle KProcess, unsigned int Addr)<br />
|<br />
|- style="border-top: double"<br />
| 0xFF<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| Stop point<br />
| The svcaccesscontrol mask doesn't apply for this SVC. This svc doesn't check the "debug mode enabled" flag either. Does nothing if there is no [[KDebug]] object associated to the current process. Stubbed on ARM9 NATIVE_FIRM.<br />
|}<br />
NF: NATIVE_FIRM. TF: TWL_FIRM.<br />
<br />
Note that "stubbed" here means that the SVC only returns an error, as in the following snippet:<br />
<br />
<pre>ROM:FFF04D98 LDR R0, =0xF8C007F4<br />
ROM:FFF04D9C BX LR</pre><br />
<br />
= Types and structures =<br />
<br />
== enum ResetType ==<br />
<br />
{| class="wikitable" border="1"<br />
! Reset type<br />
! Id<br />
|-<br />
| ONESHOT<br />
| 0<br />
|-<br />
| STICKY<br />
| 1<br />
|-<br />
| PULSE<br />
| 2<br />
|}<br />
<br />
Timers/Events may be waited on by a thread using svcWaitSynchronization. Once the timer runs out/the event gets signaled, threads waiting on the respective handles until the timer/event is reset. STICKY timers/events wake up threads until they are explicitly reset by some thread. ONESHOT timers/events will wake up exactly one thread and then are reset automatically. PULSE timers will be reset after waking up one thread too, but will also be started again immediately. It's unknown whether PULSE is a valid reset type for events.<br />
<br />
== struct StartupInfo ==<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| s32<br />
| Priority<br />
|-<br />
| u32<br />
| Stack size<br />
|-<br />
| s32<br />
| argc<br />
|-<br />
| s16*<br />
| argv<br />
|-<br />
| s16*<br />
| envp<br />
|}<br />
<br />
== enum BreakReason ==<br />
{| class="wikitable" border="1"<br />
! Break Reason<br />
! Value<br />
|-<br />
| PANIC<br />
| 0<br />
|-<br />
| ASSERT<br />
| 1<br />
|-<br />
| USER<br />
| 2<br />
|}<br />
<br />
== struct DebugEventInfo ==<br />
Size: 0x28 bytes<br />
<br />
When using svcGetProcessDebugEvent, the kernel fetches the first [[KEventInfo]] instance of the process's [[KDebug]]. The debug event is handled and parsed into this structure.<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Event type<br />
|-<br />
| u32<br />
| Thread ID (not used in all events)<br />
|-<br />
| u32<br />
| Flags. Bit0 means that svcContinueDebugEvent needs to be called for this event<br />
|-<br />
| u8[4]<br />
| Remnants of the corresponding flags in [[KEventInfo]], always 0 here<br />
|-<br />
| u32[6]<br />
| Event-specific data (see below)<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Event type<br />
! Id<br />
|-<br />
| ATTACH PROCESS<br />
| 0<br />
|-<br />
| ATTACH THREAD<br />
| 1<br />
|-<br />
| EXIT THREAD<br />
| 2<br />
|-<br />
| EXIT PROCESS (1)<br />
| 3<br />
|-<br />
| EXCEPTION<br />
| 4<br />
|-<br />
| DLL LOAD (3)<br />
| 5<br />
|-<br />
| DLL UNLOAD (3)<br />
| 6<br />
|-<br />
| SCHEDULE IN (1) (2)<br />
| 7<br />
|-<br />
| SCHEDULE OUT (1) (2)<br />
| 8<br />
|-<br />
| SYSCALL IN (1) (2)<br />
| 9<br />
|-<br />
| SYSCALL OUT (1) (2)<br />
| 10<br />
|-<br />
| OUTPUT STRING<br />
| 11<br />
|-<br />
| MAP (1) (2)<br />
| 12<br />
|}<br />
<br />
<nowiki>(1)</nowiki> Non-blocking: all other events preempt and block all the threads of their process until they are continued.<br />
<br />
<nowiki>(2)</nowiki> There is handling code in the kernel but nothing signal those events.<br />
<br />
<nowiki>(3)</nowiki> Completely removed from the kernel, but referenced in DMNT. Stubbed relocation code (e.g., in Process9 and in PXI sysmodule) and even whole libraries (e.g., in PXI sysmodule's .rodata section) seem to indicate that Nintendo used dynamic libraries early in system development. <br />
<br />
When calling svcDebugActiveProcess, an ATTACH PROCESS debug event is signaled, then ATTACH THREAD for each of its opened threads, then finally ATTACH BREAK.<br />
<br />
ATTACH THREAD events are also emitted when a thread is created from an attached process.<br />
<br />
=== ATTACH PROCESS event ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u64<br />
| Program ID<br />
|-<br />
| char[8]<br />
| Process name<br />
|-<br />
| u32<br />
| Process ID<br />
|-<br />
| u32<br />
| "Other" flag. Always 0 in available kernel versions<br />
|}<br />
<br />
=== ATTACH THREAD event ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Creator thread ID (0 if attached by svcDebugActiveProcess)<br />
|-<br />
| void *<br />
| Thread local storage<br />
|-<br />
| u32 *<br />
| Entrypoint = .text load address of the parent process<br />
|}<br />
<br />
=== EXIT THREAD/PROCESS events ===<br />
<br />
A single u32 reason field is used.<br />
<br />
Thread exit reasons:<br />
{| class="wikitable" border="1"<br />
! Reason<br />
! Id<br />
|-<br />
| (None)<br />
| 0<br />
|-<br />
| TERMINATE<br />
| 1<br />
|-<br />
| EXIT PROCESS<br />
| 2<br />
|-<br />
| TERMINATE PROCESS<br />
| 3<br />
|}<br />
<br />
Process exit reasons:<br />
{| class="wikitable" border="1"<br />
! Reason<br />
! Id<br />
|-<br />
| (None)<br />
| 0<br />
|-<br />
| TERMINATE<br />
| 1<br />
|-<br />
| DEBUG TERMINATE<br />
| 2<br />
|}<br />
<br />
=== EXCEPTION event ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Exception type<br />
|-<br />
| u32<br />
| Exception address<br />
|-<br />
| u32[4]<br />
| Type-specific data, see below<br />
|}<br />
<br />
Exception types:<br />
{| class="wikitable" border="1"<br />
! Exception type<br />
! Id<br />
|-<br />
| UNDEFINED INSTRUCTION<br />
| 0<br />
|-<br />
| PREFETCH ABORT<br />
| 1<br />
|-<br />
| DATA ABORT<br />
| 2<br />
|-<br />
| UNALIGNED DATA ACCESS<br />
| 3<br />
|-<br />
| ATTACH BREAK<br />
| 4<br />
|-<br />
| STOP POINT<br />
| 5<br />
|-<br />
| USER BREAK<br />
| 6<br />
|-<br />
| DEBUGGER BREAK<br />
| 7<br />
|-<br />
| UNDEFINED SYSCALL<br />
| 8<br />
|}<br />
<br />
==== UNDEFINED INSTRUCTION/PREFETCH ABORT/DATA ABORT/UNALIGNED DATA ACCESS/UNDEFINED SYSCALL events ====<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Fault information: Fault Address Register (for DATA ABORT and UNALIGNED DATA ACCESS),<br />
attempted SVC ID (for UNDEFINED SYSCALL), otherwise 0<br />
|}<br />
<br />
==== STOP POINT event ====<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Stop point type that caused the event: 0 = svc 0xFF, 1 = breakpoint, 2 = watchpoint<br />
|-<br />
| u32<br />
| Fault information: FAR for watchpoints, 0 otherwise<br />
|}<br />
<br />
==== USER BREAK event ====<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Break reason<br />
|-<br />
| u32[2]<br />
| Info for LOAD_RO and UNLOAD_RO<br />
|}<br />
<br />
User break types:<br />
{| class="wikitable" border="1"<br />
! Reason<br />
! Id<br />
|-<br />
| PANIC<br />
| 0<br />
|-<br />
| ASSERT<br />
| 1<br />
|-<br />
| USER<br />
| 2<br />
|-<br />
| LOAD_RO<br />
| 3<br />
|-<br />
| UNLOAD_RO<br />
| 4<br />
|}<br />
<br />
==== DEBUGGER BREAK event ====<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| s32[4]<br />
| IDs of the attached process's threads that were running on each core at the time of the @ref svcBreakDebugProcess call, or -1 (only the first 2 values are meaningful on O3DS).<br />
|}<br />
<br />
=== SCHEDULE/SYSCALL IN/OUT events ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u64<br />
| Clock tick<br />
|-<br />
| u32<br />
| CPU ID (SCHEDULE events) Syscall (SYSCALL events)<br />
|}<br />
<br />
=== OUTPUT STRING event ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| String address<br />
|-<br />
| u32<br />
| String size<br />
|}<br />
<br />
=== MAP event ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Mapped address<br />
|-<br />
| u32<br />
| Mapped size<br />
|-<br />
| u32<br />
| MemoryPermission<br />
|-<br />
| u32<br />
| MemoryState<br />
|}<br />
<br />
== struct ThreadContext ==<br />
<br />
Size: 0xCC bytes<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| CpuRegisters<br />
| Saved CPU registers (r0-r12, sp, lr, pc, cpsr)<br />
|-<br />
| 0x44<br />
| FpuRegisters<br />
| Saved FPU registers (d0-d15, fpscr, fpexc)<br />
|}<br />
<br />
The user needs to adjust pc for exceptions that occured while in Thumb mode.<br />
<br />
'''Flags for svcGetDebugThreadContext/svcSetDebugThreadContext''':<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Get/set CPU GPRs (r0-r12)<br />
|-<br />
| 1<br />
| Get/set CPU SPRs (sp, lr, pc, cpsr)<br />
|-<br />
| 2<br />
| Get/set FPU GPRs (d0-d15 aka. f0-f31)<br />
|-<br />
| 3<br />
| Get/set FPU SPRs (fpscr, fpexc)<br />
|}<br />
<br />
When setting CPSR, the following assignment is done: <code>ctx->cpsr = ctx->cpsr & 0x7F0FDFF | userCtx->cpuRegisters.cpsr & 0xF80F0200;</code>. This is to avoid obvious security issues.<br />
<br />
== enum DebugThreadParameter ==<br />
<br />
{| class="wikitable" border="1"<br />
! Parameter<br />
! Id<br />
|-<br />
| PRIORITY<br />
| 0<br />
|-<br />
| SCHEDULING_MASK_LOW<br />
| 1<br />
|-<br />
| CPU_IDEAL<br />
| 2<br />
|-<br />
| CPU_CREATOR<br />
| 3<br />
|}<br />
<br />
== typedef Handle ==<br />
<br />
User-visible references to internal objects are represented by 32-bit integers called handles. Handles are only valid in the process they have been created in; hence, they cannot be exchanged between processes directly (the [[IPC]] functions provide a mean to copy handles to other processes, though).<br />
<br />
There are a number of special-purpose handles, which provide easy access to information on objects in the current process:<br />
{| class="wikitable" border="1"<br />
! Handle<br />
! Description<br />
|-<br />
| 0xFFFF8000<br />
| Handle to the active thread<br />
|-<br />
| 0xFFFF8001<br />
| Handle to the active process<br />
|}<br />
<br />
=svcSetHardwareBreakPoint=<br />
This is essentially an interface for writing values to the debug-unit (B/W)RP registers. registerId range 0..5 = breakpoints(BRP0-5), 0x100..0x101 = watchpoints(WRP0-1), anything outside of these ranges will result in an error. This is used for both adding and removing/disabling breakpoints/watchpoints, hence the raw control value parameter.<br />
<br />
Here the kernel sets bit15 in the DSCR, to enable monitor-mode debugging.<br />
<br />
Regardless of whether this is for a BRP, when bit21 is set in the control input parameter(BRP type = contextID), the kernel will load the target process [[KProcess|contextID]] and use that internally for the value field. The target process is specified via a [[KDebug]] handle passed as the "value" parameter.<br />
<br />
Lastly, the kernel disables the specified (B/W)RP, then writes the value parameter / loaded contextID to the (B/W)VR, then writes the input control value to the (B/W)CR.<br />
<br />
= [[DMA]] =<br />
The CTRSDK code for using svcStartInterProcessDma will execute svcBreak when svcStartInterProcessDma returns an error(except for certain error value(s)). Therefore on retail, triggering a svcStartInterProcessDma via a system-module which results in an error from svcStartInterProcessDma will result in the system-module terminating.<br />
<br />
= Interrupt Handling =<br />
<br />
svcBindInterrupt registers the given event or semaphore corresponding to the handle to the global [[ARM11_Interrupts#Interrupt_Table_.28New3DS.29|"interrupt table"]] for the given interrupt ID. Interrupts 0-14 and 16-31 can never be mapped regardless of the [[NCCH/Extended_Header#ARM11_Kernel_Capabilities|interrupt flags of the process's exheader]], and the latter are not checked when mapping interrupt 15. The "is level high active"/"is manual clear" parameter must be false when binding a semaphore handle (otherwise 0xD8E007EE "invalid combination" is returned).<br />
<br />
If something was already registered for the given ID, svcBindInterrupt returns error 0xD8E007F0. See [[KBaseInterruptEvent]] for more information on what happens on receipt of an interrupt.<br />
<br />
Applications hence can wait for specific interrupts to happen by calling WaitSynchronization(N) on the event or semaphore handles.<br />
<br />
The set of existing ARM11 interrupts is listed on [[ARM11 Interrupts|this page]].<br />
<br />
= Debugging =<br />
DebugActiveProcess is used to attach to a process for debugging. This SVC can only be used when the target process' ARM11 descriptors stored in the exheader have the kernel flag for "Enable debug" set. Otherwise when that flag is clear, the kernel flags for the process using this SVC must have the "Force debug" flag set.<br />
<br />
This SVC can only be used when a certain kernel state debug flag is non-zero(it's set to zero for retail).<br />
<br />
= KernelSetState =<br />
KernelSetState uses the 6th [[ARM11_Interrupts#Private_Interrupts|software-generated interrupt]] for any operation involving synchronization between cores.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Type<br />
! Enabled for the NATIVE_FIRM ARM11 kernel<br />
! Enabled for the TWL_FIRM ARM11 kernel<br />
! Description<br />
|-<br />
| 0<br />
| Yes<br />
| No<br />
| Arguments : <code>u64 firmTitleID</code> (the high 32-bits of that title ID (0 when using N3DS pm) have a special meaning on N3DS, they're otherwise ignored, see below).<br />
This initializes the programID for launching [[FIRM]], then triggers launching [[FIRM]]. With New3DS kernel, it forces the firm title ID to be the New3DS NATIVE_FIRM, when the input firm title ID is 2. The high firm title ID is always set to 0x40138. On New3DS, the kernel disables the additional New3DS cache hw prior to calling the firmlaunch function from the <handler for the KernelSetState-types called via funcptr>.<br />
|-<br />
| 1<br />
| Yes<br />
| Yes<br />
| Does nothing.<br />
|-<br />
| 2<br />
| Yes<br />
| Yes<br />
| Powers down the GPU and syncs with Process9 (waits for <code>*(vu8 *)PXI_SYNC11</code> to be 1) during the process.<br />
On New3DS, the kernel disables the additional New3DS cache hw, when it's actually enabled, prior to executing the rest of the code from the <handler for the KernelSetState-types called via funcptr>.<br />
|-<br />
| 3<br />
| Yes<br />
| No<br />
| Arguments: <code>0, void* address</code> or <code>1</code><br />
This used for initializing the 0x1000-byte buffer used by the launched [[FIRM]]. When the first parameter is 1, this buffer is copied to the beginning of FCRAM at 0xE0000000. When it is 0, this kernel buffer is mapped to the process address specified by the second argument.<br />
|-<br />
| 4<br />
| No<br />
| Yes<br />
| This unmaps(?) the following virtual memory by writing value physaddr (where physaddr base is 0x80000000) to the L1 MMU table entries: 0x00300000..0x04300000, 0x08000000..0x0FE00000, and 0x10000000..0xF8000000.<br />
|-<br />
| 5<br />
| Yes<br />
| Yes<br />
| Used by kernelpanic. This makes core0 enter a WFI/B infinite loop. Threads that were created on core1 or core2 have their priority set to 0x3F, except if the thread was created on core1 and whose parent process (if any) has the "Runnable on sleep" [[NCCH/Extended_Header#ARM11_Kernel_Flags|ARM11 kernel flag]] set. Core1 threads with a priority of 0x40 without a parent process have their priority set to 0x3E.<br />
<br />
Prior to first invoking this handler, the global variable holding <code>UNITINFO != 0</code> is true, and if there is no [[LCD_Registers#Fill_Color|LCD fill]] set at the time kernelpanic is called, kernelpanic fills the top screen with red and the bottom screen with either yellow (if the current process was running under the APPLICATION memregion) or red. <br />
<br />
Before invoking this handler a second time, kernelpanic wait for the user to hold L+R+Start+Select down.<br />
|-<br />
| 6<br />
| Yes<br />
| No<br />
| Arguments: <code>u32 what, u64 val</code><br />
UNITINFO needs to be non-zero for <code>what</code> 1 and 2. <br />
<br />
If <code>what</code> is 0 or any invalid value, nothing is done. <br />
<br />
If it is 1, <code>val != 0</code> is written to the global variable enabling ERR:F-format register dumps on user-mode CPU/VFP exceptions (the VFP exception handler acts as if this variable was always true and works on retail environments). The user handler, stack pointer to use for exception handling, and pointer to use for the exception info structure are contiguously located in either the thread's TLS, or if the handler is NULL, in the main thread's TLS, at offset 0x40. If the specified stack pointer is 1, sp_usr - 0x5c is used instead; if the specified exception info buffer is 1, sp_usr - 0x5c is used instead, and if it is 0, <specified stack> - 0x5c is used (0x5c is the size of the exception info structure that is being pushed). Configured by NS on startup on dev-units (default being 0 on non-debugger/jtag units) using the 0x000F0000 configuration block in the [[Config_Savegame|config savegame]].<br />
<br />
If 2, kernelpanic will be called when svcBreak is used by a non-attached process. Configured by NS on startup on dev-units (default being 0 on non-debugger/jtag units) using the 0x000F0000 configuration block in the [[Config_Savegame|config savegame]].<br />
<br />
If 3, this changes the scheduling/preemption mode (when no threads are being preempted, otherwise returns error 0xC8A01414), see [[KResourceLimit]] for more details.<br />
|-<br />
| 7<br />
| Yes<br />
| No<br />
| This triggers an MCU (hard) reboot. This reboot is triggered via device address 0x4A on the second [[I2C]] bus (the MCU). Register address 0x20 is written to with value 4. This code will not return.<br />
On New3DS, the kernel disables the additional New3DS cache hw prior to calling the reboot function from the <handler for the KernelSetState-types called via funcptr>.<br />
|-<br />
| 8<br />
| Yes<br />
| No<br />
| Alternate FIRM launch code-path, with different [[PXI]] FIFO word constants. Usually not used. PTM-sysmodule can use this but it's unknown what exactly triggers that in PTM-sysmodule.<br />
|-<br />
| 9<br />
| Yes, implemented at some point after system-version v4.5.<br />
| ?<br />
| Argumens: <code>u64 titleID</code>.<br />
When creating a process, if the process has a non-zero TID equal to the parameter above (which is stored in a global variable), then KProcessHwInfo+0x32 ("process is the currently running app") is set to <code>true</code>.<br />
Used by NS conditionally based on the contents of the [[NS CFA]].<br />
|-<br />
| 10<br />
| Yes<br />
| ?<br />
| Arguments: <code>u32 config</code><br />
ConfigureNew3DSCPU. Only available for the [[New_3DS]] kernel. The actual code for processing this runs under the <handler for the KernelSetState-types called via funcptr>, which runs on all ARM11 cores. Only bit0-1 of the argument are used here. Bit 0 enables higher core clock, and bit 1 enables additional (L2) cache. This configures the hardware [[PDN_Registers|register]] for the flags listed [[NCCH/Extended_Header#Flag1|here]], among other code which uses the MPCore private memory region registers.<br />
|}<br />
<br />
= GetSystemInfo =<br />
{| class="wikitable" border="1"<br />
! SystemInfoType value<br />
! s32 param<br />
! Description<br />
|-<br />
| 0<br />
| 0<br />
| This writes the total used memory size in the following memory regions to out: APPLICATION, SYSTEM, and BASE.<br />
|-<br />
| 0<br />
| 1<br />
| This writes the total used memory size in the APPLICATION memory region to out.<br />
|-<br />
| 0<br />
| 2<br />
| This writes the total used memory size in the SYSTEM memory region to out.<br />
|-<br />
| 0<br />
| 3<br />
| This writes the total used memory size in the BASE memory region to out.<br />
|-<br />
| 2<br />
| Unused<br />
| This writes the FCRAM memory [[Memory_Allocation#FCRAM_Region_Data|used by the kernel]] to out.<br />
|-<br />
| 25<br />
| Unused<br />
| This writes the total number of threads which were directly launched by the kernel, to out. No longer exists with some kernel version?<br />
|-<br />
| 26<br />
| Unused<br />
| This writes the total number of processes which were directly launched by the kernel, to out. For the NATIVE_FIRM/SAFE_MODE_FIRM ARM11 kernel, this is normally 5, for processes sm, fs, pm, loader, and pxi.<br />
|}<br />
<br />
= GetProcessInfo =<br />
Input:<br />
R0 = unused<br />
R1 = Handle process<br />
R2 = ProcessInfoType type<br />
<br />
Output:<br />
R0 = Result<br />
R1 = output value lower word<br />
R2 = output value upper word<br />
<br />
{| class="wikitable" border="1"<br />
! ProcessInfoType value<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0<br />
| <br />
| Returns the amount of executable memory allocated to the process + thread context size + page-rounded size of the external handle table<br />
|-<br />
| 1<br />
| <br />
| Returns the amount of <unknown> memory allocated to the process + thread context size + page-rounded size of the external handle table<br />
|-<br />
| 2<br />
| <br />
| Returns the amount of DMA-able (code, data, IO pages, etc.) memory allocated to the process + thread context size + page-rounded size of the external handle table<br />
|-<br />
| 3<br />
| <br />
| Returns the amount of <unknown> memory allocated to the process + thread context size + page-rounded size of the external handle table<br />
|-<br />
| 4<br />
| <br />
| Returns the amount handles in use by the process.<br />
|-<br />
| 5<br />
| <br />
| Returns the highest count of handles that have been open at once by the process<br />
|-<br />
| 6<br />
| <br />
| Returns <code>*(u32*)(KProcess+0x234)</code> which is always 0<br />
|-<br />
| 7<br />
| <br />
| Returns the number of threads of the process<br />
|-<br />
| 8<br />
| <br />
| Returns the maximum number of threads which can be opened by this process (always 0)<br />
|-<br />
| 9-18<br />
| [[8.0.0-18]]<br />
| This only returns error 0xD8E007ED.<br />
|-<br />
| 19<br />
| Stub: [[8.0.0-18]]. Implementation: [[11.3.0-36|11.3.0-X]].<br />
| Originally this only returned 0xD8E007ED. Now with v11.3 this returns the memregion for the process: out low u32 = [[KProcess]] "Kernel flags from the exheader kernel descriptors" & 0xF00. High out u32 = 0.<br />
|-<br />
| 20<br />
| [[8.0.0-18]]<br />
| low u32 = (0x20000000 - <LINEAR virtual-memory base for this process>). That is, the output value is the value which can be added to LINEAR memory vaddrs for converting to physical-memory addrs.<br />
|-<br />
| 21<br />
| [[8.0.0-18]]. N3DS only.<br />
| Returns the maximum amount of VRAM memory allocatable by the process: 0x800000 bytes if the process has already allocated VRAM memory, otherwise 0 (+ error 0xE0E01BF4)<br />
|-<br />
| 22<br />
| [[8.0.0-18]]. N3DS only.<br />
| Returns the address of the first chunk of VRAM allocated by this process<br />
|-<br />
| 23<br />
| [[8.0.0-18]]. N3DS only.<br />
| Returns the amount of VRAM allocated by this process (?)<br />
|}<br />
<br />
= GetHandleInfo =<br />
<br />
{| class="wikitable" border="1"<br />
! HandleInfoType value<br />
! Description<br />
|-<br />
| 0<br />
| This returns the time in ticks the KProcess referenced by the handle was created. If a KProcess handle was not given, it will write whatever was in r5, r6 when the svc was called.<br />
|-<br />
| 1<br />
| Get internal refcount for kernel object (not counting the one this SVC adds internally to operate), sign-extended to 64 bits.<br />
|-<br />
| 2<br />
| Unimplemented, returns an uninitialized u64 variable (corresponding to r5-r6, which were not altered outside of userland).<br />
|-<br />
| 0x32107<br />
| Returns (u64) 0.<br />
|}<br />
<br />
= svc7B Backdoor =<br />
This saves SVC-mode SP+LR on the user-mode stack, then sets the SVC-mode SP to the user-mode SP. This then calls the specified code in SVC-mode. Once the called code returns, this pops the saved SP+LR off the stack for restoring the SVC-mode SP, then returns from the svc7b handler. Note that this svc7b handler does not disable IRQs, if any IRQs/context-switches occur while the SVC-mode SP is set to the user-mode one here, the ARM11-kernel will crash(which hangs the whole ARM11-side system).<br />
<br />
= svc 0x59 =<br />
Implemented with [[11.3.0-36|11.3.0-X]]. Used with GSP module starting with that version. This always returns 0.<br />
<br />
When input_flag is not 0x1, it will use value 0x0 internally. When a state field already matches input_flag, this will immediately return. Otherwise, after this SVC finishes running, it will write input_flag to this state field. GSP module uses 0x0 for APPLICATION-memregionid and 0x1 for non-APPLICATION-memregionid.<br />
<br />
This writes "<nowiki>0x100 | <val></nowiki>" to [[CONFIG11_Registers#CFG11_GPUPROT|pdnregbase+0x140]], where val depends on input_flag and a kernel state field for [[Configuration_Memory|APPMEMTYPE]].<br />
<br />
When input_flag is 0x1 val is fixed:<br />
* Old3DS: 0x3<br />
* New3DS: 0x460<br />
<br />
Otherwise, val depends on the kernel APPMEMTYPE state field:<br />
{| class="wikitable" border="1"<br />
|-<br />
! FIRM<br />
! [[Memory_layout|APPMEMTYPE]]<br />
! val<br />
|-<br />
| Old3DS<br />
| 2<br />
| 0x3<br />
|-<br />
| Old3DS<br />
| 3<br />
| 0x5<br />
|-<br />
| Old3DS<br />
| 4<br />
| 0x6<br />
|-<br />
| Old3DS<br />
| Non-value-{2/3/4}<br />
| 0x7<br />
|-<br />
| New3DS<br />
| 7<br />
| 0x490<br />
|-<br />
| New3DS<br />
| Non-value-7<br />
| 0x4F0<br />
|}<br />
<br />
This same register is also initialized during kernel boot starting with [[3.0.0-5]], with the following values:<br />
* Old3DS: 0x103<br />
* New3DS: 0x550<br />
<br />
= svc 0x5A =<br />
Like what NWM did previously, this one does the following:<br />
<br />
if (in_flag)<br />
CFG11_WIFICNT |= 1;<br />
else<br />
CFG11_WIFICNT &= ~1;<br />
<br />
= Kernel error-codes =<br />
See [[Error codes]].<br />
<br />
{| class="wikitable" border="1"<br />
! Error-code value<br />
! Description<br />
|-<br />
| 0x09401BFE<br />
| Timeout occurred with svcWaitSynchronization*, when timeout is not ~0.<br />
|-<br />
| 0xC8601801<br />
| No more unused/free synchronization objects left to use in a given object's linked list. (KEvent, KMutex, KTimer, KSemaphore, KAddressArbiter, KThread)<br />
|-<br />
| 0xC8601802<br />
| No more unused/free KSharedMemory objects left to use in the KSharedMemory linked list - out of blocks<br />
|-<br />
| 0xC8601809<br />
| No more unused/free KSessions left to use in the KSession linked list - out of sessions<br />
|-<br />
| 0xC860180A<br />
| Not enough free memory available for memory allocation.<br />
|-<br />
| 0xC920181A<br />
| The session was closed by the other process..<br />
|-<br />
| 0xD0401834<br />
| Max connections to port have been exceeded<br />
|-<br />
| 0xD8609013<br />
| Unknown, probably reslimit related?<br />
|-<br />
| 0xD88007FA<br />
| Returned if no KObjectName object in the linked list of such objects matches the port name provided to the svc. <br />
|-<br />
| 0xD8E007ED<br />
| This indicates that a value is outside of the enum being used.<br />
|-<br />
| 0xD8E007F1<br />
| This error indicates Misaligned address.<br />
|-<br />
| 0xD8E007F7<br />
| This error indicates that the input handle used with the SVC does not exist in the process handle-table, or that the handle kernel object type does not match the type used by the SVC.<br />
|-<br />
| 0xD9000402<br />
| Invalid memory permissions for input/output buffers, for svcStartInterProcessDma.<br />
|-<br />
| 0xD9001814<br />
| Failed unprivileged load or store - wrong permissions on memory<br />
|-<br />
| 0xD9001BF7<br />
| This error is returned when the kernel retrieves a pointer to a kernel object, but the object type doesn't match the desired one.<br />
|-<br />
| 0xD92007EA<br />
| This error is returned when a process attempts to use svcCreateMemoryBlock when the process memorytype is the application memorytype, and when addr=0.<br />
|-<br />
| 0xE0E01BF5<br />
| This indicates an invalid address was used.<br />
|-<br />
| 0xF8C007F4<br />
| Invalid type/param0-param3 input for svcKernelSetState. This is also returned for those syscalls marked as stubs.<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=APT:NotifyToWait&diff=20181APT:NotifyToWait2017-07-21T18:30:38Z<p>Subv: /* Response */</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x00430040]<br />
|-<br />
| 1<br />
| [[NS_and_APT_Services#AppIDs|AppID]]<br />
|}<br />
<br />
=Response=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code<br />
|-<br />
| 1<br />
| Result code<br />
|}<br />
<br />
=Description=<br />
This function is a stub in the NS module. It does nothing and always returns 0.</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20175NWM Services2017-07-17T13:56:05Z<p>Subv: /* Data frames */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
[There does not appear to be an association request frame sent by the client to the server, it is however possible that it was sent and just not captured by the test equipment]<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is connected to the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 ([[NWM_Services#EAPoL-Start frame|EAPoL-Start]])<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202([[NWM_Services#EAPoL-Logoff frame|EAPoL-Logoff]])<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D ([[NWM_Services#SecureData NWM header|SecureData]])]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
Application data packets are sent to the host using 802.11 unicast, which then acts as a router and forwards the packet to the right destination node id based on the SecureData header using either broadcast or unicast, it is not yet known how it chooses which to use.<br />
<br />
==Special data channels==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Channel<br />
! Description<br />
|-<br />
| 0x101<br />
| Used when broadcasting the updated node information after a new client connects.<br />
|-<br />
| 0x103<br />
| Used when sending what appears to be "ping" or "null" frames.<br />
|-<br />
| 0x104<br />
| Used to signal the ejection of all spectators in the network.<br />
|}<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Association id of the sending client in big-endian.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20174NWM Services2017-07-17T13:44:25Z<p>Subv: /* Communication protocol */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
[There does not appear to be an association request frame sent by the client to the server, it is however possible that it was sent and just not captured by the test equipment]<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is connected to the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 ([[NWM_Services#EAPoL-Start frame|EAPoL-Start]])<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202([[NWM_Services#EAPoL-Logoff frame|EAPoL-Logoff]])<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D ([[NWM_Services#SecureData NWM header|SecureData]])]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==Special data channels==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Channel<br />
! Description<br />
|-<br />
| 0x101<br />
| Used when broadcasting the updated node information after a new client connects.<br />
|-<br />
| 0x103<br />
| Used when sending what appears to be "ping" or "null" frames.<br />
|-<br />
| 0x104<br />
| Used to signal the ejection of all spectators in the network.<br />
|}<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Association id of the sending client in big-endian.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20166NWM Services2017-07-13T16:09:18Z<p>Subv: /* EAPoL-Start frame */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==Special data channels==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Channel<br />
! Description<br />
|-<br />
| 0x101<br />
| Used when broadcasting the updated node information after a new client connects.<br />
|-<br />
| 0x103<br />
| Used when sending what appears to be "ping" or "null" frames.<br />
|-<br />
| 0x104<br />
| Used to signal the ejection of all spectators in the network.<br />
|}<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Association id of the sending client in big-endian.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20165NWM Services2017-07-13T16:02:33Z<p>Subv: /* EAPoL-Start frame */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==Special data channels==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Channel<br />
! Description<br />
|-<br />
| 0x101<br />
| Used when broadcasting the updated node information after a new client connects.<br />
|-<br />
| 0x103<br />
| Used when sending what appears to be "ping" or "null" frames.<br />
|-<br />
| 0x104<br />
| Used to signal the ejection of all spectators in the network.<br />
|}<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=ClCertA&diff=20116ClCertA2017-06-29T00:56:31Z<p>Subv: </p>
<hr />
<div>This [[NCCH#CFA|CFA]] (title id: [[Title_list#0004001B_-_System_Data_Archives|0004001b00010002]]) contains the following [[PSPXI:EncryptDecryptAes|encrypted]] files in the RomFS:<br />
* "ctr-common-1-cert.bin", this is the default SSL client cert used by the SSL module in DER format.<br />
* "ctr-common-1-key.bin", this is the default SSL client private key used by the SSL module in DER format.<br />
<br />
For retail this is the "CTR Common Prod 1" cert. The final sizes passed to a function used internally by SSL-module, are 0x4C7 for the cert DER, and 0x4AA for the key DER.<br />
<br />
Each file is encrypted in CBC mode using [[PSPXI:EncryptDecryptAes#Key_Types| keyslot 0xD]]. The first 16 bytes of each file are the IV for decrypting the rest of the file.<br />
<br />
The following servers require usage of ClCertA to connect:<br />
<br />
* https://account.nintendo.net/ (Account/OAuth2 related)<br />
* https://ccif.ctr.shop.nintendo.net/ (CreditCardInfo(?), used for credit card/transaction related stuff)<br />
* https://ecs.c.shop.nintendowifi.net/ (ECommerce SOAP, ticket-related)<br />
* https://cas.c.shop.nintendowifi.net/ (Cataloging SOAP)<br />
* https://ninja.ctr.shop.nintendo.net/ (eShop-related)<br />
* https://nus.c.shop.nintendowifi.net/ (NetUpdate SOAP, used by [[NIM_Services|nim system module]])</div>Subvhttps://www.3dbrew.org/w/index.php?title=KThread&diff=20098KThread2017-06-20T17:33:18Z<p>Subv: </p>
<hr />
<div>[[Category:Kernel synchronization objects]]<br />
[[Category:Kernel interrupt events]]<br />
class [[KThread]] extends [[KSynchronizationObject]], [[KTimeableInterruptEvent]], [[KSendableInterruptEvent]] and [[KSchedulableInterruptEvent]];<br />
<br />
Size : 0xB0 bytes<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to vtable<br />
|-<br />
| 0x4<br />
| u32<br />
| Reference count<br />
|-<br />
| 0x8<br />
| u32<br />
| Count of KThreads that sync with this object - number of nodes in the linked list below<br />
|-<br />
| 0xC<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x10<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x14<br />
| [[KTimeableInterruptEvent]]<br />
| Used to suspend threads (*this)<br />
|-<br />
| 0x24<br />
| [[KSendableInterruptEvent]]<br />
| Interrupt event (*this) sent to terminate a thread, except in the case just below<br />
|-<br />
| 0x2C<br />
| [[KSchedulableInterruptEvent]]<br />
| Interrupt event (*this) scheduled by the IRQ handler when the thread should terminate (*this)<br />
|-<br />
| 0x34<br />
| u8<br />
| Scheduling mask<br />
|-<br />
| 0x35<br />
| u8<br />
| Set to 1 when a thread is woken up from a svcSendSyncRequest call due to the ServerSession endpoint closing down<br />
|-<br />
| 0x36<br />
| s8<br />
| Indicates that the thread shall terminate<br />
|-<br />
| 0x37<br />
| u8<br />
| Indicates there was an error translating the parameters in the command buffer during an IPC call<br />
|-<br />
| 0x38<br />
| KDebugThread*<br />
| Pointer to KDebugThread object used with the current KThread<br />
|-<br />
| 0x3C<br />
| u32<br />
| Base thread priority<br />
|-<br />
| 0x40<br />
| u32<br />
| Pointer to object the KThread is waiting on- can be a timer, event, session, etc.<br />
|-<br />
| 0x44<br />
| Result<br />
| Status for object above<br />
|-<br />
| 0x48<br />
| KObjectMutex*<br />
| Locking kernel mutex<br />
|-<br />
| 0x4C<br />
| u32<br />
| Arbitration address<br />
|-<br />
| 0x50<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of objects this thread is waiting on<br />
|-<br />
| 0x54<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of objects this thread is <br />
|-<br />
| 0x5C<br />
| [[KMutex|KMutexLinkedList]] *<br />
| Set in some very specific circumstances<br />
|-<br />
| 0x60<br />
| u32<br />
| Count of KMutex objects this thread is using<br />
|-<br />
| 0x64<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x68<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x6C<br />
| s32<br />
| Dynamic thread priority<br />
|-<br />
| 0x70<br />
| s32<br />
| Processor that created the thread (in the sense of "first ran") ; processor the thread is running in<br />
|-<br />
| 0x74<br />
| [[KResourceLimit|KPreemptionTimer]] *<br />
| Points to [[KResourceLimit]]+0x60, which among other things holds the amount of CPU time available in ticks, or NULL<br />
|-<br />
| 0x7C<br />
| u8<br />
| Thread is alive<br />
|-<br />
| 0x7D<br />
| u8<br />
| Thread has been terminated<br />
|-<br />
| 0x7E<br />
| u8<br />
| Thread affinity mask - set differently depending on whether the thread is created via svc call or from inside the kernel<br />
|-<br />
| 0x80<br />
| KProcess*<br />
| Process the thread belongs to (virtual address)<br />
|-<br />
| 0x84<br />
| u32<br />
| Thread id<br />
|-<br />
| 0x88<br />
| u32*<br />
| Ptr to svc mode register storage for KThread inside the thread context.<br />
|-<br />
| 0x8C<br />
| u32*<br />
| End-address of the page for this thread context allocated in the [[Memory_layout|0xFF4XX000]] region. Thus, if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000. Thread context page - used for thread svc stack, preserving svc mode registers and VFP exception register for thread.<br />
|-<br />
| 0x90<br />
| s32<br />
| Ideal processor (processorid value from [[SVC|svcCreateThread]])<br />
|-<br />
| 0x94<br />
| void*<br />
| Ptr to [[Thread Local Storage]]<br />
|-<br />
| 0x98<br />
| void*<br />
| Ptr to [[Thread Local Storage]] in FCRAM via kernel vmem<br />
|-<br />
| 0xA0<br />
| KThreadLinkedListNode<br />
| Previous and next scheduled threads<br />
|-<br />
| 0xA8<br />
| KThreadLinkedList *<br />
| Pointer to linked list of scheduled threads that has stolen it, or 0 if in normal list<br />
|-<br />
| 0xAC<br />
| s32<br />
| Priority field used for priority inheritance when needed<br />
|}<br />
<br />
With the following declarations: <code>struct KThreadLinkedList { KThread *first, *last; };</code> and <code>struct KThreadLinkedListNode { KThread *prev, *next; };</code>.<br />
<br />
=Thread Scheduling Mask=<br />
The thread scheduling mask is made of a low nibble (enum) and a high nibble (bitfield).<br />
<br />
Low nibble:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| The thread is not scheduled<br />
|-<br />
| 1<br />
| The thread is scheduled<br />
|-<br />
| 2<br />
| The thread is being terminated<br />
|}<br />
<br />
High nibble:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Mask<br />
! Description<br />
|-<br />
| 0<br />
| Nothing special<br />
|-<br />
| 0x8 (bit 3)<br />
| The thread has been debug-locked<br />
|}<br />
<br />
A thread is scheduled *if and only if* its (full) scheduling mask is exactly 1. This allows debug-(un)locking of threads to be done transparently.<br />
=Thread Affinity Mask=<br />
<br />
If the thread is created via a call to SVC 8(CreateThread), which uses thread creation type 3, and the CPU ID is -2(meaning use the core specified in the exheader), the mask is just the affinity mask from the thread's owner KProcess. If the CPU ID is -1(meaning any core), the affinity mask is set to 0xF on the New3DS and 0x3 on the Old3DS. Otherwise, the affinity mask is (1 << cpu_id) | 1.<br />
<br />
If the thread is created via a call by the kernel, which uses thread creation types 0-2, the checks for -1 and -2 are skipped and the mask is always (1 << cpu_id) | 1.</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20085NWM Services2017-06-14T05:47:23Z<p>Subv: /* SecureData NWM header */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==Special data channels==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Channel<br />
! Description<br />
|-<br />
| 0x101<br />
| Used when broadcasting the updated node information after a new client connects.<br />
|-<br />
| 0x103<br />
| Used when sending what appears to be "ping" or "null" frames.<br />
|-<br />
| 0x104<br />
| Used to signal the ejection of all spectators in the network.<br />
|}<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Probably the association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWMUDS:EjectSpectator&diff=20084NWMUDS:EjectSpectator2017-06-14T05:42:43Z<p>Subv: /* Description */</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x00060000]<br />
|}<br />
<br />
=Response=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code<br />
|-<br />
| 1<br />
| Result code<br />
|}<br />
<br />
=Description=<br />
This can be used by the host to force-disconnect the spectator(s). After sending the network msg, this calls the same code used by [[NWMUDS:UpdateNetworkAttribute]] internally, with bitmask=0x1 and flag=1. New spectator connections will not be accepted any more after using this command, until that attribute bit is cleared.<br />
<br />
This sends a broadcast data packet to channel 0x104 with a single 0 byte as data.</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20083NWM Services2017-06-14T05:41:29Z<p>Subv: /* SecureData NWM header */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Data channel. Applications can only use the low 8 bits, channels greater than 255 are reserved for management functions.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Probably the association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=20082NWM Services2017-06-14T02:32:55Z<p>Subv: /* SecureData NWM header */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?) and for broadcasting the updated node information when a new client connects. Probably a "is_management" bit.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Sequence number, incremented after each sent packet.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Probably the association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19888NWM Services2017-04-16T14:48:38Z<p>Subv: /* Data frames */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte [https://en.wikipedia.org/wiki/Subnetwork_Access_Protocol#Use LLC header], then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?) and for broadcasting the updated node information when a new client connects. Probably a "is_management" bit.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Probably the association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19887NWM Services2017-04-16T14:35:31Z<p>Subv: /* Communication protocol */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets sent using SendTo are encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
[The client also sends periodic SecureData data frames on its own, these are probably ping frames]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?) and for broadcasting the updated node information when a new client connects. Probably a "is_management" bit.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Probably the association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19880NWM Services2017-04-15T21:36:38Z<p>Subv: EAPoL-Logoff frame</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?) and for broadcasting the updated node information when a new client connects. Probably a "is_management" bit.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Probably the association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Logoff frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x202 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Always 0?<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Assigned network node id.<br />
|-<br />
| 0x6<br />
| 0x6<br />
| Mac address of the newly connected client.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 0x2<br />
| Unknown. Always 0.<br />
|-<br />
| 0x12<br />
| 0x1<br />
| Number of connected nodes, including the new client.<br />
|-<br />
| 0x13<br />
| 0x1<br />
| Max number of nodes.<br />
|-<br />
| 0x14<br />
| 0x2<br />
| Always 0.<br />
|-<br />
| 0x16<br />
| 0x2<br />
| Unknown.<br />
|-<br />
| 0x18<br />
| 0x280<br />
| List of 16 NodeInfo structures with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19879NWM Services2017-04-15T21:32:20Z<p>Subv: /* SecureData NWM header */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?) and for broadcasting the updated node information when a new client connects. Probably a "is_management" bit.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==EAPoL-Start frame==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Always 0x201 in big-endian.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Unknown. Probably the association id of the sending client.<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Unknown. Always 0x1 in big-endian. The parser for this packet errors out if this is > 3.<br />
|-<br />
| 0x6<br />
| 0x2<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x28<br />
| NodeInfo structure with all fields in big-endian<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19878NWM Services2017-04-15T21:29:28Z<p>Subv: /* Communication protocol */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x201 (EAPoL-Start)<br />
<br />
Server->Broadcast: Encrypted data packet containing the updated node information after the client connected (Using ethertype = SecureData).<br />
<br />
Server->Client: Encrypted data packet containing an 8-byte 802.2 LLC header with ethertype = EAPoL (0x888E) and an u16 header of 0x0202(EAPoL-Logoff)<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?) and for broadcasting the updated node information when a new client connects. Probably a "is_management" bit.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19877NWM Services2017-04-15T21:26:08Z<p>Subv: /* SecureData NWM header */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet with node information, using an LLC header with ethertype = 0x888E (EAPoL) and an apparently dummy EAPoL header, followed by the node information (friendcodeseed, username, and some unknown fields).<br />
<br />
Server->Broadcast: Encrypted data packet broadcasting the connection of the new client to the other clients?<br />
<br />
Server->Client: Encrypted data packet containing some sort of ack?<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?) and for broadcasting the updated node information when a new client connects. Probably a "is_management" bit.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19876NWM Services2017-04-15T19:18:13Z<p>Subv: /* SecureData NWM header */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet with node information, using an LLC header with ethertype = 0x888E (EAPoL) and an apparently dummy EAPoL header, followed by the node information (friendcodeseed, username, and some unknown fields).<br />
<br />
Server->Broadcast: Encrypted data packet broadcasting the connection of the new client to the other clients?<br />
<br />
Server->Client: Encrypted data packet containing some sort of ack?<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown. Normally 0 during SendTo data transfer. Set to 1 in the automatic periodic frames NWM sends (Ping frames?)<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19875NWM Services2017-04-15T18:54:43Z<p>Subv: UDS Data frame NWM header</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet with node information, using an LLC header with ethertype = 0x888E (EAPoL) and an apparently dummy EAPoL header, followed by the node information (friendcodeseed, username, and some unknown fields).<br />
<br />
Server->Broadcast: Encrypted data packet broadcasting the connection of the new client to the other clients?<br />
<br />
Server->Client: Encrypted data packet containing some sort of ack?<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==SecureData NWM header==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Size of the entire frame minus the 8 bytes from the LLC header.<br />
|-<br />
| 0x2<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0x4<br />
| 0x2<br />
| Size of the entire frame minus 12 bytes.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| unknown<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Data channel<br />
|-<br />
| 0x8<br />
| 0x2<br />
| unknown<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Destination network node id<br />
|-<br />
| 0xC<br />
| 0x2<br />
| Source network node id<br />
|}<br />
<br />
This data is stored as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19874NWM Services2017-04-15T18:49:24Z<p>Subv: /* Data frames */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet with node information, using an LLC header with ethertype = 0x888E (EAPoL) and an apparently dummy EAPoL header, followed by the node information (friendcodeseed, username, and some unknown fields).<br />
<br />
Server->Broadcast: Encrypted data packet broadcasting the connection of the new client to the other clients?<br />
<br />
Server->Client: Encrypted data packet containing some sort of ack?<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x8-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19873NWM Services2017-04-15T14:51:19Z<p>Subv: </p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Communication protocol==<br />
The process of connecting to a host and exchanging data follows the sequence:<br />
<br />
Client->Server: Authentication frame SEQ1<br />
<br />
Server->Client: Authentication frame SEQ2<br />
<br />
Server->Client: Association Response frame with association id<br />
<br />
[From here on, the client is paired with the server]<br />
<br />
Client->Server: Encrypted data packet with node information, using an LLC header with ethertype = 0x888E (EAPoL) and an apparently dummy EAPoL header, followed by the node information (friendcodeseed, username, and some unknown fields).<br />
<br />
Server->Broadcast: Encrypted data packet broadcasting the connection of the new client to the other clients?<br />
<br />
Server->Client: Encrypted data packet containing some sort of ack?<br />
<br />
[From here on, data packets exchanged between the client and the server contain the information passed to SendTo, encapsulated with an LLC header with ethertype = 0x876D (SecureData)]<br />
<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x10-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWM_Services&diff=19872NWM Services2017-04-14T15:01:55Z<p>Subv: /* BeaconDataReply Structure */</p>
<hr />
<div>[[Category:Services]]<br />
<br />
These NWM services are used for local-WLAN communications, NWM module handles regular wifi APs as well. These services are used for creating/connecting to networks, and for sending/receiving data over the network etc. NWM module uses the wifi SDIO hardware via the IO registers for this.<br />
<br />
=NWM local-WLAN service "nwm::UDS"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010442<br />
| <br />
| Initialize Deprecated. Appears to be handled about the same way as [[NWMUDS:InitializeWithVersion]], except this uses version=0x100 internally instead of loading it from the command request.<br />
|-<br />
| 0x00020000<br />
| <br />
| Scrap Not used by sub-wars. This sets a state value to 0x2 then signals an event. This is probably some sort of shutdown command since this state write will result in all UDS commands returning an error if used afterwards.<br />
|-<br />
| 0x00030000<br />
| <br />
| [[NWMUDS:Shutdown|Shutdown]]<br />
|-<br />
| 0x00040402<br />
| <br />
| CreateNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x00050040<br />
|<br />
| [[NWMUDS:EjectClient|EjectClient]]<br />
|-<br />
| 0x00060000<br />
| <br />
| [[NWMUDS:EjectSpectator|EjectSpectator]]<br />
|-<br />
| 0x00070080<br />
| <br />
| [[NWMUDS:UpdateNetworkAttribute|UpdateNetworkAttribute]]<br />
|-<br />
| 0x00080000<br />
| <br />
| [[NWMUDS:DestroyNetwork|DestroyNetwork]]<br />
|-<br />
| 0x00090442<br />
| <br />
| ConnectNetwork Deprecated. Only used by very old titles.<br />
|-<br />
| 0x000A0000<br />
| <br />
| [[NWMUDS:DisconnectNetwork|DisconnectNetwork]]<br />
|-<br />
| 0x000B0000<br />
| <br />
| [[NWMUDS:GetConnectionStatus|GetConnectionStatus]]<br />
|-<br />
| 0x000C0000<br />
| <br />
| This writes two output u8 values to cmdreply[2] +0/+1. Not used by sub-wars.<br />
|-<br />
| 0x000D0040<br />
| <br />
| [[NWMUDS:GetNodeInformation|GetNodeInformation]]<br />
|-<br />
| 0x000E0006<br />
| <br />
| ''Identical'' to [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]. Deprecated, only used by old titles.<br />
|-<br />
| 0x000F0404<br />
| <br />
| [[NWMUDS:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00100042<br />
| <br />
| [[NWMUDS:SetApplicationData|SetApplicationData]]<br />
|-<br />
| 0x00110040<br />
| <br />
| [[NWMUDS:GetApplicationData|GetApplicationData]]<br />
|-<br />
| 0x00120100<br />
| <br />
| [[NWMUDS:Bind|Bind]]<br />
|-<br />
| 0x00130040<br />
| <br />
| [[NWMUDS:Unbind|Unbind]]<br />
|-<br />
| 0x001400C0<br />
| <br />
| [[NWMUDS:PullPacket|PullPacket]]<br />
|-<br />
| 0x00150080<br />
| <br />
| SetMaxSendDelay(u64 unk) Not used by sub-wars.<br />
|-<br />
| 0x00160040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00170182<br />
| <br />
| [[NWMUDS:SendTo|SendTo]]<br />
|-<br />
| 0x00180040<br />
| <br />
| (u16 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00190040<br />
| <br />
| (u32 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001A0000<br />
| <br />
| [[NWMUDS:GetChannel|GetChannel]]<br />
|-<br />
| 0x001B0302<br />
| <br />
| [[NWMUDS:InitializeWithVersion|InitializeWithVersion]]<br />
|-<br />
| 0x001C0040<br />
| <br />
| (u8 inputval) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x001D0044<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:BeginHostingNetwork|BeginHostingNetwork]] This is a replacement for the original network-creation command.<br />
|-<br />
| 0x001E0084<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ConnectToNetwork|ConnectToNetwork]] This is a replacement for the original network-connection command.<br />
|-<br />
| 0x001F0006<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:DecryptBeaconData|DecryptBeaconData]]<br />
|-<br />
| 0x00200040<br />
| Unknown, >[[2.0.0-2]]<br />
| Flush (u8 data_frame_index) Unknown. Not used by sub-wars.<br />
|-<br />
| 0x00210080<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:SetProbeResponseParam|SetProbeResponseParam]]<br />
|-<br />
| 0x00220402<br />
| Unknown, >[[2.0.0-2]]<br />
| [[NWMUDS:ScanOnConnection|ScanOnConnection]]<br />
|-<br />
| 0x00230000<br />
| Unknown, >[[2.0.0-2]]<br />
| This writes an output u16 value to cmdreply[2]. Unknown. Not used by sub-wars.<br />
|}<br />
<br />
PullPacket is used for receiving data over the network and SendTo is for sending data over the network.<br />
<br />
=NWM infrastructure service "nwm::INF"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x00020000<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
|-<br />
| 0x00040000<br />
| ?<br />
|-<br />
| 0x00050000<br />
| ?<br />
|-<br />
| 0x000603C4<br />
| [[NWMINF:RecvBeaconBroadcastData|RecvBeaconBroadcastData]]<br />
|-<br />
| 0x00070742<br />
| [[NWMINF:ConnectToEncryptedAP|ConnectToEncryptedAP]]<br />
|-<br />
| 0x00080302<br />
| [[NWMINF:ConnectToAP|ConnectToAP]]<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B0000<br />
| ?, return event handle in cmdbuf[3]<br />
|-<br />
| 0x000C0040<br />
| ?<br />
|-<br />
| 0x000D0000<br />
| ?<br />
|-<br />
| 0x000E0002<br />
| ?<br />
|-<br />
| 0x000F0082<br />
| ?<br />
|-<br />
| 0x00100040<br />
| ?<br />
|}<br />
<br />
=NWM socket service "nwm::SOC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010042<br />
| (u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00020080<br />
| (u32 unk, u32 size) Unknown. Uses size=0x5F8 internally unless the input is <=0x5F8. Uses an ipc static_buffer(static_buf_id=0) for output with the specified size(also used when writing the translate-hdr). Writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00030042<br />
| (u32 unk, u32 size, <static_buffer translate-hdr with static_buf_id=0>, addr) ?<br />
|-<br />
| 0x00040042<br />
| (u32 size, u32 unk, <static_buffer translate-hdr with static_buf_id=1>, addr) ?<br />
|-<br />
| 0x00050040<br />
| (u32 unk) ?<br />
|-<br />
| 0x00060080<br />
| (u32 unk0, u16 unk1) ?<br />
|-<br />
| 0x00070040<br />
| (u16 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| [[NWMSOC:GetMACAddress|GetMACAddress]]<br />
|-<br />
| 0x00090000<br />
| This just copies data from state to the cmdreply, this always returns 0. u32 cmdreply[2] = sharedmem_size, cmdreply[4] = [[NWM_Shared_Memory|sharedmem_handle]], cmdreply[5] = eventhandle.<br />
|-<br />
| 0x000A0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000B0040<br />
| (u32 unk) This writes an output u32 to cmdreply[2].<br />
|-<br />
| 0x000C0040<br />
| (u32 unk) ?<br />
|-<br />
| 0x000D0002<br />
| ([[IPC|kernel_processid_translatehdr]], u32 processid) ?<br />
|}<br />
<br />
The only sysmodule which uses this is [[Socket_Services|socket]]-sysmodule. The first command used by socket-module is cmd9.<br />
<br />
=NWM service "nwm::SAP"=<br />
<br />
=NWM local-WLAN [[StreetPass]] service "nwm::CEC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00060002<br />
| Unknown, called by CECD module, cmdbuf[2] takes an event handle.<br />
|-<br />
| 0x000D0082<br />
| [[NWMCEC:SendProbeRequest|SendProbeRequest]]<br />
|}<br />
<br />
=NWM service "nwm::EXT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00020000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00030000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00040040<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00050002<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00060000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|-<br />
| 0x00070000<br />
| <=[[2.0.0-2]]<br />
| This copies 0x1C-bytes from NWM-module state to the data starting at cmdreply[2].<br />
|-<br />
| 0x00080040<br />
| <=[[2.0.0-2]]<br />
| [[NWMEXT:ControlWirelessEnabled|ControlWirelessEnabled]]<br />
|-<br />
| 0x00090000<br />
| <=[[2.0.0-2]]<br />
| ?<br />
|}<br />
<br />
=NWM service "nwm::TST"=<br />
<br />
=BeaconDataReply Structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Max output size, from the command request.<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Total amount of output data written relative to struct+0. 0xC when there's no entries.<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Total entries, 0 for none.<br />
|-<br />
| 0xC<br />
| <Rest of the structure><br />
| Beacon entries.<br />
|}<br />
<br />
Beacon entry:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of this entire entry. The next entry starts at curentry_startoffset+curentry_size.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x5<br />
| 0x1<br />
| AP wifi channel.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x7<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x8<br />
| 0x6<br />
| AP MAC address.<br />
|-<br />
| 0xE<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x14<br />
| 0x4<br />
| Size of this entire entry, games use this value to traverse the beacons list.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| Value 0x1C(size of this header and/or offset to the actual beacon data).<br />
|-<br />
| 0x1C<br />
| Entry_size - 0x1C<br />
| The actual beacon data is located here, starting at the 802.11 management frame header.<br />
|}<br />
<br />
This section describes the structure returned by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=ScanInputStruct=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Two unknown u16s.<br />
|-<br />
| 1<br />
| Two unknown u16s.<br />
|-<br />
| 2-3<br />
| Host MAC address. The 6-bytes located here are normally all 0xFF, for all hosts. Otherwise when not set to broadcast-MAC, the command will only return info for the specified host MAC address.<br />
|-<br />
| 4-12<br />
| Uninitialized for UDS.<br />
|}<br />
<br />
This section describes the 0x34-byte input structure used by [[NWMINF:RecvBeaconBroadcastData]] and [[NWMUDS:RecvBeaconBroadcastData]].<br />
<br />
=Local-WLAN=<br />
UDS is used for 3DS<>3DS local-WLAN communications, and for 3DS<>Wii U communications. The latter is mainly only used for multi-player in games.<br />
<br />
All UDS local-WLAN communications have the CCMP key for data encryption generated via NWM module. The CCMP key passed to nwm::CEC commands(stored in a 0x44-byte input structure) for [[StreetPass]] is generated by the CECD module. The input data used with [[Process_Services|EncryptDecryptAes]] with [[PSPXI:EncryptDecryptAes|keytype1]] is a MD5 hash over the input passphrase. This input passphrase is fixed for [[Download Play]], it's unique per local-WLAN application. The CTR is a MD5 hash over the below 0x10-byte structure. The output from encrypting that data with AES-CTR is the final CCMP key. This passphrase is a raw input buffer: while the passphrase specified by user-processes is normally a string with the NUL-terminator included, it can be anything(like the [[DLP_Services|WirelessRebootPassphrase]] for example).<br />
<br />
The maximum number of nodes(including the host) which can be on an UDS network is 16.<br />
<br />
==NodeID==<br />
There are two types of client connections: regular Client, and Spectator. The latter ''never'' sends ''any'' 802.11 frame at all to the host, hence ''nothing'' actually connected to the network(including the host) can know about any spectators. Once a spectator is "connected" to a network, it can only receive broadcasted data, no sending.<br />
<br />
DLP-client connects to the network as a spectator during DLP scanning to get various [[Download_Play|metadata]] including icon data.<br />
<br />
===NetworkNodeID===<br />
This is the network u16 ID for each device on the UDS network. NodeID 0xFFFF is a broadcast alias. 0x1 is for the host, the 0x2 for the first client, 0x3 for the second client, and so on.<br />
<br />
The spectator doesn't have a NetworkNodeID, since it can't [[NWMUDS:SendTo|send]] any data.<br />
<br />
NetworkNodeIDs for clients do not change when any clients disconnect, likewise for the encrypted node-listing stored in the wifi beacons. When a client disconnects, the corresponding NetworkNodeID bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]] is cleared. When a client is connecting, the client is assigned the NetworkNodeID with the lowest corresponding clear-bit in the [[NWMUDS:GetConnectionStatus|node_bitmask]], then that bit is set.<br />
<br />
===BindNodeID===<br />
This u32 is an ID only used on the local device. How many devices are on the network or which device this system is does not affect this ID.<br />
<br />
The spectator uses BindNodeID 0x1. DLP uses BindNodeID 0x3 when connecting as an actual client. Hence, it seems BindNodeID bit0 is spectator-related. All normal nodes(host/client) start with BindNodeID 0x2. When connecting to a network again(and probably with network creation) without reinitializing NWMUDS, official user processes increase the used BindNodeID by 0x2.<br />
<br />
BindNodeID value 0x0 is invalid. The maximum number of BindNodeIDs which can be open at the same time is 16.<br />
<br />
==Application data transfer==<br />
The protocol used for sending/receiving data over the network with UDS by official applications is [[PRUDP]](in some cases at least). Mario Kart 7 uses PRUDP here. Triforce Heroes uses plaintext for whatever protocol it uses for UDS.<br />
<br />
The UDS version of [[PRUDP]] is different from the normal UDP version it appears(no afa1/a1af data for example).<br />
<br />
==Data frames==<br />
Data is transferred over the network using [[NWMUDS:PullPacket]]/[[NWMUDS:SendTo]]. That data is transferred using 802.11 data frames using CCMP encryption. The encrypted data contained in the frame starts with the 0x10-byte LLC header, then the 0xE-byte NWM header, followed by the actual application data from the previously mentioned commands. When [[NWMUDS:SendTo]] was used with dst_NodeID = broadcast, the data frame is sent to the 802.11 broadcast MAC address. Otherwise with a specific NodeID, the data frame is sent to the actual MAC address for that device.<br />
<br />
Official application data is normally stored here as big-endian.<br />
<br />
==Structure used for generating the CTR for CCMP key generation==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| networkID<br />
|-<br />
| 0x8<br />
| 0x6<br />
| Host MAC address.<br />
|-<br />
| 0xE<br />
| 0x2<br />
| id8<br />
|}<br />
<br />
This data is stored as little-endian.<br />
<br />
==CTR used for beacon tags crypto==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| Host MAC address<br />
|-<br />
| 0x6<br />
| 0x4<br />
| wlancommID<br />
|-<br />
| 0xA<br />
| 0x1<br />
| id8<br />
|-<br />
| 0xB<br />
| 0x1<br />
| Padding, value zero.<br />
|-<br />
| 0xC<br />
| 0x4<br />
| networkID<br />
|}<br />
<br />
This data is stored as little-endian. All data here is all-zero except for the MAC address, when the u8 at offset 0x8 in the network-struct is 0.<br />
<br />
==Network structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x6<br />
| This is the MAC address of the host. This is used for when [[NWMUDS:ConnectToNetwork|connecting]] to the network.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| This is actually written as an u16 without byte-swapping. This is the network wifi channel. When connecting this is normally non-zero. When hosting, this can be 0 to automatically select a channel, otherwise the specified channel is used. When non-zero official user-processes require this value to be one of the following when hosting: 1, 6, or 11.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Padding<br />
|-<br />
| 0x8<br />
| 0x1<br />
| Initialized flag. Must be non-zero otherwise NWM-module will use value 0x0 for most/all(?) fields in this structure when reading these fields.<br />
|-<br />
| 0xC<br />
| 0x3<br />
| This is the OUI value for use with the beacon tags. Normally this is 001F32.<br />
|-<br />
| 0xF<br />
| 0x1<br />
| OUI type (21/0x15)<br />
|-<br />
| 0x10<br />
| 0x4<br />
| wlancommID. Local-WLAN communication ID, normally this is: (user_process [[Title_list|uniqueID]] << 8) | val. Where val is 0x10 on retail([[Configuration_Memory#ENVINFO|ENVINFO]] bit0 set), 0x90 for devunit. Official software includes an input bool flag parameter for setting bit0 in this wlancommID, normally that flag isn't set. For [[Download Play]], this is always 0x2810 on retail(0x2890 on devunit).<br />
<br />
This wlancommID can have the side affect of region-locking when the title uses the uniqueID for the current title(hard-coded in .text normally), instead of using a fixed input uniqueID for each region of the title.<br />
|-<br />
| 0x14<br />
| 0x1<br />
| id8. ID, for [[Download Play]] this is 0x55. 0x55/'U' seems to be used for networks where Wii U can host it(Download Play, Smash Bros, ...) - this value isn't known to be actually checked anywhere however.<br />
|-<br />
| 0x15<br />
| 0x1<br />
| Some sort of counter for how many times this network was connected to?<br />
|-<br />
| 0x16<br />
| 0x2<br />
| This network attributes u16 bitmask can be written via [[NWMUDS:UpdateNetworkAttribute]].<br />
Bitmasks:<br />
* 0x1: When set, spectators are not allowed to connect(see [[NWMUDS:EjectSpectator|here]]). Checked by official user-processes before using [[NWMUDS:ConnectToNetwork]], when connecting as a Spectator. Must be clear otherwise that code returns error 0xE10113EA. If the initialized_flag at offset 0x8 is zero, this code handles it the same way as if this bit was set. The latest NWM-module handles checking this bit itself however.<br />
* 0x2: When set, new regular-clients are not allowed to connect.<br />
* 0x4: Unknown, has no affect on new clients/spectators connecting. Official software has an option for setting this bit via an input flag from the same code using bitmask 0x2. Official software always clears bitmask 0x6 when unblocking new connections.<br />
|-<br />
| 0x18<br />
| 0x4<br />
| u32 networkID, randomly-generated when creating the network. The network SSID used when a client connects to the network is sprintf(out, "%08X", networkID).<br />
|-<br />
| 0x1C<br />
| 0x1<br />
| Total number of currently connected nodes, including the host.<br />
|-<br />
| 0x1D<br />
| 0x1<br />
| Maximum number of nodes, including the host. This also is the total number of entries stored under the array in the encrypted beacon data.<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x3F<br />
| 0x1<br />
| Size of appdata.<br />
|-<br />
| 0x40<br />
| 0xC8<br />
| Appdata(Application data), if any. Size of the appdata is specified via the u8 at offset 0x3F. This data is not used when the size-field is zero.<br />
|}<br />
<br />
This 0x108-byte structure is used for [[NWMUDS:BeginHostingNetwork]], [[NWMUDS:ConnectToNetwork]], etc. This data is stored as big-endian.<br />
<br />
==NodeInfo structure==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x8<br />
| u64 ID, this is the UDS version of the FriendCodeSeed. This is loaded from BlkID 0x00090000 in the [[Config_Savegame|system-config]] via [[CfgS:GetConfigInfoBlk2]].<br />
|-<br />
| 0x8<br />
| 0x14<br />
| The first 0x18-bytes from BlkID 0x000A0000 in the [[Config_Savegame|system-config]] loaded via [[CfgS:GetConfigInfoBlk2]] is written here by user-processes. However, the data at +0x14(absolute offset 0x1C) is written by NWM-module later.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16, unknown. Set to 0x0 with the output from [[NWMUDS:DecryptBeaconData]].<br />
|-<br />
| 0x1E<br />
| 0x1<br />
| u8 flag, unknown. Originates from the u16 bitmask in the beacon node-list header. This flag is normally 0 since that bitmask is normally 0?<br />
|-<br />
| 0x1F<br />
| 0x1<br />
| Padding?<br />
|-<br />
| 0x20<br />
| 0x2<br />
| u16 NetworkNodeID<br />
|-<br />
| 0x22<br />
| 0x6<br />
| Normally zero?<br />
|}<br />
<br />
The first 0x20-bytes are written by the user-process before using this structure with [[NWMUDS:InitializeWithVersion]]. The data starting at offset 0x8 is only initialized by NWM-module.<br />
<br />
== UDS Beacons ==<br />
The UDS host broadcasts a beacon containing at least two Nintendo-vendor tags(tag number 0xDD, see above for the OUI), normally the data stored in these tags are static. The second tag contains the big-endian u32 networkID, used by the clients when connecting to the host and for the above CCMP key generation. The Nintendo-vendor tag(s) following the first two are unique to the process using UDS, these tags are used for broadcasting metadata regarding the host.<br />
<br />
A tool for these beacons is available here: [https://github.com/yellows8/ctr-wlanbeacontool]<br />
<br />
=== UDS Beacon Tags ===<br />
The following is the structure of each tag, starting at the OUI. The order of the tags is the same as listed below. All data stored under these tags are stored as big-endian.<br />
<br />
==== OUI Type 20 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (20/0x14)<br />
|-<br />
| 0x4<br />
| 0x3<br />
| Sample data: 0a 00 00<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x07.<br />
<br />
==== OUI Type 21 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1F<br />
| This is the network structure starting at offset 0xC, with the first 0x1F-bytes from there.<br />
|-<br />
| 0x1F<br />
| 0x14<br />
| SHA1 hash. When doing the hashing, this hash is cleared to zero. The hash data starts at offset 0x0(OUI), and the size is 0x34 + <value of the u8 at offset 0x33>.<br />
|-<br />
| 0x33<br />
| 0x1<br />
| Size of appdata. Normally zero. When non-zero this appdata is located at offset 0x34.<br />
|}<br />
<br />
Normally the size of this tag(from the tag size field) is 0x34, not including appdata.<br />
<br />
==== OUI Type 24 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (24/0x18)<br />
|-<br />
| 0x4<br />
| See below<br />
| Encrypted data<br />
|}<br />
<br />
This is the tag0 used with [[NWMUDS:DecryptBeaconData]]. The size of data stored under this tag has a maximum size of 0xFA-bytes, however normally the size is smaller than that. Additional encrypted data, if any, is stored under the below tag1.<br />
<br />
==== OUI Type 25 ====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x3<br />
| OUI, see above.<br />
|-<br />
| 0x3<br />
| 0x1<br />
| OUI type (25/0x19)<br />
|-<br />
| 0x4<br />
| See above<br />
| Encrypted data<br />
|}<br />
<br />
When this exists in the beacon, this is the tag1 used with [[NWMUDS:DecryptBeaconData]]. The data stored here is the 0xFA-bytes following the previous encrypted data in tag0, for more space for storing the encrypted data.<br />
<br />
<br />
==== Encrypted beacon data ====<br />
The following structure is for the plaintext version of the encrypted data, stored as big-endian.<br />
<br />
This data is encrypted with AES-CTR, by NWM module in software. The AES key is stored in NWM module itself. See above for the CTR. The size of this encrypted data is 0x12 + (0x1E*val), where val is the u8 from networkstruct offset 0x1D.<br />
<br />
===== Structure =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| MD5 over the rest of the data following this(plaintext).<br />
|-<br />
| 0x10<br />
| 0x2<br />
| u16 bitmask. Unknown, normally 0? Bit0 is for entry0, bit1 for entry1, and so on.<br />
|-<br />
| 0x12<br />
| 0x1E * <total array entries><br />
| This is an array of entries for each of the devices on this network, the first entry is for the host and the rest is for the client(s).<br />
|}<br />
<br />
===== Array entry =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1C<br />
| This is the first 0x1C-bytes of the NodeInfo structure, stored as big-endian.<br />
|-<br />
| 0x1C<br />
| 0x2<br />
| u16 NetworkNodeID, stored as big-endian.<br />
|}<br />
<br />
Each entry is for a node.<br />
<br />
= Mapped IO =<br />
''All'' of the [[IO_Registers|IO]] mapped under the NWM-module process is listed below:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Userland address<br />
! Physical address<br />
! Size<br />
! Description<br />
|-<br />
| 0x1EC22000<br />
| 0x10122000<br />
| 0x1000<br />
| [[WIFI_Registers]]<br />
|-<br />
| 0x1EC40000<br />
| 0x10140000<br />
| 0x1000<br />
| [[PDN_Registers]]<br />
|-<br />
| 0x1EE22000<br />
| 0x10322000<br />
| 0x1000<br />
| <br />
|}<br />
<br />
=Errors=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Error code<br />
! Description<br />
|-<br />
| 0xC8A06C0D<br />
| The operation being performed is already done (e.g., if you run NWMEXT_ControlWirelessEnabled to turn wifi on when it's on already, you can't turn it on again).<br />
|-<br />
| 0xC8A113EA<br />
| Returned when the command isn't allowed to be used on this device.<br />
|-<br />
| 0xC90113FA<br />
| Node doesn't exist / invalid NetworkNodeID?<br />
|-<br />
| 0xC92113FB<br />
| Returned when trying to connect to a host when the host has the specified connection-type blocked via the network attributes. There might be other causes too.<br />
|-<br />
| 0xE10113E9<br />
| Returned when the input size is invalid. Returned by [[NWMUDS:PullPacket]] when the input size is smaller than the frame_size.<br />
|-<br />
| 0xE10113EA<br />
| Invalid bind / data_channel is invalid(0x0).<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWMUDS:GetConnectionStatus&diff=19871NWMUDS:GetConnectionStatus2017-04-14T14:26:40Z<p>Subv: /* Output structure */</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x000B0000]<br />
|}<br />
<br />
=Response=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code<br />
|-<br />
| 1<br />
| Result code<br />
|-<br />
| 2-13<br />
| Output 0x30-byte structure.<br />
|}<br />
<br />
=Output structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| u32 status<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Unknown u32. Official user-processes check for values: 0x0, 0x1, and non-zero.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| u16 NetworkNodeID for this device. This is the broadcast alias when connected as a spectator.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| u16, changed_nodes. This is a bitmask of the nodes that changed and triggered the update.<br />
|-<br />
| 0xC<br />
| 0x20<br />
| u16 nodes[16]. Array of NetworkNodeIds, the values inside this array is what's passed to [[NWMUDS:GetNodeInformation]].<br />
|-<br />
| 0x2C<br />
| 0x1<br />
| u8 total_nodes.<br />
|-<br />
| 0x2D<br />
| 0x1<br />
| u8 max_nodes, originally from the NetworkStruct.<br />
|-<br />
| 0x2E<br />
| 0x2<br />
| u16 node_bitmask. This is a bitmask of NetworkNodeIDs: bit0 for NetworkNodeID 0x1(host), bit1 for NetworkNodeID 0x2(first original client), and so on.<br />
|}<br />
<br />
Right after [[NWMUDS:InitializeWithVersion|initializing]], this structure is all-zero except for the status which is value 0x3.<br />
<br />
==Status values==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Type<br />
! Description<br />
|-<br />
| 0x3<br />
| Not connected to any network as a host/client, or just initialized.<br />
|-<br />
| 0x6<br />
| Connected to a network as a host.<br />
|-<br />
| 0x9<br />
| Connected to a network as a client.<br />
|-<br />
| 0xA<br />
| Connected to a network as a spectator.<br />
|-<br />
| 0xB<br />
| For this value official user-processes use [[NWMUDS:UpdateNetworkAttribute]] to clear attributes bitmask 0x6.<br />
|}<br />
<br />
=Description=<br />
This is mainly used when the event handle from [[NWMUDS:Initialize]] is signaled. This is also used before using [[NWMUDS:Bind]]. For certain user-processes this may be used during NWMUDS initialization as well.<br />
<br />
The event is not signaled when using [[NWMUDS:DestroyNetwork]] or [[NWMUDS:DisconnectNetwork]]. However the event does get signaled when creating or connecting to a network.</div>Subvhttps://www.3dbrew.org/w/index.php?title=NWMUDS:GetConnectionStatus&diff=19870NWMUDS:GetConnectionStatus2017-04-14T14:23:33Z<p>Subv: /* Output structure */</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x000B0000]<br />
|}<br />
<br />
=Response=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code<br />
|-<br />
| 1<br />
| Result code<br />
|-<br />
| 2-13<br />
| Output 0x30-byte structure.<br />
|}<br />
<br />
=Output structure=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| u32 status<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Unknown u32. Official user-processes check for values: 0x0, 0x1, and non-zero.<br />
|-<br />
| 0x8<br />
| 0x2<br />
| u16 NetworkNodeID for this device. This is the broadcast alias when connected as a spectator.<br />
|-<br />
| 0xA<br />
| 0x2<br />
| u16, changed_nodes. This is a bitmask of the nodes that changed and triggered the update.<br />
|-<br />
| 0xC<br />
| 0x20<br />
| u16 nodes[16]. Array of NetworkNodeIds, the values inside this array is what's passed to GetNodeInformation.<br />
|-<br />
| 0x2C<br />
| 0x1<br />
| u8 total_nodes.<br />
|-<br />
| 0x2D<br />
| 0x1<br />
| u8 max_nodes, originally from the NetworkStruct.<br />
|-<br />
| 0x2E<br />
| 0x2<br />
| u16 node_bitmask. This is a bitmask of NetworkNodeIDs: bit0 for NetworkNodeID 0x1(host), bit1 for NetworkNodeID 0x2(first original client), and so on.<br />
|}<br />
<br />
Right after [[NWMUDS:InitializeWithVersion|initializing]], this structure is all-zero except for the status which is value 0x3.<br />
<br />
==Status values==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Type<br />
! Description<br />
|-<br />
| 0x3<br />
| Not connected to any network as a host/client, or just initialized.<br />
|-<br />
| 0x6<br />
| Connected to a network as a host.<br />
|-<br />
| 0x9<br />
| Connected to a network as a client.<br />
|-<br />
| 0xA<br />
| Connected to a network as a spectator.<br />
|-<br />
| 0xB<br />
| For this value official user-processes use [[NWMUDS:UpdateNetworkAttribute]] to clear attributes bitmask 0x6.<br />
|}<br />
<br />
=Description=<br />
This is mainly used when the event handle from [[NWMUDS:Initialize]] is signaled. This is also used before using [[NWMUDS:Bind]]. For certain user-processes this may be used during NWMUDS initialization as well.<br />
<br />
The event is not signaled when using [[NWMUDS:DestroyNetwork]] or [[NWMUDS:DisconnectNetwork]]. However the event does get signaled when creating or connecting to a network.</div>Subvhttps://www.3dbrew.org/w/index.php?title=KThread&diff=19157KThread2017-01-05T14:14:19Z<p>Subv: </p>
<hr />
<div>[[Category:Kernel synchronization objects]]<br />
[[Category:Kernel interrupt events]]<br />
class [[KThread]] extends [[KSynchronizationObject]], [[KTimeableInterruptEvent]], [[KSendableInterruptEvent]] and [[KSchedulableInterruptEvent]];<br />
<br />
Size : 0xB0 bytes<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to vtable<br />
|-<br />
| 0x4<br />
| u32<br />
| Reference count<br />
|-<br />
| 0x8<br />
| u32<br />
| Count of KThreads that sync with this object - number of nodes in the linked list below<br />
|-<br />
| 0xC<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x10<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x14<br />
| [[KTimeableInterruptEvent]]<br />
| Used to suspend threads (*this)<br />
|-<br />
| 0x24<br />
| [[KSendableInterruptEvent]]<br />
| Interrupt event (*this) sent to terminate a thread, except in the case just below<br />
|-<br />
| 0x2C<br />
| [[KSchedulableInterruptEvent]]<br />
| Interrupt event (*this) scheduled by the IRQ handler when the thread should terminate (*this)<br />
|-<br />
| 0x34<br />
| u8<br />
| Whether the thread is in the scheduler's queue and is ready to run<br />
|-<br />
| 0x35<br />
| u8<br />
| Set to 1 when a thread is woken up from a svcSendSyncRequest call due to the ServerSession endpoint closing down<br />
|-<br />
| 0x36<br />
| s8<br />
| Indicates that the thread shall terminate<br />
|-<br />
| 0x37<br />
| u8<br />
| Used in syncing<br />
|-<br />
| 0x38<br />
| KDebugThread*<br />
| Pointer to KDebugThread object used with the current KThread<br />
|-<br />
| 0x3C<br />
| u32<br />
| Base thread priority<br />
|-<br />
| 0x40<br />
| u32<br />
| Pointer to object the KThread is waiting on- can be a timer, event, session, etc.<br />
|-<br />
| 0x44<br />
| Result<br />
| Status for object above<br />
|-<br />
| 0x48<br />
| KObjectMutex*<br />
| Locking kernel mutex<br />
|-<br />
| 0x4C<br />
| u32<br />
| Arbitration address<br />
|-<br />
| 0x50<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of objects this thread is waiting on<br />
|-<br />
| 0x54<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of objects this thread is <br />
|-<br />
| 0x5C<br />
| [[KMutex|KMutexLinkedList]] *<br />
| Set in some very specific circumstances<br />
|-<br />
| 0x60<br />
| u32<br />
| Count of KMutex objects this thread is using<br />
|-<br />
| 0x64<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x68<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x6C<br />
| s32<br />
| Dynamic thread priority<br />
|-<br />
| 0x70<br />
| s32<br />
| Processor that created the thread<br />
|-<br />
| 0x74<br />
| [[KResourceLimit|KPreemptionTimer]] *<br />
| Points to [[KResourceLimit]]+0x60, which among other things holds the amount of CPU time available in ticks, or NULL<br />
|-<br />
| 0x7C<br />
| u8<br />
| Thread is alive<br />
|-<br />
| 0x7D<br />
| u8<br />
| Thread has been terminated<br />
|-<br />
| 0x7E<br />
| u8<br />
| Thread affinity mask - set differently depending on whether the thread is created via svc call or from inside the kernel<br />
|-<br />
| 0x80<br />
| KProcess*<br />
| Process the thread belongs to (virtual address)<br />
|-<br />
| 0x84<br />
| u32<br />
| Thread id<br />
|-<br />
| 0x88<br />
| u32*<br />
| Ptr to svc mode register storage for KThread inside the thread context.<br />
|-<br />
| 0x8C<br />
| u32*<br />
| End-address of the page for this thread context allocated in the [[Memory_layout|0xFF4XX000]] region. Thus, if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000. Thread context page - used for thread svc stack, preserving svc mode registers and VFP exception register for thread.<br />
|-<br />
| 0x90<br />
| s32<br />
| Ideal processor (processorid value from [[SVC|svcCreateThread]])<br />
|-<br />
| 0x94<br />
| void*<br />
| Ptr to [[Thread Local Storage]]<br />
|-<br />
| 0x98<br />
| void*<br />
| Ptr to [[Thread Local Storage]] in FCRAM via kernel vmem<br />
|-<br />
| 0xA0<br />
| KThreadLinkedListNode<br />
| Previous and next scheduled threads<br />
|-<br />
| 0xA8<br />
| KThreadLinkedList *<br />
| Pointer to linked list of scheduled threads that has stolen it, or 0 if in normal list<br />
|-<br />
| 0xAC<br />
| s32<br />
| Priority field used for priority inheritance when needed<br />
|}<br />
<br />
With the following declarations: <code>struct KThreadLinkedList { KThread *first, *last; };</code> and <code>struct KThreadLinkedListNode { KThread *prev, *next; };</code>.<br />
<br />
=Thread Affinity Mask=<br />
<br />
If the thread is created via a call to SVC 8(CreateThread), which uses thread creation type 3, and the CPU ID is -2(meaning use the core specified in the exheader), the mask is just the affinity mask from the thread's owner KProcess. If the CPU ID is -1(meaning any core), the affinity mask is set to 0xF on the New3DS and 0x3 on the Old3DS. Otherwise, the affinity mask is (1 << cpu_id) | 1.<br />
<br />
If the thread is created via a call by the kernel, which uses thread creation types 0-2, the checks for -1 and -2 are skipped and the mask is always (1 << cpu_id) | 1.</div>Subvhttps://www.3dbrew.org/w/index.php?title=KThread&diff=19156KThread2017-01-05T12:55:51Z<p>Subv: </p>
<hr />
<div>[[Category:Kernel synchronization objects]]<br />
[[Category:Kernel interrupt events]]<br />
class [[KThread]] extends [[KSynchronizationObject]], [[KTimeableInterruptEvent]], [[KSendableInterruptEvent]] and [[KSchedulableInterruptEvent]];<br />
<br />
Size : 0xB0 bytes<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to vtable<br />
|-<br />
| 0x4<br />
| u32<br />
| Reference count<br />
|-<br />
| 0x8<br />
| u32<br />
| Count of KThreads that sync with this object - number of nodes in the linked list below<br />
|-<br />
| 0xC<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x10<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x14<br />
| [[KTimeableInterruptEvent]]<br />
| Used to suspend threads (*this)<br />
|-<br />
| 0x24<br />
| [[KSendableInterruptEvent]]<br />
| Interrupt event (*this) sent to terminate a thread, except in the case just below<br />
|-<br />
| 0x2C<br />
| [[KSchedulableInterruptEvent]]<br />
| Interrupt event (*this) scheduled by the IRQ handler when the thread should terminate (*this)<br />
|-<br />
| 0x34<br />
| u8<br />
| Whether the thread is in the scheduler's queue and is ready to run<br />
|-<br />
| 0x35<br />
| u8<br />
| Set to 1 when the thread is awakened after a call to svcSendSyncRequest, by the ServerSession endpoint closing down.<br />
|-<br />
| 0x36<br />
| s8<br />
| Indicates that the thread shall terminate<br />
|-<br />
| 0x37<br />
| u8<br />
| Used in syncing<br />
|-<br />
| 0x38<br />
| KDebugThread*<br />
| Pointer to KDebugThread object used with the current KThread<br />
|-<br />
| 0x3C<br />
| u32<br />
| Base thread priority<br />
|-<br />
| 0x40<br />
| u32<br />
| Pointer to object the KThread is waiting on- can be a timer, event, session, etc.<br />
|-<br />
| 0x44<br />
| Result<br />
| Status for object above<br />
|-<br />
| 0x48<br />
| KObjectMutex*<br />
| Locking kernel mutex<br />
|-<br />
| 0x4C<br />
| u32<br />
| Arbitration address<br />
|-<br />
| 0x50<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of objects this thread is waiting on<br />
|-<br />
| 0x54<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of objects this thread is <br />
|-<br />
| 0x5C<br />
| [[KMutex|KMutexLinkedList]] *<br />
| Set in some very specific circumstances<br />
|-<br />
| 0x60<br />
| u32<br />
| Count of KMutex objects this thread is using<br />
|-<br />
| 0x64<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x68<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x6C<br />
| s32<br />
| Dynamic thread priority<br />
|-<br />
| 0x70<br />
| s32<br />
| Processor that created the thread<br />
|-<br />
| 0x74<br />
| [[KResourceLimit|KPreemptionTimer]] *<br />
| Points to [[KResourceLimit]]+0x60, which among other things holds the amount of CPU time available in ticks, or NULL<br />
|-<br />
| 0x7C<br />
| u8<br />
| Thread is alive<br />
|-<br />
| 0x7D<br />
| u8<br />
| Thread has been terminated<br />
|-<br />
| 0x7E<br />
| u8<br />
| Thread affinity mask - set differently depending on whether the thread is created via svc call or from inside the kernel<br />
|-<br />
| 0x80<br />
| KProcess*<br />
| Process the thread belongs to (virtual address)<br />
|-<br />
| 0x84<br />
| u32<br />
| Thread id<br />
|-<br />
| 0x88<br />
| u32*<br />
| Ptr to svc mode register storage for KThread inside the thread context.<br />
|-<br />
| 0x8C<br />
| u32*<br />
| End-address of the page for this thread context allocated in the [[Memory_layout|0xFF4XX000]] region. Thus, if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000. Thread context page - used for thread svc stack, preserving svc mode registers and VFP exception register for thread.<br />
|-<br />
| 0x90<br />
| s32<br />
| Ideal processor (processorid value from [[SVC|svcCreateThread]])<br />
|-<br />
| 0x94<br />
| void*<br />
| Ptr to [[Thread Local Storage]]<br />
|-<br />
| 0x98<br />
| void*<br />
| Ptr to [[Thread Local Storage]] in FCRAM via kernel vmem<br />
|-<br />
| 0xA0<br />
| KThreadLinkedListNode<br />
| Previous and next scheduled threads<br />
|-<br />
| 0xA8<br />
| KThreadLinkedList *<br />
| Pointer to linked list of scheduled threads that has stolen it, or 0 if in normal list<br />
|-<br />
| 0xAC<br />
| s32<br />
| Priority field used for priority inheritance when needed<br />
|}<br />
<br />
With the following declarations: <code>struct KThreadLinkedList { KThread *first, *last; };</code> and <code>struct KThreadLinkedListNode { KThread *prev, *next; };</code>.<br />
<br />
=Thread Affinity Mask=<br />
<br />
If the thread is created via a call to SVC 8(CreateThread), which uses thread creation type 3, and the CPU ID is -2(meaning use the core specified in the exheader), the mask is just the affinity mask from the thread's owner KProcess. If the CPU ID is -1(meaning any core), the affinity mask is set to 0xF on the New3DS and 0x3 on the Old3DS. Otherwise, the affinity mask is (1 << cpu_id) | 1.<br />
<br />
If the thread is created via a call by the kernel, which uses thread creation types 0-2, the checks for -1 and -2 are skipped and the mask is always (1 << cpu_id) | 1.</div>Subvhttps://www.3dbrew.org/w/index.php?title=KThread&diff=18701KThread2016-12-03T05:25:06Z<p>Subv: </p>
<hr />
<div>[[Category:Kernel objects]]<br />
class [[KThread]] extends [[KSynchronizationObject]];<br />
<br />
Size : 0xB0 bytes<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to vtable<br />
|-<br />
| 0x4<br />
| u32<br />
| Reference count<br />
|-<br />
| 0x8<br />
| u32<br />
| Count of KThreads that sync with this object - number of nodes in the linked list below<br />
|-<br />
| 0xC<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x10<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x14<br />
| u32<br />
| Pointer to vtable for KThreadInterruptEvent<br />
|-<br />
| 0x18<br />
| u32<br />
| Pointer to object the thread is waiting on<br />
|-<br />
| 0x1C<br />
| s64<br />
| Timer for suspended thread<br />
|-<br />
| 0x24<br />
| u32<br />
| Start of 0x8 byte unnamed kernel object in KThread<br />
|-<br />
| 0x2C<br />
| u32<br />
| Start of unnamed kernel object of undetermined size in KThread<br />
|-<br />
| 0x34<br />
| u8<br />
| Whether the thread is in the scheduler's queue and is ready to run<br />
|-<br />
| 0x35<br />
| u8<br />
| Used in syncing<br />
|-<br />
| 0x36<br />
| s8<br />
| Important for syncing- seems to be based on the thread switch attempt count for the thread's core's KScheduler<br />
|-<br />
| 0x37<br />
| u8<br />
| Used in syncing<br />
|-<br />
| 0x38<br />
| KDebugThread*<br />
| Pointer to KDebugThread object used with the current KThread<br />
|-<br />
| 0x3C<br />
| u32<br />
| Base thread priority<br />
|-<br />
| 0x40<br />
| u32<br />
| Pointer to object the KThread is waiting on- can be a timer, event, session, etc.<br />
|-<br />
| 0x44<br />
| Result<br />
| Status for object above<br />
|-<br />
| 0x48<br />
| u32<br />
| Double pointer to KThread of unknown use/creation - used in scheduler<br />
|-<br />
| 0x4C<br />
| u32<br />
| Arbitration address<br />
|-<br />
| 0x50<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of objects this thread is waiting on<br />
|-<br />
| 0x54<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of objects this thread is <br />
|-<br />
| 0x5C<br />
| [[KSchedulableInterruptEvent|KMutexInterruptEvent]] *<br />
| Set in some very specific circumstances<br />
|-<br />
| 0x60<br />
| u32<br />
| Count of KMutex objects this thread is using<br />
|-<br />
| 0x64<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x68<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x6C<br />
| s32<br />
| Dynamic thread priority<br />
|-<br />
| 0x70<br />
| s32<br />
| Processor that created the thread<br />
|-<br />
| 0x74<br />
| u32<br />
| ?<br />
|-<br />
| 0x7C<br />
| u8<br />
| ?<br />
|-<br />
| 0x7D<br />
| u8<br />
| ?<br />
|-<br />
| 0x7E<br />
| u8<br />
| Thread affinity mask - set differently depending on whether the thread is created via svc call or from inside the kernel<br />
|-<br />
| 0x80<br />
| KProcess*<br />
| Process the thread belongs to (virtual address)<br />
|-<br />
| 0x84<br />
| u32<br />
| Thread id<br />
|-<br />
| 0x88<br />
| u32*<br />
| Ptr to svc mode register storage for KThread inside the thread context.<br />
|-<br />
| 0x8C<br />
| u32*<br />
| End-address of the page for this thread context allocated in the [[Memory_layout|0xFF4XX000]] region. Thus, if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000. Thread context page - used for thread svc stack, preserving svc mode registers and VFP exception register for thread.<br />
|-<br />
| 0x90<br />
| s32<br />
| Ideal processor (processorid value from [[SVC|svcCreateThread]])<br />
|-<br />
| 0x94<br />
| void*<br />
| Ptr to [[Thread Local Storage]]<br />
|-<br />
| 0x98<br />
| void*<br />
| Ptr to [[Thread Local Storage]] in FCRAM via kernel vmem<br />
|-<br />
| 0xA0<br />
| KThread*<br />
| Previous (virtual address)<br />
|-<br />
| 0xA4<br />
| KThread*<br />
| Next (virtual address)<br />
|-<br />
| 0xA8<br />
| struct { KThread* first; KThread* last; } ptr<br />
| Pointer to linked list that has stolen it, or 0 if in normal list<br />
|}<br />
<br />
<br />
=Thread Affinity Mask=<br />
<br />
If the thread is created via a call to SVC 8(CreateThread), which uses thread creation type 3, and the CPU ID is -2(meaning use the core specified in the exheader), the mask is just the affinity mask from the thread's owner KProcess. If the CPU ID is -1(meaning any core), the affinity mask is set to 0xF on the New3DS and 0x3 on the Old3DS. Otherwise, the affinity mask is (1 << cpu_id) | 1.<br />
<br />
If the thread is created via a call by the kernel, which uses thread creation types 0-2, the checks for -1 and -2 are skipped and the mask is always (1 << cpu_id) | 1.</div>Subvhttps://www.3dbrew.org/w/index.php?title=KThread&diff=18700KThread2016-12-03T05:20:25Z<p>Subv: </p>
<hr />
<div>[[Category:Kernel objects]]<br />
class [[KThread]] extends [[KSynchronizationObject]];<br />
<br />
Size : 0xB0 bytes<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to vtable<br />
|-<br />
| 0x4<br />
| u32<br />
| Reference count<br />
|-<br />
| 0x8<br />
| u32<br />
| Count of KThreads that sync with this object - number of nodes in the linked list below<br />
|-<br />
| 0xC<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x10<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KThreads that sync with this object<br />
|-<br />
| 0x14<br />
| u32<br />
| Pointer to vtable for KThreadInterruptEvent<br />
|-<br />
| 0x18<br />
| u32<br />
| Pointer to object the thread is waiting on<br />
|-<br />
| 0x1C<br />
| s64<br />
| Timer for suspended thread<br />
|-<br />
| 0x24<br />
| u32<br />
| Start of 0x8 byte unnamed kernel object in KThread<br />
|-<br />
| 0x2C<br />
| u32<br />
| Start of unnamed kernel object of undetermined size in KThread<br />
|-<br />
| 0x34<br />
| u8<br />
| Whether the thread is in the scheduler's queue and is ready to run<br />
|-<br />
| 0x35<br />
| u8<br />
| Used in syncing<br />
|-<br />
| 0x36<br />
| s8<br />
| Important for syncing- seems to be based on the thread switch attempt count for the thread's core's KScheduler<br />
|-<br />
| 0x37<br />
| u8<br />
| Used in syncing<br />
|-<br />
| 0x38<br />
| KDebugThread*<br />
| Pointer to KDebugThread object used with the current KThread<br />
|-<br />
| 0x3C<br />
| u32<br />
| Base thread priority<br />
|-<br />
| 0x40<br />
| u32<br />
| Pointer to object the KThread is waiting on- can be a timer, event, session, etc.<br />
|-<br />
| 0x44<br />
| Result<br />
| Status for object above<br />
|-<br />
| 0x48<br />
| u32<br />
| Double pointer to KThread of unknown use/creation - used in scheduler<br />
|-<br />
| 0x4C<br />
| u32<br />
| Arbitration address<br />
|-<br />
| 0x5C<br />
| [[KSchedulableInterruptEvent|KMutexInterruptEvent]] *<br />
| Set in some very specific circumstances<br />
|-<br />
| 0x60<br />
| u32<br />
| Count of KMutex objects this thread is using<br />
|-<br />
| 0x64<br />
| KLinkedListNode*<br />
| Pointer to first KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x68<br />
| KLinkedListNode*<br />
| Pointer to last KLinkedListNode in node list of KMutex objects this thread is using<br />
|-<br />
| 0x6C<br />
| s32<br />
| Dynamic thread priority<br />
|-<br />
| 0x70<br />
| s32<br />
| Processor that created the thread<br />
|-<br />
| 0x74<br />
| u32<br />
| ?<br />
|-<br />
| 0x7C<br />
| u8<br />
| ?<br />
|-<br />
| 0x7D<br />
| u8<br />
| ?<br />
|-<br />
| 0x7E<br />
| u8<br />
| Thread affinity mask - set differently depending on whether the thread is created via svc call or from inside the kernel<br />
|-<br />
| 0x80<br />
| KProcess*<br />
| Process the thread belongs to (virtual address)<br />
|-<br />
| 0x84<br />
| u32<br />
| Thread id<br />
|-<br />
| 0x88<br />
| u32*<br />
| Ptr to svc mode register storage for KThread inside the thread context.<br />
|-<br />
| 0x8C<br />
| u32*<br />
| End-address of the page for this thread context allocated in the [[Memory_layout|0xFF4XX000]] region. Thus, if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000. Thread context page - used for thread svc stack, preserving svc mode registers and VFP exception register for thread.<br />
|-<br />
| 0x90<br />
| s32<br />
| Ideal processor (processorid value from [[SVC|svcCreateThread]])<br />
|-<br />
| 0x94<br />
| void*<br />
| Ptr to [[Thread Local Storage]]<br />
|-<br />
| 0x98<br />
| void*<br />
| Ptr to [[Thread Local Storage]] in FCRAM via kernel vmem<br />
|-<br />
| 0xA0<br />
| KThread*<br />
| Previous (virtual address)<br />
|-<br />
| 0xA4<br />
| KThread*<br />
| Next (virtual address)<br />
|-<br />
| 0xA8<br />
| struct { KThread* first; KThread* last; } ptr<br />
| Pointer to linked list that has stolen it, or 0 if in normal list<br />
|}<br />
<br />
<br />
=Thread Affinity Mask=<br />
<br />
If the thread is created via a call to SVC 8(CreateThread), which uses thread creation type 3, and the CPU ID is -2(meaning use the core specified in the exheader), the mask is just the affinity mask from the thread's owner KProcess. If the CPU ID is -1(meaning any core), the affinity mask is set to 0xF on the New3DS and 0x3 on the Old3DS. Otherwise, the affinity mask is (1 << cpu_id) | 1.<br />
<br />
If the thread is created via a call by the kernel, which uses thread creation types 0-2, the checks for -1 and -2 are skipped and the mask is always (1 << cpu_id) | 1.</div>Subvhttps://www.3dbrew.org/w/index.php?title=Config_Savegame&diff=18673Config Savegame2016-11-29T22:28:11Z<p>Subv: </p>
<hr />
<div>This page describes the format of the [[Config_Services|Cfg]] [[System_SaveData|NAND]] savegame. These blocks can be accessed with the Cfg service commands.<br />
<br />
==Structure of save-file "/config"==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x2<br />
| Total entries<br />
|-<br />
| 0x2<br />
| 0x2<br />
| Data entries offset<br />
|-<br />
| 0x4<br />
| 0x4558<br />
| Block entries<br />
|-<br />
| 0x455C<br />
| <br />
| Data for the entries<br />
|}<br />
<br />
The filesize for this /config file is 0x8000-bytes.<br />
<br />
==Configuration block entry ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| BlkID<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Offset to the data for this block when size is >4, otherwise this word is the data for this block<br />
|-<br />
| 0x8<br />
| 0x2<br />
| Size<br />
|-<br />
| 0xA<br />
| 0x2<br />
| Flags<br />
|}<br />
<br />
==Configuration blocks==<br />
{| class="wikitable" border="1"<br />
|-<br />
! BlkID<br />
! Size<br />
! Flags<br />
! Description<br />
|-<br />
| 0x00000000<br />
| 0x2<br />
| 0xC<br />
| Config savegame version?<br />
|-<br />
| 0x00010000<br />
| 0x1<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00020000<br />
| 0x134<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00030000<br />
| 0x1<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00030001<br />
| 0x8<br />
| 0xE<br />
| User time offset (read by CECD)<br />
|-<br />
| 0x00030002<br />
| 0x8<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00040000<br />
| 0x10<br />
| 0xC<br />
| ? (read by HID)<br />
|-<br />
| 0x00040001<br />
| 0x1C<br />
| 0xC<br />
| ? (read by HID)<br />
|-<br />
| 0x00040002<br />
| 0x12<br />
| 0xC<br />
| ? (read by HID)<br />
|-<br />
| 0x00040003<br />
| 0xC<br />
| 0xC<br />
| ? (read by HID)<br />
|-<br />
| 0x00040004<br />
| 0x1C<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00050000<br />
| 0x2<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00050001<br />
| 0x2<br />
| 0xC<br />
| ? (read by GSP)<br />
|-<br />
| 0x00050002<br />
| 0x38<br />
| 0xC<br />
| ? (read by GSP)<br />
|-<br />
| 0x00050003<br />
| 0x20<br />
| 0xC<br />
| ? (read by GSP)<br />
|-<br />
| 0x00050004<br />
| 0x20<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00050005<br />
| 0x20<br />
| 0xE<br />
| Stereo display settings<br />
|-<br />
| 0x00050006<br />
| 0x2<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00050007<br />
| 0x4<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00050008<br />
| 0x10C<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00050009<br />
| 0x8<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00060000<br />
| 0x96<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00070000<br />
| 0x214<br />
| 0xE<br />
| ?<br />
|-<br />
| 0x00070001<br />
| 0x1<br />
| 0xE<br />
| Sound output mode (mono/stereo/surround)?<br />
|-<br />
| 0x00070002<br />
| 0x8<br />
| 0xE<br />
| ?<br />
|-<br />
| 0x00080000<br />
| 0xC00<br />
| 0xC<br />
| WiFi configuration slot 0<br />
|-<br />
| 0x00080001<br />
| 0xC00<br />
| 0xC<br />
| WiFi configuration slot 1<br />
|-<br />
| 0x00080002<br />
| 0xC00<br />
| 0xC<br />
| WiFi configuration slot 2<br />
|-<br />
| 0x00090000<br />
| 0x8<br />
| 0xE<br />
| This contains a u64 ID, used by processes using [[NWMUDS:InitializeWithVersion]]. The first word is the same as [[CfgS:GetLocalFriendCodeSeed|LocalFriendCodeSeed]], while the latter is a separate word.<br />
|-<br />
| 0x00090001<br />
| 0x8<br />
| 0xE<br />
| Same content as 0x0009000? This console-unique u64 used by [[Cfg:GenHashConsoleUnique|GenHashConsoleUnique]] is generated with the LocalFriendCodeSeed and with random data<br />
|-<br />
| 0x00090002<br />
| 0x4<br />
| 0xE<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| 0x1C<br />
| 0xE<br />
| Username<br />
|-<br />
| 0x000A0001<br />
| 0x2<br />
| 0xE<br />
| Birthday (u8 month, u8 day)<br />
|-<br />
| 0x000A0002<br />
| 0x1<br />
| 0xE<br />
| Language<br />
|-<br />
| 0x000B0000<br />
| 0x4<br />
| 0xE<br />
| CountryInfo<br />
|-<br />
| 0x000B0001<br />
| 0x800<br />
| 0xE<br />
| Country name in UTF-16, every 0x80-bytes is an entry for each language, in the order of the Language table below (not all entries are set)<br />
|-<br />
| 0x000B0002<br />
| 0x800<br />
| 0xE<br />
| State name in UTF-16, every 0x80-bytes is an entry for each language<br />
|-<br />
| 0x000B0003<br />
| 0x4<br />
| 0xE<br />
| Pair of 16-bit values, meaning unknown but related to address (ZIP code?)<br />
<br />
|-<br />
| 0x000C0000<br />
| 0xC0<br />
| 0xE<br />
| Restricted photo exchange data, and other info (includes a mirror of Parental Restrictions PIN/Secret Answer)<br />
|-<br />
| 0x000C0001<br />
| 0x14<br />
| 0xE<br />
| Same as above?<br />
|-<br />
| 0x000C0002<br />
| 0x200<br />
| 0xE<br />
| ? Contains the email address set during Parental Restriction setup.<br />
|-<br />
| 0x000D0000<br />
| 0x4<br />
| 0xE<br />
| u16 at offset 0x0: [[SMDH#EULA_Version|EULA Version]] which was agreed to.<br />
|-<br />
| 0x000E0000<br />
| 0x1<br />
| 0xE<br />
| ?<br />
|-<br />
| 0x000F0000<br />
| 0x10<br />
| 0xC<br />
| Unknown, used by [[NS]] on dev-units for [[SVC|svcKernelSetState]], where Type is 6. During NS startup on debug-units, NS compares the u32 from +8 in this config-block with the [[Configuration_Memory#APPMEMTYPE|APPMEMTYPE]]. When those don't match NS starts a FIRM-launch (with the same FIRM titleID as the currently running one) to boot into a FIRM with the APPMEMTYPE value from this config-block<br />
|-<br />
| 0x000F0001<br />
| 0x8<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x000F0003<br />
| 0x1<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x000F0004<br />
| 0x4<br />
| 0xC<br />
| The first u8 is the System-Model [[Cfg:GetSystemModel|value]], the last 3-bytes are unknown<br />
|-<br />
| 0x000F0005<br />
| 0x4<br />
| 0xC<br />
| The first u8 indicates whether network updates are enabled. (However, NIM only checks this flag with developer UNITINFO).<br />
|-<br />
| 0x000F0006<br />
| 0x28<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00100000<br />
| 0x2<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00100001<br />
| 0x94<br />
| 0xC<br />
| Stores Parental Restrictions PIN/Secret Answer and other info<br />
|-<br />
| 0x00100002<br />
| 0x1<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00100003<br />
| 0x10<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00110000<br />
| 0x4<br />
| 0xC<br />
| The low u16 indicates whether the system setup is required, such as when the system is booted for the first time or after doing a [[System Settings|System Format]]: 0 = setup required, non-zero = no setup required<br />
|-<br />
| 0x00110001<br />
| 0x8<br />
| 0xC<br />
| TitleID of the menu to launch, used by [[NS]] on dev units (this block can be edited on dev units with [[3DS Development Unit Software#Config|Config]])<br />
|-<br />
| 0x00120000<br />
| 0x8<br />
| 0xC<br />
| ? (read by HID)<br />
|-<br />
| 0x00130000<br />
| 0x4<br />
| 0xE<br />
| If response is 0x100 then debug mode is enabled.<br />
|-<br />
| 0x00150000<br />
| 0x4<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00150001<br />
| 0x8<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00150002<br />
| 0x4<br />
| 0xE<br />
| ?<br />
|-<br />
| 0x00160000<br />
| 0x4<br />
| 0xE<br />
| Unknown, first byte is used by config service-cmd [[Config_Services|0x00070040]]. (Unknown whether the last 3-bytes are used)<br />
|-<br />
| 0x00170000<br />
| 0x4<br />
| 0xE<br />
| ?<br />
|-<br />
| 0x00180000<br />
| 0x4<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00180001<br />
| 0x18<br />
| 0xC<br />
| ?<br />
|-<br />
| 0x00190000<br />
| 0x1<br />
| 0xC<br />
| Unknown. NFC-module checks for value1/non-value1.<br />
|}<br />
<br />
The developer unit TID block only exists on developer units.<br />
<br />
===Stereo Display Settings===<br />
All values are hard-coded in cfg module.<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Value<br />
! Description<br />
|-<br />
| 0x0<br />
| 4<br />
| 62.0f<br />
|assumed pupillary distance in mm?<br />
|-<br />
| 0x4<br />
| 4<br />
| 289.0f<br />
|assumed distance in mm between player's eyes and upper screen?<br />
|-<br />
| 0x8<br />
| 4<br />
| 76.80f<br />
|width in mm of (old) 3DS upper screen (doesn't vary for different models?)<br />
|-<br />
| 0xC<br />
| 4<br />
| 46.08f<br />
|height in mm of (old) 3DS upper screen (doesn't vary for different models?)<br />
|-<br />
| 0x10<br />
| 4<br />
| 10.0f<br />
|<br />
|-<br />
| 0x14<br />
| 4<br />
| 5.0f<br />
|<br />
|-<br />
| 0x18<br />
| 4<br />
| 55.58f<br />
|<br />
|-<br />
| 0x1C<br />
| 4<br />
| 21.57f<br />
|<br />
|}<br />
<br />
===Languages===<br />
{| class="wikitable" border="1"<br />
|-<br />
! ID<br />
! Description<br />
|-<br />
| 0<br />
| JP<br />
|-<br />
| 1<br />
| EN<br />
|-<br />
| 2<br />
| FR<br />
|-<br />
| 3<br />
| DE<br />
|-<br />
| 4<br />
| IT<br />
|-<br />
| 5<br />
| ES<br />
|-<br />
| 6<br />
| ZH<br />
|-<br />
| 7<br />
| KO<br />
|-<br />
| 8<br />
| NL<br />
|-<br />
| 9<br />
| PT<br />
|-<br />
| 10<br />
| RU<br />
|-<br />
| 11<br />
| TW<br />
|}<br />
<br />
===CountryInfo===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Byte<br />
! Description<br />
|-<br />
| 0<br />
|?<br />
|-<br />
| 1<br />
|?<br />
|-<br />
| 2<br />
|?<br />
|-<br />
| 3<br />
| Country code, same as DSi/Wii country codes. Value 0xFF is invalid.<br />
|}<br />
<br />
===0x000A0000 Block===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Byte<br />
! Description<br />
|-<br />
| 0x0-0x13<br />
| UTF-16 username, with no NULL-terminator.<br />
|-<br />
| 0x14-17<br />
| Usually zero?<br />
|-<br />
| 0x18-0x1B<br />
| u32 NGWord version the username was last checked with. If this value is less than the u32 stored in the NGWord CFA "romfs:/version.dat", the system then checks the username string with the bad-word list CFA again, then updates this field with the value from the CFA<br />
|}<br />
<br />
<br />
===LCD display config===<br />
There seems to be some sort of LCD display configuration stored in this cfg. When using the cfg-save from an Old3DS on a New3DS without formatting the cfg first, the bottom-screen display is somewhat off(which is fixed by formatting the cfg-save).<br />
<br />
<br />
===Parental control Block 0x00100001===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Byte<br />
! Size in bytes<br />
! Description<br />
|-<br />
| 0x0<br />
| 0xD<br />
| Unknown.<br />
|-<br />
| 0xD<br />
| 0x4<br />
| PIN<br />
|-<br />
| 0x11<br />
| ?<br />
| Secret answer in UTF-16<br />
|}</div>Subvhttps://www.3dbrew.org/w/index.php?title=DLPSRVR:Initialize&diff=18672DLPSRVR:Initialize2016-11-29T22:06:46Z<p>Subv: Copy paste error</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x00010183]<br />
|-<br />
| 1<br />
| Sharedmem size.<br />
|-<br />
| 2<br />
| u8 Max number of clients.<br />
|-<br />
| 3<br />
| Process Id<br />
|-<br />
| 4<br />
| u8 unk<br />
|-<br />
| 5<br />
| 0x40000<br />
|-<br />
| 6<br />
| 0x2<br />
|-<br />
| 7<br />
| MoveHandleDescriptor for 2 handles<br />
|-<br />
| 8<br />
| Shared mem handle<br />
|-<br />
| 9<br />
| Event handle<br />
|}<br />
<br />
=Description=<br />
This initializes the DLP server.</div>Subvhttps://www.3dbrew.org/w/index.php?title=DLP_Services&diff=18666DLP Services2016-11-29T20:36:40Z<p>Subv: /* Download Play Server Service "dlp:SRVR" */</p>
<hr />
<div>Download Play services are not used by the Download Play child application at all(the title which runs on the Download Play clients). This is used instead: [[APT:GetWirelessRebootInfo]]. The DLP-child is launched by the dlplay system-application the same way as any other system-application->system-application launching(besides using [[NSS:SetWirelessRebootInfo]]).<br />
<br />
There can only be one session open for each individual DLP service at a time.<br />
<br />
=Download Play Client Service "dlp:CLNT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x000100C3<br />
| ?<br />
| Initialize<br />
|-<br />
| 0x00020000<br />
| ?<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
| Unknown. Writes 0x18-bytes of output starting at cmdreply[2].<br />
|-<br />
| 0x00040000<br />
| ?<br />
| Unknown. Writes an output u16 to cmdreply[2].<br />
|-<br />
| 0x00050180<br />
| ?<br />
| ?<br />
|-<br />
| 0x00060000<br />
| ?<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0009....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000A....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000B....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000C....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000D....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000E....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000F....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0010....<br />
| ?<br />
| ?<br />
|-<br />
| 0x00110000<br />
| ?<br />
| [[DLP:GetWirelessRebootPassphrase|GetWirelessRebootPassphrase]]<br />
|-<br />
| 0x0012....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0013....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0014....<br />
| ?<br />
| ?<br />
|}<br />
<br />
=Download Play Server Service "dlp:SRVR"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010183<br />
| <br />
| [[DLPSRVR:Initialize|Initialize]]<br />
|-<br />
| 0x00020000<br />
| <br />
| Finalize<br />
|-<br />
| 0x00030000<br />
| <br />
| GetServerState<br />
|-<br />
| 0x00040000<br />
| <br />
| unknown...<br />
|-<br />
| 0x00050080<br />
| <br />
| StartAccepting<br />
|-<br />
| 0x00060000<br />
| <br />
| unknown...<br />
|-<br />
| 0x00070000<br />
| <br />
| StartDistribution<br />
|-<br />
| 0x000800C0<br />
| <br />
| [[DLPSRVR:SendWirelessRebootPassphrase|SendWirelessRebootPassphrase]]<br />
|-<br />
| 0x00090040<br />
| <br />
| AcceptClient<br />
|-<br />
| 0x000A0040<br />
| <br />
| unknown...<br />
|-<br />
| 0x000B0042<br />
| <br />
| GetConnectingClients<br />
|-<br />
| 0x000C0040<br />
| <br />
| GetClientInfo<br />
|-<br />
| 0x000D0040<br />
| <br />
| GetClientState<br />
|-<br />
| 0x000E0040<br />
| <br />
| unknown...<br />
|-<br />
| 0x000F0303<br />
| <br />
| unknown...<br />
|-<br />
| 0x00100000<br />
| <br />
| unknown...<br />
|}<br />
<br />
=Download Play Fake Client Service "dlp:FKCL"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010083<br />
| ?<br />
| Initialize<br />
|-<br />
| 0x0002....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0003....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0004....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0005....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0006....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0009....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000A....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000B....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000C....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000D....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000E....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000F0000<br />
| ?<br />
| [[DLP:GetWirelessRebootPassphrase|GetWirelessRebootPassphrase]]<br />
|-<br />
| 0x0010....<br />
| ?<br />
| Same as DLPCLNT cmd12.<br />
|-<br />
| 0x00110203<br />
| ?<br />
| Calls the same function as DLPFKCL:Initialize.<br />
|}<br />
<br />
=WirelessRebootPassphrase=<br />
This 9-byte UDS passphrase is sent by the DLP host application to the DLP clients via [[DLPSRVR:SendWirelessRebootPassphrase]]. The dlplay client system-application then loads it via [[DLP:GetWirelessRebootPassphrase]] for [[NSS:SetWirelessRebootInfo|setting]] the NS [[NS_and_APT_Services#WirelessRebootInfo|WirelessRebootInfo]]. Afterwards once launched, the DLP child application can then use [[APT:GetWirelessRebootInfo]] to load that data.<br />
<br />
Normally this a randomly-generated ASCII hex string, however it can be arbitrary. These strings are less than 9-bytes for some titles, the unused bytes are cleared to zero. This is the passphrase for the new UDS network which will be used by the clients and host for communicating, once the DLP child titles on those clients launch. This entire 9-byte passphrase is passed directly to the [[NWM_Services|UDS]] network connection/creation commands.</div>Subvhttps://www.3dbrew.org/w/index.php?title=DLPSRVR:Initialize&diff=18664DLPSRVR:Initialize2016-11-29T17:50:59Z<p>Subv: /* Request */</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x001B0302]<br />
|-<br />
| 1<br />
| Sharedmem size.<br />
|-<br />
| 2<br />
| u8 Max number of clients.<br />
|-<br />
| 3<br />
| Process Id<br />
|-<br />
| 4<br />
| u8 unk<br />
|-<br />
| 5<br />
| 0x40000<br />
|-<br />
| 6<br />
| 0x2<br />
|-<br />
| 7<br />
| MoveHandleDescriptor for 2 handles<br />
|-<br />
| 8<br />
| Shared mem handle<br />
|-<br />
| 9<br />
| Event handle<br />
|}<br />
<br />
=Description=<br />
This initializes the DLP server.</div>Subvhttps://www.3dbrew.org/w/index.php?title=DLP_Services&diff=18663DLP Services2016-11-29T17:39:38Z<p>Subv: </p>
<hr />
<div>Download Play services are not used by the Download Play child application at all(the title which runs on the Download Play clients). This is used instead: [[APT:GetWirelessRebootInfo]]. The DLP-child is launched by the dlplay system-application the same way as any other system-application->system-application launching(besides using [[NSS:SetWirelessRebootInfo]]).<br />
<br />
There can only be one session open for each individual DLP service at a time.<br />
<br />
=Download Play Client Service "dlp:CLNT"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x000100C3<br />
| ?<br />
| Initialize<br />
|-<br />
| 0x00020000<br />
| ?<br />
| ?<br />
|-<br />
| 0x00030000<br />
| ?<br />
| Unknown. Writes 0x18-bytes of output starting at cmdreply[2].<br />
|-<br />
| 0x00040000<br />
| ?<br />
| Unknown. Writes an output u16 to cmdreply[2].<br />
|-<br />
| 0x00050180<br />
| ?<br />
| ?<br />
|-<br />
| 0x00060000<br />
| ?<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0009....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000A....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000B....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000C....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000D....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000E....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000F....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0010....<br />
| ?<br />
| ?<br />
|-<br />
| 0x00110000<br />
| ?<br />
| [[DLP:GetWirelessRebootPassphrase|GetWirelessRebootPassphrase]]<br />
|-<br />
| 0x0012....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0013....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0014....<br />
| ?<br />
| ?<br />
|}<br />
<br />
=Download Play Server Service "dlp:SRVR"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010183<br />
| <br />
| [[DLPSRVR:Initialize|Initialize]]<br />
|-<br />
| 0x00020000<br />
| <br />
| Finalize<br />
|-<br />
| 0x00030000<br />
| <br />
| unknown...<br />
|-<br />
| 0x00040000<br />
| <br />
| unknown...<br />
|-<br />
| 0x00050080<br />
| <br />
| unknown...<br />
|-<br />
| 0x00060000<br />
| <br />
| unknown...<br />
|-<br />
| 0x00070000<br />
| <br />
| unknown...<br />
|-<br />
| 0x000800C0<br />
| <br />
| [[DLPSRVR:SendWirelessRebootPassphrase|SendWirelessRebootPassphrase]]<br />
|-<br />
| 0x00090040<br />
| <br />
| unknown...<br />
|-<br />
| 0x000A0040<br />
| <br />
| unknown...<br />
|-<br />
| 0x000B0042<br />
| <br />
| unknown...<br />
|-<br />
| 0x000C0040<br />
| <br />
| unknown...<br />
|-<br />
| 0x000D0040<br />
| <br />
| unknown...<br />
|-<br />
| 0x000E0040<br />
| <br />
| unknown...<br />
|-<br />
| 0x000F0303<br />
| <br />
| unknown...<br />
|-<br />
| 0x00100000<br />
| <br />
| unknown...<br />
|}<br />
<br />
=Download Play Fake Client Service "dlp:FKCL"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x00010083<br />
| ?<br />
| Initialize<br />
|-<br />
| 0x0002....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0003....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0004....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0005....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0006....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
| ?<br />
|-<br />
| 0x0009....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000A....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000B....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000C....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000D....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000E....<br />
| ?<br />
| ?<br />
|-<br />
| 0x000F0000<br />
| ?<br />
| [[DLP:GetWirelessRebootPassphrase|GetWirelessRebootPassphrase]]<br />
|-<br />
| 0x0010....<br />
| ?<br />
| Same as DLPCLNT cmd12.<br />
|-<br />
| 0x00110203<br />
| ?<br />
| Calls the same function as DLPFKCL:Initialize.<br />
|}<br />
<br />
=WirelessRebootPassphrase=<br />
This 9-byte UDS passphrase is sent by the DLP host application to the DLP clients via [[DLPSRVR:SendWirelessRebootPassphrase]]. The dlplay client system-application then loads it via [[DLP:GetWirelessRebootPassphrase]] for [[NSS:SetWirelessRebootInfo|setting]] the NS [[NS_and_APT_Services#WirelessRebootInfo|WirelessRebootInfo]]. Afterwards once launched, the DLP child application can then use [[APT:GetWirelessRebootInfo]] to load that data.<br />
<br />
Normally this a randomly-generated ASCII hex string, however it can be arbitrary. These strings are less than 9-bytes for some titles, the unused bytes are cleared to zero. This is the passphrase for the new UDS network which will be used by the clients and host for communicating, once the DLP child titles on those clients launch. This entire 9-byte passphrase is passed directly to the [[NWM_Services|UDS]] network connection/creation commands.</div>Subvhttps://www.3dbrew.org/w/index.php?title=DLPSRVR:Initialize&diff=18662DLPSRVR:Initialize2016-11-29T17:39:25Z<p>Subv: Created page with "=Request= {| class="wikitable" border="1" |- ! Index Word ! Description |- | 0 | Header code [0x001B0302] |- | 1 | Sharedmem size. |- | 2 | u8 unk |- | 3 | Process Id |- | 4..."</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x001B0302]<br />
|-<br />
| 1<br />
| Sharedmem size.<br />
|-<br />
| 2<br />
| u8 unk<br />
|-<br />
| 3<br />
| Process Id<br />
|-<br />
| 4<br />
| u8 unk<br />
|-<br />
| 5<br />
| 0x40000<br />
|-<br />
| 6<br />
| 0x2<br />
|-<br />
| 7<br />
| MoveHandleDescriptor for 2 handles<br />
|-<br />
| 8<br />
| Shared mem handle<br />
|-<br />
| 9<br />
| Event handle<br />
|}<br />
<br />
=Description=<br />
This initializes the DLP server.</div>Subvhttps://www.3dbrew.org/w/index.php?title=Memory_layout&diff=17042Memory layout2016-04-19T22:21:40Z<p>Subv: /* NATIVE_FIRM/SAFE_MODE_FIRM Userland Memory */</p>
<hr />
<div>= Physical Memory =<br />
<br />
== ARM11 ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Old 3DS<br />
! Address<br />
! Size<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0x00000000<br />
| 0x00010000<br />
| Bootrom (super secret code/data @ 0x8000)<br />
|-<br />
| style="background: green" | Yes<br />
| 0x00010000<br />
| 0x00010000<br />
| Bootrom mirror<br />
|-<br />
| style="background: green" | Yes<br />
| 0x10000000<br />
|?<br />
| [[IO]] memory<br />
|-<br />
| style="background: green" | Yes<br />
| 0x17E00000<br />
| 0x00002000<br />
| MPCore private memory region<br />
<br />
|-<br />
| style="background: red" | No<br />
| 0x17E10000<br />
| 0x00001000<br />
| L2C-310 Level 2 Cache Controller (2MB)<br />
|-<br />
| style="background: green" | Yes<br />
| 0x18000000<br />
| 0x00600000<br />
| VRAM (divided in two banks, VRAM and VRAMB)<br />
|-<br />
| style="background: red" | No<br />
| 0x1F000000<br />
| 0x00400000<br />
| [[New_3DS]] additional memory<br />
|-<br />
| style="background: green" | Yes<br />
| 0x1FF00000<br />
| 0x00080000<br />
| DSP memory<br />
|-<br />
| style="background: green" | Yes<br />
| 0x1FF80000<br />
| 0x00080000<br />
| AXI WRAM<br />
|-<br />
| style="background: green" | Yes<br />
| 0x20000000<br />
| 0x08000000<br />
| FCRAM<br />
|-<br />
| style="background: red" | No<br />
| 0x28000000<br />
| 0x08000000<br />
| [[New_3DS]] FCRAM extension<br />
|-<br />
| style="background: green" | Yes<br />
| 0xFFFF0000<br />
| 0x00010000<br />
| Bootrom mirror<br />
|}<br />
<br />
===0x17E10000===<br />
The 32bit register at 0x17E10000+0x100 only has bit0 set when, on New3DS, [[PTMSYSM:ConfigureNew3DSCPU]] was used with bit1 set for the input value(the L2 cache flag). All other bits in this register are normally all-zero. Therefore: bit0 set = new cache hardware enabled, clear = new cache hardware disabled(this bit is how the ARM11-kernel checks whether the additional cache hw is enabled).<br />
<br />
To enable the additional cache hw, the following is used by the ARM11-kernel:<br />
* Sets bit0 in 32bit register 0x17E10000+0x100.<br />
<br />
To disable the additional cache hw, the following is used by the ARM11-kernel:<br />
* Writes value 0xFFFF to 32bit register 0x17E10000+0x77C.<br />
* Waits for bit0 in 32bit register 0x17E10000+0x730 to become clear.<br />
* Writes value 0x0 to 32bit register 0x17E10000+0x0.<br />
* Clears bit0 in 32bit register 0x17E10000+0x100.<br />
<br />
=== 0x1F000000 ([[New_3DS]]-only) ===<br />
This area is used by [[QTM Services]](starting at offset 0x200000, size 0x180000). This area is not accessible to the GPU on the old 3DS. The old 3DS and New 3DS GSP module has vaddr->physaddr conversion code for this entire region. On the New 3DS, only the first 0x200000-bytes (half of this memory) are accessible to the GPU.<br />
<br />
== ARM9 ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Old 3DS<br />
! Address<br />
! Size<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0x00000000<br />
| 0x08000000<br />
| Instruction TCM, repeating each 0x8000 bytes.<br />
|-<br />
| style="background: green" | Yes<br />
| 0x01FF8000<br />
| 0x00008000<br />
| Instruction TCM (Accessed by the kernel and process by this address)<br />
|-<br />
| style="background: green" | Yes<br />
| 0x07FF8000<br />
| 0x00008000<br />
| Instruction TCM (Accessed by bootrom by this address)<br />
|-<br />
| style="background: green" | Yes<br />
| 0x08000000<br />
| 0x00100000<br />
| ARM9-only internal memory (ARM7's internal regions are mapped here as well)<br />
|-<br />
| style="background: red" | No<br />
| 0x08100000<br />
| 0x00080000<br />
| [[New_3DS]] ARM9-only extension, only enabled when a certain [[CONFIG_Registers|CONFIG]] register is set.<br />
|-<br />
| style="background: green" | Yes<br />
| 0x10000000<br />
| 0x08000000<br />
| [[IO]] memory<br />
|-<br />
| style="background: green" | Yes<br />
| 0x18000000<br />
| 0x00600000<br />
| VRAM (divided in two banks, VRAM and VRAMB) <br />
|-<br />
| style="background: green" | Yes<br />
| 0x1FF00000<br />
| 0x00080000<br />
| DSP memory<br />
|-<br />
| style="background: green" | Yes<br />
| 0x1FF80000<br />
| 0x00080000<br />
| AXI WRAM<br />
|-<br />
| style="background: green" | Yes<br />
| 0x20000000<br />
| 0x08000000<br />
| FCRAM<br />
|-<br />
| style="background: red" | No<br />
| 0x28000000<br />
| 0x08000000<br />
| [[New_3DS]] FCRAM extension<br />
|-<br />
| style="background: green" | Yes<br />
| 0xFFF00000<br />
| 0x00004000<br />
| Data TCM (Mapped during bootrom)<br />
|-<br />
| style="background: green" | Yes<br />
| 0xFFFF0000<br />
| 0x00010000<br />
| Bootrom, the main region is at +0x8000, which is disabled during system boot.<br />
|}<br />
<br />
==ARM9 MPU Regions==<br />
For the below instruction permissions: RO = memory is executable, while None = not-executable.<br />
<br />
===NATIVE_FIRM/SAFE_MODE_FIRM ARM9 kernel===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Region<br />
! Address<br />
! Size<br />
! Privileged-mode data permissions<br />
! User-mode data permissions<br />
! Privileged-mode instruction permissions<br />
! User-mode instruction permissions<br />
|-<br />
| 0<br />
| 0xFFFF0000<br />
| 32KB/0x8000<br />
| RO<br />
| None<br />
| RO<br />
| None<br />
|-<br />
| 1<br />
| 0x01FF8000<br />
| 32KB/0x8000<br />
| RW<br />
| RW<br />
| RO<br />
| RO<br />
|-<br />
| 2<br />
| 0x08000000<br />
| 1MB/0x100000. >=[[8.0.0-18|8.0.0-X]]: 2MB/0x200000.<br />
| RW<br />
| RW<br />
| RO<br />
| RO<br />
|-<br />
| 3<br />
| 0x10000000<br />
| 128KB/0x20000<br />
| RW<br />
| RW<br />
| None<br />
| None<br />
|-<br />
| 4<br />
| 0x10100000<br />
| 512KB/0x80000<br />
| RW<br />
| RW<br />
| None<br />
| None<br />
|-<br />
| 5<br />
| 0x20000000<br />
| 128MB/0x8000000. >=[[8.0.0-18|8.0.0-X]]: 256MB/0x10000000.<br />
| RW<br />
| RW<br />
| None<br />
| None<br />
|-<br />
| 6<br />
| 0x08000000<br />
| 128KB/0x20000<br />
| RW<br />
| None<br />
| RO<br />
| None<br />
|-<br />
| 7<br />
| 0x08020000<br />
| <[[3.0.0-5]]: 64KB/0x10000. >=[[3.0.0-5]]: 32KB/0x8000.<br />
| RW<br />
| None<br />
| RO<br />
| None<br />
|}<br />
<br />
The above is the MPU region settings setup by the ARM9-kernel in the crt0.<br />
<br />
The New3DS ARM9-kernel MPU region settings are the same as the Old3DS MPU region settings for >=[[8.0.0-18|8.0.0-X]].<br />
<br />
At the start of the Process9 function executed in kernel-mode via svc7b during firm-launching, it changes some MPU region settings. At the end of that function, before it uses the ARM9/ARM11 entrypoint fields, it disables MPU.<br />
<br />
===New3DS [[FIRM|ARM9-loader]]===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Region<br />
! Address<br />
! Size<br />
! Privileged-mode data permissions<br />
! User-mode data permissions<br />
! Privileged-mode instruction permissions<br />
! User-mode instruction permissions<br />
|-<br />
| 0<br />
| 0xFFFF0000<br />
| 32KB/0x8000<br />
| RO<br />
| None<br />
| RO<br />
| None<br />
|-<br />
| 1<br />
| 0x01FF8000<br />
| 32KB/0x8000<br />
| RW<br />
| None<br />
| RO<br />
| None<br />
|-<br />
| 2<br />
| 0x08000000<br />
| 2MB/0x200000<br />
| RW<br />
| None<br />
| RO<br />
| None<br />
|-<br />
| 3<br />
| 0x10000000<br />
| 128KB/0x20000<br />
| RW<br />
| None<br />
| None<br />
| None<br />
|}<br />
<br />
MPU regions 4-7 are disabled. Note that the entire ARM9-loader runs in SVC-mode.<br />
<br />
===TWL_FIRM/AGB_FIRM ARM9 kernel===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Region<br />
! Address<br />
! Size<br />
! Privileged-mode data permissions<br />
! User-mode data permissions<br />
! Privileged-mode instruction permissions<br />
! User-mode instruction permissions<br />
|-<br />
| 0<br />
| 0xFFFF0000<br />
| 32KB/0x8000<br />
| RO<br />
| None<br />
| RO<br />
| None<br />
|-<br />
| 1<br />
| 0x01FF8000<br />
| 32KB/0x8000<br />
| RW<br />
| RW<br />
| RO<br />
| RO<br />
|-<br />
| 2<br />
| 0x08000000<br />
| 1MB/0x100000. New3DS: 2MB/0x200000.<br />
| RW<br />
| RW<br />
| RO<br />
| RO<br />
|-<br />
| 3<br />
| 0x10000000<br />
| 2MB/0x200000.<br />
| RW<br />
| RW<br />
| None<br />
| None<br />
|-<br />
| 4<br />
| 0x1FF00000<br />
| 512KB/0x80000<br />
| RW<br />
| RW<br />
| None<br />
| None<br />
|-<br />
| 5<br />
| 0x20000000<br />
| 128MB/0x8000000. New3DS: 256MB/0x10000000.<br />
| RW<br />
| RW<br />
| None<br />
| None<br />
|-<br />
| 6<br />
| 0x08000000<br />
| <[[3.0.0-5|3.0.0-X]]: 256KB/0x40000. >=[[3.0.0-5|3.0.0-X]]: 128KB/0x20000<br />
| RW<br />
| None<br />
| RO<br />
| None<br />
|-<br />
| 7<br />
| 0x08080000<br />
| 128KB/0x20000<br />
| RW<br />
| RW<br />
| RO<br />
| RO<br />
|}<br />
<br />
==ARM9 ITCM==<br />
{| class="wikitable" border="1"<br />
|-<br />
! ITCM mirror address<br />
! ITCM bootrom mirror address<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x01FF8000<br />
| <br />
| 0x0<br />
| 0x3700<br />
| Uninitialized memory.<br />
|-<br />
| 0x01FFB700<br />
| 0x07FFB700<br />
| 0x3700<br />
| 0x100<br />
| The unprotected ARM9-bootrom code copies code from unprotected bootrom to 0x07FFB700(ITCM mirror) size 0x100, then calls the code at 0x07FFB700. The code located here is the code used for disabling access to the bootroms.<br />
|-<br />
| 0x01FFB800<br />
| <br />
| 0x3800<br />
| 0x4<br />
| This is always 0xDEADB00F.<br />
|-<br />
| 0x01FFB804<br />
| <br />
| 0x3804<br />
| 0x4<br />
| This is the u32 DeviceId.<br />
|-<br />
| 0x01FFB808<br />
| <br />
| 0x3808<br />
| 0x10<br />
| This is the fall-back keyY used for movable.sed keyY when movable.sed doesn't exist in NAND(the last two words here are used on retail for generating console-unique TWL keydata/etc). This is also used for "LocalFriendCodeSeed", etc.<br />
|-<br />
| 0x01FFB818<br />
| <br />
| 0x3818<br />
| 0x1<br />
| ?<br />
|-<br />
| 0x01FFB819<br />
| <br />
| 0x3819<br />
| 0x1<br />
| This is the [[CTCert]] issuer type: 0 = retail "Nintendo CA - G3_NintendoCTR2prod", non-zero = dev "Nintendo CA - G3_NintendoCTR2dev".<br />
|-<br />
| 0x01FFB81A<br />
| <br />
| 0x381A<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x01FFB820<br />
| <br />
| 0x3820<br />
| 0x4<br />
| This is the CTCert ECDSA exponent, this is byte-swapped when *((u8*)(0x01FFB800+0x18)) is >=5.<br />
|-<br />
| 0x01FFB824<br />
| <br />
| 0x3824<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x01FFB826<br />
| <br />
| 0x3826<br />
| 0x1E<br />
| This is the CTCert ECDSA privk.<br />
|-<br />
| 0x01FFB844<br />
| <br />
| 0x3844<br />
| 0x3C<br />
| This is the CTCert ECDSA signature.<br />
|-<br />
| 0x01FFB880<br />
| <br />
| 0x3880<br />
| 0x80<br />
| This is all-zero.<br />
|-<br />
| 0x01FFB900<br />
| <br />
| 0x3900<br />
| 0x200<br />
| This is the 0x200-bytes from NAND sector0.<br />
|-<br />
| 0x01FFBB00<br />
| <br />
| 0x3B00<br />
| 0x200<br />
| This is the 0x200-bytes from the plaintext NAND firm partition FIRM header, read by bootrom.<br />
|-<br />
| 0x01FFBD00<br />
| <br />
| 0x3D00<br />
| 0x100<br />
| This is the RSA-2048 modulus for [[RSA_Registers|RSA]]-engine slot0 set by bootrom.<br />
|-<br />
| 0x01FFBE00<br />
| <br />
| 0x3E00<br />
| 0x100<br />
| This is the RSA-2048 modulus for RSA-engine slot1 set by bootrom.<br />
|-<br />
| 0x01FFBF00<br />
| <br />
| 0x3F00<br />
| 0x100<br />
| This is the RSA-2048 modulus for RSA-engine slot2.<br />
|-<br />
| 0x01FFC000<br />
| <br />
| 0x4000<br />
| 0x100<br />
| This is the RSA-2048 modulus for RSA-engine slot3.<br />
|-<br />
| 0x01FFC100<br />
| <br />
| 0x4100<br />
| 0x800<br />
| These are RSA-2048 keys: 4 slots, each slot is 0x200-bytes. Slot+0 is the modulus, slot+0x100 is the private exponent. This can be confirmed by RSA-decrypting a message into a signature, then RSA-encrypting the signature back into a message, and comparing the original message with the output from the last operation.<br />
<br />
[[FIRM]] doesn't seem to ever use these. None of these are related to RSA-keyslot0 used for v6.0/v7.0 key generation. These moduli are separate from all other moduli used elsewhere.<br />
|-<br />
| 0x01FFC900<br />
| 0x07FFC900<br />
| 0x4900<br />
| 0x400<br />
| The unprotected ARM9-bootrom copies data to 0x07FFC900(mirror of 0x01FFC900) size 0x400. This data is copied from AXI WRAM, initialized by ARM11-bootrom(the addr used for the src is determined by [[CONFIG_Registers|REG_UNITINFO]]). These are RSA moduli: retailsrcptr = 0x1FFFD000, devsrvptr = 0x1FFFD400.<br />
* The first 0x100-bytes here is the RSA-2048 modulus for the CFA NCCH header, and for the gamecard NCSD header.<br />
* 0x01FFCA00 is the RSA-2048 modulus for the CXI accessdesc signature, written to rsaengine keyslot1 by NATIVE_FIRM.<br />
* 0x01FFCB00 size 0x200 is unknown, probably RSA related, these aren't used by [[FIRM]](these are not console-unique).<br />
|-<br />
| 0x01FFCD00<br />
| <br />
| 0x4D00<br />
| 0x80<br />
| Unknown, not used by [[FIRM]]. This isn't console-unique.<br />
The first 0x10-bytes are checked by the v6.0/v7.0 NATIVE_FIRM keyinit function, when non-zero it clears this block and continues to do the key generation. Otherwise when this block was already all-zero, it immediately returns. This memclear was probably an attempt at destroying the RSA slot0 modulus, that missed (exactly 0x1000-bytes away). Even though they "failed" here, one would still need to derive the private exponent, which would require obtaining a ciphertext and plaintext.<br />
|-<br />
| 0x01FFCD80<br />
| <br />
| 0x4D80<br />
| 0x64<br />
| 0x01FFCD84 size 0x10-bytes is the NAND CID(the 0x64-byte region at 0x01FFCD80 is initialized by Process9 + ARM9-bootrom). The u32 at 0x01FFCDC4 is the total number of NAND sectors, read from a MMC command.<br />
|-<br />
| 0x01FFCDE4<br />
| <br />
| 0x4DE4<br />
| 0x21C<br />
| Uninitialized memory.<br />
|-<br />
| 0x01FFD000<br />
| 0x07FFD000<br />
| 0x5000<br />
| 0x2470<br />
| The unprotected ARM9-bootrom copies 0x1FFFA000(AXIWRAM mem initialized by ARM11-bootrom) size 0x2470 to 0x07FFD000(mirror of 0x01FFD000). This block contains DSi keys.<br />
* 0x01FFD000 is the RSA-1024 modulus for the retail System Menu<br />
* 0x01FFD080 is the RSA-1024 modulus for DSi Wifi firmware and DSi Sound<br />
* 0x01FFD100 is the RSA-1024 modulus for base DSi apps (Settings, Shop, etc.)<br />
* 0x01FFD180 is the RSA-1024 modulus for DSiWare and RSA-signed cartridge headers<br />
* 0x01FFD210 is the keyY for per-console-encrypted ES blocks<br />
* 0x01FFD220 is the keyY for fixed-keyX ES blocks<br />
* 0x01FFD300 is the DSi common (normal)key<br />
* 0x01FFD350 is a normalkey set on keyslot 0x02, and is likely only used during boot<br />
* 0x01FFD380 is the keyslot 0x00 keyX and the first half of the retail keyX for modcrypt crypto "Nintendo"<br />
* 0x01FFD398 is the keyX used for 'Tad' crypto, usually in keyslot 0x02 "Nintendo DS", ..<br />
* 0x01FFD3A8 is set as the middle two words of keyslot 0x03's keyX, before being overwritten "NINTENDO"<br />
* 0x01FFD3BC is the keyY for keyslot 0x01, see below<br />
* 0x01FFD3C8 is the fixed keyY used for eMMC partition crypto on retail DSi, see below (keyslot 0x03)<br />
* 0x01FFD3E0 is the 0x1048-byte Blowfish data for DSi cart crypto<br />
* 0x01FFE428 is the 0x1048-byte Blowfish data for DS cart crypto<br />
On the 3DS, keyslots 0x01 and 0x03 have the last word set as 0xE1A00005 instead of the next word in ITCM. This is consistent with retail DSis.<br />
|-<br />
| 0x01FFF470<br />
| <br />
| 0x7470<br />
| 0xB90<br />
| Uninitialized memory.<br />
0x01FFFC00 size 0x100-bytes starting with [[9.5.0-22|9.5.0-X]] is the FIRM header used during FIRM-launching.<br />
|}<br />
<br />
=Memory map by firmware=<br />
* [[Virtual address mapping FW0B]]<br />
* [[Virtual address mapping FW1F]]<br />
* [[Virtual address mapping FW25]]<br />
* [[Virtual address mapping FW2E]]<br />
* [[Virtual address mapping FW37]]<br />
* [[Virtual address mapping FW38]]<br />
* [[Virtual address mapping FW3F]]<br />
* FW49([[9.6.0-24|9.6.0-X]]) and [[10.0.0-27|10.0.0-X]] ARM11-kernel vmem mapping is identical to FW40([[9.5.0-22|9.5.0-X]]).<br />
<br />
<br />
* [[Virtual address mapping TWLFIRM04]]<br />
<br />
<br />
* [[Virtual address mapping New3DS v8.1]]<br />
* [[Virtual address mapping New3DS v9.0]]<br />
* [[Virtual address mapping New3DS v9.2]]<br />
<br />
=ARM11 Detailed physical memory map=<br />
18000000 - 18600000: VRAM<br />
<br />
1FF80000 - 1FFAB000: Kernel code<br />
1FFAB000 - 1FFF0000: SlabHeap [temporarily contains boot processes]<br />
1FFF0000 - 1FFF1000: ?<br />
1FFF1000 - 1FFF2000: ?<br />
1FFF2000 - 1FFF3000: ?<br />
1FFF3000 - 1FFF4000: ?<br />
1FFF4000 - 1FFF5000: Exception vectors<br />
1FFF5000 - 1FFF5800: Unused?<br />
1FFF5800 - 1FFF5C00: 256-entry L2 MMU table for VA FF4xx000<br />
1FFF5C00 - 1FFF6000: 256-entry L2 MMU table for VA FF5xx000<br />
1FFF6000 - 1FFF6400: 256-entry L2 MMU table for VA FF6xx000<br />
1FFF6400 - 1FFF6800: 256-entry L2 MMU table for VA FF7xx000<br />
1FFF6800 - 1FFF6C00: 256-entry L2 MMU table for VA FF8xx000<br />
1FFF6C00 - 1FFF7000: 256-entry L2 MMU table for VA FF9xx000<br />
1FFF7000 - 1FFF7400: 256-entry L2 MMU table for VA FFAxx000<br />
1FFF7400 - 1FFF7800: 256-entry L2 MMU table for VA FFBxx000<br />
1FFF7800 - 1FFF7C00: MMU table but unused?<br />
1FFF7C00 - 1FFF8000: 256-entry L2 MMU table for VA FFFxx000 <br />
1FFF8000 - 1FFFC000: 4096-entry L1 MMU table for VA xxx00000 (CPU 0)<br />
1FFFC000 - 20000000: 4096-entry L1 MMU table for VA xxx00000 (CPU 1)<br />
20000000 - 28000000: Main memory<br />
<br />
The entire FCRAM is cleared during NATIVE_FIRM boot. This is done by the ARM11 kernel in order by region as it initializes after loading [[FIRM]] launch parameters from FCRAM.<br />
<br />
== FCRAM memory-regions layout ==<br />
{| class="wikitable" border="1"<br />
! [[Configuration_Memory#APPMEMTYPE|Configmem-APPMEMTYPE]] Value<br />
! Base address relative to FCRAM+0, for APPLICATION mem-region<br />
! Region size, for APPLICATION mem-region<br />
! Base address relative to FCRAM+0, for SYSTEM mem-region<br />
! Region size, for SYSTEM mem-region<br />
! Base address relative to FCRAM+0, for BASE mem-region<br />
! Region size, for BASE mem-region<br />
|-<br />
| 0 (default with regular 3DS kernel, used when the type is not 2-5)<br />
| 0x0<br />
| 0x04000000(64MB)<br />
| 0x04000000<br />
| 0x02C00000<br />
| 0x06C00000<br />
| 0x01400000<br />
|-<br />
| 2<br />
| 0x0<br />
| 0x06000000(96MB)<br />
| 0x06000000<br />
| 0x00C00000<br />
| 0x06C00000<br />
| 0x01400000<br />
|-<br />
| 3<br />
| 0x0<br />
| 0x05000000(80MB)<br />
| 0x05000000<br />
| 0x01C00000<br />
| 0x06C00000<br />
| 0x01400000<br />
|-<br />
| 4<br />
| 0x0<br />
| 0x04800000(72MB)<br />
| 0x04800000<br />
| 0x02400000<br />
| 0x06C00000<br />
| 0x01400000<br />
|-<br />
| 5<br />
| 0x0<br />
| 0x02000000(32MB)<br />
| 0x02000000<br />
| 0x04C00000<br />
| 0x06C00000<br />
| 0x01400000<br />
|-<br />
| 6 (This is the default on New3DS. With [[New_3DS]] kernel this is the type used when the value is not 7)<br />
| 0x0<br />
| 0x07C00000(124MB)<br />
| 0x07C00000<br />
| 0x06400000<br />
| 0x0E000000<br />
| 0x02000000<br />
|-<br />
| 7<br />
| 0x0<br />
| 0x0B200000(178MB)<br />
| 0x0B200000<br />
| 0x02E00000<br />
| 0x0E000000<br />
| 0x02000000<br />
|}<br />
<br />
The SYSTEM mem-region size is calculated with: size = FCRAMTOTALSIZE - (APPLICATION_MEMREGIONSIZE + BASE_MEMREGIONSIZE).<br />
<br />
Support for type6/7 was [[NCCH/Extended Header|implemented]] in [[NS]] with [[8.0.0-18]], these are only supported in the [[New_3DS]] ARM11-kernel not the regular 3DS kernel. These two types are the only ones supported by the New3DS kernel.<br />
<br />
All memory allocated by the kernel itself for kernel use is located under BASE. Most system-modules run under the BASE memregion too.<br />
<br />
Free/used memory on [[4.5.0-10]] with Home Menu / Internet Browser, with the default APPMEMTYPE on retail:<br />
{| class="wikitable" border="1"<br />
! Region<br />
! Base address relative to FCRAM+0<br />
! Region size<br />
! Used memory once [[Home Menu]] finishes loading for system boot, on [[4.5.0-10]]<br />
! Used memory with [[Internet Browser]] running instead of [[Home Menu]], on [[4.5.0-10]]<br />
! Free memory once [[Home Menu]] finishes loading for system boot, on [[4.5.0-10]]<br />
! Free memory with [[Internet Browser]] running instead of [[Home Menu]], on [[4.5.0-10]]<br />
|-<br />
| APPLICATION<br />
| 0x0<br />
| 0x04000000<br />
| 0x0<br />
| <br />
| 0x04000000<br />
| <br />
|-<br />
| SYSTEM<br />
| 0x04000000<br />
| 0x02C00000<br />
| 0x01488000<br />
| 0x02A50000<br />
| 0x01778000<br />
| 0x001B0000<br />
|-<br />
| BASE<br />
| 0x06C00000<br />
| 0x01400000<br />
| 0x01202000<br />
| 0x01236000<br />
| 0x001FE000<br />
| 0x001CA000<br />
|}<br />
<br />
=ARM11 Detailed virtual memory map=<br />
(valid only for FW0B, see [[#Memory map by firmware|Memory map by firmware]] for subsequent versions)<br />
<br />
E8000000 - E8600000: mapped VRAM (18000000 - 18600000)<br />
<br />
EFF00000 - F0000000: mapped Internal memory (1FF00000 - 20000000)<br />
F0000000 - F8000000: mapped Main memory<br />
<br />
FF401000 - FF402000: mapped ? (27FC7000 - 27FC8000)<br />
<br />
FF403000 - FF404000: mapped ? (27FC2000 - 27FC3000)<br />
<br />
FF405000 - FF406000: mapped ? (27FBB000 - 27FBC000)<br />
<br />
FF407000 - FF408000: mapped ? (27FB3000 - 27FB4000)<br />
<br />
FF409000 - FF40A000: mapped ? (27F8E000 - 27F8F000)<br />
<br />
FFF00000 - FFF45000: mapped SlabHeap <br />
<br />
FFF60000 - FFF8B000: mapped Kernel code<br />
<br />
FFFCC000 - FFFCD000: mapped IO [[I2C|I2C]] second bus (10144000 - 10145000)<br />
<br />
FFFCE000 - FFFCF000: mapped IO PDC([[LCD]]) (10400000 - 10401000)<br />
<br />
FFFD0000 - FFFD1000: mapped IO PDN (10141000 - 10142000)<br />
<br />
FFFD2000 - FFFD3000: mapped IO PXI (10163000 - 10164000)<br />
<br />
FFFD4000 - FFFD5000: mapped IO PAD (10146000 - 10147000)<br />
<br />
FFFD6000 - FFFD7000: mapped IO LCD (10202000 - 10203000)<br />
<br />
FFFD8000 - FFFD9000: mapped IO DSP (10140000 - 10141000)<br />
<br />
FFFDA000 - FFFDB000: mapped IO XDMA (10200000 - 10201000)<br />
<br />
FFFDC000 - FFFE0000: mapped ? (1FFF8000 - 1FFFC000)<br />
<br />
FFFE1000 - FFFE2000: mapped ? (1FFF0000 - 1FFF1000)<br />
<br />
FFFE3000 - FFFE4000: mapped ? (1FFF2000 - 1FFF3000)<br />
<br />
FFFE5000 - FFFE9000: mapped L1 MMU table for VA xxx00000<br />
<br />
FFFEA000 - FFFEB000: mapped ? (1FFF1000 - 1FFF2000)<br />
<br />
FFFEC000 - FFFED000: mapped ? (1FFF3000 - 1FFF4000)<br />
<br />
FFFEE000 - FFFF0000: mapped IO IRQ (17E00000 - 17E02000)<br />
<br />
FFFF0000 - FFFF1000: mapped Exception vectors<br />
<br />
FFFF2000 - FFFF6000: mapped L1 MMU table for VA xxx00000<br />
<br />
FFFF7000 - FFFF8000: mapped ? (1FFF1000 - 1FFF2000)<br />
<br />
FFFF9000 - FFFFA000: mapped ? (1FFF3000 - 1FFF4000)<br />
<br />
FFFFB000 - FFFFE000: mapped L2 MMU tables (1FFF5000 - 1FFF8000)<br />
<br />
==0xFF4XX000==<br />
Each [[KThread|thread]] is allocated a 0x1000-byte page in this region: the first page at 0xFF401000 is for the first created thread, 0xFF403000 for the second thread. This region is used to store the SVC-mode stack for the thread, and thread context data used for context switching. When the IRQ handler, prefetch/data abort handlers, and undefined instruction handler are entered where the SPSR-mode=user, these handlers then store LR+SPSR for the current mode on the SVC-mode stack, then these handlers switch to SVC-mode.<br />
<br />
This page does not contain a dedicated block for storing R0-PC(etc). For user-mode, the user-mode regs are instead saved on the SVC-mode stack when IRQs such as timers for context switching are triggered.<br />
<br />
Structure of this page, relative to page_endaddr-0xC8:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| <br />
| SVC-mode stack-top. The 0x10-byte SVC-access-control for this thread is also located here, which is checked by the SVC-handler.<br />
|-<br />
| 0x18<br />
| 0x28<br />
| SVC-mode saved registers, stored/loaded during context switches: R4-R9, SL, FP, SP, LR. After loading these registers, the context switch code will jump to the loaded LR.<br />
|-<br />
| 0xC0<br />
| 4<br />
| fpexc from vmrs, used during context switches with the above saved registers.<br />
|}<br />
<br />
For NATIVE_FIRM the memory pages for this region are located in FCRAM, however for TWL_FIRM these are located in AXI WRAM. For TWL_FIRM v6704 the first thread's page for this region is located at physical address 0x1FF93000, the next one at 0x1FF92000, etc.<br />
<br />
== IO Process virtual addressing equivalence ==<br />
It seems an IO register's process virtual address can be calculated by adding 0xEB00000 to its physical address. However for kernel mappings there is no fixed address equivalence.<br />
<br />
=ARM11 User-land memory regions=<br />
==NATIVE_FIRM/SAFE_MODE_FIRM Userland Memory==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Virtual Address Base<br />
! Physical Address Base<br />
! Region Max Size<br />
! Address-range available for svcMapMemoryBlock<br />
! Description<br />
|-<br />
| 0x00100000 / 0x14000000<br />
| <br />
| 0x03F00000<br />
| No<br />
| The [[ExeFS]]:/.code is loaded here, executables must be loaded to the 0x00100000 region when the exheader "special memory" flag is clear. The 0x03F00000-byte size restriction only applies when this flag is clear. Executables are usually loaded to 0x14000000 when the exheader "special memory" flag is set, however this address can be arbitrary.<br />
|-<br />
| 0x04000000<br />
| ?<br />
| ?<br />
| No<br />
| Used for mapping buffers during IPC, see [[IPC Command Structure]].<br />
|-<br />
| 0x08000000<br />
| Main stack physaddr - <heap size for the allocated vaddr 0x08000000 memory><br />
| 0x08000000<br />
| Yes<br />
| Heap mapped by [[SVC|ControlMemory]]<br />
|-<br />
| 0x10000000-StackSize<br />
| .bss physical address - total stack pages<br />
| StackSize from process exheader<br />
| <br />
| Stack for the main-thread, initialized by the ARM11 kernel. The StackSize from the exheader is usually 0x4000, therefore the stack-bottom is usually 0x0FFFC000. The stack for the other threads is normally located in the process .data section however this can be arbitrary.<br />
|-<br />
| 0x10000000<br />
| <br />
| 0x04000000<br />
| Yes<br />
| [[SVC|Shared]] memory<br />
|-<br />
| 0x14000000<br />
| FCRAM+0<br />
| 0x08000000<br />
| No<br />
| Can be mapped by [[SVC|ControlMemory]], this is used for processes' [[SVC|LINEAR]]/GSP heap.<br />
|-<br />
| 0x1E800000<br />
| 0x1F000000<br />
| 0x00400000<br />
| No<br />
| [[New_3DS]] additional memory, access to this is specified by the exheader. Added with [[8.0.0-18]], see above section regarding this memory.<br />
|-<br />
| 0x1EC00000<br />
| 0x10100000<br />
| 0x01000000<br />
| No<br />
| [[IO]] registers, the mapped IO pages which each process can access is specified in the [[NCCH/Extended_Header|exheader]]. (Applications normally don't have access to registers in this range)<br />
|-<br />
| 0x1F000000<br />
| 0x18000000<br />
| 0x00600000<br />
| No<br />
| VRAM, access to this is specified by the exheader.<br />
|-<br />
| 0x1FF00000<br />
| 0x1FF00000<br />
| 0x00080000<br />
| No<br />
| DSP memory, access to this is specified by the exheader.<br />
|-<br />
| 0x1FF80000<br />
| FCRAM memory page allocated by the ARM11 kernel.<br />
| 0x1000<br />
| No<br />
| [[Configuration Memory]], all processes have read-only access to this.<br />
|-<br />
| 0x1FF81000<br />
| FCRAM memory page allocated by the ARM11 kernel.<br />
| 0x1000<br />
| No<br />
| [[Configuration Memory|Shared]] page, all processes have read-access to this. Write access to this is specified by the exheader "Shared page writing" kernel flag.<br />
|-<br />
| 0x1FF82000<br />
| Dynamically taken from the BASE region of FCRAM<br />
| Number of threads * 0x1000 / 8<br />
| No<br />
| [[Thread Local Storage]]<br />
|-<br />
| 0x30000000<br />
| FCRAM+0<br />
| 0x08000000(Old3DS) / 0x10000000([[New_3DS]])<br />
| No<br />
| This LINEAR memory mapping was added with [[8.0.0-18]], see [[SVC#enum_MemoryOperation|here]]. This replaces the original 0x14000000 mapping, for system(memory-region=BASE)/newer titles. The Old3DS kernel uses size 0x08000000 for LINEAR-memory address range checks, while the New3DS kernel uses size 0x10000000 for those range checks. Old3DS/New3DS system-module code doing vaddr->phys-addr conversion uses size 0x10000000.<br />
|-<br />
| 0x20000000 / 0x40000000<br />
| <br />
| <br />
| <br />
| This is the end-address of userland memory, memory under this address is process-unique. Memory starting at this address is only accessible in privileged-mode. This address was changed from 0x20000000 to 0x40000000 with [[8.0.0-18]].<br />
|}<br />
<br />
All executable pages are read-only, and data pages have the execute-never permission set. Normally .text from the loaded ExeFS:/.code is the only mapped executable memory. Executable [[RO Services|CROs]] can be loaded into memory, once loaded the CRO .text section memory page permissions are changed via [[SVC|ControlProcessMemory]] from RW- to R-X. The address and size of each ExeFS:/.code section is stored in the exheader, the permissions for each section is: .text R-X, .rodata R--, .data RW-, and .bss RW-. The loaded .code is mapped to the addresses specified in the exheader by the ARM11 kernel. The stack permissions is initialized by the ARM11 kernel: RW-. The heap permissions is normally RW-.<br />
<br />
All userland memory is mapped with RW permissions for privileged-mode. However, normally the ARM11 kernel only uses userland read/write instructions(or checks that the memory can be written from userland first) for accessing memory specified by [[SVC|SVCs]].<br />
<br />
Processes can't directly access memory for other processes. When service [[Services API|commands]] are used, the kernel maps memory in the destination process for input/output buffers, where the addresses in the command received by the process is replaced by this mapped memory. When this is an input buffer, the buffer data is copied to the mapped memory. When this is an output buffer, the data stored in the mapped memory is copied to the destination buffer specified in the command.<br />
<br />
The physical address which memory for the application memory-type is mapped to begins at FCRAM+0, the total memory allocated for this memory-type is stored in [[Configuration_Memory]]. Applications' .text + .rodata + .data under the application memory-type is mapped at FCRAM + APPMEMALLOC - (aligned page-size for .text + .rodata + .data). The application .bss is mapped at CODEADDR - .bss size aligned down to the page size.<br />
<br />
==TWL_FIRM Userland Memory==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Virtual Address Base<br />
! Physical Address Base<br />
! Size<br />
! Description<br />
|-<br />
| 0x00100000<br />
| 0x1FFAB000 (with newer TWL_FIRM such as v6704 this is located at 0x1FFAC000)<br />
| 0x00055000<br />
| Code + .(ro)data copied from the process 0x00300000 region is located here(.bss is located here as well).<br />
|-<br />
| 0x00155000<br />
| 0x18555000<br />
| 0x000AB000<br />
| <br />
|-<br />
| 0x00200000<br />
| 0x18500000<br />
| 0x00100000<br />
| <br />
|-<br />
| 0x00300000<br />
| 0x24000000<br />
| 0x04000000<br />
| The beginning of the ARM11 process .text is located here.<br />
|-<br />
| 0x08000000<br />
| 0x20000000<br />
| 0x07E00000<br />
| <br />
|-<br />
| 0x1EC00000<br />
| 0x10100000<br />
| 0x00400000<br />
| [[IO]]<br />
|-<br />
| 0x1F000000<br />
| 0x18000000<br />
| 0x00600000<br />
| VRAM<br />
|-<br />
| 0x1FF00000<br />
| 0x1FF00000<br />
| 0x00080000<br />
| This is mapped to the DSP memory.<br />
|}<br />
<br />
The above regions are mapped by the ARM11 kernel. Later when the ARM11 process uses [[SVC|svcKernelSetState]] with type4, the kernel unmaps(?) the following regions: 0x00300000..0x04300000, 0x08000000..0x0FE00000, and 0x10000000..0xF8000000.<br />
<br />
=== Detailed TWL_FIRM ARM11 Memory ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Process Virtual Address<br />
! Physical Address<br />
! Size<br />
! Description<br />
|-<br />
| 0x08000000<br />
| 0x20000000<br />
| 0x01000000*4<br />
| DS(i) 0x02000000 RAM. Vaddr = (DSRAMOffset*4) + 0x08000000, where DSRAMOffset is DSRAMAddr-0x02000000.<br />
|-<br />
| 0x0FC00000<br />
| 0x27C00000<br />
| <br />
| Loaded SRL binary, initially the dev DSi launcher SRL is located here(copied here by the ARM11 process).<br />
|-<br />
| 0x0FD00000<br />
| 0x27D00000<br />
| <br />
| The data located here is copied to here by the ARM11 process. The data located here is a TWL NAND [http://dsibrew.org/wiki/Bootloader bootloader] image, using the same format+encryption/verification methods as the DSi NAND bootloader(stage2). The keyX for this bootloader keyslot is initially set to the retail DSi key-data, however when TWL_FIRM is launched this keyX key-data is replaced with a separate keyX. TWL_FIRM can use either the retail DSi bootloader RSA-1024 modulus, or a seperate modulus: normally only the latter is used(the former is only used when loading the image from FS instead of FCRAM). When using the image from FCRAM(default code-path), TWL_FIRM will not calculate+check the hashes for the bootloader code binaries(this is done when loading from FS however).<br />
|-<br />
| 0x0FDF7000<br />
| 0x27DF7000<br />
| 0x1000<br />
| SRL header<br />
|}<br />
<br />
= System memory details =<br />
0xFFFF9000 Pointer to the current KThread instance<br />
0xFFFF9004 Pointer to the current KProcess instance<br />
0xFFFF9008 Pointer to the current KScheduler instance<br />
0xFFFF9010 Pointer to the last KThread to encounter an exception<br />
<br />
0x8000040 Pointer to the current KThread instance on the ARM9<br />
0x8000044 Pointer to the current KProcess instance on the ARM9<br />
0x8000048 Pointer to the current KScheduler instance on the ARM9<br />
<br />
= VRAM Map While Running System Applets =<br />
*0x1E6000-0x22C500 -- top screen 3D left framebuffer 0(240x400x3) (The "3D right first-framebuf" addr stored in the LCD register is set to this, when the 3D is set to "off")<br />
*0x22C800-0x272D00 -- top screen 3D left framebuffer 1(240x400x3)<br />
*0x273000-0x2B9500 -- top screen 3D right framebuffer 0(240x400x3)<br />
*0x2B9800-0x2FFD00 -- top screen 3D right framebuffer 1(240x400x3)<br />
*0x48F000-0x4C7400 -- bottom screen framebuffer 0(240x320x3)<br />
*0x4C7800-0x4FF800 -- bottom screen framebuffer 1(240x320x3)<br />
<br />
These LCD framebuffer addresses are not changed by the system when launching regular applications, the application itself handles that if needed. These VRAM framebuffers are cleared when launching regular applications.</div>Subvhttps://www.3dbrew.org/w/index.php?title=GPU/Internal_Registers&diff=13117GPU/Internal Registers2015-08-23T00:32:17Z<p>Subv: /* Register list */</p>
<hr />
<div>[[Category:GFX]]<br />
(this page is hugely WIP)<br />
<br />
== Overview ==<br />
<br />
GPU internal registers are written to through GPU commands. They are used to control the GPU's behavior, that is to say tell it to draw stuff and how we want it drawn.<br />
<br />
== Types ==<br />
<br />
There are three main types of registers :<br />
* configuration registers, which directly map to various rendering properties (for example : [[#GPUREG_FACECULLING_CONFIG|GPUREG_FACECULLING_CONFIG]])<br />
* data transfer registers, which can be seen as FIFOs that let us send sequential chunks of data to the GPU, such as shader code or 1D samplers (for example : [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]])<br />
* action triggering registers, which tell the GPU to do something, like draw a primitive (for example : [[#GPUREG_DRAWARRAYS|GPUREG_DRAWARRAYS]])<br />
<br />
== Aliases ==<br />
<br />
It is possible for multiple register (sequential) IDs to correspond to the same register. This is done to leverage the consecutive writing mode for [[GPU Commands]], which makes it possible for a single command to write data to multiple sequential register IDs. For example, register IDs 02C1 through 02C8 all correspond to [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]] so that a consecutively writing command based at 02C0 will write its first parameter to [[#GPUREG_VSH_FLOATUNIFORM_CONFIG|GPUREG_VSH_FLOATUNIFORM_CONFIG]] and ever subsequent ones to [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
<br />
== Register list ==<br />
<br />
{| class="wikitable" border="1"<br />
! Register ID<br />
! Register name<br />
! Notes<br />
! Official Name<br />
|-<br />
| 0000<br />
| [[#GPUREG_0000|GPUREG_0000]]<br />
| <br />
|<br />
|-<br />
| 0001<br />
| [[#GPUREG_0001|GPUREG_0001]]<br />
| <br />
|<br />
|-<br />
| 0002<br />
| [[#GPUREG_0002|GPUREG_0002]]<br />
| <br />
|<br />
|-<br />
| 0003<br />
| [[#GPUREG_0003|GPUREG_0003]]<br />
| <br />
|<br />
|-<br />
| 0004<br />
| [[#GPUREG_0004|GPUREG_0004]]<br />
| <br />
|<br />
|-<br />
| 0005<br />
| [[#GPUREG_0005|GPUREG_0005]]<br />
| <br />
|<br />
|-<br />
| 0006<br />
| [[#GPUREG_0006|GPUREG_0006]]<br />
| <br />
|<br />
|-<br />
| 0007<br />
| [[#GPUREG_0007|GPUREG_0007]]<br />
| <br />
|<br />
|-<br />
| 0008<br />
| [[#GPUREG_0008|GPUREG_0008]]<br />
| <br />
|<br />
|-<br />
| 0009<br />
| [[#GPUREG_0009|GPUREG_0009]]<br />
| <br />
|<br />
|-<br />
| 000A<br />
| [[#GPUREG_000A|GPUREG_000A]]<br />
| <br />
|<br />
|-<br />
| 000B<br />
| [[#GPUREG_000B|GPUREG_000B]]<br />
| <br />
|<br />
|-<br />
| 000C<br />
| [[#GPUREG_000C|GPUREG_000C]]<br />
| <br />
|<br />
|-<br />
| 000D<br />
| [[#GPUREG_000D|GPUREG_000D]]<br />
| <br />
|<br />
|-<br />
| 000E<br />
| [[#GPUREG_000E|GPUREG_000E]]<br />
| <br />
|<br />
|-<br />
| 000F<br />
| [[#GPUREG_000F|GPUREG_000F]]<br />
| <br />
|<br />
|-<br />
| 0010<br />
| [[#GPUREG_FINALIZE|GPUREG_FINALIZE]]<br />
| <br />
|<br />
|-<br />
| 0011<br />
| [[#GPUREG_0011|GPUREG_0011]]<br />
| <br />
|<br />
|-<br />
| 0012<br />
| [[#GPUREG_0012|GPUREG_0012]]<br />
| <br />
|<br />
|-<br />
| 0013<br />
| [[#GPUREG_0013|GPUREG_0013]]<br />
| <br />
|<br />
|-<br />
| 0014<br />
| [[#GPUREG_0014|GPUREG_0014]]<br />
| <br />
|<br />
|-<br />
| 0015<br />
| [[#GPUREG_0015|GPUREG_0015]]<br />
| <br />
|<br />
|-<br />
| 0016<br />
| [[#GPUREG_0016|GPUREG_0016]]<br />
| <br />
|<br />
|-<br />
| 0017<br />
| [[#GPUREG_0017|GPUREG_0017]]<br />
| <br />
|<br />
|-<br />
| 0018<br />
| [[#GPUREG_0018|GPUREG_0018]]<br />
| <br />
|<br />
|-<br />
| 0019<br />
| [[#GPUREG_0019|GPUREG_0019]]<br />
| <br />
|<br />
|-<br />
| 001A<br />
| [[#GPUREG_001A|GPUREG_001A]]<br />
| <br />
|<br />
|-<br />
| 001B<br />
| [[#GPUREG_001B|GPUREG_001B]]<br />
| <br />
|<br />
|-<br />
| 001C<br />
| [[#GPUREG_001C|GPUREG_001C]]<br />
| <br />
|<br />
|-<br />
| 001D<br />
| [[#GPUREG_001D|GPUREG_001D]]<br />
| <br />
|<br />
|-<br />
| 001E<br />
| [[#GPUREG_001E|GPUREG_001E]]<br />
| <br />
|<br />
|-<br />
| 001F<br />
| [[#GPUREG_001F|GPUREG_001F]]<br />
| <br />
|<br />
|-<br />
| 0020<br />
| [[#GPUREG_0020|GPUREG_0020]]<br />
| <br />
|<br />
|-<br />
| 0021<br />
| [[#GPUREG_0021|GPUREG_0021]]<br />
| <br />
|<br />
|-<br />
| 0022<br />
| [[#GPUREG_0022|GPUREG_0022]]<br />
| <br />
|<br />
|-<br />
| 0023<br />
| [[#GPUREG_0023|GPUREG_0023]]<br />
| <br />
|<br />
|-<br />
| 0024<br />
| [[#GPUREG_0024|GPUREG_0024]]<br />
| <br />
|<br />
|-<br />
| 0025<br />
| [[#GPUREG_0025|GPUREG_0025]]<br />
| <br />
|<br />
|-<br />
| 0026<br />
| [[#GPUREG_0026|GPUREG_0026]]<br />
| <br />
|<br />
|-<br />
| 0027<br />
| [[#GPUREG_0027|GPUREG_0027]]<br />
| <br />
|<br />
|-<br />
| 0028<br />
| [[#GPUREG_0028|GPUREG_0028]]<br />
| <br />
|<br />
|-<br />
| 0029<br />
| [[#GPUREG_0029|GPUREG_0029]]<br />
| <br />
|<br />
|-<br />
| 002A<br />
| [[#GPUREG_002A|GPUREG_002A]]<br />
| <br />
|<br />
|-<br />
| 002B<br />
| [[#GPUREG_002B|GPUREG_002B]]<br />
| <br />
|<br />
|-<br />
| 002C<br />
| [[#GPUREG_002C|GPUREG_002C]]<br />
| <br />
|<br />
|-<br />
| 002D<br />
| [[#GPUREG_002D|GPUREG_002D]]<br />
| <br />
|<br />
|-<br />
| 002E<br />
| [[#GPUREG_002E|GPUREG_002E]]<br />
| <br />
|<br />
|-<br />
| 002F<br />
| [[#GPUREG_002F|GPUREG_002F]]<br />
| <br />
|<br />
|-<br />
| 0030<br />
| [[#GPUREG_0030|GPUREG_0030]]<br />
| <br />
|<br />
|-<br />
| 0031<br />
| [[#GPUREG_0031|GPUREG_0031]]<br />
| <br />
|<br />
|-<br />
| 0032<br />
| [[#GPUREG_0032|GPUREG_0032]]<br />
| <br />
|<br />
|-<br />
| 0033<br />
| [[#GPUREG_0033|GPUREG_0033]]<br />
| <br />
|<br />
|-<br />
| 0034<br />
| [[#GPUREG_0034|GPUREG_0034]]<br />
| <br />
|<br />
|-<br />
| 0035<br />
| [[#GPUREG_0035|GPUREG_0035]]<br />
| <br />
|<br />
|-<br />
| 0036<br />
| [[#GPUREG_0036|GPUREG_0036]]<br />
| <br />
|<br />
|-<br />
| 0037<br />
| [[#GPUREG_0037|GPUREG_0037]]<br />
| <br />
|<br />
|-<br />
| 0038<br />
| [[#GPUREG_0038|GPUREG_0038]]<br />
| <br />
|<br />
|-<br />
| 0039<br />
| [[#GPUREG_0039|GPUREG_0039]]<br />
| <br />
|<br />
|-<br />
| 003A<br />
| [[#GPUREG_003A|GPUREG_003A]]<br />
| <br />
|<br />
|-<br />
| 003B<br />
| [[#GPUREG_003B|GPUREG_003B]]<br />
| <br />
|<br />
|-<br />
| 003C<br />
| [[#GPUREG_003C|GPUREG_003C]]<br />
| <br />
|<br />
|-<br />
| 003D<br />
| [[#GPUREG_003D|GPUREG_003D]]<br />
| <br />
|<br />
|-<br />
| 003E<br />
| [[#GPUREG_003E|GPUREG_003E]]<br />
| <br />
|<br />
|-<br />
| 003F<br />
| [[#GPUREG_003F|GPUREG_003F]]<br />
| <br />
|<br />
|-<br />
| 0040<br />
| [[#GPUREG_FACECULLING_CONFIG|GPUREG_FACECULLING_CONFIG]]<br />
| <br />
|PICA_REG_CULL_FACE<br />
|-<br />
| 0041<br />
| [[#GPUREG_0041|GPUREG_0041]]<br />
|?<br />
|PICA_REG_VIEWPORT_WIDTH1<br />
|-<br />
| 0042<br />
| [[#GPUREG_0042|GPUREG_0042]]<br />
|?<br />
|PICA_REG_VIEWPORT_WIDTH2<br />
|-<br />
| 0043<br />
| [[#GPUREG_0043|GPUREG_0043]]<br />
|?<br />
|PICA_REG_VIEWPORT_HEIGHT1<br />
|-<br />
| 0044<br />
| [[#GPUREG_0044|GPUREG_0044]]<br />
| ?<br />
|PICA_REG_VIEWPORT_HEIGHT2<br />
|-<br />
| 0045<br />
| [[#GPUREG_0045|GPUREG_0045]]<br />
| <br />
|<br />
|-<br />
| 0046<br />
| [[#GPUREG_0046|GPUREG_0046]]<br />
| <br />
|<br />
|-<br />
| 0047<br />
| [[#GPUREG_0047|GPUREG_0047]]<br />
|?<br />
|PICA_REG_FRAG_OP_CLIP<br />
|-<br />
| 0048<br />
| [[#GPUREG_0048|GPUREG_0048]]<br />
|? <br />
|PICA_REG_FRAG_OP_CLIP_DATA1<br />
|-<br />
| 0049<br />
| [[#GPUREG_0049|GPUREG_0049]]<br />
|?<br />
|PICA_REG_FRAG_OP_CLIP_DATA2<br />
|-<br />
| 004A<br />
| [[#GPUREG_004A|GPUREG_004A]]<br />
|?<br />
|PICA_REG_FRAG_OP_CLIP_DATA3<br />
|-<br />
| 004B<br />
| [[#GPUREG_004B|GPUREG_004B]]<br />
|?<br />
|PICA_REG_FRAG_OP_CLIP_DATA4<br />
|-<br />
| 004C<br />
| [[#GPUREG_004C|GPUREG_004C]]<br />
| <br />
|<br />
|-<br />
| 004D<br />
| [[#GPUREG_DEPTHMAP_SCALE|GPUREG_DEPTHMAP_SCALE]]<br />
| <br />
|PICA_REG_FRAG_OP_WSCALE_DATA1<br />
|-<br />
| 004E<br />
| [[#GPUREG_DEPTHMAP_OFFSET|GPUREG_DEPTHMAP_OFFSET]]<br />
| <br />
|PICA_REG_FRAG_OP_WSCALE_DATA2<br />
|-<br />
| 004F<br />
| [[#GPUREG_SH_OUTMAP_TOTAL|GPUREG_SH_OUTMAP_TOTAL]]<br />
| <br />
|PICA_REG_GS_OUT_REG_NUM0 / PICA_REG_VS_OUT_REG_NUM0<br />
|-<br />
| 0050<br />
| [[#GPUREG_SH_OUTMAP_O0|GPUREG_SH_OUTMAP_O0]]<br />
| <br />
|PICA_REG_GS_OUT_ATTR0 / PICA_REG_VS_OUT_ATTR0<br />
|-<br />
| 0051<br />
| [[#GPUREG_SH_OUTMAP_O1|GPUREG_SH_OUTMAP_O1]]<br />
| <br />
|PICA_REG_GS_OUT_ATTR1 / PICA_REG_VS_OUT_ATTR1<br />
|-<br />
| 0052<br />
| [[#GPUREG_SH_OUTMAP_O2|GPUREG_SH_OUTMAP_O2]]<br />
| <br />
|PICA_REG_GS_OUT_ATTR2 / PICA_REG_VS_OUT_ATTR2<br />
|-<br />
| 0053<br />
| [[#GPUREG_SH_OUTMAP_O3|GPUREG_SH_OUTMAP_O3]]<br />
| <br />
|PICA_REG_GS_OUT_ATTR3 / PICA_REG_VS_OUT_ATTR3<br />
|-<br />
| 0054<br />
| [[#GPUREG_SH_OUTMAP_O4|GPUREG_SH_OUTMAP_O4]]<br />
| <br />
|PICA_REG_GS_OUT_ATTR4 / PICA_REG_VS_OUT_ATTR4<br />
|-<br />
| 0055<br />
| [[#GPUREG_SH_OUTMAP_O5|GPUREG_SH_OUTMAP_O5]]<br />
| <br />
|PICA_REG_GS_OUT_ATTR5 / PICA_REG_VS_OUT_ATTR5<br />
|-<br />
| 0056<br />
| [[#GPUREG_SH_OUTMAP_O6|GPUREG_SH_OUTMAP_O6]]<br />
| <br />
|PICA_REG_GS_OUT_ATTR6 / PICA_REG_VS_OUT_ATTR6<br />
|-<br />
| 0057<br />
| [[#GPUREG_0057|GPUREG_0057]]<br />
| <br />
|<br />
|-<br />
| 0058<br />
| [[#GPUREG_0058|GPUREG_0058]]<br />
| <br />
|<br />
|-<br />
| 0059<br />
| [[#GPUREG_0059|GPUREG_0059]]<br />
| <br />
|<br />
|-<br />
| 005A<br />
| [[#GPUREG_005A|GPUREG_005A]]<br />
| <br />
|<br />
|-<br />
| 005B<br />
| [[#GPUREG_005B|GPUREG_005B]]<br />
| <br />
|<br />
|-<br />
| 005C<br />
| [[#GPUREG_005C|GPUREG_005C]]<br />
| <br />
|<br />
|-<br />
| 005D<br />
| [[#GPUREG_005D|GPUREG_005D]]<br />
| <br />
|<br />
|-<br />
| 005E<br />
| [[#GPUREG_005E|GPUREG_005E]]<br />
| <br />
|<br />
|-<br />
| 005F<br />
| [[#GPUREG_005F|GPUREG_005F]]<br />
| <br />
|<br />
|-<br />
| 0060<br />
| [[#GPUREG_0060|GPUREG_0060]]<br />
| <br />
|<br />
|-<br />
| 0061<br />
| [[#GPUREG_0061|GPUREG_0061]]<br />
|?<br />
|PICA_REG_EARLY_DEPTH_FUNC<br />
|-<br />
| 0062<br />
| [[#GPUREG_0062|GPUREG_0062]]<br />
|?<br />
|PICA_REG_EARLY_DEPTH_TEST1<br />
|-<br />
| 0063<br />
| [[#GPUREG_0063|GPUREG_0063]]<br />
| <br />
|<br />
|-<br />
| 0064<br />
| [[#GPUREG_0064|GPUREG_0064]]<br />
|?<br />
|PICA_REG_GS_OUT_ATTR_MODE / PICA_REG_VS_OUT_ATTR_MODE<br />
|-<br />
| 0065<br />
| [[#GPUREG_SCISSORTEST_MODE|GPUREG_SCISSORTEST_MODE]]<br />
| <br />
|PICA_REG_SCISSOR<br />
|-<br />
| 0066<br />
| [[#GPUREG_SCISSORTEST_POS|GPUREG_SCISSORTEST_POS]]<br />
| <br />
|PICA_REG_SCISSOR_XY<br />
|-<br />
| 0067<br />
| [[#GPUREG_SCISSORTEST_DIM|GPUREG_SCISSORTEST_DIM]]<br />
| <br />
|PICA_REG_SCISSOR_SIZE<br />
|-<br />
| 0068<br />
| [[#GPUREG_0068|GPUREG_0068]]<br />
| <br />
|PICA_REG_VIEWPORT_XY<br />
|-<br />
| 0069<br />
| [[#GPUREG_0069|GPUREG_0069]]<br />
| <br />
|<br />
|-<br />
| 006A<br />
| [[#GPUREG_006A|GPUREG_006A]]<br />
|<br />
|PICA_REG_EARLY_DEPTH_DATA<br />
|-<br />
| 006B<br />
| [[#GPUREG_006B|GPUREG_006B]]<br />
| <br />
|<br />
|-<br />
| 006C<br />
| [[#GPUREG_006C|GPUREG_006C]]<br />
| <br />
|<br />
|-<br />
| 006D<br />
| [[#GPUREG_006D|GPUREG_006D]]<br />
|?<br />
|PICA_REG_FRAG_OP_WSCALE<br />
|-<br />
| 006E<br />
| [[#GPUREG_006E|GPUREG_006E]]<br />
|?<br />
|PICA_REG_RENDER_BUF_RESOLUTION1<br />
|-<br />
| 006F<br />
| [[#GPUREG_006F|GPUREG_006F]]<br />
|?<br />
|PICA_REG_GS_OUT_ATTR_CLK / PICA_REG_VS_OUT_ATTR_CLK<br />
|-<br />
| 0070<br />
| [[#GPUREG_0070|GPUREG_0070]]<br />
| <br />
|<br />
|-<br />
| 0071<br />
| [[#GPUREG_0071|GPUREG_0071]]<br />
| <br />
|<br />
|-<br />
| 0072<br />
| [[#GPUREG_0072|GPUREG_0072]]<br />
| <br />
|<br />
|-<br />
| 0073<br />
| [[#GPUREG_0073|GPUREG_0073]]<br />
| <br />
|<br />
|-<br />
| 0074<br />
| [[#GPUREG_0074|GPUREG_0074]]<br />
| <br />
|<br />
|-<br />
| 0075<br />
| [[#GPUREG_0075|GPUREG_0075]]<br />
| <br />
|<br />
|-<br />
| 0076<br />
| [[#GPUREG_0076|GPUREG_0076]]<br />
| <br />
|<br />
|-<br />
| 0077<br />
| [[#GPUREG_0077|GPUREG_0077]]<br />
| <br />
|<br />
|-<br />
| 0078<br />
| [[#GPUREG_0078|GPUREG_0078]]<br />
| <br />
|<br />
|-<br />
| 0079<br />
| [[#GPUREG_0079|GPUREG_0079]]<br />
| <br />
|<br />
|-<br />
| 007A<br />
| [[#GPUREG_007A|GPUREG_007A]]<br />
| <br />
|<br />
|-<br />
| 007B<br />
| [[#GPUREG_007B|GPUREG_007B]]<br />
| <br />
|<br />
|-<br />
| 007C<br />
| [[#GPUREG_007C|GPUREG_007C]]<br />
| <br />
|<br />
|-<br />
| 007D<br />
| [[#GPUREG_007D|GPUREG_007D]]<br />
| <br />
|<br />
|-<br />
| 007E<br />
| [[#GPUREG_007E|GPUREG_007E]]<br />
| <br />
|<br />
|-<br />
| 007F<br />
| [[#GPUREG_007F|GPUREG_007F]]<br />
| <br />
|<br />
|-<br />
| 0080<br />
| [[#GPUREG_TEXUNITS_CONFIG|GPUREG_TEXUNITS_CONFIG]]<br />
| <br />
|PICA_REG_TEXTURE_FUNC<br />
|-<br />
| 0081<br />
| [[#GPUREG_0081|GPUREG_0081]]<br />
|?<br />
|PICA_REG_TEXTURE0_BORDER_COLOR<br />
|-<br />
| 0082<br />
| [[#GPUREG_TEXUNIT0_DIM|GPUREG_TEXUNIT0_DIM]]<br />
|<br />
|PICA_REG_TEXTURE0_SIZE<br />
|-<br />
| 0083<br />
| [[#GPUREG_TEXUNIT0_PARAM|GPUREG_TEXUNIT0_PARAM]]<br />
| <br />
|PICA_REG_TEXTURE0_WRAP_FILTER<br />
|-<br />
| 0084<br />
| [[#GPUREG_0084|GPUREG_0084]]<br />
|?<br />
|PICA_REG_TEXTURE0_LOD<br />
|-<br />
| 0085<br />
| [[#GPUREG_TEXUNIT0_LOC|GPUREG_TEXUNIT0_LOC]]<br />
| <br />
|PICA_REG_TEXTURE0_ADDR1<br />
|-<br />
| 0086<br />
| [[#GPUREG_0086|GPUREG_0086]]<br />
| <br />
|PICA_REG_TEXTURE0_ADDR2<br />
|-<br />
| 0087<br />
| [[#GPUREG_0087|GPUREG_0087]]<br />
| <br />
|PICA_REG_TEXTURE0_ADDR3<br />
|-<br />
| 0088<br />
| [[#GPUREG_0088|GPUREG_0088]]<br />
| <br />
|PICA_REG_TEXTURE0_ADDR4<br />
|-<br />
| 0089<br />
| [[#GPUREG_0089|GPUREG_0089]]<br />
| <br />
|PICA_REG_TEXTURE0_ADDR5<br />
|-<br />
| 008A<br />
| [[#GPUREG_008A|GPUREG_008A]]<br />
| <br />
|PICA_REG_TEXTURE0_ADDR6<br />
|-<br />
| 008B<br />
| [[#GPUREG_008B|GPUREG_008B]]<br />
|?<br />
|PICA_REG_TEXTURE0_SHADOW<br />
|-<br />
| 008C<br />
| [[#GPUREG_008C|GPUREG_008C]]<br />
|<br />
|<br />
|-<br />
| 008D<br />
| [[#GPUREG_008D|GPUREG_008D]]<br />
|<br />
|<br />
|-<br />
| 008E<br />
| [[#GPUREG_TEXUNIT0_TYPE|GPUREG_TEXUNIT0_TYPE]]<br />
|?<br />
|PICA_REG_TEXTURE0_FORMAT<br />
|-<br />
| 008F<br />
| [[#GPUREG_008F|GPUREG_008F]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_EN0<br />
|-<br />
| 0090<br />
| [[#GPUREG_0090|GPUREG_0090]]<br />
| <br />
|<br />
|-<br />
| 0091<br />
| [[#GPUREG_0091|GPUREG_0091]]<br />
|?<br />
|PICA_REG_TEXTURE1_BORDER_COLOR<br />
|-<br />
| 0092<br />
| [[#GPUREG_TEXUNIT1_DIM|GPUREG_TEXUNIT1_DIM]]<br />
| <br />
|PICA_REG_TEXTURE1_SIZE<br />
|-<br />
| 0093<br />
| [[#GPUREG_TEXUNIT1_PARAM|GPUREG_TEXUNIT1_PARAM]]<br />
| <br />
|PICA_REG_TEXTURE1_WRAP_FILTER<br />
|-<br />
| 0094<br />
| [[#GPUREG_0094|GPUREG_0094]]<br />
|?<br />
|PICA_REG_TEXTURE1_LOD<br />
|-<br />
| 0095<br />
| [[#GPUREG_TEXUNIT1_LOC|GPUREG_TEXUNIT1_LOC]]<br />
| <br />
|PICA_REG_TEXTURE1_ADDR<br />
|-<br />
| 0096<br />
| [[#GPUREG_TEXUNIT1_TYPE|GPUREG_TEXUNIT1_TYPE]]<br />
| <br />
|PICA_REG_TEXTURE1_FORMAT<br />
|-<br />
| 0097<br />
| [[#GPUREG_0097|GPUREG_0097]]<br />
| <br />
|<br />
|-<br />
| 0098<br />
| [[#GPUREG_0098|GPUREG_0098]]<br />
| <br />
|<br />
|-<br />
| 0099<br />
| [[#GPUREG_0099|GPUREG_0099]]<br />
|?<br />
|PICA_REG_TEXTURE2_BORDER_COLOR<br />
|-<br />
| 009A<br />
| [[#GPUREG_TEXUNIT2_DIM|GPUREG_TEXUNIT2_DIM]]<br />
| <br />
|PICA_REG_TEXTURE2_SIZE<br />
|-<br />
| 009B<br />
| [[#GPUREG_TEXUNIT2_PARAM|GPUREG_TEXUNIT2_PARAM]]<br />
| <br />
|PICA_REG_TEXTURE2_WRAP_FILTER<br />
|-<br />
| 009C<br />
| [[#GPUREG_009C|GPUREG_009C]]<br />
|?<br />
|PICA_REG_TEXTURE2_LOD<br />
|-<br />
| 009D<br />
| [[#GPUREG_TEXUNIT2_LOC|GPUREG_TEXUNIT2_LOC]]<br />
|<br />
|PICA_REG_TEXTURE2_ADDR<br />
|-<br />
| 009E<br />
| [[#GPUREG_TEXUNIT2_TYPE|GPUREG_TEXUNIT2_TYPE]]<br />
| <br />
|PICA_REG_TEXTURE2_FORMAT<br />
|-<br />
| 009F<br />
| [[#GPUREG_009F|GPUREG_009F]]<br />
| <br />
|<br />
|-<br />
| 00A0<br />
| [[#GPUREG_00A0|GPUREG_00A0]]<br />
| <br />
|<br />
|-<br />
| 00A1<br />
| [[#GPUREG_00A1|GPUREG_00A1]]<br />
| <br />
|<br />
|-<br />
| 00A2<br />
| [[#GPUREG_00A2|GPUREG_00A2]]<br />
| <br />
|<br />
|-<br />
| 00A3<br />
| [[#GPUREG_00A3|GPUREG_00A3]]<br />
| <br />
|<br />
|-<br />
| 00A4<br />
| [[#GPUREG_00A4|GPUREG_00A4]]<br />
| <br />
|<br />
|-<br />
| 00A5<br />
| [[#GPUREG_00A5|GPUREG_00A5]]<br />
| <br />
|<br />
|-<br />
| 00A6<br />
| [[#GPUREG_00A6|GPUREG_00A6]]<br />
| <br />
|<br />
|-<br />
| 00A7<br />
| [[#GPUREG_00A7|GPUREG_00A7]]<br />
| <br />
|<br />
|-<br />
| 00A8<br />
| [[#GPUREG_00A8|GPUREG_00A8]]<br />
|?<br />
|PICA_REG_TEXTURE3_PROTEX0<br />
|-<br />
| 00A9<br />
| [[#GPUREG_00A9|GPUREG_00A9]]<br />
|?<br />
|PICA_REG_TEXTURE3_PROTEX1<br />
|-<br />
| 00AA<br />
| [[#GPUREG_00AA|GPUREG_00AA]]<br />
|? <br />
|PICA_REG_TEXTURE3_PROTEX2<br />
|-<br />
| 00AB<br />
| [[#GPUREG_00AB|GPUREG_00AB]]<br />
|?<br />
|PICA_REG_TEXTURE3_PROTEX3<br />
|-<br />
| 00AC<br />
| [[#GPUREG_00AC|GPUREG_00AC]]<br />
|?<br />
|PICA_REG_TEXTURE3_PROTEX4<br />
|-<br />
| 00AD<br />
| [[#GPUREG_00AD|GPUREG_00AD]]<br />
|?<br />
|PICA_REG_TEXTURE3_PROTEX5<br />
|-<br />
| 00AE<br />
| [[#GPUREG_00AE|GPUREG_00AE]]<br />
| <br />
|<br />
|-<br />
| 00AF<br />
| [[#GPUREG_00AF|GPUREG_00AF]]<br />
|?<br />
|PICA_REG_PROTEX_LUT<br />
|-<br />
| 00B0<br />
| [[#GPUREG_00B0|GPUREG_00B0]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA0<br />
|-<br />
| 00B1<br />
| [[#GPUREG_00B1|GPUREG_00B1]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA1<br />
|-<br />
| 00B2<br />
| [[#GPUREG_00B2|GPUREG_00B2]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA2<br />
|-<br />
| 00B3<br />
| [[#GPUREG_00B3|GPUREG_00B3]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA3<br />
|-<br />
| 00B4<br />
| [[#GPUREG_00B4|GPUREG_00B4]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA4<br />
|-<br />
| 00B5<br />
| [[#GPUREG_00B5|GPUREG_00B5]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA5<br />
|-<br />
| 00B6<br />
| [[#GPUREG_00B6|GPUREG_00B6]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA6<br />
|-<br />
| 00B7<br />
| [[#GPUREG_00B7|GPUREG_00B7]]<br />
| ?<br />
|PICA_REG_PROTEX_LUT_DATA7<br />
|-<br />
| 00B8<br />
| [[#GPUREG_00B8|GPUREG_00B8]]<br />
| <br />
|<br />
|-<br />
| 00B9<br />
| [[#GPUREG_00B9|GPUREG_00B9]]<br />
| <br />
|<br />
|-<br />
| 00BA<br />
| [[#GPUREG_00BA|GPUREG_00BA]]<br />
| <br />
|<br />
|-<br />
| 00BB<br />
| [[#GPUREG_00BB|GPUREG_00BB]]<br />
| <br />
|<br />
|-<br />
| 00BC<br />
| [[#GPUREG_00BC|GPUREG_00BC]]<br />
| <br />
|<br />
|-<br />
| 00BD<br />
| [[#GPUREG_00BD|GPUREG_00BD]]<br />
| <br />
|<br />
|-<br />
| 00BE<br />
| [[#GPUREG_00BE|GPUREG_00BE]]<br />
| <br />
|<br />
|-<br />
| 00BF<br />
| [[#GPUREG_00BF|GPUREG_00BF]]<br />
| <br />
|<br />
|-<br />
| 00C0<br />
| [[#GPUREG_TEXENV0_CONFIG0|GPUREG_TEXENV0_CONFIG0]]<br />
| <br />
|PICA_REG_TEX_ENV_0<br />
|-<br />
| 00C1<br />
| [[#GPUREG_TEXENV0_CONFIG1|GPUREG_TEXENV0_CONFIG1]]<br />
| <br />
|PICA_REG_TEX_ENV_0_OPERAND<br />
|-<br />
| 00C2<br />
| [[#GPUREG_TEXENV0_CONFIG2|GPUREG_TEXENV0_CONFIG2]]<br />
| <br />
|PICA_REG_TEX_ENV_0_COMBINE<br />
|-<br />
| 00C3<br />
| [[#GPUREG_TEXENV0_CONFIG3|GPUREG_TEXENV0_CONFIG3]]<br />
| <br />
|PICA_REG_TEX_ENV_0_COLOR<br />
|-<br />
| 00C4<br />
| [[#GPUREG_TEXENV0_CONFIG4|GPUREG_TEXENV0_CONFIG4]]<br />
| <br />
|PICA_REG_TEX_ENV_0_SCALE<br />
|-<br />
| 00C5<br />
| [[#GPUREG_00C5|GPUREG_00C5]]<br />
| <br />
|<br />
|-<br />
| 00C6<br />
| [[#GPUREG_00C6|GPUREG_00C6]]<br />
| <br />
|<br />
|-<br />
| 00C7<br />
| [[#GPUREG_00C7|GPUREG_00C7]]<br />
| <br />
|<br />
|-<br />
| 00C8<br />
| [[#GPUREG_TEXENV1_CONFIG0|GPUREG_TEXENV1_CONFIG0]]<br />
| <br />
|PICA_REG_TEX_ENV_1<br />
|-<br />
| 00C9<br />
| [[#GPUREG_TEXENV1_CONFIG1|GPUREG_TEXENV1_CONFIG1]]<br />
| <br />
|PICA_REG_TEX_ENV_1_OPERAND<br />
|-<br />
| 00CA<br />
| [[#GPUREG_TEXENV1_CONFIG2|GPUREG_TEXENV1_CONFIG2]]<br />
| <br />
|PICA_REG_TEX_ENV_1_COMBINE<br />
|-<br />
| 00CB<br />
| [[#GPUREG_TEXENV1_CONFIG3|GPUREG_TEXENV1_CONFIG3]]<br />
| <br />
|PICA_REG_TEX_ENV_1_COLOR<br />
|-<br />
| 00CC<br />
| [[#GPUREG_TEXENV1_CONFIG4|GPUREG_TEXENV1_CONFIG4]]<br />
| <br />
|PICA_REG_TEX_ENV_1_SCALE<br />
|-<br />
| 00CD<br />
| [[#GPUREG_00CD|GPUREG_00CD]]<br />
| <br />
|<br />
|-<br />
| 00CE<br />
| [[#GPUREG_00CE|GPUREG_00CE]]<br />
| <br />
|<br />
|-<br />
| 00CF<br />
| [[#GPUREG_00CF|GPUREG_00CF]]<br />
| <br />
|<br />
|-<br />
| 00D0<br />
| [[#GPUREG_TEXENV2_CONFIG0|GPUREG_TEXENV2_CONFIG0]]<br />
| <br />
|PICA_REG_TEX_ENV_2<br />
|-<br />
| 00D1<br />
| [[#GPUREG_TEXENV2_CONFIG1|GPUREG_TEXENV2_CONFIG1]]<br />
| <br />
|PICA_REG_TEX_ENV_2_OPERAND<br />
|-<br />
| 00D2<br />
| [[#GPUREG_TEXENV2_CONFIG2|GPUREG_TEXENV2_CONFIG2]]<br />
| <br />
|PICA_REG_TEX_ENV_2_COMBINE<br />
|-<br />
| 00D3<br />
| [[#GPUREG_TEXENV2_CONFIG3|GPUREG_TEXENV2_CONFIG3]]<br />
| <br />
|PICA_REG_TEX_ENV_2_COLOR<br />
|-<br />
| 00D4<br />
| [[#GPUREG_TEXENV2_CONFIG4|GPUREG_TEXENV2_CONFIG4]]<br />
| <br />
|PICA_REG_TEX_ENV_2_SCALE<br />
|-<br />
| 00D5<br />
| [[#GPUREG_00D5|GPUREG_00D5]]<br />
| <br />
|<br />
|-<br />
| 00D6<br />
| [[#GPUREG_00D6|GPUREG_00D6]]<br />
| <br />
|<br />
|-<br />
| 00D7<br />
| [[#GPUREG_00D7|GPUREG_00D7]]<br />
| <br />
|<br />
|-<br />
| 00D8<br />
| [[#GPUREG_TEXENV3_CONFIG0|GPUREG_TEXENV3_CONFIG0]]<br />
| <br />
|PICA_REG_TEX_ENV_3<br />
|-<br />
| 00D9<br />
| [[#GPUREG_TEXENV3_CONFIG1|GPUREG_TEXENV3_CONFIG1]]<br />
| <br />
|PICA_REG_TEX_ENV_3_OPERAND<br />
|-<br />
| 00DA<br />
| [[#GPUREG_TEXENV3_CONFIG2|GPUREG_TEXENV3_CONFIG2]]<br />
| <br />
|PICA_REG_TEX_ENV_3_COMBINE<br />
|-<br />
| 00DB<br />
| [[#GPUREG_TEXENV3_CONFIG3|GPUREG_TEXENV3_CONFIG3]]<br />
| <br />
|PICA_REG_TEX_ENV_3_COLOR<br />
|-<br />
| 00DC<br />
| [[#GPUREG_TEXENV3_CONFIG4|GPUREG_TEXENV3_CONFIG4]]<br />
| <br />
|PICA_REG_TEX_ENV_3_SCALE<br />
|-<br />
| 00DD<br />
| [[#GPUREG_00DD|GPUREG_00DD]]<br />
| <br />
|<br />
|-<br />
| 00DE<br />
| [[#GPUREG_00DE|GPUREG_00DE]]<br />
| <br />
|<br />
|-<br />
| 00DF<br />
| [[#GPUREG_00DF|GPUREG_00DF]]<br />
| <br />
|<br />
|-<br />
| 00E0<br />
| [[#GPUREG_TEXENV_BUFFER_CONFIG|GPUREG_TEXENV_BUFFER_CONFIG]]<br />
|?<br />
|PICA_REG_GAS_FOG_MODE / PICA_REG_TEX_ENV_BUF_INPUT<br />
|-<br />
| 00E1<br />
| [[#GPUREG_00E1|GPUREG_00E1]]<br />
|?<br />
|PICA_REG_FOG_COLOR<br />
|-<br />
| 00E2<br />
| [[#GPUREG_00E2|GPUREG_00E2]]<br />
| <br />
|<br />
|-<br />
| 00E3<br />
| [[#GPUREG_00E3|GPUREG_00E3]]<br />
| <br />
|<br />
|-<br />
| 00E4<br />
| [[#GPUREG_00E4|GPUREG_00E4]]<br />
|?<br />
|PICA_REG_GAS_ATTENUATION<br />
|-<br />
| 00E5<br />
| [[#GPUREG_00E5|GPUREG_00E5]]<br />
|?<br />
|PICA_REG_GAS_ACCMAX<br />
|-<br />
| 00E6<br />
| [[#GPUREG_00E6|GPUREG_00E6]]<br />
|?<br />
|PICA_REG_FOG_LUT_INDEX<br />
|-<br />
| 00E7<br />
| [[#GPUREG_00E7|GPUREG_00E7]]<br />
| <br />
|<br />
|-<br />
| 00E8<br />
| [[#GPUREG_00E8|GPUREG_00E8]]<br />
|?<br />
|PICA_REG_FOG_LUT_DATA0<br />
|-<br />
| 00E9<br />
| [[#GPUREG_00E9|GPUREG_00E9]]<br />
|? <br />
|PICA_REG_FOG_LUT_DATA1<br />
|-<br />
| 00EA<br />
| [[#GPUREG_00EA|GPUREG_00EA]]<br />
|?<br />
|PICA_REG_FOG_LUT_DATA2<br />
|-<br />
| 00EB<br />
| [[#GPUREG_00EB|GPUREG_00EB]]<br />
|?<br />
|PICA_REG_FOG_LUT_DATA3<br />
|-<br />
| 00EC<br />
| [[#GPUREG_00EC|GPUREG_00EC]]<br />
|?<br />
|PICA_REG_FOG_LUT_DATA4<br />
|-<br />
| 00ED<br />
| [[#GPUREG_00ED|GPUREG_00ED]]<br />
|?<br />
|PICA_REG_FOG_LUT_DATA5<br />
|-<br />
| 00EE<br />
| [[#GPUREG_00EE|GPUREG_00EE]]<br />
|?<br />
|PICA_REG_FOG_LUT_DATA6<br />
|-<br />
| 00EF<br />
| [[#GPUREG_00EF|GPUREG_00EF]]<br />
|?<br />
|PICA_REG_FOG_LUT_DATA7<br />
|-<br />
| 00F0<br />
| [[#GPUREG_TEXENV4_CONFIG0|GPUREG_TEXENV4_CONFIG0]]<br />
| <br />
|PICA_REG_TEX_ENV_4<br />
|-<br />
| 00F1<br />
| [[#GPUREG_TEXENV4_CONFIG1|GPUREG_TEXENV4_CONFIG1]]<br />
| <br />
|PICA_REG_TEX_ENV_4_OPERAND<br />
|-<br />
| 00F2<br />
| [[#GPUREG_TEXENV4_CONFIG2|GPUREG_TEXENV4_CONFIG2]]<br />
| <br />
|PICA_REG_TEX_ENV_4_COMBINE<br />
|-<br />
| 00F3<br />
| [[#GPUREG_TEXENV4_CONFIG3|GPUREG_TEXENV4_CONFIG3]]<br />
| <br />
|PICA_REG_TEX_ENV_4_COLOR<br />
|-<br />
| 00F4<br />
| [[#GPUREG_TEXENV4_CONFIG4|GPUREG_TEXENV4_CONFIG4]]<br />
| <br />
|PICA_REG_TEX_ENV_4_SCALE<br />
|-<br />
| 00F5<br />
| [[#GPUREG_00F5|GPUREG_00F5]]<br />
| <br />
|<br />
|-<br />
| 00F6<br />
| [[#GPUREG_00F6|GPUREG_00F6]]<br />
| <br />
|<br />
|-<br />
| 00F7<br />
| [[#GPUREG_00F7|GPUREG_00F7]]<br />
| <br />
|<br />
|-<br />
| 00F8<br />
| [[#GPUREG_TEXENV5_CONFIG0|GPUREG_TEXENV5_CONFIG0]]<br />
| <br />
|PICA_REG_TEX_ENV_5<br />
|-<br />
| 00F9<br />
| [[#GPUREG_TEXENV5_CONFIG1|GPUREG_TEXENV5_CONFIG1]]<br />
| <br />
|PICA_REG_TEX_ENV_5_OPERAND<br />
|-<br />
| 00FA<br />
| [[#GPUREG_TEXENV5_CONFIG2|GPUREG_TEXENV5_CONFIG2]]<br />
| <br />
|PICA_REG_TEX_ENV_5_COMBINE<br />
|-<br />
| 00FB<br />
| [[#GPUREG_TEXENV5_CONFIG3|GPUREG_TEXENV5_CONFIG3]]<br />
| <br />
|PICA_REG_TEX_ENV_5_COLOR<br />
|-<br />
| 00FC<br />
| [[#GPUREG_TEXENV5_CONFIG4|GPUREG_TEXENV5_CONFIG4]]<br />
| <br />
|PICA_REG_TEX_ENV_5_SCALE<br />
|-<br />
| 00FD<br />
| [[#GPUREG_TEXENV_BUFFER_COLOR|GPUREG_TEXENV_BUFFER_COLOR]]<br />
|?<br />
|PICA_REG_TEX_ENV_BUF_COLOR<br />
|-<br />
| 00FE<br />
| [[#GPUREG_00FE|GPUREG_00FE]]<br />
| <br />
|<br />
|-<br />
| 00FF<br />
| [[#GPUREG_00FF|GPUREG_00FF]]<br />
| <br />
|<br />
|-<br />
| 0100<br />
| [[#GPUREG_COLOROUTPUT_CONFIG|GPUREG_COLOROUTPUT_CONFIG]]<br />
| ?<br />
|PICA_REG_COLOR_OPERATION<br />
|-<br />
| 0101<br />
| [[#GPUREG_BLEND_CONFIG|GPUREG_BLEND_CONFIG]]<br />
| <br />
|PICA_REG_BLEND_FUNC<br />
|-<br />
| 0102<br />
| [[#GPUREG_COLORLOGICOP_CONFIG|GPUREG_COLORLOGICOP_CONFIG]]<br />
| <br />
|PICA_REG_LOGIC_OP<br />
|-<br />
| 0103<br />
| [[#GPUREG_BLEND_COLOR|GPUREG_BLEND_COLOR]]<br />
| <br />
|PICA_REG_BLEND_COLOR<br />
|-<br />
| 0104<br />
| [[#GPUREG_ALPHATEST_CONFIG|GPUREG_ALPHATEST_CONFIG]]<br />
| <br />
|PICA_REG_FRAG_OP_ALPHA_TEST<br />
|-<br />
| 0105<br />
| [[#GPUREG_STENCILTEST_CONFIG|GPUREG_STENCILTEST_CONFIG]]<br />
| <br />
|PICA_REG_STENCIL_TEST<br />
|-<br />
| 0106<br />
| [[#GPUREG_STENCILOP_CONFIG|GPUREG_STENCILOP_CONFIG]]<br />
| <br />
|PICA_REG_STENCIL_OP<br />
|-<br />
| 0107<br />
| [[#GPUREG_DEPTHTEST_CONFIG|GPUREG_DEPTHTEST_CONFIG]]<br />
| <br />
|PICA_REG_DEPTH_COLOR_MASK<br />
|-<br />
| 0108<br />
| [[#GPUREG_0108|GPUREG_0108]]<br />
| <br />
|<br />
|-<br />
| 0109<br />
| [[#GPUREG_0109|GPUREG_0109]]<br />
| <br />
|<br />
|-<br />
| 010A<br />
| [[#GPUREG_010A|GPUREG_010A]]<br />
| <br />
|<br />
|-<br />
| 010B<br />
| [[#GPUREG_010B|GPUREG_010B]]<br />
| <br />
|<br />
|-<br />
| 010C<br />
| [[#GPUREG_010C|GPUREG_010C]]<br />
| <br />
|<br />
|-<br />
| 010D<br />
| [[#GPUREG_010D|GPUREG_010D]]<br />
| <br />
|<br />
|-<br />
| 010E<br />
| [[#GPUREG_010E|GPUREG_010E]]<br />
| <br />
|<br />
|-<br />
| 010F<br />
| [[#GPUREG_010F|GPUREG_010F]]<br />
| <br />
|<br />
|-<br />
| 0110<br />
| [[#GPUREG_0110|GPUREG_0110]]<br />
|?<br />
|PICA_REG_COLOR_BUFFER_CLEAR0<br />
|-<br />
| 0111<br />
| [[#GPUREG_0111|GPUREG_0111]]<br />
|?<br />
|PICA_REG_COLOR_BUFFER_CLEAR1<br />
|-<br />
| 0112<br />
| [[#GPUREG_COLORBUFFER_READ|GPUREG_COLORBUFFER_READ]]<br />
| <br />
|PICA_REG_COLOR_BUFFER_READ<br />
|-<br />
| 0113<br />
| [[#GPUREG_COLORBUFFER_WRITE|GPUREG_COLORBUFFER_WRITE]]<br />
| <br />
|PICA_REG_COLOR_BUFFER_WRITE<br />
|-<br />
| 0114<br />
| [[#GPUREG_DEPTHBUFFER_READ|GPUREG_DEPTHBUFFER_READ]]<br />
| <br />
|PICA_REG_DEPTH_STENCIL_READ<br />
|-<br />
| 0115<br />
| [[#GPUREG_DEPTHBUFFER_WRITE|GPUREG_DEPTHBUFFER_WRITE]]<br />
| <br />
|PICA_REG_DEPTH_STENCIL_WRITE<br />
|-<br />
| 0116<br />
| [[#GPUREG_DEPTHBUFFER_FORMAT|GPUREG_DEPTHBUFFER_FORMAT]]<br />
| <br />
|PICA_REG_RENDER_BUF_DEPTH_MODE<br />
|-<br />
| 0117<br />
| [[#GPUREG_COLORBUFFER_FORMAT|GPUREG_COLORBUFFER_FORMAT]]<br />
| <br />
|PICA_REG_RENDER_BUF_COLOR_MODE<br />
|-<br />
| 0118<br />
| [[#GPUREG_0118|GPUREG_0118]]<br />
|?<br />
|PICA_REG_EARLY_DEPTH_TEST2<br />
|-<br />
| 0119<br />
| [[#GPUREG_0119|GPUREG_0119]]<br />
| <br />
|<br />
|-<br />
| 011A<br />
| [[#GPUREG_011A|GPUREG_011A]]<br />
| <br />
|<br />
|-<br />
| 011B<br />
| [[#GPUREG_011B|GPUREG_011B]]<br />
|?<br />
|PICA_REG_RENDER_BLOCK_FORMAT<br />
|-<br />
| 011C<br />
| [[#GPUREG_DEPTHBUFFER_LOC|GPUREG_DEPTHBUFFER_LOC]]<br />
|<br />
|PICA_REG_RENDER_BUF_DEPTH_ADDR<br />
|-<br />
| 011D<br />
| [[#GPUREG_COLORBUFFER_LOC|GPUREG_COLORBUFFER_LOC]]<br />
| <br />
|PICA_REG_RENDER_BUF_COLOR_ADDR<br />
|-<br />
| 011E<br />
| [[#GPUREG_OUTBUFFER_DIM|GPUREG_OUTBUFFER_DIM]]<br />
| <br />
|PICA_REG_RENDER_BUF_RESOLUTION0<br />
|-<br />
| 011F<br />
| [[#GPUREG_011F|GPUREG_011F]]<br />
| <br />
|<br />
|-<br />
| 0120<br />
| [[#GPUREG_0120|GPUREG_0120]]<br />
|?<br />
|PICA_REG_GAS_LIGHT_XY<br />
|-<br />
| 0121<br />
| [[#GPUREG_0121|GPUREG_0121]]<br />
|?<br />
|PICA_REG_GAS_LIGHT_Z<br />
|-<br />
| 0122<br />
| [[#GPUREG_0122|GPUREG_0122]]<br />
|?<br />
|PICA_REG_GAS_LIGHT_Z_COLOR<br />
|-<br />
| 0123<br />
| [[#GPUREG_0123|GPUREG_0123]]<br />
|?<br />
|PICA_REG_GAS_LUT_INDEX<br />
|-<br />
| 0124<br />
| [[#GPUREG_0124|GPUREG_0124]]<br />
|?<br />
|PICA_REG_GAS_LUT_DATA<br />
|-<br />
| 0125<br />
| [[#GPUREG_0125|GPUREG_0125]]<br />
| <br />
|<br />
|-<br />
| 0126<br />
| [[#GPUREG_0126|GPUREG_0126]]<br />
|?<br />
|PICA_REG_GAS_DELTAZ_DEPTH<br />
|-<br />
| 0127<br />
| [[#GPUREG_0127|GPUREG_0127]]<br />
| <br />
|<br />
|-<br />
| 0128<br />
| [[#GPUREG_0128|GPUREG_0128]]<br />
| <br />
|<br />
|-<br />
| 0129<br />
| [[#GPUREG_0129|GPUREG_0129]]<br />
| <br />
|<br />
|-<br />
| 012A<br />
| [[#GPUREG_012A|GPUREG_012A]]<br />
| <br />
|<br />
|-<br />
| 012B<br />
| [[#GPUREG_012B|GPUREG_012B]]<br />
| <br />
|<br />
|-<br />
| 012C<br />
| [[#GPUREG_012C|GPUREG_012C]]<br />
| <br />
|<br />
|-<br />
| 012D<br />
| [[#GPUREG_012D|GPUREG_012D]]<br />
| <br />
|<br />
|-<br />
| 012E<br />
| [[#GPUREG_012E|GPUREG_012E]]<br />
| <br />
|<br />
|-<br />
| 012F<br />
| [[#GPUREG_012F|GPUREG_012F]]<br />
| <br />
|<br />
|-<br />
| 0130<br />
| [[#GPUREG_0130|GPUREG_0130]]<br />
|?<br />
|PICA_REG_FRAG_OP_SHADOW<br />
|-<br />
| 0131<br />
| [[#GPUREG_0131|GPUREG_0131]]<br />
| <br />
|<br />
|-<br />
| 0132<br />
| [[#GPUREG_0132|GPUREG_0132]]<br />
| <br />
|<br />
|-<br />
| 0133<br />
| [[#GPUREG_0133|GPUREG_0133]]<br />
| <br />
|<br />
|-<br />
| 0134<br />
| [[#GPUREG_0134|GPUREG_0134]]<br />
| <br />
|<br />
|-<br />
| 0135<br />
| [[#GPUREG_0135|GPUREG_0135]]<br />
| <br />
|<br />
|-<br />
| 0136<br />
| [[#GPUREG_0136|GPUREG_0136]]<br />
| <br />
|<br />
|-<br />
| 0137<br />
| [[#GPUREG_0137|GPUREG_0137]]<br />
| <br />
|<br />
|-<br />
| 0138<br />
| [[#GPUREG_0138|GPUREG_0138]]<br />
| <br />
|<br />
|-<br />
| 0139<br />
| [[#GPUREG_0139|GPUREG_0139]]<br />
| <br />
|<br />
|-<br />
| 013A<br />
| [[#GPUREG_013A|GPUREG_013A]]<br />
| <br />
|<br />
|-<br />
| 013B<br />
| [[#GPUREG_013B|GPUREG_013B]]<br />
| <br />
|<br />
|-<br />
| 013C<br />
| [[#GPUREG_013C|GPUREG_013C]]<br />
| <br />
|<br />
|-<br />
| 013D<br />
| [[#GPUREG_013D|GPUREG_013D]]<br />
| <br />
|<br />
|-<br />
| 013E<br />
| [[#GPUREG_013E|GPUREG_013E]]<br />
| <br />
|<br />
|-<br />
| 013F<br />
| [[#GPUREG_013F|GPUREG_013F]]<br />
| <br />
|<br />
|-<br />
| 0140<br />
| [[#GPUREG_0140|GPUREG_0140]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_SPECULAR0 / PICA_REG_FRAG_LIGHT_START<br />
|-<br />
| 0141<br />
| [[#GPUREG_0141|GPUREG_0141]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_SPECULAR1<br />
|-<br />
| 0142<br />
| [[#GPUREG_0142|GPUREG_0142]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_DIFFUSE<br />
|-<br />
| 0143<br />
| [[#GPUREG_0143|GPUREG_0143]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_AMBIENT<br />
|-<br />
| 0144<br />
| [[#GPUREG_0144|GPUREG_0144]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_POSITION_XY<br />
|-<br />
| 0145<br />
| [[#GPUREG_0145|GPUREG_0145]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_POSITION_Z<br />
|-<br />
| 0146<br />
| [[#GPUREG_0146|GPUREG_0146]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_SPOT_XY<br />
|-<br />
| 0147<br />
| [[#GPUREG_0147|GPUREG_0147]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_SPOT_Z<br />
|-<br />
| 0148<br />
| [[#GPUREG_0148|GPUREG_0148]]<br />
| <br />
|<br />
|-<br />
| 0149<br />
| [[#GPUREG_0149|GPUREG_0149]]<br />
| <br />
|PICA_REG_FRAG_LIGHT0_TYPE<br />
|-<br />
| 014A<br />
| [[#GPUREG_014A|GPUREG_014A]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_DIST_ATTN_BIAS<br />
|-<br />
| 014B<br />
| [[#GPUREG_014B|GPUREG_014B]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT0_DIST_ATTN_SCALE<br />
|-<br />
| 014C<br />
| [[#GPUREG_014C|GPUREG_014C]]<br />
| <br />
|<br />
|-<br />
| 014D<br />
| [[#GPUREG_014D|GPUREG_014D]]<br />
| <br />
|<br />
|-<br />
| 014E<br />
| [[#GPUREG_014E|GPUREG_014E]]<br />
| <br />
|<br />
|-<br />
| 014F<br />
| [[#GPUREG_014F|GPUREG_014F]]<br />
| <br />
|<br />
|-<br />
| 0150<br />
| [[#GPUREG_0150|GPUREG_0150]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_SPECULAR0<br />
|-<br />
| 0151<br />
| [[#GPUREG_0151|GPUREG_0151]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_SPECULAR1<br />
|-<br />
| 0152<br />
| [[#GPUREG_0152|GPUREG_0152]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_DIFFUSE<br />
|-<br />
| 0153<br />
| [[#GPUREG_0153|GPUREG_0153]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_AMBIENT<br />
|-<br />
| 0154<br />
| [[#GPUREG_0154|GPUREG_0154]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_POSITION_XY<br />
|-<br />
| 0155<br />
| [[#GPUREG_0155|GPUREG_0155]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_POSITION_Z<br />
|-<br />
| 0156<br />
| [[#GPUREG_0156|GPUREG_0156]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_SPOT_XY<br />
|-<br />
| 0157<br />
| [[#GPUREG_0157|GPUREG_0157]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_SPOT_Z<br />
|-<br />
| 0158<br />
| [[#GPUREG_0158|GPUREG_0158]]<br />
| <br />
|<br />
|-<br />
| 0159<br />
| [[#GPUREG_0159|GPUREG_0159]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_TYPE<br />
|-<br />
| 015A<br />
| [[#GPUREG_015A|GPUREG_015A]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_DIST_ATTN_BIAS<br />
|-<br />
| 015B<br />
| [[#GPUREG_015B|GPUREG_015B]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT1_DIST_ATTN_SCALE<br />
|-<br />
| 015C<br />
| [[#GPUREG_015C|GPUREG_015C]]<br />
| <br />
|<br />
|-<br />
| 015D<br />
| [[#GPUREG_015D|GPUREG_015D]]<br />
| <br />
|<br />
|-<br />
| 015E<br />
| [[#GPUREG_015E|GPUREG_015E]]<br />
| <br />
|<br />
|-<br />
| 015F<br />
| [[#GPUREG_015F|GPUREG_015F]]<br />
| <br />
|<br />
|-<br />
| 0160<br />
| [[#GPUREG_0160|GPUREG_0160]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_SPECULAR0<br />
|-<br />
| 0161<br />
| [[#GPUREG_0161|GPUREG_0161]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_SPECULAR1<br />
|-<br />
| 0162<br />
| [[#GPUREG_0162|GPUREG_0162]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_DIFFUSE<br />
|-<br />
| 0163<br />
| [[#GPUREG_0163|GPUREG_0163]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_AMBIENT<br />
|-<br />
| 0164<br />
| [[#GPUREG_0164|GPUREG_0164]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_POSITION_XY<br />
|-<br />
| 0165<br />
| [[#GPUREG_0165|GPUREG_0165]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_POSITION_Z<br />
|-<br />
| 0166<br />
| [[#GPUREG_0166|GPUREG_0166]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_SPOT_XY<br />
|-<br />
| 0167<br />
| [[#GPUREG_0167|GPUREG_0167]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_SPOT_Z<br />
|-<br />
| 0168<br />
| [[#GPUREG_0168|GPUREG_0168]]<br />
| <br />
|<br />
|-<br />
| 0169<br />
| [[#GPUREG_0169|GPUREG_0169]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_TYPE<br />
|-<br />
| 016A<br />
| [[#GPUREG_016A|GPUREG_016A]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_DIST_ATTN_BIAS<br />
|-<br />
| 016B<br />
| [[#GPUREG_016B|GPUREG_016B]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT2_DIST_ATTN_SCALE<br />
|-<br />
| 016C<br />
| [[#GPUREG_016C|GPUREG_016C]]<br />
| <br />
|<br />
|-<br />
| 016D<br />
| [[#GPUREG_016D|GPUREG_016D]]<br />
| <br />
|<br />
|-<br />
| 016E<br />
| [[#GPUREG_016E|GPUREG_016E]]<br />
| <br />
|<br />
|-<br />
| 016F<br />
| [[#GPUREG_016F|GPUREG_016F]]<br />
| <br />
|<br />
|-<br />
| 0170<br />
| [[#GPUREG_0170|GPUREG_0170]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_SPECULAR0<br />
|-<br />
| 0171<br />
| [[#GPUREG_0171|GPUREG_0171]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_SPECULAR1<br />
|-<br />
| 0172<br />
| [[#GPUREG_0172|GPUREG_0172]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_DIFFUSE<br />
|-<br />
| 0173<br />
| [[#GPUREG_0173|GPUREG_0173]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_AMBIENT<br />
|-<br />
| 0174<br />
| [[#GPUREG_0174|GPUREG_0174]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_POSITION_XY<br />
|-<br />
| 0175<br />
| [[#GPUREG_0175|GPUREG_0175]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_POSITION_Z<br />
|-<br />
| 0176<br />
| [[#GPUREG_0176|GPUREG_0176]]<br />
|? <br />
|PICA_REG_FRAG_LIGHT3_SPOT_XY<br />
|-<br />
| 0177<br />
| [[#GPUREG_0177|GPUREG_0177]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_SPOT_Z<br />
|-<br />
| 0178<br />
| [[#GPUREG_0178|GPUREG_0178]]<br />
| <br />
|<br />
|-<br />
| 0179<br />
| [[#GPUREG_0179|GPUREG_0179]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_TYPE<br />
|-<br />
| 017A<br />
| [[#GPUREG_017A|GPUREG_017A]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_DIST_ATTN_BIAS<br />
|-<br />
| 017B<br />
| [[#GPUREG_017B|GPUREG_017B]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT3_DIST_ATTN_SCALE<br />
|-<br />
| 017C<br />
| [[#GPUREG_017C|GPUREG_017C]]<br />
| <br />
|<br />
|-<br />
| 017D<br />
| [[#GPUREG_017D|GPUREG_017D]]<br />
| <br />
|<br />
|-<br />
| 017E<br />
| [[#GPUREG_017E|GPUREG_017E]]<br />
| <br />
|<br />
|-<br />
| 017F<br />
| [[#GPUREG_017F|GPUREG_017F]]<br />
| <br />
|<br />
|-<br />
| 0180<br />
| [[#GPUREG_0180|GPUREG_0180]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_SPECULAR0<br />
|-<br />
| 0181<br />
| [[#GPUREG_0181|GPUREG_0181]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_SPECULAR1<br />
|-<br />
| 0182<br />
| [[#GPUREG_0182|GPUREG_0182]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_DIFFUSE<br />
|-<br />
| 0183<br />
| [[#GPUREG_0183|GPUREG_0183]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_AMBIENT<br />
|-<br />
| 0184<br />
| [[#GPUREG_0184|GPUREG_0184]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_POSITION_XY<br />
|-<br />
| 0185<br />
| [[#GPUREG_0185|GPUREG_0185]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_POSITION_Z<br />
|-<br />
| 0186<br />
| [[#GPUREG_0186|GPUREG_0186]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_SPOT_XY<br />
|-<br />
| 0187<br />
| [[#GPUREG_0187|GPUREG_0187]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_SPOT_Z<br />
|-<br />
| 0188<br />
| [[#GPUREG_0188|GPUREG_0188]]<br />
| <br />
|<br />
|-<br />
| 0189<br />
| [[#GPUREG_0189|GPUREG_0189]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_TYPE<br />
|-<br />
| 018A<br />
| [[#GPUREG_018A|GPUREG_018A]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_DIST_ATTN_BIAS<br />
|-<br />
| 018B<br />
| [[#GPUREG_018B|GPUREG_018B]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT4_DIST_ATTN_SCALE<br />
|-<br />
| 018C<br />
| [[#GPUREG_018C|GPUREG_018C]]<br />
| <br />
|<br />
|-<br />
| 018D<br />
| [[#GPUREG_018D|GPUREG_018D]]<br />
| <br />
|<br />
|-<br />
| 018E<br />
| [[#GPUREG_018E|GPUREG_018E]]<br />
| <br />
|<br />
|-<br />
| 018F<br />
| [[#GPUREG_018F|GPUREG_018F]]<br />
| <br />
|<br />
|-<br />
| 0190<br />
| [[#GPUREG_0190|GPUREG_0190]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_SPECULAR0<br />
|-<br />
| 0191<br />
| [[#GPUREG_0191|GPUREG_0191]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_SPECULAR1<br />
|-<br />
| 0192<br />
| [[#GPUREG_0192|GPUREG_0192]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_DIFFUSE<br />
|-<br />
| 0193<br />
| [[#GPUREG_0193|GPUREG_0193]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_AMBIENT<br />
|-<br />
| 0194<br />
| [[#GPUREG_0194|GPUREG_0194]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_POSITION_XY<br />
|-<br />
| 0195<br />
| [[#GPUREG_0195|GPUREG_0195]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_POSITION_Z<br />
|-<br />
| 0196<br />
| [[#GPUREG_0196|GPUREG_0196]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_SPOT_XY<br />
|-<br />
| 0197<br />
| [[#GPUREG_0197|GPUREG_0197]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_SPOT_Z<br />
|-<br />
| 0198<br />
| [[#GPUREG_0198|GPUREG_0198]]<br />
| <br />
|<br />
|-<br />
| 0199<br />
| [[#GPUREG_0199|GPUREG_0199]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT5_TYPE<br />
|-<br />
| 019A<br />
| [[#GPUREG_019A|GPUREG_019A]]<br />
| <br />
|<br />
|-<br />
| 019B<br />
| [[#GPUREG_019B|GPUREG_019B]]<br />
| <br />
|<br />
|-<br />
| 019C<br />
| [[#GPUREG_019C|GPUREG_019C]]<br />
| <br />
|<br />
|-<br />
| 019D<br />
| [[#GPUREG_019D|GPUREG_019D]]<br />
| <br />
|<br />
|-<br />
| 019E<br />
| [[#GPUREG_019E|GPUREG_019E]]<br />
| <br />
|<br />
|-<br />
| 019F<br />
| [[#GPUREG_019F|GPUREG_019F]]<br />
| <br />
|<br />
|-<br />
| 01A0<br />
| [[#GPUREG_01A0|GPUREG_01A0]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT6_SPECULAR0<br />
|-<br />
| 01A1<br />
| [[#GPUREG_01A1|GPUREG_01A1]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT6_SPECULAR1<br />
|-<br />
| 01A2<br />
| [[#GPUREG_01A2|GPUREG_01A2]]<br />
| <br />
|PICA_REG_FRAG_LIGHT6_DIFFUSE<br />
|-<br />
| 01A3<br />
| [[#GPUREG_01A3|GPUREG_01A3]]<br />
| <br />
|PICA_REG_FRAG_LIGHT6_AMBIENT<br />
|-<br />
| 01A4<br />
| [[#GPUREG_01A4|GPUREG_01A4]]<br />
| <br />
|PICA_REG_FRAG_LIGHT6_POSITION_XY<br />
|-<br />
| 01A5<br />
| [[#GPUREG_01A5|GPUREG_01A5]]<br />
| <br />
|PICA_REG_FRAG_LIGHT6_POSITION_Z<br />
|-<br />
| 01A6<br />
| [[#GPUREG_01A6|GPUREG_01A6]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT6_SPOT_XY<br />
|-<br />
| 01A7<br />
| [[#GPUREG_01A7|GPUREG_01A7]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT6_SPOT_Z<br />
|-<br />
| 01A8<br />
| [[#GPUREG_01A8|GPUREG_01A8]]<br />
| <br />
|<br />
|-<br />
| 01A9<br />
| [[#GPUREG_01A9|GPUREG_01A9]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT6_TYPE<br />
|-<br />
| 01AA<br />
| [[#GPUREG_01AA|GPUREG_01AA]]<br />
| <br />
|<br />
|-<br />
| 01AB<br />
| [[#GPUREG_01AB|GPUREG_01AB]]<br />
| <br />
|<br />
|-<br />
| 01AC<br />
| [[#GPUREG_01AC|GPUREG_01AC]]<br />
| <br />
|<br />
|-<br />
| 01AD<br />
| [[#GPUREG_01AD|GPUREG_01AD]]<br />
| <br />
|<br />
|-<br />
| 01AE<br />
| [[#GPUREG_01AE|GPUREG_01AE]]<br />
| <br />
|<br />
|-<br />
| 01AF<br />
| [[#GPUREG_01AF|GPUREG_01AF]]<br />
| <br />
|<br />
|-<br />
| 01B0<br />
| [[#GPUREG_01B0|GPUREG_01B0]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_SPECULAR0<br />
|-<br />
| 01B1<br />
| [[#GPUREG_01B1|GPUREG_01B1]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_SPECULAR1<br />
|-<br />
| 01B2<br />
| [[#GPUREG_01B2|GPUREG_01B2]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_DIFFUSE<br />
|-<br />
| 01B3<br />
| [[#GPUREG_01B3|GPUREG_01B3]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_AMBIENT<br />
|-<br />
| 01B4<br />
| [[#GPUREG_01B4|GPUREG_01B4]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_POSITION_XY<br />
|-<br />
| 01B5<br />
| [[#GPUREG_01B5|GPUREG_01B5]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_POSITION_Z<br />
|-<br />
| 01B6<br />
| [[#GPUREG_01B6|GPUREG_01B6]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_SPOT_XY<br />
|-<br />
| 01B7<br />
| [[#GPUREG_01B7|GPUREG_01B7]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_SPOT_Z<br />
|-<br />
| 01B8<br />
| [[#GPUREG_01B8|GPUREG_01B8]]<br />
| <br />
|<br />
|-<br />
| 01B9<br />
| [[#GPUREG_01B9|GPUREG_01B9]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT7_TYPE<br />
|-<br />
| 01BA<br />
| [[#GPUREG_01BA|GPUREG_01BA]]<br />
| <br />
|<br />
|-<br />
| 01BB<br />
| [[#GPUREG_01BB|GPUREG_01BB]]<br />
| <br />
|<br />
|-<br />
| 01BC<br />
| [[#GPUREG_01BC|GPUREG_01BC]]<br />
| <br />
|<br />
|-<br />
| 01BD<br />
| [[#GPUREG_01BD|GPUREG_01BD]]<br />
| <br />
|<br />
|-<br />
| 01BE<br />
| [[#GPUREG_01BE|GPUREG_01BE]]<br />
| <br />
|<br />
|-<br />
| 01BF<br />
| [[#GPUREG_01BF|GPUREG_01BF]]<br />
| <br />
|<br />
|-<br />
| 01C0<br />
| [[#GPUREG_01C0|GPUREG_01C0]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_AMBIENT<br />
|-<br />
| 01C1<br />
| [[#GPUREG_01C1|GPUREG_01C1]]<br />
| <br />
|<br />
|-<br />
| 01C2<br />
| [[#GPUREG_01C2|GPUREG_01C2]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_SRC_NUM<br />
|-<br />
| 01C3<br />
| [[#GPUREG_01C3|GPUREG_01C3]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_FUNC_MODE0<br />
|-<br />
| 01C4<br />
| [[#GPUREG_01C4|GPUREG_01C4]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_FUNC_MODE1<br />
|-<br />
| 01C5<br />
| [[#GPUREG_01C5|GPUREG_01C5]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT<br />
|-<br />
| 01C6<br />
| [[#GPUREG_01C6|GPUREG_01C6]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_EN1<br />
|-<br />
| 01C7<br />
| [[#GPUREG_01C7|GPUREG_01C7]]<br />
| <br />
|<br />
|-<br />
| 01C8<br />
| [[#GPUREG_01C8|GPUREG_01C8]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA0<br />
|-<br />
| 01C9<br />
| [[#GPUREG_01C9|GPUREG_01C9]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA1<br />
|-<br />
| 01CA<br />
| [[#GPUREG_01CA|GPUREG_01CA]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA2<br />
|-<br />
| 01CB<br />
| [[#GPUREG_01CB|GPUREG_01CB]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA3<br />
|-<br />
| 01CC<br />
| [[#GPUREG_01CC|GPUREG_01CC]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA4<br />
|-<br />
| 01CD<br />
| [[#GPUREG_01CD|GPUREG_01CD]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA8<br />
|-<br />
| 01CE<br />
| [[#GPUREG_01CE|GPUREG_01CE]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA6<br />
|-<br />
| 01CF<br />
| [[#GPUREG_01CF|GPUREG_01CF]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUT_DATA7<br />
|-<br />
| 01D0<br />
| [[#GPUREG_01D0|GPUREG_01D0]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_ABSLUTINPUT<br />
|-<br />
| 01D1<br />
| [[#GPUREG_01D1|GPUREG_01D1]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUTINPUT<br />
|-<br />
| 01D2<br />
| [[#GPUREG_01D2|GPUREG_01D2]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_LUTSCALE<br />
|-<br />
| 01D3<br />
| [[#GPUREG_01D3|GPUREG_01D3]]<br />
| <br />
|<br />
|-<br />
| 01D4<br />
| [[#GPUREG_01D4|GPUREG_01D4]]<br />
| <br />
|<br />
|-<br />
| 01D5<br />
| [[#GPUREG_01D5|GPUREG_01D5]]<br />
| <br />
|<br />
|-<br />
| 01D6<br />
| [[#GPUREG_01D6|GPUREG_01D6]]<br />
| <br />
|<br />
|-<br />
| 01D7<br />
| [[#GPUREG_01D7|GPUREG_01D7]]<br />
| <br />
|<br />
|-<br />
| 01D8<br />
| [[#GPUREG_01D8|GPUREG_01D8]]<br />
| <br />
|<br />
|-<br />
| 01D9<br />
| [[#GPUREG_01D9|GPUREG_01D9]]<br />
|?<br />
|PICA_REG_FRAG_LIGHT_SRC_EN_ID<br />
|-<br />
| 01DA<br />
| [[#GPUREG_01DA|GPUREG_01DA]]<br />
| <br />
|<br />
|-<br />
| 01DB<br />
| [[#GPUREG_01DB|GPUREG_01DB]]<br />
| <br />
|<br />
|-<br />
| 01DC<br />
| [[#GPUREG_01DC|GPUREG_01DC]]<br />
| <br />
|<br />
|-<br />
| 01DD<br />
| [[#GPUREG_01DD|GPUREG_01DD]]<br />
| <br />
|<br />
|-<br />
| 01DE<br />
| [[#GPUREG_01DE|GPUREG_01DE]]<br />
| <br />
|<br />
|-<br />
| 01DF<br />
| [[#GPUREG_01DF|GPUREG_01DF]]<br />
| <br />
|<br />
|-<br />
| 01E0<br />
| [[#GPUREG_01E0|GPUREG_01E0]]<br />
| <br />
|<br />
|-<br />
| 01E1<br />
| [[#GPUREG_01E1|GPUREG_01E1]]<br />
| <br />
|<br />
|-<br />
| 01E2<br />
| [[#GPUREG_01E2|GPUREG_01E2]]<br />
| <br />
|<br />
|-<br />
| 01E3<br />
| [[#GPUREG_01E3|GPUREG_01E3]]<br />
| <br />
|<br />
|-<br />
| 01E4<br />
| [[#GPUREG_01E4|GPUREG_01E4]]<br />
| <br />
|<br />
|-<br />
| 01E5<br />
| [[#GPUREG_01E5|GPUREG_01E5]]<br />
| <br />
|<br />
|-<br />
| 01E6<br />
| [[#GPUREG_01E6|GPUREG_01E6]]<br />
| <br />
|<br />
|-<br />
| 01E7<br />
| [[#GPUREG_01E7|GPUREG_01E7]]<br />
| <br />
|<br />
|-<br />
| 01E8<br />
| [[#GPUREG_01E8|GPUREG_01E8]]<br />
| <br />
|<br />
|-<br />
| 01E9<br />
| [[#GPUREG_01E9|GPUREG_01E9]]<br />
| <br />
|<br />
|-<br />
| 01EA<br />
| [[#GPUREG_01EA|GPUREG_01EA]]<br />
| <br />
|<br />
|-<br />
| 01EB<br />
| [[#GPUREG_01EB|GPUREG_01EB]]<br />
| <br />
|<br />
|-<br />
| 01EC<br />
| [[#GPUREG_01EC|GPUREG_01EC]]<br />
| <br />
|<br />
|-<br />
| 01ED<br />
| [[#GPUREG_01ED|GPUREG_01ED]]<br />
| <br />
|<br />
|-<br />
| 01EE<br />
| [[#GPUREG_01EE|GPUREG_01EE]]<br />
| <br />
|<br />
|-<br />
| 01EF<br />
| [[#GPUREG_01EF|GPUREG_01EF]]<br />
| <br />
|<br />
|-<br />
| 01F0<br />
| [[#GPUREG_01F0|GPUREG_01F0]]<br />
| <br />
|<br />
|-<br />
| 01F1<br />
| [[#GPUREG_01F1|GPUREG_01F1]]<br />
| <br />
|<br />
|-<br />
| 01F2<br />
| [[#GPUREG_01F2|GPUREG_01F2]]<br />
| <br />
|<br />
|-<br />
| 01F3<br />
| [[#GPUREG_01F3|GPUREG_01F3]]<br />
| <br />
|<br />
|-<br />
| 01F4<br />
| [[#GPUREG_01F4|GPUREG_01F4]]<br />
| <br />
|<br />
|-<br />
| 01F5<br />
| [[#GPUREG_01F5|GPUREG_01F5]]<br />
| <br />
|<br />
|-<br />
| 01F6<br />
| [[#GPUREG_01F6|GPUREG_01F6]]<br />
| <br />
|<br />
|-<br />
| 01F7<br />
| [[#GPUREG_01F7|GPUREG_01F7]]<br />
| <br />
|<br />
|-<br />
| 01F8<br />
| [[#GPUREG_01F8|GPUREG_01F8]]<br />
| <br />
|<br />
|-<br />
| 01F9<br />
| [[#GPUREG_01F9|GPUREG_01F9]]<br />
| <br />
|<br />
|-<br />
| 01FA<br />
| [[#GPUREG_01FA|GPUREG_01FA]]<br />
| <br />
|<br />
|-<br />
| 01FB<br />
| [[#GPUREG_01FB|GPUREG_01FB]]<br />
| <br />
|<br />
|-<br />
| 01FC<br />
| [[#GPUREG_01FC|GPUREG_01FC]]<br />
| <br />
|<br />
|-<br />
| 01FD<br />
| [[#GPUREG_01FD|GPUREG_01FD]]<br />
| <br />
|<br />
|-<br />
| 01FE<br />
| [[#GPUREG_01FE|GPUREG_01FE]]<br />
| <br />
|<br />
|-<br />
| 01FF<br />
| [[#GPUREG_01FF|GPUREG_01FF]]<br />
| <br />
|<br />
|-<br />
! colspan=3 | Geometry pipeline registers<br />
|<br />
|-<br />
| 0200<br />
| [[#GPUREG_ATTRIBBUFFERS_LOC|GPUREG_ATTRIBBUFFERS_LOC]]<br />
| <br />
|PICA_REG_VTX_ATTR_ARRAYS_BASE_ADDR<br />
|-<br />
| 0201<br />
| [[#GPUREG_ATTRIBBUFFERS_FORMAT_LOW|GPUREG_ATTRIBBUFFERS_FORMAT_LOW]]<br />
| <br />
|PICA_REG_VTX_ATTR_ARRAYS0<br />
|-<br />
| 0202<br />
| [[#GPUREG_ATTRIBBUFFERS_FORMAT_HIGH|GPUREG_ATTRIBBUFFERS_FORMAT_HIGH]]<br />
| <br />
|PICA_REG_VTX_ATTR_ARRAYS1<br />
|-<br />
| 0203<br />
| [[#GPUREG_ATTRIBBUFFER0_CONFIG0|GPUREG_ATTRIBBUFFER0_CONFIG0]]<br />
| <br />
|PICA_REG_LOAD_ARRAY0_ATTR_OFFSET<br />
|-<br />
| 0204<br />
| [[#GPUREG_ATTRIBBUFFER0_CONFIG1|GPUREG_ATTRIBBUFFER0_CONFIG1]]<br />
| <br />
|PICA_REG_LOAD_ARRAY0_ELEMENT0<br />
|-<br />
| 0205<br />
| [[#GPUREG_ATTRIBBUFFER0_CONFIG2|GPUREG_ATTRIBBUFFER0_CONFIG2]]<br />
| <br />
|PICA_REG_LOAD_ARRAY0_ELEMENT1<br />
|-<br />
| 0206<br />
| [[#GPUREG_ATTRIBBUFFER1_CONFIG0|GPUREG_ATTRIBBUFFER1_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 0207<br />
| [[#GPUREG_ATTRIBBUFFER1_CONFIG1|GPUREG_ATTRIBBUFFER1_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 0208<br />
| [[#GPUREG_ATTRIBBUFFER1_CONFIG2|GPUREG_ATTRIBBUFFER1_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 0209<br />
| [[#GPUREG_ATTRIBBUFFER2_CONFIG0|GPUREG_ATTRIBBUFFER2_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 020A<br />
| [[#GPUREG_ATTRIBBUFFER2_CONFIG1|GPUREG_ATTRIBBUFFER2_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 020B<br />
| [[#GPUREG_ATTRIBBUFFER2_CONFIG2|GPUREG_ATTRIBBUFFER2_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 020C<br />
| [[#GPUREG_ATTRIBBUFFER3_CONFIG0|GPUREG_ATTRIBBUFFER3_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 020D<br />
| [[#GPUREG_ATTRIBBUFFER3_CONFIG1|GPUREG_ATTRIBBUFFER3_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 020E<br />
| [[#GPUREG_ATTRIBBUFFER3_CONFIG2|GPUREG_ATTRIBBUFFER3_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 020F<br />
| [[#GPUREG_ATTRIBBUFFER4_CONFIG0|GPUREG_ATTRIBBUFFER4_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 0210<br />
| [[#GPUREG_ATTRIBBUFFER4_CONFIG1|GPUREG_ATTRIBBUFFER4_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 0211<br />
| [[#GPUREG_ATTRIBBUFFER4_CONFIG2|GPUREG_ATTRIBBUFFER4_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 0212<br />
| [[#GPUREG_ATTRIBBUFFER5_CONFIG0|GPUREG_ATTRIBBUFFER5_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 0213<br />
| [[#GPUREG_ATTRIBBUFFER5_CONFIG1|GPUREG_ATTRIBBUFFER5_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 0214<br />
| [[#GPUREG_ATTRIBBUFFER5_CONFIG2|GPUREG_ATTRIBBUFFER5_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 0215<br />
| [[#GPUREG_ATTRIBBUFFER6_CONFIG0|GPUREG_ATTRIBBUFFER6_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 0216<br />
| [[#GPUREG_ATTRIBBUFFER6_CONFIG1|GPUREG_ATTRIBBUFFER6_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 0217<br />
| [[#GPUREG_ATTRIBBUFFER6_CONFIG2|GPUREG_ATTRIBBUFFER6_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 0218<br />
| [[#GPUREG_ATTRIBBUFFER7_CONFIG0|GPUREG_ATTRIBBUFFER7_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 0219<br />
| [[#GPUREG_ATTRIBBUFFER7_CONFIG1|GPUREG_ATTRIBBUFFER7_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 021A<br />
| [[#GPUREG_ATTRIBBUFFER7_CONFIG2|GPUREG_ATTRIBBUFFER7_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 021B<br />
| [[#GPUREG_ATTRIBBUFFER8_CONFIG0|GPUREG_ATTRIBBUFFER8_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 021C<br />
| [[#GPUREG_ATTRIBBUFFER8_CONFIG1|GPUREG_ATTRIBBUFFER8_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 021D<br />
| [[#GPUREG_ATTRIBBUFFER8_CONFIG2|GPUREG_ATTRIBBUFFER8_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 021E<br />
| [[#GPUREG_ATTRIBBUFFER9_CONFIG0|GPUREG_ATTRIBBUFFER9_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 021F<br />
| [[#GPUREG_ATTRIBBUFFER9_CONFIG1|GPUREG_ATTRIBBUFFER9_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 0220<br />
| [[#GPUREG_ATTRIBBUFFER9_CONFIG2|GPUREG_ATTRIBBUFFER9_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 0221<br />
| [[#GPUREG_ATTRIBBUFFERA_CONFIG0|GPUREG_ATTRIBBUFFERA_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 0222<br />
| [[#GPUREG_ATTRIBBUFFERA_CONFIG1|GPUREG_ATTRIBBUFFERA_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 0223<br />
| [[#GPUREG_ATTRIBBUFFERA_CONFIG2|GPUREG_ATTRIBBUFFERA_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 0224<br />
| [[#GPUREG_ATTRIBBUFFERB_CONFIG0|GPUREG_ATTRIBBUFFERB_CONFIG0]]<br />
| <br />
|<br />
|-<br />
| 0225<br />
| [[#GPUREG_ATTRIBBUFFERB_CONFIG1|GPUREG_ATTRIBBUFFERB_CONFIG1]]<br />
| <br />
|<br />
|-<br />
| 0226<br />
| [[#GPUREG_ATTRIBBUFFERB_CONFIG2|GPUREG_ATTRIBBUFFERB_CONFIG2]]<br />
| <br />
|<br />
|-<br />
| 0227<br />
| [[#GPUREG_INDEXBUFFER_CONFIG|GPUREG_INDEXBUFFER_CONFIG]]<br />
| <br />
|PICA_REG_INDEX_ARRAY_ADDR_OFFSET<br />
|-<br />
| 0228<br />
| [[#GPUREG_NUMVERTICES|GPUREG_NUMVERTICES]]<br />
| <br />
|PICA_REG_DRAW_VERTEX_NUM<br />
|-<br />
| 0229<br />
| [[#GPUREG_GEOSTAGE_CONFIG|GPUREG_GEOSTAGE_CONFIG]]<br />
| ?<br />
|PICA_REG_DRAW_MODE0<br />
|-<br />
| 022A<br />
| [[#GPUREG_022A|GPUREG_022A]]<br />
|?<br />
|PICA_REG_DRAW_VERTEX_OFFSET<br />
|-<br />
| 022B<br />
| [[#GPUREG_022B|GPUREG_022B]]<br />
| <br />
|<br />
|-<br />
| 022C<br />
| [[#GPUREG_022C|GPUREG_022C]]<br />
| <br />
|<br />
|-<br />
| 022D<br />
| [[#GPUREG_022D|GPUREG_022D]]<br />
| <br />
|<br />
|-<br />
| 022E<br />
| [[#GPUREG_DRAWARRAYS|GPUREG_DRAWARRAYS]]<br />
|<br />
|PICA_REG_START_DRAW_ARRAY<br />
|-<br />
| 022F<br />
| [[#GPUREG_DRAWELEMENTS|GPUREG_DRAWELEMENTS]]<br />
|<br />
|PICA_REG_START_DRAW_ELEMENT<br />
|-<br />
| 0230<br />
| [[#GPUREG_0230|GPUREG_0230]]<br />
| <br />
|<br />
|-<br />
| 0231<br />
| [[#GPUREG_0231|GPUREG_0231]]<br />
|?<br />
|PICA_REG_VTX_FUNC<br />
|-<br />
| 0232<br />
| [[#GPUREG_FIXEDATTRIB_INDEX|GPUREG_FIXEDATTRIB_INDEX]]<br />
|?<br />
|PICA_REG_VS_FIXED_ATTR<br />
|-<br />
| 0233<br />
| [[#GPUREG_FIXEDATTRIB_DATA|GPUREG_FIXEDATTRIB_DATA]]<br />
|?<br />
|PICA_REG_VS_FIXED_ATTR_DATA0<br />
|-<br />
| 0234<br />
| [[#GPUREG_FIXEDATTRIB_DATA|GPUREG_FIXEDATTRIB_DATA]]<br />
|?<br />
|PICA_REG_VS_FIXED_ATTR_DATA1<br />
|-<br />
| 0235<br />
| [[#GPUREG_FIXEDATTRIB_DATA|GPUREG_FIXEDATTRIB_DATA]]<br />
|?<br />
|PICA_REG_VS_FIXED_ATTR_DATA2<br />
|-<br />
| 0236<br />
| [[#GPUREG_0236|GPUREG_0236]]<br />
| <br />
|<br />
|-<br />
| 0237<br />
| [[#GPUREG_0237|GPUREG_0237]]<br />
| <br />
|<br />
|-<br />
| 0238<br />
| [[#GPUREG_0238|GPUREG_0238]]<br />
| <br />
|<br />
|-<br />
| 0239<br />
| [[#GPUREG_0239|GPUREG_0239]]<br />
| <br />
|<br />
|-<br />
| 023A<br />
| [[#GPUREG_023A|GPUREG_023A]]<br />
| <br />
|<br />
|-<br />
| 023B<br />
| [[#GPUREG_023B|GPUREG_023B]]<br />
| <br />
|<br />
|-<br />
| 023C<br />
| [[#GPUREG_023C|GPUREG_023C]]<br />
| <br />
|<br />
|-<br />
| 023D<br />
| [[#GPUREG_023D|GPUREG_023D]]<br />
| <br />
|<br />
|-<br />
| 023E<br />
| [[#GPUREG_023E|GPUREG_023E]]<br />
| <br />
|<br />
|-<br />
| 023F<br />
| [[#GPUREG_023F|GPUREG_023F]]<br />
| <br />
|<br />
|-<br />
| 0240<br />
| [[#GPUREG_0240|GPUREG_0240]]<br />
| <br />
|<br />
|-<br />
| 0241<br />
| [[#GPUREG_0241|GPUREG_0241]]<br />
| <br />
|<br />
|-<br />
| 0242<br />
| [[#GPUREG_0242|GPUREG_0242]]<br />
|?<br />
|PICA_REG_VS_ATTR_NUM1<br />
|-<br />
| 0243<br />
| [[#GPUREG_0243|GPUREG_0243]]<br />
| <br />
|<br />
|-<br />
| 0244<br />
| [[#GPUREG_0244|GPUREG_0244]]<br />
|?<br />
|PICA_REG_VS_COM_MODE<br />
|-<br />
| 0245<br />
| [[#GPUREG_0245|GPUREG_0245]]<br />
|?<br />
|PICA_REG_START_DRAW_FUNC0<br />
|-<br />
| 0246<br />
| [[#GPUREG_0246|GPUREG_0246]]<br />
| <br />
|<br />
|-<br />
| 0247<br />
| [[#GPUREG_0247|GPUREG_0247]]<br />
| <br />
|<br />
|-<br />
| 0248<br />
| [[#GPUREG_0248|GPUREG_0248]]<br />
| <br />
|<br />
|-<br />
| 0249<br />
| [[#GPUREG_0249|GPUREG_0249]]<br />
| <br />
|<br />
|-<br />
| 024A<br />
| [[#GPUREG_024A|GPUREG_024A]]<br />
|?<br />
|PICA_REG_VS_OUT_REG_NUM1<br />
|-<br />
| 024B<br />
| [[#GPUREG_024B|GPUREG_024B]]<br />
|<br />
|<br />
|-<br />
| 024C<br />
| [[#GPUREG_024C|GPUREG_024C]]<br />
| <br />
|<br />
|-<br />
| 024D<br />
| [[#GPUREG_024D|GPUREG_024D]]<br />
| <br />
|<br />
|-<br />
| 024E<br />
| [[#GPUREG_024E|GPUREG_024E]]<br />
| <br />
|<br />
|-<br />
| 024F<br />
| [[#GPUREG_024F|GPUREG_024F]]<br />
| <br />
|<br />
|-<br />
| 0250<br />
| [[#GPUREG_0250|GPUREG_0250]]<br />
| <br />
|<br />
|-<br />
| 0251<br />
| [[#GPUREG_0251|GPUREG_0251]]<br />
|?<br />
|PICA_REG_VS_OUT_REG_NUM2<br />
|-<br />
| 0252<br />
| [[#GPUREG_0252|GPUREG_0252]]<br />
|?<br />
|PICA_REG_GS_MISC_REG0<br />
|-<br />
| 0253<br />
| [[#GPUREG_0253|GPUREG_0253]]<br />
|?<br />
|PICA_REG_DRAW_MODE1<br />
|-<br />
| 0254<br />
| [[#GPUREG_0254|GPUREG_0254]]<br />
|?<br />
|PICA_REG_GS_MISC_REG1<br />
|-<br />
| 0255<br />
| [[#GPUREG_0255|GPUREG_0255]]<br />
| <br />
|<br />
|-<br />
| 0256<br />
| [[#GPUREG_0256|GPUREG_0256]]<br />
| <br />
|<br />
|-<br />
| 0257<br />
| [[#GPUREG_0257|GPUREG_0257]]<br />
| <br />
|<br />
|-<br />
| 0258<br />
| [[#GPUREG_0258|GPUREG_0258]]<br />
| <br />
|<br />
|-<br />
| 0259<br />
| [[#GPUREG_0259|GPUREG_0259]]<br />
| <br />
|<br />
|-<br />
| 025A<br />
| [[#GPUREG_025A|GPUREG_025A]]<br />
| <br />
|<br />
|-<br />
| 025B<br />
| [[#GPUREG_025B|GPUREG_025B]]<br />
| <br />
|<br />
|-<br />
| 025C<br />
| [[#GPUREG_025C|GPUREG_025C]]<br />
| <br />
|<br />
|-<br />
| 025D<br />
| [[#GPUREG_025D|GPUREG_025D]]<br />
| <br />
|<br />
|-<br />
| 025E<br />
| [[#GPUREG_PRIMITIVE_CONFIG|GPUREG_PRIMITIVE_CONFIG]]<br />
| ?<br />
|PICA_REG_GS_OUT_REG_NUM3 / PICA_REG_VS_OUT_REG_NUM3<br />
|-<br />
| 025F<br />
| [[#GPUREG_RESTART_PRIMITIVE|GPUREG_RESTART_PRIMITIVE]]<br />
|?<br />
|PICA_REG_START_DRAW_FUNC1<br />
|-<br />
| 0260<br />
| [[#GPUREG_0260|GPUREG_0260]]<br />
| <br />
|<br />
|-<br />
| 0261<br />
| [[#GPUREG_0261|GPUREG_0261]]<br />
| <br />
|<br />
|-<br />
| 0262<br />
| [[#GPUREG_0262|GPUREG_0262]]<br />
| <br />
|<br />
|-<br />
| 0263<br />
| [[#GPUREG_0263|GPUREG_0263]]<br />
| <br />
|<br />
|-<br />
| 0264<br />
| [[#GPUREG_0264|GPUREG_0264]]<br />
| <br />
|<br />
|-<br />
| 0265<br />
| [[#GPUREG_0265|GPUREG_0265]]<br />
| <br />
|<br />
|-<br />
| 0266<br />
| [[#GPUREG_0266|GPUREG_0266]]<br />
| <br />
|<br />
|-<br />
| 0267<br />
| [[#GPUREG_0267|GPUREG_0267]]<br />
| <br />
|<br />
|-<br />
| 0268<br />
| [[#GPUREG_0268|GPUREG_0268]]<br />
| <br />
|<br />
|-<br />
| 0269<br />
| [[#GPUREG_0269|GPUREG_0269]]<br />
| <br />
|<br />
|-<br />
| 026A<br />
| [[#GPUREG_026A|GPUREG_026A]]<br />
| <br />
|<br />
|-<br />
| 026B<br />
| [[#GPUREG_026B|GPUREG_026B]]<br />
| <br />
|<br />
|-<br />
| 026C<br />
| [[#GPUREG_026C|GPUREG_026C]]<br />
| <br />
|<br />
|-<br />
| 026D<br />
| [[#GPUREG_026D|GPUREG_026D]]<br />
| <br />
|<br />
|-<br />
| 026E<br />
| [[#GPUREG_026E|GPUREG_026E]]<br />
| <br />
|<br />
|-<br />
| 026F<br />
| [[#GPUREG_026F|GPUREG_026F]]<br />
| <br />
|<br />
|-<br />
| 0270<br />
| [[#GPUREG_0270|GPUREG_0270]]<br />
| <br />
|<br />
|-<br />
| 0271<br />
| [[#GPUREG_0271|GPUREG_0271]]<br />
| <br />
|<br />
|-<br />
| 0272<br />
| [[#GPUREG_0272|GPUREG_0272]]<br />
| <br />
|<br />
|-<br />
| 0273<br />
| [[#GPUREG_0273|GPUREG_0273]]<br />
| <br />
|<br />
|-<br />
| 0274<br />
| [[#GPUREG_0274|GPUREG_0274]]<br />
| <br />
|<br />
|-<br />
| 0275<br />
| [[#GPUREG_0275|GPUREG_0275]]<br />
| <br />
|<br />
|-<br />
| 0276<br />
| [[#GPUREG_0276|GPUREG_0276]]<br />
| <br />
|<br />
|-<br />
| 0277<br />
| [[#GPUREG_0277|GPUREG_0277]]<br />
| <br />
|<br />
|-<br />
| 0278<br />
| [[#GPUREG_0278|GPUREG_0278]]<br />
| <br />
|<br />
|-<br />
| 0279<br />
| [[#GPUREG_0279|GPUREG_0279]]<br />
| <br />
|<br />
|-<br />
| 027A<br />
| [[#GPUREG_027A|GPUREG_027A]]<br />
| <br />
|<br />
|-<br />
| 027B<br />
| [[#GPUREG_027B|GPUREG_027B]]<br />
| <br />
|<br />
|-<br />
| 027C<br />
| [[#GPUREG_027C|GPUREG_027C]]<br />
| <br />
|<br />
|-<br />
| 027D<br />
| [[#GPUREG_027D|GPUREG_027D]]<br />
| <br />
|<br />
|-<br />
| 027E<br />
| [[#GPUREG_027E|GPUREG_027E]]<br />
| <br />
|<br />
|-<br />
| 027F<br />
| [[#GPUREG_027F|GPUREG_027F]]<br />
| <br />
|<br />
|-<br />
! colspan=4 | Geometry shader registers<br />
|-<br />
| 0280<br />
| [[#GPUREG_GSH_BOOLUNIFORM|GPUREG_GSH_BOOLUNIFORM]]<br />
| <br />
|PICA_REG_GS_BOOL<br />
|-<br />
| 0281<br />
| [[#GPUREG_GSH_INTUNIFORM_I0|GPUREG_GSH_INTUNIFORM_I0]]<br />
| <br />
|PICA_REG_GS_INT0<br />
|-<br />
| 0282<br />
| [[#GPUREG_GSH_INTUNIFORM_I1|GPUREG_GSH_INTUNIFORM_I1]]<br />
| <br />
|PICA_REG_GS_INT1<br />
|-<br />
| 0283<br />
| [[#GPUREG_GSH_INTUNIFORM_I2|GPUREG_GSH_INTUNIFORM_I2]]<br />
| <br />
|PICA_REG_GS_INT2<br />
|-<br />
| 0284<br />
| [[#GPUREG_GSH_INTUNIFORM_I3|GPUREG_GSH_INTUNIFORM_I3]]<br />
| <br />
|PICA_REG_GS_INT3<br />
|-<br />
| 0285<br />
| [[#GPUREG_0285|GPUREG_0285]]<br />
| <br />
|<br />
|-<br />
| 0286<br />
| [[#GPUREG_0286|GPUREG_0286]]<br />
| <br />
|<br />
|-<br />
| 0287<br />
| [[#GPUREG_0287|GPUREG_0287]]<br />
| <br />
|<br />
|-<br />
| 0288<br />
| [[#GPUREG_0288|GPUREG_0288]]<br />
| <br />
|<br />
|-<br />
| 0289<br />
| [[#GPUREG_GSH_INPUTBUFFER_CONFIG|GPUREG_GSH_INPUTBUFFER_CONFIG]]<br />
| <br />
|PICA_REG_GS_ATTR_NUM<br />
|-<br />
| 028A<br />
| [[#GPUREG_GSH_ENTRYPOINT|GPUREG_GSH_ENTRYPOINT]]<br />
| <br />
|PICA_REG_GS_START_ADDR<br />
|-<br />
| 028B<br />
| [[#GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW|GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW]]<br />
| <br />
|PICA_REG_GS_ATTR_IN_REG_MAP0<br />
|-<br />
| 028C<br />
| [[#GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH|GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH]]<br />
| <br />
|PICA_REG_GS_ATTR_IN_REG_MAP1<br />
|-<br />
| 028D<br />
| [[#GPUREG_GSH_OUTMAP_MASK|GPUREG_GSH_OUTMAP_MASK]]<br />
| <br />
|PICA_REG_GS_OUT_REG_MASK<br />
|-<br />
| 028E<br />
| [[#GPUREG_028E|GPUREG_028E]]<br />
| <br />
|<br />
|-<br />
| 028F<br />
| [[#GPUREG_GSH_CODETRANSFER_END|GPUREG_GSH_CODETRANSFER_END]]<br />
| <br />
|PICA_REG_GS_PROG_RENEWAL_END<br />
|-<br />
| 0290<br />
| [[#GPUREG_GSH_FLOATUNIFORM_CONFIG|GPUREG_GSH_FLOATUNIFORM_CONFIG]]<br />
| <br />
|PICA_REG_GS_FLOAT_ADDR<br />
|-<br />
| 0291<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA1<br />
|-<br />
| 0292<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA2<br />
|-<br />
| 0293<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA3<br />
|-<br />
| 0294<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA4<br />
|-<br />
| 0295<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA5<br />
|-<br />
| 0296<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA6<br />
|-<br />
| 0297<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA7<br />
|-<br />
| 0298<br />
| [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_GS_FLOAT_DATA8<br />
|-<br />
| 0299<br />
| [[#GPUREG_0299|GPUREG_0299]]<br />
| <br />
|<br />
|-<br />
| 029A<br />
| [[#GPUREG_029A|GPUREG_029A]]<br />
| <br />
|<br />
|-<br />
| 029B<br />
| [[#GPUREG_GSH_CODETRANSFER_CONFIG|GPUREG_GSH_CODETRANSFER_CONFIG]]<br />
| ?<br />
|PICA_REG_GS_PROG_ADDR<br />
|-<br />
| 029C<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA0<br />
|-<br />
| 029D<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA1<br />
|-<br />
| 029E<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA2<br />
|-<br />
| 029F<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA3<br />
|-<br />
| 02A0<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA4<br />
|-<br />
| 02A1<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA5<br />
|-<br />
| 02A2<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA6<br />
|-<br />
| 02A3<br />
| [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_DATA7<br />
|-<br />
| 02A4<br />
| [[#GPUREG_02A4|GPUREG_02A4]]<br />
| <br />
|<br />
|-<br />
| 02A5<br />
| [[#GPUREG_GSH_OPDESCS_CONFIG|GPUREG_GSH_OPDESCS_CONFIG]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_ADDR<br />
|-<br />
| 02A6<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA0<br />
|-<br />
| 02A7<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA1<br />
|-<br />
| 02A8<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA2<br />
|-<br />
| 02A9<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA3<br />
|-<br />
| 02AA<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA4<br />
|-<br />
| 02AB<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA5<br />
|-<br />
| 02AC<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA6<br />
|-<br />
| 02AD<br />
| [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_GS_PROG_SWIZZLE_DATA7<br />
|-<br />
| 02AE<br />
| [[#GPUREG_02AE|GPUREG_02AE]]<br />
| <br />
|<br />
|-<br />
| 02AF<br />
| [[#GPUREG_02AF|GPUREG_02AF]]<br />
| <br />
|<br />
|-<br />
! colspan=4 | Vertex shader registers<br />
|-<br />
| 02B0<br />
| [[#GPUREG_VSH_BOOLUNIFORM|GPUREG_VSH_BOOLUNIFORM]]<br />
| <br />
|PICA_REG_VS_BOOL<br />
|-<br />
| 02B1<br />
| [[#GPUREG_VSH_INTUNIFORM_I0|GPUREG_VSH_INTUNIFORM_I0]]<br />
| <br />
|PICA_REG_VS_INT0<br />
|-<br />
| 02B2<br />
| [[#GPUREG_VSH_INTUNIFORM_I1|GPUREG_VSH_INTUNIFORM_I1]]<br />
| <br />
|PICA_REG_VS_INT1<br />
|-<br />
| 02B3<br />
| [[#GPUREG_VSH_INTUNIFORM_I2|GPUREG_VSH_INTUNIFORM_I2]]<br />
| <br />
|PICA_REG_VS_INT2<br />
|-<br />
| 02B4<br />
| [[#GPUREG_VSH_INTUNIFORM_I3|GPUREG_VSH_INTUNIFORM_I3]]<br />
| <br />
|PICA_REG_VS_INT3<br />
|-<br />
| 02B5<br />
| [[#GPUREG_02B5|GPUREG_02B5]]<br />
| <br />
|<br />
|-<br />
| 02B6<br />
| [[#GPUREG_02B6|GPUREG_02B6]]<br />
| <br />
|<br />
|-<br />
| 02B7<br />
| [[#GPUREG_02B7|GPUREG_02B7]]<br />
| <br />
|<br />
|-<br />
| 02B8<br />
| [[#GPUREG_02B8|GPUREG_02B8]]<br />
| <br />
|<br />
|-<br />
| 02B9<br />
| [[#GPUREG_VSH_INPUTBUFFER_CONFIG|GPUREG_VSH_INPUTBUFFER_CONFIG]]<br />
| <br />
|PICA_REG_VS_ATTR_NUM0<br />
|-<br />
| 02BA<br />
| [[#GPUREG_VSH_ENTRYPOINT|GPUREG_VSH_ENTRYPOINT]]<br />
| <br />
|PICA_REG_VS_START_ADDR<br />
|-<br />
| 02BB<br />
| [[#GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW|GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW]]<br />
| <br />
|PICA_REG_VS_ATTR_IN_REG_MAP0<br />
|-<br />
| 02BC<br />
| [[#GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH|GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH]]<br />
| <br />
|PICA_REG_VS_ATTR_IN_REG_MAP1<br />
|-<br />
| 02BD<br />
| [[#GPUREG_VSH_OUTMAP_MASK|GPUREG_VSH_OUTMAP_MASK]]<br />
| <br />
|PICA_REG_VS_OUT_REG_MASK<br />
|-<br />
| 02BE<br />
| [[#GPUREG_02BE|GPUREG_02BE]]<br />
| <br />
|<br />
|-<br />
| 02BF<br />
| [[#GPUREG_VSH_CODETRANSFER_END|GPUREG_VSH_CODETRANSFER_END]]<br />
| <br />
|PICA_REG_VS_PROG_RENEWAL_END<br />
|-<br />
| 02C0<br />
| [[#GPUREG_VSH_FLOATUNIFORM_CONFIG|GPUREG_VSH_FLOATUNIFORM_CONFIG]]<br />
| <br />
|PICA_REG_VS_FLOAT_ADDR<br />
|-<br />
| 02C1<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA1<br />
|-<br />
| 02C2<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA2<br />
|-<br />
| 02C3<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA3<br />
|-<br />
| 02C4<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA4<br />
|-<br />
| 02C5<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA5<br />
|-<br />
| 02C6<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA6<br />
|-<br />
| 02C7<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA7<br />
|-<br />
| 02C8<br />
| [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]]<br />
| <br />
|PICA_REG_VS_FLOAT_DATA8<br />
|-<br />
| 02C9<br />
| [[#GPUREG_02C9|GPUREG_02C9]]<br />
| <br />
|<br />
|-<br />
| 02CA<br />
| [[#GPUREG_02CA|GPUREG_02CA]]<br />
| <br />
|<br />
|-<br />
| 02CB<br />
| [[#GPUREG_VSH_CODETRANSFER_CONFIG|GPUREG_VSH_CODETRANSFER_CONFIG]]<br />
| ?<br />
|PICA_REG_VS_PROG_ADDR<br />
|-<br />
| 02CC<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA0<br />
|-<br />
| 02CD<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA1<br />
|-<br />
| 02CE<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA2<br />
|-<br />
| 02CF<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA3<br />
|-<br />
| 02D0<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA4<br />
|-<br />
| 02D1<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA5<br />
|-<br />
| 02D2<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA6<br />
|-<br />
| 02D3<br />
| [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_DATA7<br />
|-<br />
| 02D4<br />
| [[#GPUREG_02D4|GPUREG_02D4]]<br />
| <br />
|<br />
|-<br />
| 02D5<br />
| [[#GPUREG_VSH_OPDESCS_CONFIG|GPUREG_VSH_OPDESCS_CONFIG]]<br />
| ?<br />
|PICA_REG_VS_PROG_SWIZZLE_ADDR<br />
|-<br />
| 02D6<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA0<br />
|-<br />
| 02D7<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA1<br />
|-<br />
| 02D8<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA2<br />
|-<br />
| 02D9<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA3<br />
|-<br />
| 02DA<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA4<br />
|-<br />
| 02DB<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA5<br />
|-<br />
| 02DC<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA6<br />
|-<br />
| 02DD<br />
| [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]]<br />
| <br />
|PICA_REG_VS_PROG_SWIZZLE_DATA7<br />
|-<br />
! colspan=4 | Unknown registers<br />
|-<br />
| 02DE<br />
| [[#GPUREG_02DE|GPUREG_02DE]]<br />
| <br />
|<br />
|-<br />
| 02DF<br />
| [[#GPUREG_02DF|GPUREG_02DF]]<br />
| <br />
|<br />
|-<br />
| 02E0<br />
| [[#GPUREG_02E0|GPUREG_02E0]]<br />
| <br />
|<br />
|-<br />
| 02E1<br />
| [[#GPUREG_02E1|GPUREG_02E1]]<br />
| <br />
|<br />
|-<br />
| 02E2<br />
| [[#GPUREG_02E2|GPUREG_02E2]]<br />
| <br />
|<br />
|-<br />
| 02E3<br />
| [[#GPUREG_02E3|GPUREG_02E3]]<br />
| <br />
|<br />
|-<br />
| 02E4<br />
| [[#GPUREG_02E4|GPUREG_02E4]]<br />
| <br />
|<br />
|-<br />
| 02E5<br />
| [[#GPUREG_02E5|GPUREG_02E5]]<br />
| <br />
|<br />
|-<br />
| 02E6<br />
| [[#GPUREG_02E6|GPUREG_02E6]]<br />
| <br />
|<br />
|-<br />
| 02E7<br />
| [[#GPUREG_02E7|GPUREG_02E7]]<br />
| <br />
|<br />
|-<br />
| 02E8<br />
| [[#GPUREG_02E8|GPUREG_02E8]]<br />
| <br />
|<br />
|-<br />
| 02E9<br />
| [[#GPUREG_02E9|GPUREG_02E9]]<br />
| <br />
|<br />
|-<br />
| 02EA<br />
| [[#GPUREG_02EA|GPUREG_02EA]]<br />
| <br />
|<br />
|-<br />
| 02EB<br />
| [[#GPUREG_02EB|GPUREG_02EB]]<br />
| <br />
|<br />
|-<br />
| 02EC<br />
| [[#GPUREG_02EC|GPUREG_02EC]]<br />
| <br />
|<br />
|-<br />
| 02ED<br />
| [[#GPUREG_02ED|GPUREG_02ED]]<br />
| <br />
|<br />
|-<br />
| 02EE<br />
| [[#GPUREG_02EE|GPUREG_02EE]]<br />
| <br />
|<br />
|-<br />
| 02EF<br />
| [[#GPUREG_02EF|GPUREG_02EF]]<br />
| <br />
|<br />
|-<br />
| 02F0<br />
| [[#GPUREG_02F0|GPUREG_02F0]]<br />
| <br />
|<br />
|-<br />
| 02F1<br />
| [[#GPUREG_02F1|GPUREG_02F1]]<br />
| <br />
|<br />
|-<br />
| 02F2<br />
| [[#GPUREG_02F2|GPUREG_02F2]]<br />
| <br />
|<br />
|-<br />
| 02F3<br />
| [[#GPUREG_02F3|GPUREG_02F3]]<br />
| <br />
|<br />
|-<br />
| 02F4<br />
| [[#GPUREG_02F4|GPUREG_02F4]]<br />
| <br />
|<br />
|-<br />
| 02F5<br />
| [[#GPUREG_02F5|GPUREG_02F5]]<br />
| <br />
|<br />
|-<br />
| 02F6<br />
| [[#GPUREG_02F6|GPUREG_02F6]]<br />
| <br />
|<br />
|-<br />
| 02F7<br />
| [[#GPUREG_02F7|GPUREG_02F7]]<br />
| <br />
|<br />
|-<br />
| 02F8<br />
| [[#GPUREG_02F8|GPUREG_02F8]]<br />
| <br />
|<br />
|-<br />
| 02F9<br />
| [[#GPUREG_02F9|GPUREG_02F9]]<br />
| <br />
|<br />
|-<br />
| 02FA<br />
| [[#GPUREG_02FA|GPUREG_02FA]]<br />
| <br />
|<br />
|-<br />
| 02FB<br />
| [[#GPUREG_02FB|GPUREG_02FB]]<br />
| <br />
|<br />
|-<br />
| 02FC<br />
| [[#GPUREG_02FC|GPUREG_02FC]]<br />
| <br />
|<br />
|-<br />
| 02FD<br />
| [[#GPUREG_02FD|GPUREG_02FD]]<br />
| <br />
|<br />
|-<br />
| 02FE<br />
| [[#GPUREG_02FE|GPUREG_02FE]]<br />
| <br />
|<br />
|-<br />
| 02FF<br />
| [[#GPUREG_02FF|GPUREG_02FF]]<br />
| <br />
|<br />
|}<br />
<br />
=== GPUREG_FINALIZE ===<br />
<br />
Writing to this register seems to signal the GPU to stop processing GPU commands from the current buffer; any command following a write to this register will be ignored. The value written to this register does not appear to matter, although 0x12345678 is the value typically written by commercial software.<br />
Failure to write to this register in any command buffer will result in the GPU hanging.<br />
<br />
=== GPUREG_DEPTHBUFFER_FORMAT ===<br />
<br />
The format the current depth buffer should be written into. Following values are possible:<br />
<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| 16-bit depth<br />
|-<br />
| 1<br />
| ?? seems to freeze the GPU<br />
|-<br />
| 2<br />
| 24-bit depth<br />
|-<br />
| 3<br />
| 24-bit depth + 8-bit stencil (stencil is within bit 24-31)<br />
|}<br />
<br />
=== GPUREG_COLORBUFFER_FORMAT ===<br />
<br />
Describes the format of the current color buffer used for 3D rendering.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Pixel size (0=16-bit, 1=24-bit, 2=32-bit, 3=64-bit?)<br />
|-<br />
| 16-23<br />
| Framebuffer Format (0=GL_RGBA8, 1=GL_RGB8, 2=GL_RGB5_A1, 3=GL_R5_G6_B5, 4=GL_RGBA4).<br />
Note that these values are slightly different from those in [[GPU#Framebuffer_color_formats]].<br />
<br />
Color components are laid out in reverse byte order, with the most significant bits used first.<br />
|}<br />
<br />
==== GPUREG_01C4 ====<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Disable bit for frag light source 0 shadows<br />
|-<br />
| 1<br />
| Disable bit for frag light source 1 shadows<br />
|-<br />
| 2<br />
| Disable bit for frag light source 2 shadows<br />
|-<br />
| 3<br />
| Disable bit for frag light source 3 shadows<br />
|-<br />
| 4<br />
| Disable bit for frag light source 4 shadows<br />
|-<br />
| 5<br />
| Disable bit for frag light source 5 shadows<br />
|-<br />
| 6<br />
| Disable bit for frag light source 6 shadows<br />
|-<br />
| 7<br />
| Disable bit for frag light source 7 shadows<br />
|-<br />
| 8<br />
| Disable bit for frag light source 0 spot<br />
|-<br />
| 9<br />
| Disable bit for frag light source 1 spot<br />
|-<br />
| 10<br />
| Disable bit for frag light source 2 spot<br />
|-<br />
| 11<br />
| Disable bit for frag light source 3 spot<br />
|-<br />
| 12<br />
| Disable bit for frag light source 4 spot<br />
|-<br />
| 13<br />
| Disable bit for frag light source 5 spot<br />
|-<br />
| 14<br />
| Disable bit for frag light source 6 spot<br />
|-<br />
| 15<br />
| Disable bit for frag light source 7 spot<br />
|-<br />
| 24<br />
| Disable bit for frag light source 0 distance attenuation<br />
|-<br />
| 25<br />
| Disable bit for frag light source 1 distance attenuation<br />
|-<br />
| 26<br />
| Disable bit for frag light source 2 distance attenuation<br />
|-<br />
| 27<br />
| Disable bit for frag light source 3 distance attenuation<br />
|-<br />
| 28<br />
| Disable bit for frag light source 4 distance attenuation<br />
|-<br />
| 29<br />
| Disable bit for frag light source 5 distance attenuation<br />
|-<br />
| 30<br />
| Disable bit for frag light source 6 distance attenuation<br />
|-<br />
| 31<br />
| Disable bit for frag light source 7 distance attenuation<br />
|}<br />
<br />
== Geometry pipeline registers ==<br />
<br />
=== GPUREG_GEOSTAGE_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Geometry stage mode. (0=Vertex shader only, 2=Vertex shader + geometry shader)<br />
|-<br />
| 0-7<br />
| Unknown. Often set to 1.<br />
|-<br />
| 0-7<br />
| Unknown.<br />
|-<br />
| 0-7<br />
| Unknown. Often set to 0.<br />
|}<br />
<br />
This register configures the geometry stage of the GPU pipeline.<br />
<br />
=== GPUREG_FIXEDATTRIB_INDEX ===<br />
<br />
See [[GPU/Fixed Vertex Attributes]] and [[GPU/Immediate-Mode Vertex Submission]] for usage info.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-31<br />
| Sets the active fixed attribute index. This is the fixed attribute which will be set when writing to [[#GPUREG_FIXEDATTRIB_DATA|GPUREG_FIXEDATTRIB_DATA]]. Valid values are 0-11. If the special value 0xF is written here, this sets up immediate-mode vertex submission instead, and writes to the data register will input vertex data directly into the pipeline.<br />
|}<br />
<br />
=== GPUREG_FIXEDATTRIB_DATA ===<br />
<br />
Accepts a packed 4-tuple of float24 values (in the same format used for [[#GPUREG_VSH_FLOATUNIFORM_DATA|specifying shader uniforms]]). This is stored as the fixed attribute value for the attribute currently specified in the index register. Attributes are always specified as a 4-tuple of floats, regardless of the format configured in [[#GPUREG_ATTRIBBUFFERS_FORMAT_HIGH|GPUREG_ATTRIBBUFFERS_FORMAT_HIGH]].<br />
<br />
If immediate-mode vertex submission is enabled (by writing 0xF to the index register) then vertex data is input here directly. The index register does not need to be re-set after each write.<br />
<br />
=== GPUREG_RESTART_PRIMITIVE ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Writing 0x01 to this field ends the current triangle strip or fan. This is necessary before using these kinds of primitives with [[GPU:Immediate-Mode Vertex Submission|immediate-mode]], but most games seem to write to it before every draw call.<br />
|}<br />
<br />
== Geometry shader registers ==<br />
<br />
=== GPUREG_GSH_BOOLUNIFORM ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Value of geometry shader unit's b0 boolean register. (0=true, 1=false)<br />
|-<br />
| 1<br />
| Value of geometry shader unit's b1 boolean register. (0=true, 1=false)<br />
|-<br />
| 2<br />
| Value of geometry shader unit's b2 boolean register. (0=true, 1=false)<br />
|-<br />
| 3<br />
| Value of geometry shader unit's b3 boolean register. (0=true, 1=false)<br />
|-<br />
| 4<br />
| Value of geometry shader unit's b4 boolean register. (0=true, 1=false)<br />
|-<br />
| 5<br />
| Value of geometry shader unit's b5 boolean register. (0=true, 1=false)<br />
|-<br />
| 6<br />
| Value of geometry shader unit's b6 boolean register. (0=true, 1=false)<br />
|-<br />
| 7<br />
| Value of geometry shader unit's b7 boolean register. (0=true, 1=false)<br />
|-<br />
| 8<br />
| Value of geometry shader unit's b8 boolean register. (0=true, 1=false)<br />
|-<br />
| 9<br />
| Value of geometry shader unit's b9 boolean register. (0=true, 1=false)<br />
|-<br />
| 10<br />
| Value of geometry shader unit's b10 boolean register. (0=true, 1=false)<br />
|-<br />
| 11<br />
| Value of geometry shader unit's b11 boolean register. (0=true, 1=false)<br />
|-<br />
| 12<br />
| Value of geometry shader unit's b12 boolean register. (0=true, 1=false)<br />
|-<br />
| 13<br />
| Value of geometry shader unit's b13 boolean register. (0=true, 1=false)<br />
|-<br />
| 14<br />
| Value of geometry shader unit's b14 boolean register. (0=true, 1=false)<br />
|-<br />
| 15<br />
| Value of geometry shader unit's b15 boolean register. (0=true, 1=false)<br />
|-<br />
| 16-31<br />
| Unknown. This seems to always be set to 0x7FFF, and other values may cause the GPU to hang<br />
|}<br />
<br />
This register is used to set the geometry shader unit's boolean registers.<br />
<br />
=== GPUREG_GSH_INTUNIFORM_I0 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for geometry shader's i0.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for geometry shader's i0.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for geometry shader's i0.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for geometry shader's i0.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the geometry shader's i0 integer register.<br />
<br />
=== GPUREG_GSH_INTUNIFORM_I1 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for geometry shader's i1.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for geometry shader's i1.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for geometry shader's i1.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for geometry shader's i1.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the geometry shader's i1 integer register.<br />
<br />
=== GPUREG_GSH_INTUNIFORM_I2 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for geometry shader's i2.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for geometry shader's i2.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for geometry shader's i2.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for geometry shader's i2.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the geometry shader's i2 integer register.<br />
<br />
=== GPUREG_GSH_INTUNIFORM_I3 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for geometry shader's i3.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for geometry shader's i3.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for geometry shader's i3.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for geometry shader's i3.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the geometry shader's i3 integer register.<br />
<br />
=== GPUREG_GSH_INPUTBUFFER_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Input buffer stride minus 1, in float vec4 registers. (value 0 means a stride of 1 float vec4 register)<br />
|-<br />
| 8-23<br />
| Unknown. These bits typically aren't updated by games.<br />
|-<br />
| 24-31<br />
| Unknown. This is typically set to 8 for geometry shaders.<br />
|}<br />
<br />
This register is used to configure the geometry shader's input buffer. In the context of a geometry shader, the stride parameter can be interpreted as the input primitive size in registers, though it is not a limit on the number of input registers which can be accessed from the geometry shader.<br />
<br />
<br />
=== GPUREG_GSH_ENTRYPOINT ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-15<br />
| Geometry shader unit entrypoint, in words.<br />
|-<br />
| 16-31<br />
| Unknown. This seems to always be set to 0x7FFF, and other values may cause the GPU to hang<br />
|}<br />
<br />
This sets the entrypoint for the program running on the single shader unit which can be dedicated to running geometry shaders, regardless of the current geometry stage mode. This is means that while this register is normally used to set the geometry shader entrypoint, it can also be used to set this single shader unit to run from a different entrypoint than the other three even when running a vertex shader.<br />
<br />
=== GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-3<br />
| Index of geometry shader input register which the 1st attribute will be stored in.<br />
|-<br />
| 4-7<br />
| Index of geometry shader input register which the 2nd attribute will be stored in.<br />
|-<br />
| 8-11<br />
| Index of geometry shader input register which the 3rd attribute will be stored in.<br />
|-<br />
| 12-15<br />
| Index of geometry shader input register which the 4th attribute will be stored in.<br />
|-<br />
| 16-19<br />
| Index of geometry shader input register which the 5th attribute will be stored in.<br />
|-<br />
| 20-23<br />
| Index of geometry shader input register which the 6th attribute will be stored in.<br />
|-<br />
| 24-27<br />
| Index of geometry shader input register which the 7th attribute will be stored in.<br />
|-<br />
| 28-31<br />
| Index of geometry shader input register which the 8th attribute will be stored in.<br />
|}<br />
<br />
This register sets the geometry shader input register index which will correspond to each attribute contained by the input buffer (which in the case of geometry shaders is the vertex shader output buffer) for the first 8 attributes.<br />
For example, having bits 0-3 set to 5 means that, in the geometry shader program, v5 will contain the input buffer's 1st attribute.<br />
<br />
=== GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-3<br />
| Index of geometry shader input register which the 9th attribute will be stored in.<br />
|-<br />
| 4-7<br />
| Index of geometry shader input register which the 10th attribute will be stored in.<br />
|-<br />
| 8-11<br />
| Index of geometry shader input register which the 11th attribute will be stored in.<br />
|-<br />
| 12-15<br />
| Index of geometry shader input register which the 12th attribute will be stored in.<br />
|-<br />
| 16-19<br />
| Index of geometry shader input register which the 13th attribute will be stored in.<br />
|-<br />
| 20-23<br />
| Index of geometry shader input register which the 14th attribute will be stored in.<br />
|-<br />
| 24-27<br />
| Index of geometry shader input register which the 15th attribute will be stored in.<br />
|-<br />
| 28-31<br />
| Index of geometry shader input register which the 16th attribute will be stored in.<br />
|}<br />
<br />
This register sets the geometry shader input register index which will correspond to each attribute contained by the input buffer (which in the case of geometry shaders is the vertex shader output buffer) for attributes 8 through 15.<br />
For example, having bits 0-3 set to 5 means that, in the geometry shader program, v5 will contain the input buffer's 9th attribute.<br />
<br />
=== GPUREG_GSH_OUTMAP_MASK ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bit for geometry shader's o0 output register. (1 = o0 enabled, 0 = o0 disabled)<br />
|-<br />
| 1<br />
| Enable bit for geometry shader's o1 output register. (1 = o1 enabled, 0 = o1 disabled)<br />
|-<br />
| 2<br />
| Enable bit for geometry shader's o2 output register. (1 = o2 enabled, 0 = o2 disabled)<br />
|-<br />
| 3<br />
| Enable bit for geometry shader's o3 output register. (1 = o3 enabled, 0 = o3 disabled)<br />
|-<br />
| 4<br />
| Enable bit for geometry shader's o4 output register. (1 = o4 enabled, 0 = o4 disabled)<br />
|-<br />
| 5<br />
| Enable bit for geometry shader's o5 output register. (1 = o5 enabled, 0 = o5 disabled)<br />
|-<br />
| 6<br />
| Enable bit for geometry shader's o6 output register. (1 = o6 enabled, 0 = o6 disabled)<br />
|}<br />
<br />
This register toggles the geometry shader unit's output registers.<br />
<br />
=== GPUREG_GSH_CODETRANSFER_END ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Code data transfer end signal bit.<br />
|}<br />
<br />
This register's value should be set to 1 in order to finalize the transfer of geometry shader code. It is unknown whether this register is used for other functions.<br />
<br />
=== GPUREG_GSH_FLOATUNIFORM_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-6<br />
| Target float vec4 geometry shader uniform ID for transfer. (range 0-95, where 0 = c0 and 95 = c95)<br />
|-<br />
| 31<br />
| Float vec4 geometry shader uniform data transfer mode. (0 = float24, 1 = float32)<br />
|}<br />
<br />
This register sets the target float vec4 geometry shader uniform ID and transfer mode for the data transfer system. As such it is typically used right before [[#GPUREG_GSH_FLOATUNIFORM_DATA|GPUREG_GSH_FLOATUNIFORM_DATA]], though writing to one register does not make writing to the other mandatory.<br />
<br />
=== GPUREG_GSH_FLOATUNIFORM_DATA ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-31<br />
| Float vec4 geometry shader uniform data. (format depends on transfer mode, see below for details)<br />
|}<br />
<br />
This register is used to set the value of float vec4 geometry shader uniform registers. The data format which should be written to it depends on the transfer mode set with [[#GPUREG_GSH_FLOATUNIFORM_CONFIG|GPUREG_GSH_FLOATUNIFORM_CONFIG]]. This register functions as a FIFO queue : after each time a uniform register is successfully set, the target uniform ID value is incremented, meaning that groups of uniforms with contiguous register IDs can be set with only one initial write to [[#GPUREG_GSH_FLOATUNIFORM_CONFIG|GPUREG_GSH_FLOATUNIFORM_CONFIG]].<br />
<br />
* In the case of float24 transfer mode, data should be sent by writing three words which are the concatenation of the float24 value of the uniform register's 4 components, in the reverse order. Assuming each letter corresponds to 4 bits, the format becomes :<br />
** first word : ZZWWWWWW<br />
** second word : YYYYZZZZ<br />
** third word : XXXXXXYY<br />
* In the case of float32 transfer mode, data should be sent by writing four words which are each the float32 value of the uniform register's 4 components, in the reverse order.<br />
<br />
=== GPUREG_GSH_CODETRANSFER_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-11<br />
| Target geometry shader code offset for data transfer.<br />
|}<br />
<br />
This register is used to set the offset at which upcoming geometry shader code data transferred through [[#GPUREG_GSH_CODETRANSFER_DATA|GPUREG_GSH_CODETRANSFER_DATA]] should be written.<br />
<br />
NOTE : as we do not yet know what a shader program's maximum size is yet, we also do not know how many bits the code offset parameter holds. The biggest shader binary observed so far was 2422 instructions long. The [[Shader_Instruction_Set#Instruction_formats|shader control flow instructions]] only have room to address 12 bits though, so it's likely that the maximum is 4095.<br />
<br />
=== GPUREG_GSH_CODETRANSFER_DATA ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-31<br />
| Geometry shader instruction data.<br />
|}<br />
<br />
This register is used to transfer geometry shader code data. This register behaves as a FIFO queue : each write to this register writes the provided value to the GPU geometry shader code memory bank at the offset initially set by [[#GPUREG_GSH_CODETRANSFER_CONFIG|GPUREG_GSH_CODETRANSFER_CONFIG]]. The offset in question is incremented after each write to this register.<br />
<br />
=== GPUREG_GSH_OPDESCS_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-6<br />
| Target geometry shader operand descriptor offset for data transfer.<br />
|}<br />
<br />
This register is used to set the offset at which upcoming geometry shader operand descriptor data transferred through [[#GPUREG_GSH_OPDESCS_DATA|GPUREG_GSH_OPDESCS_DATA]] should be written.<br />
<br />
=== GPUREG_GSH_OPDESCS_DATA ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-31<br />
| Geometry shader operand descriptor data.<br />
|}<br />
<br />
This register is used to transfer geometry shader operand descriptor data. This register behaves as a FIFO queue : each write to this register writes the provided value to the GPU geometry shader operand descriptor memory bank at the offset initially set by [[#GPUREG_GSH_OPDESCS_CONFIG|GPUREG_GSH_OPDESCS_CONFIG]]. The offset in question is incremented after each write to this register.<br />
<br />
== Vertex shader registers ==<br />
<br />
=== GPUREG_VSH_BOOLUNIFORM ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Value of vertex shader unit's b0 boolean register. (0=true, 1=false)<br />
|-<br />
| 1<br />
| Value of vertex shader unit's b1 boolean register. (0=true, 1=false)<br />
|-<br />
| 2<br />
| Value of vertex shader unit's b2 boolean register. (0=true, 1=false)<br />
|-<br />
| 3<br />
| Value of vertex shader unit's b3 boolean register. (0=true, 1=false)<br />
|-<br />
| 4<br />
| Value of vertex shader unit's b4 boolean register. (0=true, 1=false)<br />
|-<br />
| 5<br />
| Value of vertex shader unit's b5 boolean register. (0=true, 1=false)<br />
|-<br />
| 6<br />
| Value of vertex shader unit's b6 boolean register. (0=true, 1=false)<br />
|-<br />
| 7<br />
| Value of vertex shader unit's b7 boolean register. (0=true, 1=false)<br />
|-<br />
| 8<br />
| Value of vertex shader unit's b8 boolean register. (0=true, 1=false)<br />
|-<br />
| 9<br />
| Value of vertex shader unit's b9 boolean register. (0=true, 1=false)<br />
|-<br />
| 10<br />
| Value of vertex shader unit's b10 boolean register. (0=true, 1=false)<br />
|-<br />
| 11<br />
| Value of vertex shader unit's b11 boolean register. (0=true, 1=false)<br />
|-<br />
| 12<br />
| Value of vertex shader unit's b12 boolean register. (0=true, 1=false)<br />
|-<br />
| 13<br />
| Value of vertex shader unit's b13 boolean register. (0=true, 1=false)<br />
|-<br />
| 14<br />
| Value of vertex shader unit's b14 boolean register. (0=true, 1=false)<br />
|-<br />
| 15<br />
| Value of vertex shader unit's b15 boolean register. (0=true, 1=false)<br />
|-<br />
| 16-31<br />
| Unknown. This seems to always be set to 0x7FFF, and other values may cause the GPU to hang<br />
|}<br />
<br />
This register is used to set the vertex shader unit's boolean registers.<br />
<br />
=== GPUREG_VSH_INTUNIFORM_I0 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for vertex shader's i0.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for vertex shader's i0.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for vertex shader's i0.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for vertex shader's i0.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the vertex shader's i0 integer register.<br />
<br />
=== GPUREG_VSH_INTUNIFORM_I1 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for vertex shader's i1.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for vertex shader's i1.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for vertex shader's i1.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for vertex shader's i1.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the vertex shader's i1 integer register.<br />
<br />
=== GPUREG_VSH_INTUNIFORM_I2 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for vertex shader's i2.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for vertex shader's i2.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for vertex shader's i2.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for vertex shader's i2.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the vertex shader's i2 integer register.<br />
<br />
=== GPUREG_VSH_INTUNIFORM_I3 ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Value for vertex shader's i3.x (u8, 0-255)<br />
|-<br />
| 8-15<br />
| Value for vertex shader's i3.y (u8, 0-255)<br />
|-<br />
| 16-23<br />
| Value for vertex shader's i3.z (u8, 0-255)<br />
|-<br />
| 24-31<br />
| Value for vertex shader's i3.w (u8, 0-255)<br />
|}<br />
<br />
This register is used to set the vertex shader's i3 integer register.<br />
<br />
=== GPUREG_VSH_INPUTBUFFER_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-7<br />
| Input buffer stride minus 1, in float vec4 registers. (value 0 means a stride of 1 float vec4 register)<br />
|-<br />
| 8-23<br />
| Unknown. These bits typically aren't updated by games.<br />
|-<br />
| 24-31<br />
| Unknown. This is typically set to 0xA for vertex shaders.<br />
|}<br />
<br />
This register is used to configure the vertex shader's input buffer. In the context of a geometry shader, the stride parameter can be interpreted as the number of attributes per vertex.<br />
<br />
=== GPUREG_VSH_ENTRYPOINT ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-15<br />
| Vertex shader entrypoint, in words.<br />
|-<br />
| 16-31<br />
| Unknown. This seems to always be set to 0x7FFF, and other values may cause the GPU to hang<br />
|}<br />
<br />
This sets the entrypoint for the program running on shader units set to vertex shader mode. Depending on the current geometry stage mode this can include either all 4 shader units or just 3 of them.<br />
<br />
=== GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-3<br />
| Index of vertex shader input register which the 1st attribute will be stored in.<br />
|-<br />
| 4-7<br />
| Index of vertex shader input register which the 2nd attribute will be stored in.<br />
|-<br />
| 8-11<br />
| Index of vertex shader input register which the 3rd attribute will be stored in.<br />
|-<br />
| 12-15<br />
| Index of vertex shader input register which the 4th attribute will be stored in.<br />
|-<br />
| 16-19<br />
| Index of vertex shader input register which the 5th attribute will be stored in.<br />
|-<br />
| 20-23<br />
| Index of vertex shader input register which the 6th attribute will be stored in.<br />
|-<br />
| 24-27<br />
| Index of vertex shader input register which the 7th attribute will be stored in.<br />
|-<br />
| 28-31<br />
| Index of vertex shader input register which the 8th attribute will be stored in.<br />
|}<br />
<br />
This register sets the vertex shader input register index which will correspond to each attribute contained by the input buffer for the first 8 attributes.<br />
For example, having bits 0-3 set to 5 means that, in the vertex shader program, v5 will contain the input buffer's 1st attribute.<br />
<br />
=== GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-3<br />
| Index of vertex shader input register which the 9th attribute will be stored in.<br />
|-<br />
| 4-7<br />
| Index of vertex shader input register which the 10th attribute will be stored in.<br />
|-<br />
| 8-11<br />
| Index of vertex shader input register which the 11th attribute will be stored in.<br />
|-<br />
| 12-15<br />
| Index of vertex shader input register which the 12th attribute will be stored in.<br />
|-<br />
| 16-19<br />
| Index of vertex shader input register which the 13th attribute will be stored in.<br />
|-<br />
| 20-23<br />
| Index of vertex shader input register which the 14th attribute will be stored in.<br />
|-<br />
| 24-27<br />
| Index of vertex shader input register which the 15th attribute will be stored in.<br />
|-<br />
| 28-31<br />
| Index of vertex shader input register which the 16th attribute will be stored in.<br />
|}<br />
<br />
This register sets the vertex shader input register index which will correspond to each attribute contained by the input buffer for attributes 8 through 15.<br />
For example, having bits 0-3 set to 5 means that, in the vertex shader program, v5 will contain the input buffer's 9th attribute.<br />
<br />
=== GPUREG_VSH_OUTMAP_MASK ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bit for vertex shader's o0 output register. (1 = o0 enabled, 0 = o0 disabled)<br />
|-<br />
| 1<br />
| Enable bit for vertex shader's o1 output register. (1 = o1 enabled, 0 = o1 disabled)<br />
|-<br />
| 2<br />
| Enable bit for vertex shader's o2 output register. (1 = o2 enabled, 0 = o2 disabled)<br />
|-<br />
| 3<br />
| Enable bit for vertex shader's o3 output register. (1 = o3 enabled, 0 = o3 disabled)<br />
|-<br />
| 4<br />
| Enable bit for vertex shader's o4 output register. (1 = o4 enabled, 0 = o4 disabled)<br />
|-<br />
| 5<br />
| Enable bit for vertex shader's o5 output register. (1 = o5 enabled, 0 = o5 disabled)<br />
|-<br />
| 6<br />
| Enable bit for vertex shader's o6 output register. (1 = o6 enabled, 0 = o6 disabled)<br />
|-<br />
| 7<br />
| Enable bit for vertex shader's o7 output register. (1 = o7 enabled, 0 = o7 disabled)<br />
|-<br />
| 8<br />
| Enable bit for vertex shader's o8 output register. (1 = o8 enabled, 0 = o8 disabled)<br />
|-<br />
| 9<br />
| Enable bit for vertex shader's o9 output register. (1 = o9 enabled, 0 = o9 disabled)<br />
|-<br />
| 10<br />
| Enable bit for vertex shader's o10 output register. (1 = o10 enabled, 0 = o10 disabled)<br />
|-<br />
| 11<br />
| Enable bit for vertex shader's o11 output register. (1 = o11 enabled, 0 = o11 disabled)<br />
|-<br />
| 12<br />
| Enable bit for vertex shader's o12 output register. (1 = o12 enabled, 0 = o12 disabled)<br />
|-<br />
| 13<br />
| Enable bit for vertex shader's o13 output register. (1 = o13 enabled, 0 = o13 disabled)<br />
|-<br />
| 14<br />
| Enable bit for vertex shader's o14 output register. (1 = o14 enabled, 0 = o14 disabled)<br />
|-<br />
| 15<br />
| Enable bit for vertex shader's o15 output register. (1 = o15 enabled, 0 = o15 disabled)<br />
|}<br />
<br />
This register toggles the vertex shader units' output registers.<br />
<br />
=== GPUREG_VSH_CODETRANSFER_END ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Code data transfer end signal bit.<br />
|}<br />
<br />
This register's value should be set to 1 in order to finalize the transfer of vertex shader code. It is unknown whether this register is used for other functions.<br />
<br />
=== GPUREG_VSH_FLOATUNIFORM_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-6<br />
| Target float vec4 vertex shader uniform ID for transfer. (range 0-95, where 0 = c0 and 95 = c95)<br />
|-<br />
| 31<br />
| Float vec4 vertex shader uniform data transfer mode. (0 = float24, 1 = float32)<br />
|}<br />
<br />
This register sets the target float vec4 vertex shader uniform ID and transfer mode for the data transfer system. As such it is typically used right before [[#GPUREG_VSH_FLOATUNIFORM_DATA|GPUREG_VSH_FLOATUNIFORM_DATA]], though writing to one register does not make writing to the other mandatory.<br />
<br />
=== GPUREG_VSH_FLOATUNIFORM_DATA ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-31<br />
| Float vec4 vertex shader uniform data. (format depends on transfer mode, see below for details)<br />
|}<br />
<br />
This register is used to set the value of float vec4 vertex shader uniform registers. The data format which should be written to it depends on the transfer mode set with [[#GPUREG_VSH_FLOATUNIFORM_CONFIG|GPUREG_VSH_FLOATUNIFORM_CONFIG]]. This register functions as a FIFO queue : after each time a uniform register is successfully set, the target uniform ID value is incremented, meaning that groups of uniforms with contiguous register IDs can be set with only one initial write to [[#GPUREG_VSH_FLOATUNIFORM_CONFIG|GPUREG_VSH_FLOATUNIFORM_CONFIG]].<br />
<br />
* In the case of float24 transfer mode, data should be sent by writing three words which are the concatenation of the float24 value of the uniform register's 4 components, in the reverse order. Assuming each letter corresponds to 4 bits, the format becomes :<br />
** first word : ZZWWWWWW<br />
** second word : YYYYZZZZ<br />
** third word : XXXXXXYY<br />
* In the case of float32 transfer mode, data should be sent by writing four words which are each the float32 value of the uniform register's 4 components, in the reverse order.<br />
<br />
=== GPUREG_VSH_CODETRANSFER_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-11<br />
| Target vertex shader code offset for data transfer.<br />
|}<br />
<br />
This register is used to set the offset at which upcoming vertex shader code data transferred through [[#GPUREG_VSH_CODETRANSFER_DATA|GPUREG_VSH_CODETRANSFER_DATA]] should be written.<br />
<br />
NOTE : as we do not yet know what a shader program's maximum size is yet, we also do not know how many bits the code offset parameter holds. The biggest shader binary observed so far was 2422 instructions long. The [[Shader_Instruction_Set#Instruction_formats|shader control flow instructions]] only have room to address 12 bits though, so it's likely that the maximum is 4095.<br />
<br />
=== GPUREG_VSH_CODETRANSFER_DATA ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-31<br />
| Vertex shader instruction data.<br />
|}<br />
<br />
This register is used to transfer vertex shader code data. This register behaves as a FIFO queue : each write to this register writes the provided value to the GPU vertex shader code memory bank at the offset initially set by [[#GPUREG_VSH_CODETRANSFER_CONFIG|GPUREG_VSH_CODETRANSFER_CONFIG]]. The offset in question is incremented after each write to this register.<br />
<br />
=== GPUREG_VSH_OPDESCS_CONFIG ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-6<br />
| Target vertex shader operand descriptor offset for data transfer.<br />
|}<br />
<br />
This register is used to set the offset at which upcoming vertex shader operand descriptor data transferred through [[#GPUREG_VSH_OPDESCS_DATA|GPUREG_VSH_OPDESCS_DATA]] should be written.<br />
<br />
=== GPUREG_VSH_OPDESCS_DATA ===<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-31<br />
| Vertex shader operand descriptor data.<br />
|}<br />
<br />
This register is used to transfer vertex shader operand descriptor data. This register behaves as a FIFO queue : each write to this register writes the provided value to the GPU vertex shader operand descriptor memory bank at the offset initially set by [[#GPUREG_VSH_OPDESCS_CONFIG|GPUREG_VSH_OPDESCS_CONFIG]]. The offset in question is incremented after each write to this register.<br />
<br />
[[Category:GPU]]</div>Subvhttps://www.3dbrew.org/w/index.php?title=GPU/Commands&diff=13104GPU/Commands2015-08-21T15:59:09Z<p>Subv: /* Parameter value format for command 0x0106 */</p>
<hr />
<div>This page describes the structure of the buffer submitted via the registers at [[GPU|0x1EF018E0]] (or equivalently via [[GSP_Shared_Memory|GX command]] 1). This buffer is used for GPU commands including functionality equivalent to OpenGL commands.<br />
<br />
[[GPU Internal Registers]] provides a more structured overview for the available commands but is still work in progress, and hence should be used as a complementary source of information.<br />
<br />
=== Overview ===<br />
Each command is at least 8 bytes wide. The first word is the command parameter and the second word constitutes the command header. Optionally, more parameter words may follow (potentially including a padding word to align commands to multiples of 8 bytes).<br />
<br />
In the simplest case, a command is exactly 8 bytes wide. You can think of such a command as writing the parameter word to an internal register (the index of which is given in the command header). The more general case where more than one parameter word is given is equivalent to multiple simple commands (one for each parameter word). If consecutive writing mode is enabled in the command header, the current command index will be incremented after each parameter write. Otherwise, the parameters will be consecutively written to the same register.<br />
<br />
For example, the sequence "0xAAAAAAAA 0x802F011C 0xBBBBBBBB 0xCCCCCCCC" is equivalent to a call to commands 0xF011C with parameter 0xAAAAAAAA, 0xF011D with parameter 0xBBBBBBBB and 0xF011E with parameter 0xCCCCCCCC. If consecutive writing mode were disabled, the command would be equivalent to three consecutive calls to 0xF011C (once with parameter 0xAAAAAAAA, once with 0xBBBBBBBB, and finally with 0xCCCCCCCC).<br />
<br />
Invalid GPU command parameters including NaN floats can cause the GPU to hang, which then causes the GSP module to hang as well.<br />
<br />
The size of GPU command buffers must be 0x10-byte aligned; the lower 3 bits of the size are cleared. A common pitfall is having the finalization command (write to register 0x0010) not executed because it was the last 8 bytes of a non-0x10 byte aligned command buffer, and having the GPU hang as a result.<br />
<br />
=== Command Header ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Command ID<br />
|-<br />
| 19-16<br />
| Parameter mask<br />
|-<br />
| 30-20<br />
| Number of extra parameters (may be zero)<br />
|-<br />
| 31<br />
| Consecutive writing mode<br />
|}<br />
<br />
=== Parameter masking ===<br />
<br />
Using a value other than 0xF, parts of a word in internal GPU memory can be updated without touching the other bits of it. For example, setting bit 16 to zero indicates that the least significant byte of the parameter will not be overwritten, setting bit 17 to zero indicates that the parameter's second LSB will not be overwritten, etc. This means that for instance commands 0x00010107 and 0x00020107 refer to the same thing but write different parts of the parameter.<br />
<br />
=== Command IDs ===<br />
{| class="wikitable" border="1"<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0x0010<br />
| Value is 0x12345678<br />
| This command is always the last command in the buffer.<br />
|-<br />
| 0x0110<br />
| Value 0x1<br />
| This command is immediately before command 0x0010, this is also used elsewhere for beginning rendering of mesh(es) as well.<br />
|-<br />
| 0x0111<br />
| Value 0x1<br />
| This command is immediately before command 0x0110, however command 0x0110 doesn't always follow this command.<br />
|-<br />
| 0x0040<br />
| u32, valid values are 0x1 and 0x2, values 0x0 and 0x3 have the same effect as value 0x2. Only bits 1-0 are used.<br />
| Value 2 = GL_FRONT/GL_CW or GL_BACK/GL_CCW. Value 1 = GL_FRONT/GL_CCW or GL_BACK/GL_CW.<br />
|-<br />
| 0x0041<br />
| float24<br />
| VIEWPORT_WIDTH. See command set 0x0041.<br />
|-<br />
| 0x0042<br />
| float32<br />
| VIEWPORT_WIDTH_INV. See command set 0x0041.<br />
|-<br />
| 0x0043<br />
| float24<br />
| VIEWPORT_HEIGHT. See command set 0x0041.<br />
|-<br />
| 0x0044<br />
| float32<br />
| VIEWPORT_HEIGHT_INV. See command set 0x0041.<br />
|-<br />
| 0x004D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x0065<br />
| <br />
| Scissor test. See command set 0x0065.<br />
|-<br />
| 0x0068<br />
| u32<br />
| VIEWPORT Y/X. See command set 0x0041.<br />
|-<br />
| 0x006D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x006E<br />
| u32<br />
| See command set 0x0111.<br />
|-<br />
| 0x006F<br />
| u32<br />
| See command set 0x006F.<br />
|-<br />
| 0x0080<br />
| u32<br />
| See command set 0x0080.<br />
|-<br />
| 0x0081<br />
| <br />
| This is used to set the current texture info used for rendering, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x008E<br />
| u32 color type<br />
| This command sets the texture color type, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x0091<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0091]].<br />
|-<br />
| 0x0099<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0099]].<br />
|-<br />
| 0x00C3<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00CB<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00C0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00CC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00DC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00FC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00E0<br />
| Normally value zero.<br />
| Unknown, fragment related?<br />
|-<br />
| 0x00E0<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E1<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E6<br />
| Value zero<br />
| See command set 0x00E6.<br />
|-<br />
| 0x00E8<br />
| <br />
| See command set 0x00E6.<br />
|-<br />
| 0x0100<br />
| u32, value is 0x00E40100<br />
| See command set 0x0100.<br />
|-<br />
| 0x0100<br />
| <nowiki>0x00E40000 | val</nowiki>.<br />
| See command set 0x0100.<br />
|-<br />
| 0x0101<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0102<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0103<br />
| <br />
| See command set 0x0100.<br />
|-<br />
| 0x0104<br />
| u32<br />
| glAlphaFunc()<br />
|-<br />
| 0x0105<br />
| u32<br />
| Stencil test settings<br />
|-<br />
| 0x0106<br />
| u32<br />
| Stencil replacement operators<br />
|-<br />
| 0x0107<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0116<br />
| u32<br />
| DEPTHBUFFER FORMAT. See command set 0x0111.<br />
|-<br />
| 0x0117<br />
| u32<br />
| COLORBUFFER FORMAT/PIXEL. See command set 0x0111.<br />
|-<br />
| 0x011C<br />
| Physical address>>3<br />
| DEPTHBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011D<br />
| Physical address>>3<br />
| COLORBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011E<br />
| u32<br />
| COLORBUFFER HEIGHT/WIDTH. See command set 0x0111.<br />
|-<br />
| 0x0112<br />
| <br />
| ?<br />
|-<br />
| 0x01C5<br />
| <nowiki>(dmp_FragmentLightSource ID)<<8 | (sampler ID)<<11</nowiki> ?<br />
| This command is in conjunction with 0x01C8 used to send fragment 1D samplers. (LUTs) sampler ID 1 for sampler samplerSP and 2 for samplerDA<br />
|-<br />
| 0x01C8<br />
| LUT as parameter<br />
| Used to send fragment LUT data.<br />
|-<br />
| 0x0200<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0126<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0227<br />
| u32<br />
| This specifies the address of an array containing vertex array indices, and the data-type of the indices, used for rendering primitives. See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0228<br />
| u32 total elements in the array to use for rendering.<br />
| See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0232<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0244<br />
| bool ?<br />
| Set geo shader enabled/disabled ?<br />
|-<br />
| 0x025E<br />
| u32, val<<8.<br />
| This sets the GL rendering mode, see command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0280<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set geo shader boolean uniforms. ((val>>i)&1 = !b_i) value (b0 = False => val&1 == 1)<br />
|-<br />
| 0x0281<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (geo shader)<br />
|-<br />
| 0x0282<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (geo shader)<br />
|-<br />
| 0x0283<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (geo shader)<br />
|-<br />
| 0x0284<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (geo shader)<br />
|-<br />
| 0x028A<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the geometry shader program<br />
|-<br />
| 0x0290<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| Geometry shader equivalent of 0x02C0<br />
|-<br />
| 0x02B0<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set the 16 vertex shader boolean uniforms. (b_i = (val>>i)&1)<br />
|-<br />
| 0x02B1<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (vertex shader)<br />
|-<br />
| 0x02B2<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (vertex shader)<br />
|-<br />
| 0x02B3<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (vertex shader)<br />
|-<br />
| 0x02B4<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (vertex shader)<br />
|-<br />
| 0x02BB<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x02BA<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the vertex shader program<br />
|-<br />
| 0x02C0<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| This is used immediately before command 0x02C1. This type field controls the command parameter buffer type. This command can also be used to send over (float24 only ?) data directly, without using 0x02C1. In that case, the first parameter is still Type but with bit 31 not set; the actual data follows.<br />
|-<br />
| 0x02C1<br />
| First word in the first entry<br />
| A list of entries follow this command.<br />
|-<br />
| 0x02C2<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C3<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C4<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C5<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C6<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C7<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C8<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x029B<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x029C. It is used to indicate that geometry shader program data will follow.<br />
|-<br />
| 0x029C<br />
| First word of geometry shader program data chunk.<br />
| This command is used to transfer geometry shader program data (as the parameter data). It can be called multiple times in a row if the shader program is too big to fit into a single call.<br />
|-<br />
| 0x028F<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x029C. It is used to indicate that geometry shader program data transfer is complete.<br />
|-<br />
| 0x02A5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02A6<br />
| First entry.<br />
| This is used to send over the geometry shader program operand descriptor table.<br />
|-<br />
| 0x02CB<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02CC. It is used to indicate that shader program data will follow.<br />
|-<br />
| 0x02CC<br />
| First word of vertex shader program data chunk.<br />
| This command is used to transfer vertex shader program data (as the parameter data). It can be called multiple times in a row if the vertex shader program is too big to fit into a single call.<br />
|-<br />
| 0x02BF<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x02CC. It is used to indicate that vertex shader program data transfer is complete.<br />
|-<br />
| 0x02D5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02D6<br />
| First entry.<br />
| This is used to send over the vertex shader program operand descriptor table.<br />
|-<br />
| 0x004F<br />
| Number of vertex shader output attributes<br />
| Sets number of vertex shader output attributes<br />
|-<br />
| 0x0050<br />
| First entry<br />
| This command is used to setup vertex shader output registers. The n-th word-long entry is a map of the (n*2)-th output register's components. Each byte of each entry corresponds to where a component is mapped. Value 0x1F indicates that the corresponding component is unused.<br />
|}<br />
<br />
==== Command Sets ====<br />
<br />
===== glDrawElements() =====<br />
See [[GPU_GL_Arrays|GPU GL Arrays]].<br />
<br />
===== glClear() / glClearColor() =====<br />
The GPU does not have dedicated commands for clearing the color buffer, therefore applications implement color buffer clearing by rendering a quad. Applications normally store this vertex and color [[GPU_GL_Arrays|array]] in the GSP application heap.<br />
<br />
===== Command 0x0081 =====<br />
This sets current texture info, see [[GPU Textures|GPU textures]].<br />
<br />
===== Command 0x0065 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0065<br />
| Scissor test enable<br />
| 0 = disabled, 1 = inverted (pixels within the scissor box are excluded), 2 = disabled, 3 = normal (pixels outside of the scissor box are excluded)<br />
|-<br />
| 1<br />
| 0x0066<br />
| Scissor box X/Y<br />
| Bit 0-15: X, bit 16-31: Y<br />
|-<br />
| 2<br />
| 0x0067<br />
| Scissor box width/height<br />
| Bit 0-15: width-1, bit 16-31: height-1<br />
|}<br />
<br />
===== Command 0x006F =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x006F<br />
| Typically only bit8-10 are used.<br />
| Bit8 enables texture coordinate output for texture unit 0, bit9 enables texcoords for texture unit 1, and bit2 enables texcoords for texture unit 2.<br />
|}<br />
<br />
===== Command 0x0080 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0080<br />
| <nowiki>0x11000 | val</nowiki>, where only bits 2-0 are used in val.<br />
| bit0-2 enables/disables texture units 0-2 respectively<br />
|}<br />
Note that bit0-2 in this command only enable texture processing. For texturing to work fully, the corresponding texture coordinate outputs must be enabled as well via command 0x006F.<br />
<br />
===== Command 0x00C0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| <nowiki>SlotCmdID</nowiki><br />
| <br />
| <br />
|-<br />
| 1<br />
| <nowiki>SlotCmdID + 4</nowiki><br />
| <br />
| <br />
|}<br />
<br />
This is used for glTexEnv(), for the slot indicated by the command id. There's a total of 6 slots, where each slot corresponds to the following u16 command ids: 0xC0, 0xC8, 0xD0, 0xD8, 0xF0, 0xF8.<br />
<br />
===== Command 0x00E0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E0<br />
| <nowiki>5 | val<<16</nowiki>, where val is 0 or 1.<br />
| Val0 = enable, val1 = disable.<br />
|-<br />
| 1<br />
| 0x00E1<br />
| <br />
| This specifies a color.<br />
|}<br />
<br />
This is usually used immediately after command set glDrawElements(). This is used to specify a color used for blending?<br />
<br />
===== Command 0x00E6 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E6<br />
| Value 0<br />
| ?<br />
|-<br />
| 1<br />
| 0x00E8<br />
| <br />
| <br />
|}<br />
<br />
This is usually the last command set used for rendering a mesh, when command set 0x00E0 was used. This command set is used immediately after command set 0x00E0.<br />
<br />
===== Command 0x0100 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0100<br />
| Value 0x00E40100<br />
| Controls color compositing<br />
|-<br />
| 1<br />
| 0x0101<br />
| 0x01010000 when disabled<br />
| Alphablending equations and factors<br />
|-<br />
| 2<br />
| 0x0103<br />
| This is set to zero when the command 0x0101 parameter is value 0x01010000.<br />
| Constant color for alphablending<br />
|}<br />
<br />
This is fragment related?<br />
<br />
===== Command 0x004D =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x004D<br />
| <br />
| glDepthRange()<br />
|-<br />
| 1<br />
| 0x006D<br />
| 0 = unknown, 1 = unknown.<br />
| Value zero causes the mesh to not be rendered.<br />
|}<br />
<br />
===== Command 0x0041 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0041<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 1<br />
| 0x0043<br />
| float<br />
| This parameter value is calculated the same way as the command 0x0041 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 2<br />
| 0x0042<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 3<br />
| 0x0044<br />
| float<br />
| This parameter value value is calculated the same way as the command 0x0042 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 4<br />
| 0x0068<br />
| u32<br />
| This sets the X/Y coordinates used for glViewport().<br />
|}<br />
<br />
This command set initializes the projection matrix. This command set is used twice when beginning rendering for each screen. The framebuffer width used here for the main screen is 240, however this is 480 with stereoscopy enabled for the second time this command set is used.<br />
<br />
===== Command 0x0111 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0111<br />
| Value 1<br />
| <br />
|-<br />
| 1<br />
| 0x0110<br />
| Value 1<br />
| <br />
|-<br />
| 2<br />
| 0x0117<br />
| Framebuffer color format descriptor<br />
| See [[GPU_Internal_Registers#GPUREG_COLORBUFFER_FORMAT]]<br />
|-<br />
| 3<br />
| 0x011D<br />
| Physical address>>3<br />
| This initializes the framebuffer address used for rendering, this framebuffer is used for the input framebuffer with [[GSP_Shared_Memory|GX command]] 3 and 4. This command is used immediately after command 0x0117.<br />
|-<br />
| 4<br />
| 0x0116<br />
| <br />
| ?<br />
|-<br />
| 5<br />
| 0x011C<br />
| Physical address>>3<br />
| Unknown, normally this address is located in VRAM.<br />
|-<br />
| 6<br />
| 0x011E<br />
| u32, 0x01000000|(((h-1)&0xFFF)<<12)|(w&0xFFF)<br />
| This sets the width and height for the framebuffer used for rendering. Therefore this is glViewport(), x/y are specified by command 0x0068.<br />
|-<br />
| 7<br />
| 0x006E<br />
| Same input parameter value as command 0x011E.<br />
| <br />
|}<br />
<br />
This command set is normally used after the two 0x0041 command sets.<br />
<br />
===== Command 0x0107 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0107<br />
| <br />
| <br />
|-<br />
| 1<br />
| 0x0126<br />
| type<<24<br />
| <br />
|}<br />
<br />
This command set is used for disabling the alpha-blending info set by command set 0x0107? The GL AlphaFunction used here is normally GL_ALWAYS.<br />
<br />
=== Parameter format for command 0x0107 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_DEPTH_TEST, 1 = enable GL_DEPTH_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Depth test function<br />
|-<br />
| 8<br />
| Enable color writing for red component<br />
|-<br />
| 9<br />
| Enable color writing for green component<br />
|-<br />
| 10<br />
| Enable color writing for blue component<br />
|-<br />
| 11<br />
| Enable color writing for alpha component<br />
|-<br />
| 12<br />
| Enable depth writing (doesn't affect stencil writing)<br />
|-<br />
| 31-13<br />
| Unused<br />
|}<br />
<br />
==== Alpha function values ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_EQUAL<br />
|-<br />
| 3<br />
| GL_NOTEQUAL<br />
|-<br />
| 4<br />
| GL_LESS<br />
|-<br />
| 5<br />
| GL_LEQUAL<br />
|-<br />
| 6<br />
| GL_GREATER<br />
|-<br />
| 7<br />
| GL_GEQUAL<br />
|}<br />
<br />
=== Alpha types for command 0x0126 ===<br />
{| class="wikitable" border="1"<br />
! Type<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_GREATER/GL_GEQUAL<br />
|-<br />
| 3<br />
| The remaining GL alpha functions.<br />
|}<br />
<br />
=== Parameter value format for command 0x0104 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_ALPHA_TEST, 1 = enable GL_ALPHA_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Alpha function<br />
|-<br />
| 15-8<br />
| u8 ref, range is 0-255<br />
|-<br />
| 31-16<br />
| Unused?<br />
|}<br />
<br />
This is glAlphaFunc().<br />
<br />
=== Parameter value format for command 0x011E ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 11-0<br />
| Framebuffer/viewport width<br />
|-<br />
| 23-12<br />
| Framebuffer/viewport height - 1<br />
|-<br />
| 24<br />
| Must be set<br />
|-<br />
| 31-25<br />
| Unused?<br />
|}<br />
<br />
This specifies the width/height for glViewport(). Normally the framebuffer width and height is set to the same [[GPU|dimensions]] used with GX [[GSP_Shared_Memory|command]] 3 and 4.<br />
<br />
=== Parameter value format for command 0x0068 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| X<br />
|-<br />
| 31-16<br />
| Y<br />
|}<br />
<br />
This specifies the X/Y coordinates for glViewport().<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Value 0xFFF0FFF / 0x0<br />
|-<br />
| 1<br />
| Value 0x0<br />
|-<br />
| 2<br />
| Value 0x0<br />
|-<br />
| 3<br />
| Value 0xFFFFFFFF<br />
|-<br />
| 4<br />
| Value 0x0<br />
|}<br />
<br />
This individual command is used instead of the 0x80XF00C0 command set when none of the associated rendering parameters for this slot are set.<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Param0<br />
|-<br />
| 1<br />
| Param1<br />
|-<br />
| 2<br />
| Param2<br />
|-<br />
| 3<br />
| Constant. 0xAABBBGGRR format (or same as the color buffer ?)<br />
|-<br />
| 4<br />
| Param4<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
==== Param0 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values.(Field0 index0)<br />
|-<br />
| 7-4<br />
| See below values.(Field0 index1)<br />
|-<br />
| 11-8<br />
| See below values.(Field0 index2)<br />
|-<br />
| 15-12<br />
| Unused<br />
|-<br />
| 19-16<br />
| See below values.(Field1 index0)<br />
|-<br />
| 23-20<br />
| See below values.(Field1 index1)<br />
|-<br />
| 27-24<br />
| See below values.(Field1 index2)<br />
|-<br />
| 31-28<br />
| Unused<br />
|}<br />
<br />
==== Param0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
! Comment<br />
|-<br />
| 0x0<br />
| GL_PRIMARY_COLOR<br />
|The color that comes from the upper shader<br />
|-<br />
| 0x1<br />
| GL_FRAGMENT_PRIMARY_COLOR<br />
| Sum of ambient, emissive, and diffuse components of lightning stage<br />
|-<br />
| 0x2<br />
| GL_FRAGMENT_SECONDARY_COLOR<br />
| Specular component of the lightning stage + ?<br />
|-<br />
| 0x3<br />
| GL_TEXTURE0<br />
|<br />
|-<br />
| 0x4<br />
| GL_TEXTURE1<br />
|<br />
|-<br />
| 0x5<br />
| GL_TEXTURE2<br />
|<br />
|-<br />
| 0x6<br />
| GL_TEXTURE3<br />
|<br />
|-<br />
| 0xC-0x7<br />
|(GL_PRIMARY_COLOR)No?<br />
| Please detail. Gives 0 on TexEnv0<br />
|-<br />
| 0xD<br />
| ?<br />
|<br />
|-<br />
| 0xE<br />
| GL_CONSTANT<br />
|<br />
|-<br />
| 0xF<br />
| GL_PREVIOUS<br />
| Color that comes from the previous texture stage<br />
|}<br />
<br />
==== Param1 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values for field0.(Index0)<br />
|-<br />
| 7-4<br />
| See below values for field0.(Index1)<br />
|-<br />
| 11-8<br />
| See below values for field0.(Index2)<br />
|-<br />
| 15-12<br />
| See below values for field1.(Index0)<br />
|-<br />
| 19-16<br />
| See below values for field1.(Index1)<br />
|-<br />
| 23-20<br />
| See below values for field1.(Index2)<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
This specifies the pname for glTexEnv().<br />
<br />
==== Param1 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 0x2<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x4<br />
| GL_SRC_R<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x6<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x7<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x8<br />
| GL_SRC_G<br />
|-<br />
| 0x9<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0xA<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xB<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xC<br />
| GL_SRC_B<br />
|-<br />
| 0xD<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
Note : GL_SRC_X and GL_ONE_MINUS_SRC_X where X=R|G|B are the same as GL_SRC_COLOR and GL_ONE_MINUS_SRC_COLOR but will use only the corresponding color component.<br />
<br />
==== Param1 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x2<br />
| GL_SRC_R<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x4<br />
| GL_SRC_G<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0x6<br />
| GL_SRC_B<br />
|-<br />
| 0x7<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
<br />
==== Param2 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| See below field0 values.<br />
|-<br />
| 31-16<br />
| See below field1 values.<br />
|}<br />
<br />
This is used to specify the param for glTexEnv(..., ..., param).<br />
<br />
==== Param2 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGBA<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param2 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_REPLACE<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param4 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 31-18<br />
| Unused<br />
|-<br />
| 17-16<br />
| Alpha output scale factor<br />
|-<br />
| 15-2<br />
| Unused<br />
|-<br />
| 1-0<br />
| Color output scale factor<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Scale value<br />
! Corresponding factor<br />
|-<br />
| 0x0<br />
| 1.0<br />
|-<br />
| 0x1<br />
| 2.0<br />
|-<br />
| 0x2<br />
| 4.0<br />
|}<br />
<br />
=== Parameter value format for command 0x00C4 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Valid values: 0=unknown, 1=unknown, 2=unknown.<br />
|-<br />
| 31-16<br />
| Same format as bits15-0.<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
=== Parameter value format for command 0x00E1 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Red component<br />
|-<br />
| 15-8<br />
| Green component<br />
|-<br />
| 23-16<br />
| Blue component<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
=== Parameter value format for command 0x0100 ===<br />
This command controls color compositing. It is typically used right after commands 0x0101 or 0x0102 to select the appropriate blending mode.<br />
<br />
Alphablending and color logic op can't be used together. Attempting to issue commands 0x0101 and 0x0102 at the same time can freeze the GPU.<br />
<br />
For blending to work correctly, color buffer reading needs to be enabled (see command set 0x0112). Otherwise zero values will be used as destination color/alpha.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Weird mode (see below)<br />
|-<br />
| 1<br />
| When set, nothing is drawn to the color, depth and stencil buffers. This bit can cause a noisy picture when used with bit 0 (this seems to also cause the depth buffer's endianness to be reversed, and forces stencil values to 0xFF).<br />
|-<br />
| 8<br />
| Selects blending mode. 0 = color logic op, 1 = alphablending<br />
|-<br />
| 23-16<br />
| Unknown, typically set to 0xE4. No observed effect when changing this.<br />
|-<br />
| 25-24<br />
| 0 = normal, 1-3 = apply dithering (3 = 0% source)<br />
|}<br />
<br />
When "weird mode" is enabled, the source color/alpha values are ignored. Instead, each 16-bit value in the destination color buffer is converted according to its bits 14-8, as follows:<br />
* if bits 14-8 are between 0x00 and 0x03, the value is replaced with 0x0000<br />
* if bits 14-8 are between 0x7D and 0x7F, the value is replaced with 0x7FFF<br />
* in all other cases, the value is left unchanged<br />
<br />
=== Parameter value format for command 0x0101 ===<br />
This command controls alphablending. To disable alphablending, the value is set to 0x01010000.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Color blend equation<br />
|-<br />
| 15-8<br />
| Alpha blend equation<br />
|-<br />
| 19-16<br />
| Color source factor<br />
|-<br />
| 23-20<br />
| Color destination factor<br />
|-<br />
| 27-24<br />
| Alpha source factor<br />
|-<br />
| 31-28<br />
| Alpha destination factor<br />
|}<br />
<br />
Blend equation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_FUNC_ADD<br />
|-<br />
| 1<br />
| GL_FUNC_SUBTRACT<br />
|-<br />
| 2<br />
| GL_FUNC_REVERSE_SUBTRACT<br />
|-<br />
| 3<br />
| GL_MIN<br />
|-<br />
| 4<br />
| GL_MAX<br />
|}<br />
<br />
Source/destination factor values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_ZERO<br />
|-<br />
| 1<br />
| GL_ONE<br />
|-<br />
| 2<br />
| GL_SRC_COLOR<br />
|-<br />
| 3<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 4<br />
| GL_DST_COLOR<br />
|-<br />
| 5<br />
| GL_ONE_MINUS_DST_COLOR<br />
|-<br />
| 6<br />
| GL_SRC_ALPHA<br />
|-<br />
| 7<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 8<br />
| GL_DST_ALPHA<br />
|-<br />
| 9<br />
| GL_ONE_MINUS_DST_ALPHA<br />
|-<br />
| 10<br />
| GL_CONSTANT_COLOR<br />
|-<br />
| 11<br />
| GL_ONE_MINUS_CONSTANT_COLOR<br />
|-<br />
| 12<br />
| GL_CONSTANT_ALPHA<br />
|-<br />
| 13<br />
| GL_ONE_MINUS_CONSTANT_ALPHA<br />
|-<br />
| 14<br />
| GL_SRC_ALPHA_SATURATE<br />
|}<br />
<br />
=== Parameter value format for command 0x0102 ===<br />
This command controls color logic op.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| Logic operation<br />
|}<br />
<br />
Logic operation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_CLEAR<br />
|-<br />
| 1<br />
| GL_AND<br />
|-<br />
| 2<br />
| GL_AND_REVERSE<br />
|-<br />
| 3<br />
| GL_COPY<br />
|-<br />
| 4<br />
| GL_SET<br />
|-<br />
| 5<br />
| GL_COPY_INVERTED<br />
|-<br />
| 6<br />
| GL_NOOP<br />
|-<br />
| 7<br />
| GL_INVERT<br />
|-<br />
| 8<br />
| GL_NAND<br />
|-<br />
| 9<br />
| GL_OR<br />
|-<br />
| 10<br />
| GL_NOR<br />
|-<br />
| 11<br />
| GL_XOR<br />
|-<br />
| 12<br />
| GL_EQUIV<br />
|-<br />
| 13<br />
| GL_AND_INVERTED<br />
|-<br />
| 14<br />
| GL_OR_REVERSE<br />
|-<br />
| 15<br />
| GL_OR_INVERTED<br />
|}<br />
<br />
=== Parameter value format for command 0x0105 ===<br />
This command controls stencil testing.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable stencil test<br />
|-<br />
| 7-4<br />
| Stencil test function (values same as for alpha and depth tests)<br />
|-<br />
| 15-8<br />
| Stencil buffer write mask<br />
|-<br />
| 23-16<br />
| Reference value for the stencil test. Note that the test does "reference FUNC value".<br />
|-<br />
| 31-24<br />
| Mask for the stencil test.<br />
|}<br />
<br />
=== Parameter value format for command 0x0106 ===<br />
This command controls stencil buffer replacement.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Action when the stencil test fails<br />
|-<br />
| 6-4<br />
| Action when the stencil test passes but the depth test fails<br />
|-<br />
| 10-8<br />
| Action when both stencil test and depth test pass<br />
|}<br />
<br />
Action values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Final stencil value<br />
! OpenGL equivalent<br />
|-<br />
| 0<br />
| old_stencil<br />
| GL_KEEP<br />
|-<br />
| 1<br />
| 0<br />
| GL_ZERO<br />
|-<br />
| 2<br />
| reference<br />
| GL_REPLACE<br />
|-<br />
| 3<br />
| min(old_stencil + 1, 255)<br />
| GL_INCR<br />
|-<br />
| 4<br />
| max(old_stencil - 1, 0)<br />
| GL_DECR<br />
|-<br />
| 5<br />
| ~old_stencil<br />
| GL_INVERT<br />
|-<br />
| 6<br />
| old_stencil + 1<br />
| GL_INCR_WRAP<br />
|-<br />
| 7<br />
| old_stencil - 1<br />
| GL_DECR_WRAP<br />
|}<br />
<br />
'old_stencil' is the value present in the stencil buffer, 'reference' is the reference value specified in command 0x0105.<br />
<br />
=== Parameter structure for command 0x004D ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float far<br />
|-<br />
| 1<br />
| float near<br />
|}<br />
<br />
This is glDepthRange().<br />
<br />
=== Parameter structure for command 0x00E8 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0x7D-0x00<br />
| Usually value 0x00FFE000.<br />
|-<br />
| 0x7E<br />
| Usually value 0x00FFFEE6?<br />
|-<br />
| 0x7F<br />
| Usually value 0x00DCD919?<br />
|}<br />
<br />
=== Parameter structure for command 0x0112 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Setting bits 3-0 to a nonzero value allows the GPU to read from the color buffer.<br />
|-<br />
| 1<br />
| Setting bits 3-0 to a nonzero value allows the GPU to write to the color buffer.<br />
|-<br />
| 2<br />
| Setting bits 1-0 to a nonzero value allows the GPU to read from the depth/stencil buffer.<br />
|-<br />
| 3<br />
| Setting bits 1-0 to a nonzero value allows the GPU to write to the depth/stencil buffer.<br />
|}<br />
<br />
=== Entries for command 0x02C1 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float, the GPU handles this as the 4th word.<br />
|-<br />
| 1<br />
| float, the GPU handles this as the 3rd word.<br />
|-<br />
| 2<br />
| float, the GPU handles this as the 2nd word.<br />
|-<br />
| 3<br />
| float, the GPU handles this as the 1st word.<br />
|}<br />
<br />
The below entry structure info is in the raw order used for the command, not the order used by the GPU.<br />
<br />
==== Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Red component<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Alpha<br />
|}<br />
<br />
==== Lighting Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Alpha<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Red component<br />
|}<br />
<br />
=== Types for command 0x02C0 ===<br />
<br />
The 0x02C0/0x02C1 is actually used as a generic way to set uniforms, regardless of what they represent. 0x02C0's parameter represents the ID of the destination GPU register (0x0 is c0, 0x1 is c1 etc). As such, the meaning of the data being sent over is entirely dependant on the shader currently in use.<br />
The values below may be "default" values used by Nintendo's openGL implementation.<br />
<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Entries per chunk<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| This specifies 16-floats for a 4x4 matrix, used for glLoadMatrix() for the projection matrix.<br />
|-<br />
| 0x04<br />
| 4<br />
| This specifies a 4x4 matrix, used for glLoadMatrix() for the model-view matrix. This is usually an identity matrix.<br />
|-<br />
| 0x08<br />
| 2<br />
| Sets the color.<br />
|-<br />
| 0x0A<br />
| 4<br />
| Specifies a 4x4 matrix, used for glLoadMatrix() for the texture matrix.(Index0)<br />
|-<br />
| 0x0E<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index1)<br />
|-<br />
| 0x11<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index2)<br />
|-<br />
| 0x14<br />
| <=30<br />
| Used to specify a 4xN matrix, where N is the total command 0x02C1 entries. This is glMultMatrix() for the model-view matrix, except the input matrix is 4xN instead of 4x4.<br />
|-<br />
| 0x4C<br />
| 4<br />
| This specifies a 4x4 float matrix.<br />
|-<br />
| 0x50, 0x53, and 0x56<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_AMBIENT?<br />
|-<br />
| 0x51, 0x54, and 0x57<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_DIFFUSE?<br />
|-<br />
| 0x52, 0x55, and 0x58<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_SPECULAR?<br />
|-<br />
| 0x59<br />
| 1<br />
| Unknown, the entry data is floats converted from s32s. Usually each entry word is zeros.<br />
|-<br />
| 0x5A<br />
| 2<br />
| Color related?<br />
|-<br />
| 0x5C<br />
| 1<br />
| ?<br />
|}<br />
<br />
The matrices for types 0x00 and 0x04 use row-major order, instead of column-major order.<br />
<br />
[[Category:GPU]]</div>Subvhttps://www.3dbrew.org/w/index.php?title=GPU/Commands&diff=13080GPU/Commands2015-08-19T04:09:29Z<p>Subv: /* Parameter value format for command 0x0106 */</p>
<hr />
<div>This page describes the structure of the buffer submitted via the registers at [[GPU|0x1EF018E0]] (or equivalently via [[GSP_Shared_Memory|GX command]] 1). This buffer is used for GPU commands including functionality equivalent to OpenGL commands.<br />
<br />
[[GPU Internal Registers]] provides a more structured overview for the available commands but is still work in progress, and hence should be used as a complementary source of information.<br />
<br />
=== Overview ===<br />
Each command is at least 8 bytes wide. The first word is the command parameter and the second word constitutes the command header. Optionally, more parameter words may follow (potentially including a padding word to align commands to multiples of 8 bytes).<br />
<br />
In the simplest case, a command is exactly 8 bytes wide. You can think of such a command as writing the parameter word to an internal register (the index of which is given in the command header). The more general case where more than one parameter word is given is equivalent to multiple simple commands (one for each parameter word). If consecutive writing mode is enabled in the command header, the current command index will be incremented after each parameter write. Otherwise, the parameters will be consecutively written to the same register.<br />
<br />
For example, the sequence "0xAAAAAAAA 0x802F011C 0xBBBBBBBB 0xCCCCCCCC" is equivalent to a call to commands 0xF011C with parameter 0xAAAAAAAA, 0xF011D with parameter 0xBBBBBBBB and 0xF011E with parameter 0xCCCCCCCC. If consecutive writing mode were disabled, the command would be equivalent to three consecutive calls to 0xF011C (once with parameter 0xAAAAAAAA, once with 0xBBBBBBBB, and finally with 0xCCCCCCCC).<br />
<br />
Invalid GPU command parameters including NaN floats can cause the GPU to hang, which then causes the GSP module to hang as well.<br />
<br />
The size of GPU command buffers must be 0x10-byte aligned; the lower 3 bits of the size are cleared. A common pitfall is having the finalization command (write to register 0x0010) not executed because it was the last 8 bytes of a non-0x10 byte aligned command buffer, and having the GPU hang as a result.<br />
<br />
=== Command Header ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Command ID<br />
|-<br />
| 19-16<br />
| Parameter mask<br />
|-<br />
| 30-20<br />
| Number of extra parameters (may be zero)<br />
|-<br />
| 31<br />
| Consecutive writing mode<br />
|}<br />
<br />
=== Parameter masking ===<br />
<br />
Using a value other than 0xF, parts of a word in internal GPU memory can be updated without touching the other bits of it. For example, setting bit 16 to zero indicates that the least significant byte of the parameter will not be overwritten, setting bit 17 to zero indicates that the parameter's second LSB will not be overwritten, etc. This means that for instance commands 0x00010107 and 0x00020107 refer to the same thing but write different parts of the parameter.<br />
<br />
=== Command IDs ===<br />
{| class="wikitable" border="1"<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0x0010<br />
| Value is 0x12345678<br />
| This command is always the last command in the buffer.<br />
|-<br />
| 0x0110<br />
| Value 0x1<br />
| This command is immediately before command 0x0010, this is also used elsewhere for beginning rendering of mesh(es) as well.<br />
|-<br />
| 0x0111<br />
| Value 0x1<br />
| This command is immediately before command 0x0110, however command 0x0110 doesn't always follow this command.<br />
|-<br />
| 0x0040<br />
| u32, valid values are 0x1 and 0x2, values 0x0 and 0x3 have the same effect as value 0x2. Only bits 1-0 are used.<br />
| Value 2 = GL_FRONT/GL_CW or GL_BACK/GL_CCW. Value 1 = GL_FRONT/GL_CCW or GL_BACK/GL_CW.<br />
|-<br />
| 0x0041<br />
| float24<br />
| VIEWPORT_WIDTH. See command set 0x0041.<br />
|-<br />
| 0x0042<br />
| float32<br />
| VIEWPORT_WIDTH_INV. See command set 0x0041.<br />
|-<br />
| 0x0043<br />
| float24<br />
| VIEWPORT_HEIGHT. See command set 0x0041.<br />
|-<br />
| 0x0044<br />
| float32<br />
| VIEWPORT_HEIGHT_INV. See command set 0x0041.<br />
|-<br />
| 0x004D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x0065<br />
| <br />
| Scissor test. See command set 0x0065.<br />
|-<br />
| 0x0068<br />
| u32<br />
| VIEWPORT Y/X. See command set 0x0041.<br />
|-<br />
| 0x006D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x006E<br />
| u32<br />
| See command set 0x0111.<br />
|-<br />
| 0x006F<br />
| u32<br />
| See command set 0x006F.<br />
|-<br />
| 0x0080<br />
| u32<br />
| See command set 0x0080.<br />
|-<br />
| 0x0081<br />
| <br />
| This is used to set the current texture info used for rendering, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x008E<br />
| u32 color type<br />
| This command sets the texture color type, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x0091<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0091]].<br />
|-<br />
| 0x0099<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0099]].<br />
|-<br />
| 0x00C3<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00CB<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00C0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00CC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00DC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00FC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00E0<br />
| Normally value zero.<br />
| Unknown, fragment related?<br />
|-<br />
| 0x00E0<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E1<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E6<br />
| Value zero<br />
| See command set 0x00E6.<br />
|-<br />
| 0x00E8<br />
| <br />
| See command set 0x00E6.<br />
|-<br />
| 0x0100<br />
| u32, value is 0x00E40100<br />
| See command set 0x0100.<br />
|-<br />
| 0x0100<br />
| <nowiki>0x00E40000 | val</nowiki>.<br />
| See command set 0x0100.<br />
|-<br />
| 0x0101<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0102<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0103<br />
| <br />
| See command set 0x0100.<br />
|-<br />
| 0x0104<br />
| u32<br />
| glAlphaFunc()<br />
|-<br />
| 0x0105<br />
| u32<br />
| Stencil test settings<br />
|-<br />
| 0x0106<br />
| u32<br />
| Stencil replacement operators<br />
|-<br />
| 0x0107<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0116<br />
| u32<br />
| DEPTHBUFFER FORMAT. See command set 0x0111.<br />
|-<br />
| 0x0117<br />
| u32<br />
| COLORBUFFER FORMAT/PIXEL. See command set 0x0111.<br />
|-<br />
| 0x011C<br />
| Physical address>>3<br />
| DEPTHBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011D<br />
| Physical address>>3<br />
| COLORBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011E<br />
| u32<br />
| COLORBUFFER HEIGHT/WIDTH. See command set 0x0111.<br />
|-<br />
| 0x0112<br />
| <br />
| ?<br />
|-<br />
| 0x01C5<br />
| <nowiki>(dmp_FragmentLightSource ID)<<8 | (sampler ID)<<11</nowiki> ?<br />
| This command is in conjunction with 0x01C8 used to send fragment 1D samplers. (LUTs) sampler ID 1 for sampler samplerSP and 2 for samplerDA<br />
|-<br />
| 0x01C8<br />
| LUT as parameter<br />
| Used to send fragment LUT data.<br />
|-<br />
| 0x0200<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0126<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0227<br />
| u32<br />
| This specifies the address of an array containing vertex array indices, and the data-type of the indices, used for rendering primitives. See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0228<br />
| u32 total elements in the array to use for rendering.<br />
| See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0232<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0244<br />
| bool ?<br />
| Set geo shader enabled/disabled ?<br />
|-<br />
| 0x025E<br />
| u32, val<<8.<br />
| This sets the GL rendering mode, see command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0280<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set geo shader boolean uniforms. ((val>>i)&1 = !b_i) value (b0 = False => val&1 == 1)<br />
|-<br />
| 0x0281<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (geo shader)<br />
|-<br />
| 0x0282<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (geo shader)<br />
|-<br />
| 0x0283<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (geo shader)<br />
|-<br />
| 0x0284<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (geo shader)<br />
|-<br />
| 0x028A<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the geometry shader program<br />
|-<br />
| 0x0290<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| Geometry shader equivalent of 0x02C0<br />
|-<br />
| 0x02B0<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set the 16 vertex shader boolean uniforms. (b_i = (val>>i)&1)<br />
|-<br />
| 0x02B1<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (vertex shader)<br />
|-<br />
| 0x02B2<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (vertex shader)<br />
|-<br />
| 0x02B3<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (vertex shader)<br />
|-<br />
| 0x02B4<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (vertex shader)<br />
|-<br />
| 0x02BB<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x02BA<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the vertex shader program<br />
|-<br />
| 0x02C0<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| This is used immediately before command 0x02C1. This type field controls the command parameter buffer type. This command can also be used to send over (float24 only ?) data directly, without using 0x02C1. In that case, the first parameter is still Type but with bit 31 not set; the actual data follows.<br />
|-<br />
| 0x02C1<br />
| First word in the first entry<br />
| A list of entries follow this command.<br />
|-<br />
| 0x02C2<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C3<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C4<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C5<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C6<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C7<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C8<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x029B<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x029C. It is used to indicate that geometry shader program data will follow.<br />
|-<br />
| 0x029C<br />
| First word of geometry shader program data chunk.<br />
| This command is used to transfer geometry shader program data (as the parameter data). It can be called multiple times in a row if the shader program is too big to fit into a single call.<br />
|-<br />
| 0x028F<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x029C. It is used to indicate that geometry shader program data transfer is complete.<br />
|-<br />
| 0x02A5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02A6<br />
| First entry.<br />
| This is used to send over the geometry shader program operand descriptor table.<br />
|-<br />
| 0x02CB<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02CC. It is used to indicate that shader program data will follow.<br />
|-<br />
| 0x02CC<br />
| First word of vertex shader program data chunk.<br />
| This command is used to transfer vertex shader program data (as the parameter data). It can be called multiple times in a row if the vertex shader program is too big to fit into a single call.<br />
|-<br />
| 0x02BF<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x02CC. It is used to indicate that vertex shader program data transfer is complete.<br />
|-<br />
| 0x02D5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02D6<br />
| First entry.<br />
| This is used to send over the vertex shader program operand descriptor table.<br />
|-<br />
| 0x004F<br />
| Number of vertex shader output attributes<br />
| Sets number of vertex shader output attributes<br />
|-<br />
| 0x0050<br />
| First entry<br />
| This command is used to setup vertex shader output registers. The n-th word-long entry is a map of the (n*2)-th output register's components. Each byte of each entry corresponds to where a component is mapped. Value 0x1F indicates that the corresponding component is unused.<br />
|}<br />
<br />
==== Command Sets ====<br />
<br />
===== glDrawElements() =====<br />
See [[GPU_GL_Arrays|GPU GL Arrays]].<br />
<br />
===== glClear() / glClearColor() =====<br />
The GPU does not have dedicated commands for clearing the color buffer, therefore applications implement color buffer clearing by rendering a quad. Applications normally store this vertex and color [[GPU_GL_Arrays|array]] in the GSP application heap.<br />
<br />
===== Command 0x0081 =====<br />
This sets current texture info, see [[GPU Textures|GPU textures]].<br />
<br />
===== Command 0x0065 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0065<br />
| Scissor test enable<br />
| 0 = disabled, 1 = inverted (pixels within the scissor box are excluded), 2 = disabled, 3 = normal (pixels outside of the scissor box are excluded)<br />
|-<br />
| 1<br />
| 0x0066<br />
| Scissor box X/Y<br />
| Bit 0-15: X, bit 16-31: Y<br />
|-<br />
| 2<br />
| 0x0067<br />
| Scissor box width/height<br />
| Bit 0-15: width-1, bit 16-31: height-1<br />
|}<br />
<br />
===== Command 0x006F =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x006F<br />
| Typically only bit8-10 are used.<br />
| Bit8 enables texture coordinate output for texture unit 0, bit9 enables texcoords for texture unit 1, and bit2 enables texcoords for texture unit 2.<br />
|}<br />
<br />
===== Command 0x0080 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0080<br />
| <nowiki>0x11000 | val</nowiki>, where only bits 2-0 are used in val.<br />
| bit0-2 enables/disables texture units 0-2 respectively<br />
|}<br />
Note that bit0-2 in this command only enable texture processing. For texturing to work fully, the corresponding texture coordinate outputs must be enabled as well via command 0x006F.<br />
<br />
===== Command 0x00C0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| <nowiki>SlotCmdID</nowiki><br />
| <br />
| <br />
|-<br />
| 1<br />
| <nowiki>SlotCmdID + 4</nowiki><br />
| <br />
| <br />
|}<br />
<br />
This is used for glTexEnv(), for the slot indicated by the command id. There's a total of 6 slots, where each slot corresponds to the following u16 command ids: 0xC0, 0xC8, 0xD0, 0xD8, 0xF0, 0xF8.<br />
<br />
===== Command 0x00E0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E0<br />
| <nowiki>5 | val<<16</nowiki>, where val is 0 or 1.<br />
| Val0 = enable, val1 = disable.<br />
|-<br />
| 1<br />
| 0x00E1<br />
| <br />
| This specifies a color.<br />
|}<br />
<br />
This is usually used immediately after command set glDrawElements(). This is used to specify a color used for blending?<br />
<br />
===== Command 0x00E6 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E6<br />
| Value 0<br />
| ?<br />
|-<br />
| 1<br />
| 0x00E8<br />
| <br />
| <br />
|}<br />
<br />
This is usually the last command set used for rendering a mesh, when command set 0x00E0 was used. This command set is used immediately after command set 0x00E0.<br />
<br />
===== Command 0x0100 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0100<br />
| Value 0x00E40100<br />
| Controls color compositing<br />
|-<br />
| 1<br />
| 0x0101<br />
| 0x01010000 when disabled<br />
| Alphablending equations and factors<br />
|-<br />
| 2<br />
| 0x0103<br />
| This is set to zero when the command 0x0101 parameter is value 0x01010000.<br />
| Constant color for alphablending<br />
|}<br />
<br />
This is fragment related?<br />
<br />
===== Command 0x004D =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x004D<br />
| <br />
| glDepthRange()<br />
|-<br />
| 1<br />
| 0x006D<br />
| 0 = unknown, 1 = unknown.<br />
| Value zero causes the mesh to not be rendered.<br />
|}<br />
<br />
===== Command 0x0041 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0041<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 1<br />
| 0x0043<br />
| float<br />
| This parameter value is calculated the same way as the command 0x0041 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 2<br />
| 0x0042<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 3<br />
| 0x0044<br />
| float<br />
| This parameter value value is calculated the same way as the command 0x0042 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 4<br />
| 0x0068<br />
| u32<br />
| This sets the X/Y coordinates used for glViewport().<br />
|}<br />
<br />
This command set initializes the projection matrix. This command set is used twice when beginning rendering for each screen. The framebuffer width used here for the main screen is 240, however this is 480 with stereoscopy enabled for the second time this command set is used.<br />
<br />
===== Command 0x0111 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0111<br />
| Value 1<br />
| <br />
|-<br />
| 1<br />
| 0x0110<br />
| Value 1<br />
| <br />
|-<br />
| 2<br />
| 0x0117<br />
| Framebuffer color format descriptor<br />
| See [[GPU_Internal_Registers#GPUREG_COLORBUFFER_FORMAT]]<br />
|-<br />
| 3<br />
| 0x011D<br />
| Physical address>>3<br />
| This initializes the framebuffer address used for rendering, this framebuffer is used for the input framebuffer with [[GSP_Shared_Memory|GX command]] 3 and 4. This command is used immediately after command 0x0117.<br />
|-<br />
| 4<br />
| 0x0116<br />
| <br />
| ?<br />
|-<br />
| 5<br />
| 0x011C<br />
| Physical address>>3<br />
| Unknown, normally this address is located in VRAM.<br />
|-<br />
| 6<br />
| 0x011E<br />
| u32, 0x01000000|(((h-1)&0xFFF)<<12)|(w&0xFFF)<br />
| This sets the width and height for the framebuffer used for rendering. Therefore this is glViewport(), x/y are specified by command 0x0068.<br />
|-<br />
| 7<br />
| 0x006E<br />
| Same input parameter value as command 0x011E.<br />
| <br />
|}<br />
<br />
This command set is normally used after the two 0x0041 command sets.<br />
<br />
===== Command 0x0107 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0107<br />
| <br />
| <br />
|-<br />
| 1<br />
| 0x0126<br />
| type<<24<br />
| <br />
|}<br />
<br />
This command set is used for disabling the alpha-blending info set by command set 0x0107? The GL AlphaFunction used here is normally GL_ALWAYS.<br />
<br />
=== Parameter format for command 0x0107 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_DEPTH_TEST, 1 = enable GL_DEPTH_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Depth test function<br />
|-<br />
| 8<br />
| Enable color writing for red component<br />
|-<br />
| 9<br />
| Enable color writing for green component<br />
|-<br />
| 10<br />
| Enable color writing for blue component<br />
|-<br />
| 11<br />
| Enable color writing for alpha component<br />
|-<br />
| 12<br />
| Enable depth writing (doesn't affect stencil writing)<br />
|-<br />
| 31-13<br />
| Unused<br />
|}<br />
<br />
==== Alpha function values ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_EQUAL<br />
|-<br />
| 3<br />
| GL_NOTEQUAL<br />
|-<br />
| 4<br />
| GL_LESS<br />
|-<br />
| 5<br />
| GL_LEQUAL<br />
|-<br />
| 6<br />
| GL_GREATER<br />
|-<br />
| 7<br />
| GL_GEQUAL<br />
|}<br />
<br />
=== Alpha types for command 0x0126 ===<br />
{| class="wikitable" border="1"<br />
! Type<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_GREATER/GL_GEQUAL<br />
|-<br />
| 3<br />
| The remaining GL alpha functions.<br />
|}<br />
<br />
=== Parameter value format for command 0x0104 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_ALPHA_TEST, 1 = enable GL_ALPHA_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Alpha function<br />
|-<br />
| 15-8<br />
| u8 ref, range is 0-255<br />
|-<br />
| 31-16<br />
| Unused?<br />
|}<br />
<br />
This is glAlphaFunc().<br />
<br />
=== Parameter value format for command 0x011E ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 11-0<br />
| Framebuffer/viewport width<br />
|-<br />
| 23-12<br />
| Framebuffer/viewport height - 1<br />
|-<br />
| 24<br />
| Must be set<br />
|-<br />
| 31-25<br />
| Unused?<br />
|}<br />
<br />
This specifies the width/height for glViewport(). Normally the framebuffer width and height is set to the same [[GPU|dimensions]] used with GX [[GSP_Shared_Memory|command]] 3 and 4.<br />
<br />
=== Parameter value format for command 0x0068 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| X<br />
|-<br />
| 31-16<br />
| Y<br />
|}<br />
<br />
This specifies the X/Y coordinates for glViewport().<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Value 0xFFF0FFF / 0x0<br />
|-<br />
| 1<br />
| Value 0x0<br />
|-<br />
| 2<br />
| Value 0x0<br />
|-<br />
| 3<br />
| Value 0xFFFFFFFF<br />
|-<br />
| 4<br />
| Value 0x0<br />
|}<br />
<br />
This individual command is used instead of the 0x80XF00C0 command set when none of the associated rendering parameters for this slot are set.<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Param0<br />
|-<br />
| 1<br />
| Param1<br />
|-<br />
| 2<br />
| Param2<br />
|-<br />
| 3<br />
| Constant. 0xAABBBGGRR format (or same as the color buffer ?)<br />
|-<br />
| 4<br />
| Param4<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
==== Param0 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values.(Field0 index0)<br />
|-<br />
| 7-4<br />
| See below values.(Field0 index1)<br />
|-<br />
| 11-8<br />
| See below values.(Field0 index2)<br />
|-<br />
| 15-12<br />
| Unused<br />
|-<br />
| 19-16<br />
| See below values.(Field1 index0)<br />
|-<br />
| 23-20<br />
| See below values.(Field1 index1)<br />
|-<br />
| 27-24<br />
| See below values.(Field1 index2)<br />
|-<br />
| 31-28<br />
| Unused<br />
|}<br />
<br />
==== Param0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
! Comment<br />
|-<br />
| 0x0<br />
| GL_PRIMARY_COLOR<br />
|The color that comes from the upper shader<br />
|-<br />
| 0x1<br />
| GL_FRAGMENT_PRIMARY_COLOR<br />
| Sum of ambient, emissive, and diffuse components of lightning stage<br />
|-<br />
| 0x2<br />
| GL_FRAGMENT_SECONDARY_COLOR<br />
| Specular component of the lightning stage + ?<br />
|-<br />
| 0x3<br />
| GL_TEXTURE0<br />
|<br />
|-<br />
| 0x4<br />
| GL_TEXTURE1<br />
|<br />
|-<br />
| 0x5<br />
| GL_TEXTURE2<br />
|<br />
|-<br />
| 0x6<br />
| GL_TEXTURE3<br />
|<br />
|-<br />
| 0xC-0x7<br />
|(GL_PRIMARY_COLOR)No?<br />
| Please detail. Gives 0 on TexEnv0<br />
|-<br />
| 0xD<br />
| ?<br />
|<br />
|-<br />
| 0xE<br />
| GL_CONSTANT<br />
|<br />
|-<br />
| 0xF<br />
| GL_PREVIOUS<br />
| Color that comes from the previous texture stage<br />
|}<br />
<br />
==== Param1 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values for field0.(Index0)<br />
|-<br />
| 7-4<br />
| See below values for field0.(Index1)<br />
|-<br />
| 11-8<br />
| See below values for field0.(Index2)<br />
|-<br />
| 15-12<br />
| See below values for field1.(Index0)<br />
|-<br />
| 19-16<br />
| See below values for field1.(Index1)<br />
|-<br />
| 23-20<br />
| See below values for field1.(Index2)<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
This specifies the pname for glTexEnv().<br />
<br />
==== Param1 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 0x2<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x4<br />
| GL_SRC_R<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x6<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x7<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x8<br />
| GL_SRC_G<br />
|-<br />
| 0x9<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0xA<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xB<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xC<br />
| GL_SRC_B<br />
|-<br />
| 0xD<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
Note : GL_SRC_X and GL_ONE_MINUS_SRC_X where X=R|G|B are the same as GL_SRC_COLOR and GL_ONE_MINUS_SRC_COLOR but will use only the corresponding color component.<br />
<br />
==== Param1 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x2<br />
| GL_SRC_R<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x4<br />
| GL_SRC_G<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0x6<br />
| GL_SRC_B<br />
|-<br />
| 0x7<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
<br />
==== Param2 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| See below field0 values.<br />
|-<br />
| 31-16<br />
| See below field1 values.<br />
|}<br />
<br />
This is used to specify the param for glTexEnv(..., ..., param).<br />
<br />
==== Param2 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGBA<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param2 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_REPLACE<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param4 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 31-18<br />
| Unused<br />
|-<br />
| 17-16<br />
| Alpha output scale factor<br />
|-<br />
| 15-2<br />
| Unused<br />
|-<br />
| 1-0<br />
| Color output scale factor<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Scale value<br />
! Corresponding factor<br />
|-<br />
| 0x0<br />
| 1.0<br />
|-<br />
| 0x1<br />
| 2.0<br />
|-<br />
| 0x2<br />
| 4.0<br />
|}<br />
<br />
=== Parameter value format for command 0x00C4 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Valid values: 0=unknown, 1=unknown, 2=unknown.<br />
|-<br />
| 31-16<br />
| Same format as bits15-0.<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
=== Parameter value format for command 0x00E1 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Red component<br />
|-<br />
| 15-8<br />
| Green component<br />
|-<br />
| 23-16<br />
| Blue component<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
=== Parameter value format for command 0x0100 ===<br />
This command controls color compositing. It is typically used right after commands 0x0101 or 0x0102 to select the appropriate blending mode.<br />
<br />
Alphablending and color logic op can't be used together. Attempting to issue commands 0x0101 and 0x0102 at the same time can freeze the GPU.<br />
<br />
For blending to work correctly, color buffer reading needs to be enabled (see command set 0x0112). Otherwise zero values will be used as destination color/alpha.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Weird mode (see below)<br />
|-<br />
| 1<br />
| When set, nothing is drawn to the color, depth and stencil buffers. This bit can cause a noisy picture when used with bit 0 (this seems to also cause the depth buffer's endianness to be reversed, and forces stencil values to 0xFF).<br />
|-<br />
| 8<br />
| Selects blending mode. 0 = color logic op, 1 = alphablending<br />
|-<br />
| 23-16<br />
| Unknown, typically set to 0xE4. No observed effect when changing this.<br />
|-<br />
| 25-24<br />
| 0 = normal, 1-3 = apply dithering (3 = 0% source)<br />
|}<br />
<br />
When "weird mode" is enabled, the source color/alpha values are ignored. Instead, each 16-bit value in the destination color buffer is converted according to its bits 14-8, as follows:<br />
* if bits 14-8 are between 0x00 and 0x03, the value is replaced with 0x0000<br />
* if bits 14-8 are between 0x7D and 0x7F, the value is replaced with 0x7FFF<br />
* in all other cases, the value is left unchanged<br />
<br />
=== Parameter value format for command 0x0101 ===<br />
This command controls alphablending. To disable alphablending, the value is set to 0x01010000.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Color blend equation<br />
|-<br />
| 15-8<br />
| Alpha blend equation<br />
|-<br />
| 19-16<br />
| Color source factor<br />
|-<br />
| 23-20<br />
| Color destination factor<br />
|-<br />
| 27-24<br />
| Alpha source factor<br />
|-<br />
| 31-28<br />
| Alpha destination factor<br />
|}<br />
<br />
Blend equation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_FUNC_ADD<br />
|-<br />
| 1<br />
| GL_FUNC_SUBTRACT<br />
|-<br />
| 2<br />
| GL_FUNC_REVERSE_SUBTRACT<br />
|-<br />
| 3<br />
| GL_MIN<br />
|-<br />
| 4<br />
| GL_MAX<br />
|}<br />
<br />
Source/destination factor values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_ZERO<br />
|-<br />
| 1<br />
| GL_ONE<br />
|-<br />
| 2<br />
| GL_SRC_COLOR<br />
|-<br />
| 3<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 4<br />
| GL_DST_COLOR<br />
|-<br />
| 5<br />
| GL_ONE_MINUS_DST_COLOR<br />
|-<br />
| 6<br />
| GL_SRC_ALPHA<br />
|-<br />
| 7<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 8<br />
| GL_DST_ALPHA<br />
|-<br />
| 9<br />
| GL_ONE_MINUS_DST_ALPHA<br />
|-<br />
| 10<br />
| GL_CONSTANT_COLOR<br />
|-<br />
| 11<br />
| GL_ONE_MINUS_CONSTANT_COLOR<br />
|-<br />
| 12<br />
| GL_CONSTANT_ALPHA<br />
|-<br />
| 13<br />
| GL_ONE_MINUS_CONSTANT_ALPHA<br />
|-<br />
| 14<br />
| GL_SRC_ALPHA_SATURATE<br />
|}<br />
<br />
=== Parameter value format for command 0x0102 ===<br />
This command controls color logic op.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| Logic operation<br />
|}<br />
<br />
Logic operation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_CLEAR<br />
|-<br />
| 1<br />
| GL_AND<br />
|-<br />
| 2<br />
| GL_AND_REVERSE<br />
|-<br />
| 3<br />
| GL_COPY<br />
|-<br />
| 4<br />
| GL_SET<br />
|-<br />
| 5<br />
| GL_COPY_INVERTED<br />
|-<br />
| 6<br />
| GL_NOOP<br />
|-<br />
| 7<br />
| GL_INVERT<br />
|-<br />
| 8<br />
| GL_NAND<br />
|-<br />
| 9<br />
| GL_OR<br />
|-<br />
| 10<br />
| GL_NOR<br />
|-<br />
| 11<br />
| GL_XOR<br />
|-<br />
| 12<br />
| GL_EQUIV<br />
|-<br />
| 13<br />
| GL_AND_INVERTED<br />
|-<br />
| 14<br />
| GL_OR_REVERSE<br />
|-<br />
| 15<br />
| GL_OR_INVERTED<br />
|}<br />
<br />
=== Parameter value format for command 0x0105 ===<br />
This command controls stencil testing.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable stencil test<br />
|-<br />
| 7-4<br />
| Stencil test function (values same as for alpha and depth tests)<br />
|-<br />
| 15-8<br />
| Stencil buffer write mask<br />
|-<br />
| 23-16<br />
| Reference value for the stencil test. Note that the test does "reference FUNC value".<br />
|-<br />
| 31-24<br />
| Mask for the stencil test.<br />
|}<br />
<br />
=== Parameter value format for command 0x0106 ===<br />
This command controls stencil buffer replacement.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Action when the stencil test fails<br />
|-<br />
| 6-4<br />
| Action when the stencil test passes but the depth test fails<br />
|-<br />
| 10-8<br />
| Action when both stencil test and depth test pass<br />
|}<br />
<br />
Action values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Final stencil value<br />
! OpenGL equivalent<br />
|-<br />
| 0<br />
| old_stencil<br />
| GL_KEEP<br />
|-<br />
| 1<br />
| unknown<br />
| <br />
|-<br />
| 2<br />
| reference<br />
| GL_REPLACE<br />
|-<br />
| 3<br />
| min(old_stencil + 1, 255)<br />
| GL_INCR<br />
|-<br />
| 4<br />
| max(old_stencil - 1, 0)<br />
| GL_DECR<br />
|-<br />
| 5<br />
| ~old_stencil<br />
| GL_INVERT<br />
|-<br />
| 6<br />
| unknown<br />
|<br />
|-<br />
| 7<br />
| unknown<br />
|<br />
|}<br />
<br />
'old_stencil' is the value present in the stencil buffer, 'reference' is the reference value specified in command 0x0105.<br />
<br />
=== Parameter structure for command 0x004D ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float far<br />
|-<br />
| 1<br />
| float near<br />
|}<br />
<br />
This is glDepthRange().<br />
<br />
=== Parameter structure for command 0x00E8 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0x7D-0x00<br />
| Usually value 0x00FFE000.<br />
|-<br />
| 0x7E<br />
| Usually value 0x00FFFEE6?<br />
|-<br />
| 0x7F<br />
| Usually value 0x00DCD919?<br />
|}<br />
<br />
=== Parameter structure for command 0x0112 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Setting bits 3-0 to a nonzero value allows the GPU to read from the color buffer.<br />
|-<br />
| 1<br />
| Setting bits 3-0 to a nonzero value allows the GPU to write to the color buffer.<br />
|-<br />
| 2<br />
| Setting bits 1-0 to a nonzero value allows the GPU to read from the depth/stencil buffer.<br />
|-<br />
| 3<br />
| Setting bits 1-0 to a nonzero value allows the GPU to write to the depth/stencil buffer.<br />
|}<br />
<br />
=== Entries for command 0x02C1 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float, the GPU handles this as the 4th word.<br />
|-<br />
| 1<br />
| float, the GPU handles this as the 3rd word.<br />
|-<br />
| 2<br />
| float, the GPU handles this as the 2nd word.<br />
|-<br />
| 3<br />
| float, the GPU handles this as the 1st word.<br />
|}<br />
<br />
The below entry structure info is in the raw order used for the command, not the order used by the GPU.<br />
<br />
==== Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Red component<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Alpha<br />
|}<br />
<br />
==== Lighting Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Alpha<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Red component<br />
|}<br />
<br />
=== Types for command 0x02C0 ===<br />
<br />
The 0x02C0/0x02C1 is actually used as a generic way to set uniforms, regardless of what they represent. 0x02C0's parameter represents the ID of the destination GPU register (0x0 is c0, 0x1 is c1 etc). As such, the meaning of the data being sent over is entirely dependant on the shader currently in use.<br />
The values below may be "default" values used by Nintendo's openGL implementation.<br />
<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Entries per chunk<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| This specifies 16-floats for a 4x4 matrix, used for glLoadMatrix() for the projection matrix.<br />
|-<br />
| 0x04<br />
| 4<br />
| This specifies a 4x4 matrix, used for glLoadMatrix() for the model-view matrix. This is usually an identity matrix.<br />
|-<br />
| 0x08<br />
| 2<br />
| Sets the color.<br />
|-<br />
| 0x0A<br />
| 4<br />
| Specifies a 4x4 matrix, used for glLoadMatrix() for the texture matrix.(Index0)<br />
|-<br />
| 0x0E<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index1)<br />
|-<br />
| 0x11<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index2)<br />
|-<br />
| 0x14<br />
| <=30<br />
| Used to specify a 4xN matrix, where N is the total command 0x02C1 entries. This is glMultMatrix() for the model-view matrix, except the input matrix is 4xN instead of 4x4.<br />
|-<br />
| 0x4C<br />
| 4<br />
| This specifies a 4x4 float matrix.<br />
|-<br />
| 0x50, 0x53, and 0x56<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_AMBIENT?<br />
|-<br />
| 0x51, 0x54, and 0x57<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_DIFFUSE?<br />
|-<br />
| 0x52, 0x55, and 0x58<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_SPECULAR?<br />
|-<br />
| 0x59<br />
| 1<br />
| Unknown, the entry data is floats converted from s32s. Usually each entry word is zeros.<br />
|-<br />
| 0x5A<br />
| 2<br />
| Color related?<br />
|-<br />
| 0x5C<br />
| 1<br />
| ?<br />
|}<br />
<br />
The matrices for types 0x00 and 0x04 use row-major order, instead of column-major order.<br />
<br />
[[Category:GPU]]</div>Subvhttps://www.3dbrew.org/w/index.php?title=GPU/Commands&diff=13079GPU/Commands2015-08-19T04:07:28Z<p>Subv: /* Parameter value format for command 0x0106 */</p>
<hr />
<div>This page describes the structure of the buffer submitted via the registers at [[GPU|0x1EF018E0]] (or equivalently via [[GSP_Shared_Memory|GX command]] 1). This buffer is used for GPU commands including functionality equivalent to OpenGL commands.<br />
<br />
[[GPU Internal Registers]] provides a more structured overview for the available commands but is still work in progress, and hence should be used as a complementary source of information.<br />
<br />
=== Overview ===<br />
Each command is at least 8 bytes wide. The first word is the command parameter and the second word constitutes the command header. Optionally, more parameter words may follow (potentially including a padding word to align commands to multiples of 8 bytes).<br />
<br />
In the simplest case, a command is exactly 8 bytes wide. You can think of such a command as writing the parameter word to an internal register (the index of which is given in the command header). The more general case where more than one parameter word is given is equivalent to multiple simple commands (one for each parameter word). If consecutive writing mode is enabled in the command header, the current command index will be incremented after each parameter write. Otherwise, the parameters will be consecutively written to the same register.<br />
<br />
For example, the sequence "0xAAAAAAAA 0x802F011C 0xBBBBBBBB 0xCCCCCCCC" is equivalent to a call to commands 0xF011C with parameter 0xAAAAAAAA, 0xF011D with parameter 0xBBBBBBBB and 0xF011E with parameter 0xCCCCCCCC. If consecutive writing mode were disabled, the command would be equivalent to three consecutive calls to 0xF011C (once with parameter 0xAAAAAAAA, once with 0xBBBBBBBB, and finally with 0xCCCCCCCC).<br />
<br />
Invalid GPU command parameters including NaN floats can cause the GPU to hang, which then causes the GSP module to hang as well.<br />
<br />
The size of GPU command buffers must be 0x10-byte aligned; the lower 3 bits of the size are cleared. A common pitfall is having the finalization command (write to register 0x0010) not executed because it was the last 8 bytes of a non-0x10 byte aligned command buffer, and having the GPU hang as a result.<br />
<br />
=== Command Header ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Command ID<br />
|-<br />
| 19-16<br />
| Parameter mask<br />
|-<br />
| 30-20<br />
| Number of extra parameters (may be zero)<br />
|-<br />
| 31<br />
| Consecutive writing mode<br />
|}<br />
<br />
=== Parameter masking ===<br />
<br />
Using a value other than 0xF, parts of a word in internal GPU memory can be updated without touching the other bits of it. For example, setting bit 16 to zero indicates that the least significant byte of the parameter will not be overwritten, setting bit 17 to zero indicates that the parameter's second LSB will not be overwritten, etc. This means that for instance commands 0x00010107 and 0x00020107 refer to the same thing but write different parts of the parameter.<br />
<br />
=== Command IDs ===<br />
{| class="wikitable" border="1"<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0x0010<br />
| Value is 0x12345678<br />
| This command is always the last command in the buffer.<br />
|-<br />
| 0x0110<br />
| Value 0x1<br />
| This command is immediately before command 0x0010, this is also used elsewhere for beginning rendering of mesh(es) as well.<br />
|-<br />
| 0x0111<br />
| Value 0x1<br />
| This command is immediately before command 0x0110, however command 0x0110 doesn't always follow this command.<br />
|-<br />
| 0x0040<br />
| u32, valid values are 0x1 and 0x2, values 0x0 and 0x3 have the same effect as value 0x2. Only bits 1-0 are used.<br />
| Value 2 = GL_FRONT/GL_CW or GL_BACK/GL_CCW. Value 1 = GL_FRONT/GL_CCW or GL_BACK/GL_CW.<br />
|-<br />
| 0x0041<br />
| float24<br />
| VIEWPORT_WIDTH. See command set 0x0041.<br />
|-<br />
| 0x0042<br />
| float32<br />
| VIEWPORT_WIDTH_INV. See command set 0x0041.<br />
|-<br />
| 0x0043<br />
| float24<br />
| VIEWPORT_HEIGHT. See command set 0x0041.<br />
|-<br />
| 0x0044<br />
| float32<br />
| VIEWPORT_HEIGHT_INV. See command set 0x0041.<br />
|-<br />
| 0x004D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x0065<br />
| <br />
| Scissor test. See command set 0x0065.<br />
|-<br />
| 0x0068<br />
| u32<br />
| VIEWPORT Y/X. See command set 0x0041.<br />
|-<br />
| 0x006D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x006E<br />
| u32<br />
| See command set 0x0111.<br />
|-<br />
| 0x006F<br />
| u32<br />
| See command set 0x006F.<br />
|-<br />
| 0x0080<br />
| u32<br />
| See command set 0x0080.<br />
|-<br />
| 0x0081<br />
| <br />
| This is used to set the current texture info used for rendering, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x008E<br />
| u32 color type<br />
| This command sets the texture color type, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x0091<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0091]].<br />
|-<br />
| 0x0099<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0099]].<br />
|-<br />
| 0x00C3<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00CB<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00C0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00CC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00DC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00FC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00E0<br />
| Normally value zero.<br />
| Unknown, fragment related?<br />
|-<br />
| 0x00E0<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E1<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E6<br />
| Value zero<br />
| See command set 0x00E6.<br />
|-<br />
| 0x00E8<br />
| <br />
| See command set 0x00E6.<br />
|-<br />
| 0x0100<br />
| u32, value is 0x00E40100<br />
| See command set 0x0100.<br />
|-<br />
| 0x0100<br />
| <nowiki>0x00E40000 | val</nowiki>.<br />
| See command set 0x0100.<br />
|-<br />
| 0x0101<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0102<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0103<br />
| <br />
| See command set 0x0100.<br />
|-<br />
| 0x0104<br />
| u32<br />
| glAlphaFunc()<br />
|-<br />
| 0x0105<br />
| u32<br />
| Stencil test settings<br />
|-<br />
| 0x0106<br />
| u32<br />
| Stencil replacement operators<br />
|-<br />
| 0x0107<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0116<br />
| u32<br />
| DEPTHBUFFER FORMAT. See command set 0x0111.<br />
|-<br />
| 0x0117<br />
| u32<br />
| COLORBUFFER FORMAT/PIXEL. See command set 0x0111.<br />
|-<br />
| 0x011C<br />
| Physical address>>3<br />
| DEPTHBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011D<br />
| Physical address>>3<br />
| COLORBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011E<br />
| u32<br />
| COLORBUFFER HEIGHT/WIDTH. See command set 0x0111.<br />
|-<br />
| 0x0112<br />
| <br />
| ?<br />
|-<br />
| 0x01C5<br />
| <nowiki>(dmp_FragmentLightSource ID)<<8 | (sampler ID)<<11</nowiki> ?<br />
| This command is in conjunction with 0x01C8 used to send fragment 1D samplers. (LUTs) sampler ID 1 for sampler samplerSP and 2 for samplerDA<br />
|-<br />
| 0x01C8<br />
| LUT as parameter<br />
| Used to send fragment LUT data.<br />
|-<br />
| 0x0200<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0126<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0227<br />
| u32<br />
| This specifies the address of an array containing vertex array indices, and the data-type of the indices, used for rendering primitives. See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0228<br />
| u32 total elements in the array to use for rendering.<br />
| See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0232<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0244<br />
| bool ?<br />
| Set geo shader enabled/disabled ?<br />
|-<br />
| 0x025E<br />
| u32, val<<8.<br />
| This sets the GL rendering mode, see command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0280<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set geo shader boolean uniforms. ((val>>i)&1 = !b_i) value (b0 = False => val&1 == 1)<br />
|-<br />
| 0x0281<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (geo shader)<br />
|-<br />
| 0x0282<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (geo shader)<br />
|-<br />
| 0x0283<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (geo shader)<br />
|-<br />
| 0x0284<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (geo shader)<br />
|-<br />
| 0x028A<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the geometry shader program<br />
|-<br />
| 0x0290<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| Geometry shader equivalent of 0x02C0<br />
|-<br />
| 0x02B0<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set the 16 vertex shader boolean uniforms. (b_i = (val>>i)&1)<br />
|-<br />
| 0x02B1<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (vertex shader)<br />
|-<br />
| 0x02B2<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (vertex shader)<br />
|-<br />
| 0x02B3<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (vertex shader)<br />
|-<br />
| 0x02B4<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (vertex shader)<br />
|-<br />
| 0x02BB<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x02BA<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the vertex shader program<br />
|-<br />
| 0x02C0<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| This is used immediately before command 0x02C1. This type field controls the command parameter buffer type. This command can also be used to send over (float24 only ?) data directly, without using 0x02C1. In that case, the first parameter is still Type but with bit 31 not set; the actual data follows.<br />
|-<br />
| 0x02C1<br />
| First word in the first entry<br />
| A list of entries follow this command.<br />
|-<br />
| 0x02C2<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C3<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C4<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C5<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C6<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C7<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C8<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x029B<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x029C. It is used to indicate that geometry shader program data will follow.<br />
|-<br />
| 0x029C<br />
| First word of geometry shader program data chunk.<br />
| This command is used to transfer geometry shader program data (as the parameter data). It can be called multiple times in a row if the shader program is too big to fit into a single call.<br />
|-<br />
| 0x028F<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x029C. It is used to indicate that geometry shader program data transfer is complete.<br />
|-<br />
| 0x02A5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02A6<br />
| First entry.<br />
| This is used to send over the geometry shader program operand descriptor table.<br />
|-<br />
| 0x02CB<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02CC. It is used to indicate that shader program data will follow.<br />
|-<br />
| 0x02CC<br />
| First word of vertex shader program data chunk.<br />
| This command is used to transfer vertex shader program data (as the parameter data). It can be called multiple times in a row if the vertex shader program is too big to fit into a single call.<br />
|-<br />
| 0x02BF<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x02CC. It is used to indicate that vertex shader program data transfer is complete.<br />
|-<br />
| 0x02D5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02D6<br />
| First entry.<br />
| This is used to send over the vertex shader program operand descriptor table.<br />
|-<br />
| 0x004F<br />
| Number of vertex shader output attributes<br />
| Sets number of vertex shader output attributes<br />
|-<br />
| 0x0050<br />
| First entry<br />
| This command is used to setup vertex shader output registers. The n-th word-long entry is a map of the (n*2)-th output register's components. Each byte of each entry corresponds to where a component is mapped. Value 0x1F indicates that the corresponding component is unused.<br />
|}<br />
<br />
==== Command Sets ====<br />
<br />
===== glDrawElements() =====<br />
See [[GPU_GL_Arrays|GPU GL Arrays]].<br />
<br />
===== glClear() / glClearColor() =====<br />
The GPU does not have dedicated commands for clearing the color buffer, therefore applications implement color buffer clearing by rendering a quad. Applications normally store this vertex and color [[GPU_GL_Arrays|array]] in the GSP application heap.<br />
<br />
===== Command 0x0081 =====<br />
This sets current texture info, see [[GPU Textures|GPU textures]].<br />
<br />
===== Command 0x0065 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0065<br />
| Scissor test enable<br />
| 0 = disabled, 1 = inverted (pixels within the scissor box are excluded), 2 = disabled, 3 = normal (pixels outside of the scissor box are excluded)<br />
|-<br />
| 1<br />
| 0x0066<br />
| Scissor box X/Y<br />
| Bit 0-15: X, bit 16-31: Y<br />
|-<br />
| 2<br />
| 0x0067<br />
| Scissor box width/height<br />
| Bit 0-15: width-1, bit 16-31: height-1<br />
|}<br />
<br />
===== Command 0x006F =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x006F<br />
| Typically only bit8-10 are used.<br />
| Bit8 enables texture coordinate output for texture unit 0, bit9 enables texcoords for texture unit 1, and bit2 enables texcoords for texture unit 2.<br />
|}<br />
<br />
===== Command 0x0080 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0080<br />
| <nowiki>0x11000 | val</nowiki>, where only bits 2-0 are used in val.<br />
| bit0-2 enables/disables texture units 0-2 respectively<br />
|}<br />
Note that bit0-2 in this command only enable texture processing. For texturing to work fully, the corresponding texture coordinate outputs must be enabled as well via command 0x006F.<br />
<br />
===== Command 0x00C0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| <nowiki>SlotCmdID</nowiki><br />
| <br />
| <br />
|-<br />
| 1<br />
| <nowiki>SlotCmdID + 4</nowiki><br />
| <br />
| <br />
|}<br />
<br />
This is used for glTexEnv(), for the slot indicated by the command id. There's a total of 6 slots, where each slot corresponds to the following u16 command ids: 0xC0, 0xC8, 0xD0, 0xD8, 0xF0, 0xF8.<br />
<br />
===== Command 0x00E0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E0<br />
| <nowiki>5 | val<<16</nowiki>, where val is 0 or 1.<br />
| Val0 = enable, val1 = disable.<br />
|-<br />
| 1<br />
| 0x00E1<br />
| <br />
| This specifies a color.<br />
|}<br />
<br />
This is usually used immediately after command set glDrawElements(). This is used to specify a color used for blending?<br />
<br />
===== Command 0x00E6 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E6<br />
| Value 0<br />
| ?<br />
|-<br />
| 1<br />
| 0x00E8<br />
| <br />
| <br />
|}<br />
<br />
This is usually the last command set used for rendering a mesh, when command set 0x00E0 was used. This command set is used immediately after command set 0x00E0.<br />
<br />
===== Command 0x0100 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0100<br />
| Value 0x00E40100<br />
| Controls color compositing<br />
|-<br />
| 1<br />
| 0x0101<br />
| 0x01010000 when disabled<br />
| Alphablending equations and factors<br />
|-<br />
| 2<br />
| 0x0103<br />
| This is set to zero when the command 0x0101 parameter is value 0x01010000.<br />
| Constant color for alphablending<br />
|}<br />
<br />
This is fragment related?<br />
<br />
===== Command 0x004D =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x004D<br />
| <br />
| glDepthRange()<br />
|-<br />
| 1<br />
| 0x006D<br />
| 0 = unknown, 1 = unknown.<br />
| Value zero causes the mesh to not be rendered.<br />
|}<br />
<br />
===== Command 0x0041 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0041<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 1<br />
| 0x0043<br />
| float<br />
| This parameter value is calculated the same way as the command 0x0041 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 2<br />
| 0x0042<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 3<br />
| 0x0044<br />
| float<br />
| This parameter value value is calculated the same way as the command 0x0042 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 4<br />
| 0x0068<br />
| u32<br />
| This sets the X/Y coordinates used for glViewport().<br />
|}<br />
<br />
This command set initializes the projection matrix. This command set is used twice when beginning rendering for each screen. The framebuffer width used here for the main screen is 240, however this is 480 with stereoscopy enabled for the second time this command set is used.<br />
<br />
===== Command 0x0111 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0111<br />
| Value 1<br />
| <br />
|-<br />
| 1<br />
| 0x0110<br />
| Value 1<br />
| <br />
|-<br />
| 2<br />
| 0x0117<br />
| Framebuffer color format descriptor<br />
| See [[GPU_Internal_Registers#GPUREG_COLORBUFFER_FORMAT]]<br />
|-<br />
| 3<br />
| 0x011D<br />
| Physical address>>3<br />
| This initializes the framebuffer address used for rendering, this framebuffer is used for the input framebuffer with [[GSP_Shared_Memory|GX command]] 3 and 4. This command is used immediately after command 0x0117.<br />
|-<br />
| 4<br />
| 0x0116<br />
| <br />
| ?<br />
|-<br />
| 5<br />
| 0x011C<br />
| Physical address>>3<br />
| Unknown, normally this address is located in VRAM.<br />
|-<br />
| 6<br />
| 0x011E<br />
| u32, 0x01000000|(((h-1)&0xFFF)<<12)|(w&0xFFF)<br />
| This sets the width and height for the framebuffer used for rendering. Therefore this is glViewport(), x/y are specified by command 0x0068.<br />
|-<br />
| 7<br />
| 0x006E<br />
| Same input parameter value as command 0x011E.<br />
| <br />
|}<br />
<br />
This command set is normally used after the two 0x0041 command sets.<br />
<br />
===== Command 0x0107 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0107<br />
| <br />
| <br />
|-<br />
| 1<br />
| 0x0126<br />
| type<<24<br />
| <br />
|}<br />
<br />
This command set is used for disabling the alpha-blending info set by command set 0x0107? The GL AlphaFunction used here is normally GL_ALWAYS.<br />
<br />
=== Parameter format for command 0x0107 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_DEPTH_TEST, 1 = enable GL_DEPTH_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Depth test function<br />
|-<br />
| 8<br />
| Enable color writing for red component<br />
|-<br />
| 9<br />
| Enable color writing for green component<br />
|-<br />
| 10<br />
| Enable color writing for blue component<br />
|-<br />
| 11<br />
| Enable color writing for alpha component<br />
|-<br />
| 12<br />
| Enable depth writing (doesn't affect stencil writing)<br />
|-<br />
| 31-13<br />
| Unused<br />
|}<br />
<br />
==== Alpha function values ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_EQUAL<br />
|-<br />
| 3<br />
| GL_NOTEQUAL<br />
|-<br />
| 4<br />
| GL_LESS<br />
|-<br />
| 5<br />
| GL_LEQUAL<br />
|-<br />
| 6<br />
| GL_GREATER<br />
|-<br />
| 7<br />
| GL_GEQUAL<br />
|}<br />
<br />
=== Alpha types for command 0x0126 ===<br />
{| class="wikitable" border="1"<br />
! Type<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_GREATER/GL_GEQUAL<br />
|-<br />
| 3<br />
| The remaining GL alpha functions.<br />
|}<br />
<br />
=== Parameter value format for command 0x0104 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_ALPHA_TEST, 1 = enable GL_ALPHA_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Alpha function<br />
|-<br />
| 15-8<br />
| u8 ref, range is 0-255<br />
|-<br />
| 31-16<br />
| Unused?<br />
|}<br />
<br />
This is glAlphaFunc().<br />
<br />
=== Parameter value format for command 0x011E ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 11-0<br />
| Framebuffer/viewport width<br />
|-<br />
| 23-12<br />
| Framebuffer/viewport height - 1<br />
|-<br />
| 24<br />
| Must be set<br />
|-<br />
| 31-25<br />
| Unused?<br />
|}<br />
<br />
This specifies the width/height for glViewport(). Normally the framebuffer width and height is set to the same [[GPU|dimensions]] used with GX [[GSP_Shared_Memory|command]] 3 and 4.<br />
<br />
=== Parameter value format for command 0x0068 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| X<br />
|-<br />
| 31-16<br />
| Y<br />
|}<br />
<br />
This specifies the X/Y coordinates for glViewport().<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Value 0xFFF0FFF / 0x0<br />
|-<br />
| 1<br />
| Value 0x0<br />
|-<br />
| 2<br />
| Value 0x0<br />
|-<br />
| 3<br />
| Value 0xFFFFFFFF<br />
|-<br />
| 4<br />
| Value 0x0<br />
|}<br />
<br />
This individual command is used instead of the 0x80XF00C0 command set when none of the associated rendering parameters for this slot are set.<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Param0<br />
|-<br />
| 1<br />
| Param1<br />
|-<br />
| 2<br />
| Param2<br />
|-<br />
| 3<br />
| Constant. 0xAABBBGGRR format (or same as the color buffer ?)<br />
|-<br />
| 4<br />
| Param4<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
==== Param0 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values.(Field0 index0)<br />
|-<br />
| 7-4<br />
| See below values.(Field0 index1)<br />
|-<br />
| 11-8<br />
| See below values.(Field0 index2)<br />
|-<br />
| 15-12<br />
| Unused<br />
|-<br />
| 19-16<br />
| See below values.(Field1 index0)<br />
|-<br />
| 23-20<br />
| See below values.(Field1 index1)<br />
|-<br />
| 27-24<br />
| See below values.(Field1 index2)<br />
|-<br />
| 31-28<br />
| Unused<br />
|}<br />
<br />
==== Param0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
! Comment<br />
|-<br />
| 0x0<br />
| GL_PRIMARY_COLOR<br />
|The color that comes from the upper shader<br />
|-<br />
| 0x1<br />
| GL_FRAGMENT_PRIMARY_COLOR<br />
| Sum of ambient, emissive, and diffuse components of lightning stage<br />
|-<br />
| 0x2<br />
| GL_FRAGMENT_SECONDARY_COLOR<br />
| Specular component of the lightning stage + ?<br />
|-<br />
| 0x3<br />
| GL_TEXTURE0<br />
|<br />
|-<br />
| 0x4<br />
| GL_TEXTURE1<br />
|<br />
|-<br />
| 0x5<br />
| GL_TEXTURE2<br />
|<br />
|-<br />
| 0x6<br />
| GL_TEXTURE3<br />
|<br />
|-<br />
| 0xC-0x7<br />
|(GL_PRIMARY_COLOR)No?<br />
| Please detail. Gives 0 on TexEnv0<br />
|-<br />
| 0xD<br />
| ?<br />
|<br />
|-<br />
| 0xE<br />
| GL_CONSTANT<br />
|<br />
|-<br />
| 0xF<br />
| GL_PREVIOUS<br />
| Color that comes from the previous texture stage<br />
|}<br />
<br />
==== Param1 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values for field0.(Index0)<br />
|-<br />
| 7-4<br />
| See below values for field0.(Index1)<br />
|-<br />
| 11-8<br />
| See below values for field0.(Index2)<br />
|-<br />
| 15-12<br />
| See below values for field1.(Index0)<br />
|-<br />
| 19-16<br />
| See below values for field1.(Index1)<br />
|-<br />
| 23-20<br />
| See below values for field1.(Index2)<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
This specifies the pname for glTexEnv().<br />
<br />
==== Param1 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 0x2<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x4<br />
| GL_SRC_R<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x6<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x7<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x8<br />
| GL_SRC_G<br />
|-<br />
| 0x9<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0xA<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xB<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xC<br />
| GL_SRC_B<br />
|-<br />
| 0xD<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
Note : GL_SRC_X and GL_ONE_MINUS_SRC_X where X=R|G|B are the same as GL_SRC_COLOR and GL_ONE_MINUS_SRC_COLOR but will use only the corresponding color component.<br />
<br />
==== Param1 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x2<br />
| GL_SRC_R<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x4<br />
| GL_SRC_G<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0x6<br />
| GL_SRC_B<br />
|-<br />
| 0x7<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
<br />
==== Param2 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| See below field0 values.<br />
|-<br />
| 31-16<br />
| See below field1 values.<br />
|}<br />
<br />
This is used to specify the param for glTexEnv(..., ..., param).<br />
<br />
==== Param2 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGBA<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param2 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_REPLACE<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param4 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 31-18<br />
| Unused<br />
|-<br />
| 17-16<br />
| Alpha output scale factor<br />
|-<br />
| 15-2<br />
| Unused<br />
|-<br />
| 1-0<br />
| Color output scale factor<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Scale value<br />
! Corresponding factor<br />
|-<br />
| 0x0<br />
| 1.0<br />
|-<br />
| 0x1<br />
| 2.0<br />
|-<br />
| 0x2<br />
| 4.0<br />
|}<br />
<br />
=== Parameter value format for command 0x00C4 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Valid values: 0=unknown, 1=unknown, 2=unknown.<br />
|-<br />
| 31-16<br />
| Same format as bits15-0.<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
=== Parameter value format for command 0x00E1 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Red component<br />
|-<br />
| 15-8<br />
| Green component<br />
|-<br />
| 23-16<br />
| Blue component<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
=== Parameter value format for command 0x0100 ===<br />
This command controls color compositing. It is typically used right after commands 0x0101 or 0x0102 to select the appropriate blending mode.<br />
<br />
Alphablending and color logic op can't be used together. Attempting to issue commands 0x0101 and 0x0102 at the same time can freeze the GPU.<br />
<br />
For blending to work correctly, color buffer reading needs to be enabled (see command set 0x0112). Otherwise zero values will be used as destination color/alpha.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Weird mode (see below)<br />
|-<br />
| 1<br />
| When set, nothing is drawn to the color, depth and stencil buffers. This bit can cause a noisy picture when used with bit 0 (this seems to also cause the depth buffer's endianness to be reversed, and forces stencil values to 0xFF).<br />
|-<br />
| 8<br />
| Selects blending mode. 0 = color logic op, 1 = alphablending<br />
|-<br />
| 23-16<br />
| Unknown, typically set to 0xE4. No observed effect when changing this.<br />
|-<br />
| 25-24<br />
| 0 = normal, 1-3 = apply dithering (3 = 0% source)<br />
|}<br />
<br />
When "weird mode" is enabled, the source color/alpha values are ignored. Instead, each 16-bit value in the destination color buffer is converted according to its bits 14-8, as follows:<br />
* if bits 14-8 are between 0x00 and 0x03, the value is replaced with 0x0000<br />
* if bits 14-8 are between 0x7D and 0x7F, the value is replaced with 0x7FFF<br />
* in all other cases, the value is left unchanged<br />
<br />
=== Parameter value format for command 0x0101 ===<br />
This command controls alphablending. To disable alphablending, the value is set to 0x01010000.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Color blend equation<br />
|-<br />
| 15-8<br />
| Alpha blend equation<br />
|-<br />
| 19-16<br />
| Color source factor<br />
|-<br />
| 23-20<br />
| Color destination factor<br />
|-<br />
| 27-24<br />
| Alpha source factor<br />
|-<br />
| 31-28<br />
| Alpha destination factor<br />
|}<br />
<br />
Blend equation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_FUNC_ADD<br />
|-<br />
| 1<br />
| GL_FUNC_SUBTRACT<br />
|-<br />
| 2<br />
| GL_FUNC_REVERSE_SUBTRACT<br />
|-<br />
| 3<br />
| GL_MIN<br />
|-<br />
| 4<br />
| GL_MAX<br />
|}<br />
<br />
Source/destination factor values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_ZERO<br />
|-<br />
| 1<br />
| GL_ONE<br />
|-<br />
| 2<br />
| GL_SRC_COLOR<br />
|-<br />
| 3<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 4<br />
| GL_DST_COLOR<br />
|-<br />
| 5<br />
| GL_ONE_MINUS_DST_COLOR<br />
|-<br />
| 6<br />
| GL_SRC_ALPHA<br />
|-<br />
| 7<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 8<br />
| GL_DST_ALPHA<br />
|-<br />
| 9<br />
| GL_ONE_MINUS_DST_ALPHA<br />
|-<br />
| 10<br />
| GL_CONSTANT_COLOR<br />
|-<br />
| 11<br />
| GL_ONE_MINUS_CONSTANT_COLOR<br />
|-<br />
| 12<br />
| GL_CONSTANT_ALPHA<br />
|-<br />
| 13<br />
| GL_ONE_MINUS_CONSTANT_ALPHA<br />
|-<br />
| 14<br />
| GL_SRC_ALPHA_SATURATE<br />
|}<br />
<br />
=== Parameter value format for command 0x0102 ===<br />
This command controls color logic op.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| Logic operation<br />
|}<br />
<br />
Logic operation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_CLEAR<br />
|-<br />
| 1<br />
| GL_AND<br />
|-<br />
| 2<br />
| GL_AND_REVERSE<br />
|-<br />
| 3<br />
| GL_COPY<br />
|-<br />
| 4<br />
| GL_SET<br />
|-<br />
| 5<br />
| GL_COPY_INVERTED<br />
|-<br />
| 6<br />
| GL_NOOP<br />
|-<br />
| 7<br />
| GL_INVERT<br />
|-<br />
| 8<br />
| GL_NAND<br />
|-<br />
| 9<br />
| GL_OR<br />
|-<br />
| 10<br />
| GL_NOR<br />
|-<br />
| 11<br />
| GL_XOR<br />
|-<br />
| 12<br />
| GL_EQUIV<br />
|-<br />
| 13<br />
| GL_AND_INVERTED<br />
|-<br />
| 14<br />
| GL_OR_REVERSE<br />
|-<br />
| 15<br />
| GL_OR_INVERTED<br />
|}<br />
<br />
=== Parameter value format for command 0x0105 ===<br />
This command controls stencil testing.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable stencil test<br />
|-<br />
| 7-4<br />
| Stencil test function (values same as for alpha and depth tests)<br />
|-<br />
| 15-8<br />
| Stencil buffer write mask<br />
|-<br />
| 23-16<br />
| Reference value for the stencil test. Note that the test does "reference FUNC value".<br />
|-<br />
| 31-24<br />
| Mask for the stencil test.<br />
|}<br />
<br />
=== Parameter value format for command 0x0106 ===<br />
This command controls stencil buffer replacement.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Action when the stencil test fails<br />
|-<br />
| 6-4<br />
| Action when the stencil test passes but the depth test fails<br />
|-<br />
| 10-8<br />
| Action when both stencil test and depth test pass<br />
|}<br />
<br />
Action values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Final stencil value<br />
! OpenGL equivalent<br />
|-<br />
| 0<br />
| old_stencil<br />
| GL_KEEP<br />
|-<br />
| 1<br />
| unknown<br />
| <br />
|-<br />
| 2<br />
| reference<br />
| GL_REPLACE<br />
|-<br />
| 3<br />
| max(old_stencil + 1, 255)<br />
| GL_INCR<br />
|-<br />
| 4<br />
| min(old_stencil - 1, 0)<br />
| GL_DECR<br />
|-<br />
| 5<br />
| ~old_stencil<br />
| GL_INVERT<br />
|-<br />
| 6<br />
| unknown<br />
|<br />
|-<br />
| 7<br />
| unknown<br />
|<br />
|}<br />
<br />
'old_stencil' is the value present in the stencil buffer, 'reference' is the reference value specified in command 0x0105.<br />
<br />
=== Parameter structure for command 0x004D ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float far<br />
|-<br />
| 1<br />
| float near<br />
|}<br />
<br />
This is glDepthRange().<br />
<br />
=== Parameter structure for command 0x00E8 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0x7D-0x00<br />
| Usually value 0x00FFE000.<br />
|-<br />
| 0x7E<br />
| Usually value 0x00FFFEE6?<br />
|-<br />
| 0x7F<br />
| Usually value 0x00DCD919?<br />
|}<br />
<br />
=== Parameter structure for command 0x0112 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Setting bits 3-0 to a nonzero value allows the GPU to read from the color buffer.<br />
|-<br />
| 1<br />
| Setting bits 3-0 to a nonzero value allows the GPU to write to the color buffer.<br />
|-<br />
| 2<br />
| Setting bits 1-0 to a nonzero value allows the GPU to read from the depth/stencil buffer.<br />
|-<br />
| 3<br />
| Setting bits 1-0 to a nonzero value allows the GPU to write to the depth/stencil buffer.<br />
|}<br />
<br />
=== Entries for command 0x02C1 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float, the GPU handles this as the 4th word.<br />
|-<br />
| 1<br />
| float, the GPU handles this as the 3rd word.<br />
|-<br />
| 2<br />
| float, the GPU handles this as the 2nd word.<br />
|-<br />
| 3<br />
| float, the GPU handles this as the 1st word.<br />
|}<br />
<br />
The below entry structure info is in the raw order used for the command, not the order used by the GPU.<br />
<br />
==== Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Red component<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Alpha<br />
|}<br />
<br />
==== Lighting Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Alpha<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Red component<br />
|}<br />
<br />
=== Types for command 0x02C0 ===<br />
<br />
The 0x02C0/0x02C1 is actually used as a generic way to set uniforms, regardless of what they represent. 0x02C0's parameter represents the ID of the destination GPU register (0x0 is c0, 0x1 is c1 etc). As such, the meaning of the data being sent over is entirely dependant on the shader currently in use.<br />
The values below may be "default" values used by Nintendo's openGL implementation.<br />
<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Entries per chunk<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| This specifies 16-floats for a 4x4 matrix, used for glLoadMatrix() for the projection matrix.<br />
|-<br />
| 0x04<br />
| 4<br />
| This specifies a 4x4 matrix, used for glLoadMatrix() for the model-view matrix. This is usually an identity matrix.<br />
|-<br />
| 0x08<br />
| 2<br />
| Sets the color.<br />
|-<br />
| 0x0A<br />
| 4<br />
| Specifies a 4x4 matrix, used for glLoadMatrix() for the texture matrix.(Index0)<br />
|-<br />
| 0x0E<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index1)<br />
|-<br />
| 0x11<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index2)<br />
|-<br />
| 0x14<br />
| <=30<br />
| Used to specify a 4xN matrix, where N is the total command 0x02C1 entries. This is glMultMatrix() for the model-view matrix, except the input matrix is 4xN instead of 4x4.<br />
|-<br />
| 0x4C<br />
| 4<br />
| This specifies a 4x4 float matrix.<br />
|-<br />
| 0x50, 0x53, and 0x56<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_AMBIENT?<br />
|-<br />
| 0x51, 0x54, and 0x57<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_DIFFUSE?<br />
|-<br />
| 0x52, 0x55, and 0x58<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_SPECULAR?<br />
|-<br />
| 0x59<br />
| 1<br />
| Unknown, the entry data is floats converted from s32s. Usually each entry word is zeros.<br />
|-<br />
| 0x5A<br />
| 2<br />
| Color related?<br />
|-<br />
| 0x5C<br />
| 1<br />
| ?<br />
|}<br />
<br />
The matrices for types 0x00 and 0x04 use row-major order, instead of column-major order.<br />
<br />
[[Category:GPU]]</div>Subvhttps://www.3dbrew.org/w/index.php?title=GPU/Commands&diff=13078GPU/Commands2015-08-19T04:03:48Z<p>Subv: /* Parameter value format for command 0x0105 */</p>
<hr />
<div>This page describes the structure of the buffer submitted via the registers at [[GPU|0x1EF018E0]] (or equivalently via [[GSP_Shared_Memory|GX command]] 1). This buffer is used for GPU commands including functionality equivalent to OpenGL commands.<br />
<br />
[[GPU Internal Registers]] provides a more structured overview for the available commands but is still work in progress, and hence should be used as a complementary source of information.<br />
<br />
=== Overview ===<br />
Each command is at least 8 bytes wide. The first word is the command parameter and the second word constitutes the command header. Optionally, more parameter words may follow (potentially including a padding word to align commands to multiples of 8 bytes).<br />
<br />
In the simplest case, a command is exactly 8 bytes wide. You can think of such a command as writing the parameter word to an internal register (the index of which is given in the command header). The more general case where more than one parameter word is given is equivalent to multiple simple commands (one for each parameter word). If consecutive writing mode is enabled in the command header, the current command index will be incremented after each parameter write. Otherwise, the parameters will be consecutively written to the same register.<br />
<br />
For example, the sequence "0xAAAAAAAA 0x802F011C 0xBBBBBBBB 0xCCCCCCCC" is equivalent to a call to commands 0xF011C with parameter 0xAAAAAAAA, 0xF011D with parameter 0xBBBBBBBB and 0xF011E with parameter 0xCCCCCCCC. If consecutive writing mode were disabled, the command would be equivalent to three consecutive calls to 0xF011C (once with parameter 0xAAAAAAAA, once with 0xBBBBBBBB, and finally with 0xCCCCCCCC).<br />
<br />
Invalid GPU command parameters including NaN floats can cause the GPU to hang, which then causes the GSP module to hang as well.<br />
<br />
The size of GPU command buffers must be 0x10-byte aligned; the lower 3 bits of the size are cleared. A common pitfall is having the finalization command (write to register 0x0010) not executed because it was the last 8 bytes of a non-0x10 byte aligned command buffer, and having the GPU hang as a result.<br />
<br />
=== Command Header ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Command ID<br />
|-<br />
| 19-16<br />
| Parameter mask<br />
|-<br />
| 30-20<br />
| Number of extra parameters (may be zero)<br />
|-<br />
| 31<br />
| Consecutive writing mode<br />
|}<br />
<br />
=== Parameter masking ===<br />
<br />
Using a value other than 0xF, parts of a word in internal GPU memory can be updated without touching the other bits of it. For example, setting bit 16 to zero indicates that the least significant byte of the parameter will not be overwritten, setting bit 17 to zero indicates that the parameter's second LSB will not be overwritten, etc. This means that for instance commands 0x00010107 and 0x00020107 refer to the same thing but write different parts of the parameter.<br />
<br />
=== Command IDs ===<br />
{| class="wikitable" border="1"<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0x0010<br />
| Value is 0x12345678<br />
| This command is always the last command in the buffer.<br />
|-<br />
| 0x0110<br />
| Value 0x1<br />
| This command is immediately before command 0x0010, this is also used elsewhere for beginning rendering of mesh(es) as well.<br />
|-<br />
| 0x0111<br />
| Value 0x1<br />
| This command is immediately before command 0x0110, however command 0x0110 doesn't always follow this command.<br />
|-<br />
| 0x0040<br />
| u32, valid values are 0x1 and 0x2, values 0x0 and 0x3 have the same effect as value 0x2. Only bits 1-0 are used.<br />
| Value 2 = GL_FRONT/GL_CW or GL_BACK/GL_CCW. Value 1 = GL_FRONT/GL_CCW or GL_BACK/GL_CW.<br />
|-<br />
| 0x0041<br />
| float24<br />
| VIEWPORT_WIDTH. See command set 0x0041.<br />
|-<br />
| 0x0042<br />
| float32<br />
| VIEWPORT_WIDTH_INV. See command set 0x0041.<br />
|-<br />
| 0x0043<br />
| float24<br />
| VIEWPORT_HEIGHT. See command set 0x0041.<br />
|-<br />
| 0x0044<br />
| float32<br />
| VIEWPORT_HEIGHT_INV. See command set 0x0041.<br />
|-<br />
| 0x004D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x0065<br />
| <br />
| Scissor test. See command set 0x0065.<br />
|-<br />
| 0x0068<br />
| u32<br />
| VIEWPORT Y/X. See command set 0x0041.<br />
|-<br />
| 0x006D<br />
| <br />
| See command set 0x004D.<br />
|-<br />
| 0x006E<br />
| u32<br />
| See command set 0x0111.<br />
|-<br />
| 0x006F<br />
| u32<br />
| See command set 0x006F.<br />
|-<br />
| 0x0080<br />
| u32<br />
| See command set 0x0080.<br />
|-<br />
| 0x0081<br />
| <br />
| This is used to set the current texture info used for rendering, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x008E<br />
| u32 color type<br />
| This command sets the texture color type, see command set [[GPU_Textures|0x0081]].<br />
|-<br />
| 0x0091<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0091]].<br />
|-<br />
| 0x0099<br />
| <br />
| This sets current texture info, see command [[GPU_Textures|0x0099]].<br />
|-<br />
| 0x00C3<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00CB<br />
| val<<24<br />
| Val is usually 0xFF or 0x00, however 0x00-0xFF is valid as well. This is alpha-blending related?<br />
|-<br />
| 0x00C0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00C8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00CC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00D8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00DC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F0<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F4<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00F8<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00FC<br />
| <br />
| See command set 0x00C0.<br />
|-<br />
| 0x00E0<br />
| Normally value zero.<br />
| Unknown, fragment related?<br />
|-<br />
| 0x00E0<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E1<br />
| <br />
| See command set 0x00E0.<br />
|-<br />
| 0x00E6<br />
| Value zero<br />
| See command set 0x00E6.<br />
|-<br />
| 0x00E8<br />
| <br />
| See command set 0x00E6.<br />
|-<br />
| 0x0100<br />
| u32, value is 0x00E40100<br />
| See command set 0x0100.<br />
|-<br />
| 0x0100<br />
| <nowiki>0x00E40000 | val</nowiki>.<br />
| See command set 0x0100.<br />
|-<br />
| 0x0101<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0102<br />
| u32<br />
| See command set 0x0100.<br />
|-<br />
| 0x0103<br />
| <br />
| See command set 0x0100.<br />
|-<br />
| 0x0104<br />
| u32<br />
| glAlphaFunc()<br />
|-<br />
| 0x0105<br />
| u32<br />
| Stencil test settings<br />
|-<br />
| 0x0106<br />
| u32<br />
| Stencil replacement operators<br />
|-<br />
| 0x0107<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0116<br />
| u32<br />
| DEPTHBUFFER FORMAT. See command set 0x0111.<br />
|-<br />
| 0x0117<br />
| u32<br />
| COLORBUFFER FORMAT/PIXEL. See command set 0x0111.<br />
|-<br />
| 0x011C<br />
| Physical address>>3<br />
| DEPTHBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011D<br />
| Physical address>>3<br />
| COLORBUFFER ADDRESS. See command set 0x0111.<br />
|-<br />
| 0x011E<br />
| u32<br />
| COLORBUFFER HEIGHT/WIDTH. See command set 0x0111.<br />
|-<br />
| 0x0112<br />
| <br />
| ?<br />
|-<br />
| 0x01C5<br />
| <nowiki>(dmp_FragmentLightSource ID)<<8 | (sampler ID)<<11</nowiki> ?<br />
| This command is in conjunction with 0x01C8 used to send fragment 1D samplers. (LUTs) sampler ID 1 for sampler samplerSP and 2 for samplerDA<br />
|-<br />
| 0x01C8<br />
| LUT as parameter<br />
| Used to send fragment LUT data.<br />
|-<br />
| 0x0200<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0126<br />
| <br />
| See command set command 0x0107.<br />
|-<br />
| 0x0227<br />
| u32<br />
| This specifies the address of an array containing vertex array indices, and the data-type of the indices, used for rendering primitives. See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0228<br />
| u32 total elements in the array to use for rendering.<br />
| See command set [[GPU_GL_Arrays|glDrawElements()]].<br />
|-<br />
| 0x0232<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0244<br />
| bool ?<br />
| Set geo shader enabled/disabled ?<br />
|-<br />
| 0x025E<br />
| u32, val<<8.<br />
| This sets the GL rendering mode, see command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x0280<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set geo shader boolean uniforms. ((val>>i)&1 = !b_i) value (b0 = False => val&1 == 1)<br />
|-<br />
| 0x0281<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (geo shader)<br />
|-<br />
| 0x0282<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (geo shader)<br />
|-<br />
| 0x0283<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (geo shader)<br />
|-<br />
| 0x0284<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (geo shader)<br />
|-<br />
| 0x028A<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the geometry shader program<br />
|-<br />
| 0x0290<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| Geometry shader equivalent of 0x02C0<br />
|-<br />
| 0x02B0<br />
| u32, value is <nowiki>0x7FFF0000 | val</nowiki>.<br />
| Used to set the 16 vertex shader boolean uniforms. (b_i = (val>>i)&1)<br />
|-<br />
| 0x02B1<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i0 (vertex shader)<br />
|-<br />
| 0x02B2<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i1 (vertex shader)<br />
|-<br />
| 0x02B3<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i2 (vertex shader)<br />
|-<br />
| 0x02B4<br />
| u32, value is <nowiki>(x&0xff)|((y&0xff)<<8)|((z&0xff)<<16)|((w&0xff)<<24)</nowiki>.<br />
| Used to set i3 (vertex shader)<br />
|-<br />
| 0x02BB<br />
| <br />
| See command set [[GPU_GL_Arrays|0x0200]].<br />
|-<br />
| 0x02BA<br />
| <nowiki>0x7FFF0000 | entrypoint offset</nowiki><br />
| Sets the entrypoint offset for the vertex shader program<br />
|-<br />
| 0x02C0<br />
| <nowiki>0x80000000 | Type</nowiki><br />
| This is used immediately before command 0x02C1. This type field controls the command parameter buffer type. This command can also be used to send over (float24 only ?) data directly, without using 0x02C1. In that case, the first parameter is still Type but with bit 31 not set; the actual data follows.<br />
|-<br />
| 0x02C1<br />
| First word in the first entry<br />
| A list of entries follow this command.<br />
|-<br />
| 0x02C2<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C3<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C4<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C5<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C6<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C7<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x02C8<br />
| First word in the first entry<br />
| Alias for 0x02C1<br />
|-<br />
| 0x029B<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x029C. It is used to indicate that geometry shader program data will follow.<br />
|-<br />
| 0x029C<br />
| First word of geometry shader program data chunk.<br />
| This command is used to transfer geometry shader program data (as the parameter data). It can be called multiple times in a row if the shader program is too big to fit into a single call.<br />
|-<br />
| 0x028F<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x029C. It is used to indicate that geometry shader program data transfer is complete.<br />
|-<br />
| 0x02A5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02A6<br />
| First entry.<br />
| This is used to send over the geometry shader program operand descriptor table.<br />
|-<br />
| 0x02CB<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02CC. It is used to indicate that shader program data will follow.<br />
|-<br />
| 0x02CC<br />
| First word of vertex shader program data chunk.<br />
| This command is used to transfer vertex shader program data (as the parameter data). It can be called multiple times in a row if the vertex shader program is too big to fit into a single call.<br />
|-<br />
| 0x02BF<br />
| Value 0x1 ?<br />
| This is used immediately after a set of command 0x02CC. It is used to indicate that vertex shader program data transfer is complete.<br />
|-<br />
| 0x02D5<br />
| Value 0x0 ?<br />
| This is used immediately before command 0x02A6.<br />
|-<br />
| 0x02D6<br />
| First entry.<br />
| This is used to send over the vertex shader program operand descriptor table.<br />
|-<br />
| 0x004F<br />
| Number of vertex shader output attributes<br />
| Sets number of vertex shader output attributes<br />
|-<br />
| 0x0050<br />
| First entry<br />
| This command is used to setup vertex shader output registers. The n-th word-long entry is a map of the (n*2)-th output register's components. Each byte of each entry corresponds to where a component is mapped. Value 0x1F indicates that the corresponding component is unused.<br />
|}<br />
<br />
==== Command Sets ====<br />
<br />
===== glDrawElements() =====<br />
See [[GPU_GL_Arrays|GPU GL Arrays]].<br />
<br />
===== glClear() / glClearColor() =====<br />
The GPU does not have dedicated commands for clearing the color buffer, therefore applications implement color buffer clearing by rendering a quad. Applications normally store this vertex and color [[GPU_GL_Arrays|array]] in the GSP application heap.<br />
<br />
===== Command 0x0081 =====<br />
This sets current texture info, see [[GPU Textures|GPU textures]].<br />
<br />
===== Command 0x0065 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0065<br />
| Scissor test enable<br />
| 0 = disabled, 1 = inverted (pixels within the scissor box are excluded), 2 = disabled, 3 = normal (pixels outside of the scissor box are excluded)<br />
|-<br />
| 1<br />
| 0x0066<br />
| Scissor box X/Y<br />
| Bit 0-15: X, bit 16-31: Y<br />
|-<br />
| 2<br />
| 0x0067<br />
| Scissor box width/height<br />
| Bit 0-15: width-1, bit 16-31: height-1<br />
|}<br />
<br />
===== Command 0x006F =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x006F<br />
| Typically only bit8-10 are used.<br />
| Bit8 enables texture coordinate output for texture unit 0, bit9 enables texcoords for texture unit 1, and bit2 enables texcoords for texture unit 2.<br />
|}<br />
<br />
===== Command 0x0080 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0080<br />
| <nowiki>0x11000 | val</nowiki>, where only bits 2-0 are used in val.<br />
| bit0-2 enables/disables texture units 0-2 respectively<br />
|}<br />
Note that bit0-2 in this command only enable texture processing. For texturing to work fully, the corresponding texture coordinate outputs must be enabled as well via command 0x006F.<br />
<br />
===== Command 0x00C0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| <nowiki>SlotCmdID</nowiki><br />
| <br />
| <br />
|-<br />
| 1<br />
| <nowiki>SlotCmdID + 4</nowiki><br />
| <br />
| <br />
|}<br />
<br />
This is used for glTexEnv(), for the slot indicated by the command id. There's a total of 6 slots, where each slot corresponds to the following u16 command ids: 0xC0, 0xC8, 0xD0, 0xD8, 0xF0, 0xF8.<br />
<br />
===== Command 0x00E0 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E0<br />
| <nowiki>5 | val<<16</nowiki>, where val is 0 or 1.<br />
| Val0 = enable, val1 = disable.<br />
|-<br />
| 1<br />
| 0x00E1<br />
| <br />
| This specifies a color.<br />
|}<br />
<br />
This is usually used immediately after command set glDrawElements(). This is used to specify a color used for blending?<br />
<br />
===== Command 0x00E6 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x00E6<br />
| Value 0<br />
| ?<br />
|-<br />
| 1<br />
| 0x00E8<br />
| <br />
| <br />
|}<br />
<br />
This is usually the last command set used for rendering a mesh, when command set 0x00E0 was used. This command set is used immediately after command set 0x00E0.<br />
<br />
===== Command 0x0100 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0100<br />
| Value 0x00E40100<br />
| Controls color compositing<br />
|-<br />
| 1<br />
| 0x0101<br />
| 0x01010000 when disabled<br />
| Alphablending equations and factors<br />
|-<br />
| 2<br />
| 0x0103<br />
| This is set to zero when the command 0x0101 parameter is value 0x01010000.<br />
| Constant color for alphablending<br />
|}<br />
<br />
This is fragment related?<br />
<br />
===== Command 0x004D =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x004D<br />
| <br />
| glDepthRange()<br />
|-<br />
| 1<br />
| 0x006D<br />
| 0 = unknown, 1 = unknown.<br />
| Value zero causes the mesh to not be rendered.<br />
|}<br />
<br />
===== Command 0x0041 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0041<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 1<br />
| 0x0043<br />
| float<br />
| This parameter value is calculated the same way as the command 0x0041 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 2<br />
| 0x0042<br />
| float<br />
| This corresponds to the framebuffer width.<br />
|-<br />
| 3<br />
| 0x0044<br />
| float<br />
| This parameter value value is calculated the same way as the command 0x0042 parameter, except the framebuffer height is used instead.<br />
|-<br />
| 4<br />
| 0x0068<br />
| u32<br />
| This sets the X/Y coordinates used for glViewport().<br />
|}<br />
<br />
This command set initializes the projection matrix. This command set is used twice when beginning rendering for each screen. The framebuffer width used here for the main screen is 240, however this is 480 with stereoscopy enabled for the second time this command set is used.<br />
<br />
===== Command 0x0111 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0111<br />
| Value 1<br />
| <br />
|-<br />
| 1<br />
| 0x0110<br />
| Value 1<br />
| <br />
|-<br />
| 2<br />
| 0x0117<br />
| Framebuffer color format descriptor<br />
| See [[GPU_Internal_Registers#GPUREG_COLORBUFFER_FORMAT]]<br />
|-<br />
| 3<br />
| 0x011D<br />
| Physical address>>3<br />
| This initializes the framebuffer address used for rendering, this framebuffer is used for the input framebuffer with [[GSP_Shared_Memory|GX command]] 3 and 4. This command is used immediately after command 0x0117.<br />
|-<br />
| 4<br />
| 0x0116<br />
| <br />
| ?<br />
|-<br />
| 5<br />
| 0x011C<br />
| Physical address>>3<br />
| Unknown, normally this address is located in VRAM.<br />
|-<br />
| 6<br />
| 0x011E<br />
| u32, 0x01000000|(((h-1)&0xFFF)<<12)|(w&0xFFF)<br />
| This sets the width and height for the framebuffer used for rendering. Therefore this is glViewport(), x/y are specified by command 0x0068.<br />
|-<br />
| 7<br />
| 0x006E<br />
| Same input parameter value as command 0x011E.<br />
| <br />
|}<br />
<br />
This command set is normally used after the two 0x0041 command sets.<br />
<br />
===== Command 0x0107 =====<br />
{| class="wikitable" border="1"<br />
! Command Index<br />
! CommandID<br />
! Parameter<br />
! Description<br />
|-<br />
| 0<br />
| 0x0107<br />
| <br />
| <br />
|-<br />
| 1<br />
| 0x0126<br />
| type<<24<br />
| <br />
|}<br />
<br />
This command set is used for disabling the alpha-blending info set by command set 0x0107? The GL AlphaFunction used here is normally GL_ALWAYS.<br />
<br />
=== Parameter format for command 0x0107 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_DEPTH_TEST, 1 = enable GL_DEPTH_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Depth test function<br />
|-<br />
| 8<br />
| Enable color writing for red component<br />
|-<br />
| 9<br />
| Enable color writing for green component<br />
|-<br />
| 10<br />
| Enable color writing for blue component<br />
|-<br />
| 11<br />
| Enable color writing for alpha component<br />
|-<br />
| 12<br />
| Enable depth writing (doesn't affect stencil writing)<br />
|-<br />
| 31-13<br />
| Unused<br />
|}<br />
<br />
==== Alpha function values ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_EQUAL<br />
|-<br />
| 3<br />
| GL_NOTEQUAL<br />
|-<br />
| 4<br />
| GL_LESS<br />
|-<br />
| 5<br />
| GL_LEQUAL<br />
|-<br />
| 6<br />
| GL_GREATER<br />
|-<br />
| 7<br />
| GL_GEQUAL<br />
|}<br />
<br />
=== Alpha types for command 0x0126 ===<br />
{| class="wikitable" border="1"<br />
! Type<br />
! GL AlphaFunction<br />
|-<br />
| 0<br />
| GL_NEVER<br />
|-<br />
| 1<br />
| GL_ALWAYS<br />
|-<br />
| 2<br />
| GL_GREATER/GL_GEQUAL<br />
|-<br />
| 3<br />
| The remaining GL alpha functions.<br />
|}<br />
<br />
=== Parameter value format for command 0x0104 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| 0 = disable GL_ALPHA_TEST, 1 = enable GL_ALPHA_TEST<br />
|-<br />
| 3-1<br />
| Unused?<br />
|-<br />
| 7-4<br />
| Alpha function<br />
|-<br />
| 15-8<br />
| u8 ref, range is 0-255<br />
|-<br />
| 31-16<br />
| Unused?<br />
|}<br />
<br />
This is glAlphaFunc().<br />
<br />
=== Parameter value format for command 0x011E ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 11-0<br />
| Framebuffer/viewport width<br />
|-<br />
| 23-12<br />
| Framebuffer/viewport height - 1<br />
|-<br />
| 24<br />
| Must be set<br />
|-<br />
| 31-25<br />
| Unused?<br />
|}<br />
<br />
This specifies the width/height for glViewport(). Normally the framebuffer width and height is set to the same [[GPU|dimensions]] used with GX [[GSP_Shared_Memory|command]] 3 and 4.<br />
<br />
=== Parameter value format for command 0x0068 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| X<br />
|-<br />
| 31-16<br />
| Y<br />
|}<br />
<br />
This specifies the X/Y coordinates for glViewport().<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Value 0xFFF0FFF / 0x0<br />
|-<br />
| 1<br />
| Value 0x0<br />
|-<br />
| 2<br />
| Value 0x0<br />
|-<br />
| 3<br />
| Value 0xFFFFFFFF<br />
|-<br />
| 4<br />
| Value 0x0<br />
|}<br />
<br />
This individual command is used instead of the 0x80XF00C0 command set when none of the associated rendering parameters for this slot are set.<br />
<br />
=== Parameter structure for command 0x00C0 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Param0<br />
|-<br />
| 1<br />
| Param1<br />
|-<br />
| 2<br />
| Param2<br />
|-<br />
| 3<br />
| Constant. 0xAABBBGGRR format (or same as the color buffer ?)<br />
|-<br />
| 4<br />
| Param4<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
==== Param0 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values.(Field0 index0)<br />
|-<br />
| 7-4<br />
| See below values.(Field0 index1)<br />
|-<br />
| 11-8<br />
| See below values.(Field0 index2)<br />
|-<br />
| 15-12<br />
| Unused<br />
|-<br />
| 19-16<br />
| See below values.(Field1 index0)<br />
|-<br />
| 23-20<br />
| See below values.(Field1 index1)<br />
|-<br />
| 27-24<br />
| See below values.(Field1 index2)<br />
|-<br />
| 31-28<br />
| Unused<br />
|}<br />
<br />
==== Param0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
! Comment<br />
|-<br />
| 0x0<br />
| GL_PRIMARY_COLOR<br />
|The color that comes from the upper shader<br />
|-<br />
| 0x1<br />
| GL_FRAGMENT_PRIMARY_COLOR<br />
| Sum of ambient, emissive, and diffuse components of lightning stage<br />
|-<br />
| 0x2<br />
| GL_FRAGMENT_SECONDARY_COLOR<br />
| Specular component of the lightning stage + ?<br />
|-<br />
| 0x3<br />
| GL_TEXTURE0<br />
|<br />
|-<br />
| 0x4<br />
| GL_TEXTURE1<br />
|<br />
|-<br />
| 0x5<br />
| GL_TEXTURE2<br />
|<br />
|-<br />
| 0x6<br />
| GL_TEXTURE3<br />
|<br />
|-<br />
| 0xC-0x7<br />
|(GL_PRIMARY_COLOR)No?<br />
| Please detail. Gives 0 on TexEnv0<br />
|-<br />
| 0xD<br />
| ?<br />
|<br />
|-<br />
| 0xE<br />
| GL_CONSTANT<br />
|<br />
|-<br />
| 0xF<br />
| GL_PREVIOUS<br />
| Color that comes from the previous texture stage<br />
|}<br />
<br />
==== Param1 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| See below values for field0.(Index0)<br />
|-<br />
| 7-4<br />
| See below values for field0.(Index1)<br />
|-<br />
| 11-8<br />
| See below values for field0.(Index2)<br />
|-<br />
| 15-12<br />
| See below values for field1.(Index0)<br />
|-<br />
| 19-16<br />
| See below values for field1.(Index1)<br />
|-<br />
| 23-20<br />
| See below values for field1.(Index2)<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
This specifies the pname for glTexEnv().<br />
<br />
==== Param1 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 0x2<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x4<br />
| GL_SRC_R<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x6<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x7<br />
| GL_SRC_COLOR<br />
|-<br />
| 0x8<br />
| GL_SRC_G<br />
|-<br />
| 0x9<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0xA<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xB<br />
| GL_SRC_COLOR<br />
|-<br />
| 0xC<br />
| GL_SRC_B<br />
|-<br />
| 0xD<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
Note : GL_SRC_X and GL_ONE_MINUS_SRC_X where X=R|G|B are the same as GL_SRC_COLOR and GL_ONE_MINUS_SRC_COLOR but will use only the corresponding color component.<br />
<br />
==== Param1 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_SRC_ALPHA<br />
|-<br />
| 0x1<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 0x2<br />
| GL_SRC_R<br />
|-<br />
| 0x3<br />
| GL_ONE_MINUS_SRC_R<br />
|-<br />
| 0x4<br />
| GL_SRC_G<br />
|-<br />
| 0x5<br />
| GL_ONE_MINUS_SRC_G<br />
|-<br />
| 0x6<br />
| GL_SRC_B<br />
|-<br />
| 0x7<br />
| GL_ONE_MINUS_SRC_B<br />
|}<br />
<br />
==== Param2 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| See below field0 values.<br />
|-<br />
| 31-16<br />
| See below field1 values.<br />
|}<br />
<br />
This is used to specify the param for glTexEnv(..., ..., param).<br />
<br />
==== Param2 field0 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGBA<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param2 field1 values for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Value<br />
! GL type<br />
|-<br />
| 0x0<br />
| GL_REPLACE<br />
|-<br />
| 0x1<br />
| GL_MODULATE<br />
|-<br />
| 0x2<br />
| GL_ADD<br />
|-<br />
| 0x3<br />
| GL_ADD_SIGNED<br />
|-<br />
| 0x4<br />
| GL_INTERPOLATE<br />
|-<br />
| 0x5<br />
| GL_SUBTRACT<br />
|-<br />
| 0x6<br />
| GL_REPLACE<br />
|-<br />
| 0x7<br />
| GL_DOT3_RGB<br />
|-<br />
| 0x8<br />
| ?<br />
|-<br />
| 0x9<br />
| ?<br />
|}<br />
<br />
==== Param4 format for command 0x00C0 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 31-18<br />
| Unused<br />
|-<br />
| 17-16<br />
| Alpha output scale factor<br />
|-<br />
| 15-2<br />
| Unused<br />
|-<br />
| 1-0<br />
| Color output scale factor<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Scale value<br />
! Corresponding factor<br />
|-<br />
| 0x0<br />
| 1.0<br />
|-<br />
| 0x1<br />
| 2.0<br />
|-<br />
| 0x2<br />
| 4.0<br />
|}<br />
<br />
=== Parameter value format for command 0x00C4 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Valid values: 0=unknown, 1=unknown, 2=unknown.<br />
|-<br />
| 31-16<br />
| Same format as bits15-0.<br />
|}<br />
<br />
See command set 0x80XF00C0.<br />
<br />
=== Parameter value format for command 0x00E1 ===<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Red component<br />
|-<br />
| 15-8<br />
| Green component<br />
|-<br />
| 23-16<br />
| Blue component<br />
|-<br />
| 31-24<br />
| Unused<br />
|}<br />
<br />
=== Parameter value format for command 0x0100 ===<br />
This command controls color compositing. It is typically used right after commands 0x0101 or 0x0102 to select the appropriate blending mode.<br />
<br />
Alphablending and color logic op can't be used together. Attempting to issue commands 0x0101 and 0x0102 at the same time can freeze the GPU.<br />
<br />
For blending to work correctly, color buffer reading needs to be enabled (see command set 0x0112). Otherwise zero values will be used as destination color/alpha.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Weird mode (see below)<br />
|-<br />
| 1<br />
| When set, nothing is drawn to the color, depth and stencil buffers. This bit can cause a noisy picture when used with bit 0 (this seems to also cause the depth buffer's endianness to be reversed, and forces stencil values to 0xFF).<br />
|-<br />
| 8<br />
| Selects blending mode. 0 = color logic op, 1 = alphablending<br />
|-<br />
| 23-16<br />
| Unknown, typically set to 0xE4. No observed effect when changing this.<br />
|-<br />
| 25-24<br />
| 0 = normal, 1-3 = apply dithering (3 = 0% source)<br />
|}<br />
<br />
When "weird mode" is enabled, the source color/alpha values are ignored. Instead, each 16-bit value in the destination color buffer is converted according to its bits 14-8, as follows:<br />
* if bits 14-8 are between 0x00 and 0x03, the value is replaced with 0x0000<br />
* if bits 14-8 are between 0x7D and 0x7F, the value is replaced with 0x7FFF<br />
* in all other cases, the value is left unchanged<br />
<br />
=== Parameter value format for command 0x0101 ===<br />
This command controls alphablending. To disable alphablending, the value is set to 0x01010000.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 7-0<br />
| Color blend equation<br />
|-<br />
| 15-8<br />
| Alpha blend equation<br />
|-<br />
| 19-16<br />
| Color source factor<br />
|-<br />
| 23-20<br />
| Color destination factor<br />
|-<br />
| 27-24<br />
| Alpha source factor<br />
|-<br />
| 31-28<br />
| Alpha destination factor<br />
|}<br />
<br />
Blend equation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_FUNC_ADD<br />
|-<br />
| 1<br />
| GL_FUNC_SUBTRACT<br />
|-<br />
| 2<br />
| GL_FUNC_REVERSE_SUBTRACT<br />
|-<br />
| 3<br />
| GL_MIN<br />
|-<br />
| 4<br />
| GL_MAX<br />
|}<br />
<br />
Source/destination factor values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_ZERO<br />
|-<br />
| 1<br />
| GL_ONE<br />
|-<br />
| 2<br />
| GL_SRC_COLOR<br />
|-<br />
| 3<br />
| GL_ONE_MINUS_SRC_COLOR<br />
|-<br />
| 4<br />
| GL_DST_COLOR<br />
|-<br />
| 5<br />
| GL_ONE_MINUS_DST_COLOR<br />
|-<br />
| 6<br />
| GL_SRC_ALPHA<br />
|-<br />
| 7<br />
| GL_ONE_MINUS_SRC_ALPHA<br />
|-<br />
| 8<br />
| GL_DST_ALPHA<br />
|-<br />
| 9<br />
| GL_ONE_MINUS_DST_ALPHA<br />
|-<br />
| 10<br />
| GL_CONSTANT_COLOR<br />
|-<br />
| 11<br />
| GL_ONE_MINUS_CONSTANT_COLOR<br />
|-<br />
| 12<br />
| GL_CONSTANT_ALPHA<br />
|-<br />
| 13<br />
| GL_ONE_MINUS_CONSTANT_ALPHA<br />
|-<br />
| 14<br />
| GL_SRC_ALPHA_SATURATE<br />
|}<br />
<br />
=== Parameter value format for command 0x0102 ===<br />
This command controls color logic op.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 3-0<br />
| Logic operation<br />
|}<br />
<br />
Logic operation values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_CLEAR<br />
|-<br />
| 1<br />
| GL_AND<br />
|-<br />
| 2<br />
| GL_AND_REVERSE<br />
|-<br />
| 3<br />
| GL_COPY<br />
|-<br />
| 4<br />
| GL_SET<br />
|-<br />
| 5<br />
| GL_COPY_INVERTED<br />
|-<br />
| 6<br />
| GL_NOOP<br />
|-<br />
| 7<br />
| GL_INVERT<br />
|-<br />
| 8<br />
| GL_NAND<br />
|-<br />
| 9<br />
| GL_OR<br />
|-<br />
| 10<br />
| GL_NOR<br />
|-<br />
| 11<br />
| GL_XOR<br />
|-<br />
| 12<br />
| GL_EQUIV<br />
|-<br />
| 13<br />
| GL_AND_INVERTED<br />
|-<br />
| 14<br />
| GL_OR_REVERSE<br />
|-<br />
| 15<br />
| GL_OR_INVERTED<br />
|}<br />
<br />
=== Parameter value format for command 0x0105 ===<br />
This command controls stencil testing.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable stencil test<br />
|-<br />
| 7-4<br />
| Stencil test function (values same as for alpha and depth tests)<br />
|-<br />
| 15-8<br />
| Stencil buffer write mask<br />
|-<br />
| 23-16<br />
| Reference value for the stencil test. Note that the test does "reference FUNC value".<br />
|-<br />
| 31-24<br />
| Mask for the stencil test.<br />
|}<br />
<br />
=== Parameter value format for command 0x0106 ===<br />
This command controls stencil buffer replacement.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Action when the stencil test fails<br />
|-<br />
| 6-4<br />
| Action when the stencil test passes but the depth test fails<br />
|-<br />
| 10-8<br />
| Action when both stencil test and depth test pass<br />
|}<br />
<br />
Action values:<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Final stencil value<br />
|-<br />
| 0<br />
| destination<br />
|-<br />
| 1<br />
| destination & ~source<br />
|-<br />
| 2<br />
| same as 1<br />
|-<br />
| 3<br />
| Weird operation.<br />
|-<br />
| 4<br />
| Weird operation. TODO: find out what it is exactly.<br />
|-<br />
| 5<br />
| destination ^ source<br />
|-<br />
| 6<br />
| Another weird operation.<br />
|-<br />
| 7<br />
| same as 4<br />
|}<br />
'destination' is the value present in the stencil buffer, 'source' is the replacement value specified in command 0x0105.<br />
<br />
=== Parameter structure for command 0x004D ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float far<br />
|-<br />
| 1<br />
| float near<br />
|}<br />
<br />
This is glDepthRange().<br />
<br />
=== Parameter structure for command 0x00E8 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0x7D-0x00<br />
| Usually value 0x00FFE000.<br />
|-<br />
| 0x7E<br />
| Usually value 0x00FFFEE6?<br />
|-<br />
| 0x7F<br />
| Usually value 0x00DCD919?<br />
|}<br />
<br />
=== Parameter structure for command 0x0112 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Setting bits 3-0 to a nonzero value allows the GPU to read from the color buffer.<br />
|-<br />
| 1<br />
| Setting bits 3-0 to a nonzero value allows the GPU to write to the color buffer.<br />
|-<br />
| 2<br />
| Setting bits 1-0 to a nonzero value allows the GPU to read from the depth/stencil buffer.<br />
|-<br />
| 3<br />
| Setting bits 1-0 to a nonzero value allows the GPU to write to the depth/stencil buffer.<br />
|}<br />
<br />
=== Entries for command 0x02C1 ===<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float, the GPU handles this as the 4th word.<br />
|-<br />
| 1<br />
| float, the GPU handles this as the 3rd word.<br />
|-<br />
| 2<br />
| float, the GPU handles this as the 2nd word.<br />
|-<br />
| 3<br />
| float, the GPU handles this as the 1st word.<br />
|}<br />
<br />
The below entry structure info is in the raw order used for the command, not the order used by the GPU.<br />
<br />
==== Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Red component<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Alpha<br />
|}<br />
<br />
==== Lighting Color Entry ====<br />
{| class="wikitable" border="1"<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| float Alpha<br />
|-<br />
| 1<br />
| float Blue component<br />
|-<br />
| 2<br />
| float Green component<br />
|-<br />
| 3<br />
| float Red component<br />
|}<br />
<br />
=== Types for command 0x02C0 ===<br />
<br />
The 0x02C0/0x02C1 is actually used as a generic way to set uniforms, regardless of what they represent. 0x02C0's parameter represents the ID of the destination GPU register (0x0 is c0, 0x1 is c1 etc). As such, the meaning of the data being sent over is entirely dependant on the shader currently in use.<br />
The values below may be "default" values used by Nintendo's openGL implementation.<br />
<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Entries per chunk<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| This specifies 16-floats for a 4x4 matrix, used for glLoadMatrix() for the projection matrix.<br />
|-<br />
| 0x04<br />
| 4<br />
| This specifies a 4x4 matrix, used for glLoadMatrix() for the model-view matrix. This is usually an identity matrix.<br />
|-<br />
| 0x08<br />
| 2<br />
| Sets the color.<br />
|-<br />
| 0x0A<br />
| 4<br />
| Specifies a 4x4 matrix, used for glLoadMatrix() for the texture matrix.(Index0)<br />
|-<br />
| 0x0E<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index1)<br />
|-<br />
| 0x11<br />
| 3<br />
| Specifies a 4x3 texture matrix.(Index2)<br />
|-<br />
| 0x14<br />
| <=30<br />
| Used to specify a 4xN matrix, where N is the total command 0x02C1 entries. This is glMultMatrix() for the model-view matrix, except the input matrix is 4xN instead of 4x4.<br />
|-<br />
| 0x4C<br />
| 4<br />
| This specifies a 4x4 float matrix.<br />
|-<br />
| 0x50, 0x53, and 0x56<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_AMBIENT?<br />
|-<br />
| 0x51, 0x54, and 0x57<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_DIFFUSE?<br />
|-<br />
| 0x52, 0x55, and 0x58<br />
| 1<br />
| This specifies the GL_LIGHT0-2 color for GL_SPECULAR?<br />
|-<br />
| 0x59<br />
| 1<br />
| Unknown, the entry data is floats converted from s32s. Usually each entry word is zeros.<br />
|-<br />
| 0x5A<br />
| 2<br />
| Color related?<br />
|-<br />
| 0x5C<br />
| 1<br />
| ?<br />
|}<br />
<br />
The matrices for types 0x00 and 0x04 use row-major order, instead of column-major order.<br />
<br />
[[Category:GPU]]</div>Subvhttps://www.3dbrew.org/w/index.php?title=Filesystem_services&diff=12741Filesystem services2015-06-02T02:37:38Z<p>Subv: </p>
<hr />
<div>[[Category:Services]]<br />
<br />
= Filesystem service "fs:USER" =<br />
You can at most have 32 FS archive handles.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version <br />
! Description<br />
! scope="col" width="400" | Required [[NCCH/Extended_Header|exheader]] access info bitmask<br />
|-<br />
| 0x000100C6<br />
|?<br />
| Dummy1<br />
| None<br />
|-<br />
| 0x040100C4<br />
|?<br />
| Control<br />
| None<br />
|-<br />
| 0x08010002<br />
|?<br />
| [[FS:Initialize|Initialize]]<br />
| None<br />
|-<br />
| 0x080201C2<br />
|?<br />
| [[FS:OpenFile|OpenFile]]<br />
| None<br />
|-<br />
| 0x08030204<br />
|?<br />
| [[FS:OpenFileDirectly|OpenFileDirectly]]<br />
| None<br />
|-<br />
| 0x08040142<br />
|?<br />
| [[FS:DeleteFile|DeleteFile]]<br />
| None<br />
|-<br />
| 0x08050244<br />
|?<br />
| [[FS:RenameFile|RenameFile]]<br />
| None<br />
|-<br />
| 0x08060142<br />
|?<br />
| [[FS:DeleteDirectory|DeleteDirectory]]<br />
| None<br />
|-<br />
| 0x08070142<br />
|?<br />
| [[FS:DeleteDirectoryRecursively|DeleteDirectoryRecursively]]<br />
| None<br />
|-<br />
| 0x08080202<br />
|?<br />
| [[FS:CreateFile|CreateFile]]<br />
| None<br />
|-<br />
| 0x08090182<br />
|?<br />
| [[FS:CreateDirectory|CreateDirectory]]<br />
| None<br />
|-<br />
| 0x080A0244<br />
|?<br />
| [[FS:RenameDirectory|RenameDirectory]]<br />
| None<br />
|-<br />
| 0x080B0102<br />
|?<br />
| [[FS:OpenDirectory|OpenDirectory]]<br />
| None<br />
|-<br />
| 0x080C00C2<br />
|?<br />
| [[FS:OpenArchive|OpenArchive]]<br />
| Each archive ID code has separate access info bitmasks, if it has any<br />
|-<br />
| 0x080D0144<br />
|?<br />
| ControlArchive<br />
| None<br />
|-<br />
| 0x080E0080<br />
|?<br />
| [[FS:CloseArchive|CloseArchive]]<br />
| None<br />
|-<br />
| 0x080F0180<br />
|?<br />
| [[FS:FormatThisUserSaveData|FormatThisUserSaveData]]<br />
| None<br />
|-<br />
| 0x08100200<br />
|?<br />
| CreateSystemSaveData<br />
| 0x4, for when the input saveID doesn't match the exheader saveID<br />
|-<br />
| 0x08110040<br />
|?<br />
| DeleteSystemSaveData<br />
| 0x1004, for when the input saveID doesn't match the exheader saveID<br />
|-<br />
| 0x08120080<br />
|?<br />
| GetFreeBytes<br />
| None<br />
|-<br />
| 0x08130000<br />
|?<br />
| GetCardType<br />
| 0x1017<br />
|-<br />
| 0x08140000<br />
|?<br />
| [[FS:GetSdmcArchiveResource|GetSdmcArchiveResource]]<br />
| None<br />
|-<br />
| 0x08150000<br />
|?<br />
| [[FS:GetNandArchiveResource|GetNandArchiveResource]]<br />
| 0x1007<br />
|-<br />
| 0x08160000<br />
|?<br />
| GetSdmcFatfsError<br />
| 0x2<br />
|-<br />
| 0x08170000<br />
|?<br />
| [[FS:IsSdmcDetected|IsSdmcDetected]]<br />
| None<br />
|-<br />
| 0x08180000<br />
|?<br />
| [[FS:IsSdmcWritable|IsSdmcWritable]]<br />
| None<br />
|-<br />
| 0x08190042<br />
|?<br />
| GetSdmcCid<br />
| 0x2<br />
|-<br />
| 0x081A0042<br />
|?<br />
| GetNandCid<br />
| 0x2<br />
|-<br />
| 0x081B0000<br />
|?<br />
| GetSdmcSpeedInfo<br />
| 0x2<br />
|-<br />
| 0x081C0000<br />
|?<br />
| GetNandSpeedInfo<br />
| 0x2<br />
|-<br />
| 0x081D0042<br />
|?<br />
| GetSdmcLog<br />
| 0x2<br />
|-<br />
| 0x081E0042<br />
|?<br />
| GetNandLog<br />
| 0x2<br />
|-<br />
| 0x081F0000<br />
|?<br />
| ClearSdmcLog<br />
| 0x2<br />
|-<br />
| 0x08200000<br />
|?<br />
| ClearNandLog<br />
| 0x2<br />
|-<br />
| 0x08210000<br />
|?<br />
| CardSlotIsInserted<br />
| 0x1017<br />
|-<br />
| 0x08220000<br />
|?<br />
| CardSlotPowerOn<br />
| 0x2<br />
|-<br />
| 0x08230000<br />
|?<br />
| CardSlotPowerOff<br />
| 0x2<br />
|-<br />
| 0x08240000<br />
|?<br />
| CardSlotGetCardIFPowerStatus<br />
| 0x2<br />
|-<br />
| 0x08250040<br />
|?<br />
| CardNorDirectCommand<br />
| 0x2<br />
|-<br />
| 0x08260080<br />
|?<br />
| CardNorDirectCommandWithAddress<br />
| 0x2<br />
|-<br />
| 0x08270082<br />
|?<br />
| CardNorDirectRead<br />
| 0x2<br />
|-<br />
| 0x082800C2<br />
|?<br />
| CardNorDirectReadWithAddress<br />
| 0x2<br />
|-<br />
| 0x08290082<br />
|?<br />
| CardNorDirectWrite<br />
| 0x2<br />
|-<br />
| 0x082A00C2<br />
|?<br />
| CardNorDirectWriteWithAddress<br />
| 0x2<br />
|-<br />
| 0x082B00C2<br />
|?<br />
| CardNorDirectRead_4xIO<br />
| 0x2<br />
|-<br />
| 0x082C0082<br />
|?<br />
| CardNorDirectCpuWriteWithoutVerify<br />
| 0x2<br />
|-<br />
| 0x082D0040<br />
|?<br />
| CardNorDirectSectorEraseWithoutVerify<br />
| 0x2<br />
|-<br />
| 0x082E0040<br />
|?<br />
| [[FS:GetProductInfo|GetProductInfo]]<br />
| 0x1005<br />
|-<br />
| 0x082F0040<br />
|?<br />
| [[FS:GetProgramLaunchInfo|GetProgramLaunchInfo]]<br />
| 0x1005<br />
|-<br />
| 0x08300182<br />
|?<br />
| CreateExtSaveData<br />
| 0xC, for when the input extdataID doesn't match the exheader extdataID<br />
|-<br />
| 0x08310180<br />
|?<br />
| CreateSharedExtSaveData<br />
| 0x1005<br />
|-<br />
| 0x08320102<br />
|?<br />
| [[FS:ReadExtSaveDataIcon|ReadExtSaveDataIcon]]<br />
| 0x100D, for when the input extdataID doesn't match the exheader extdataID<br />
|-<br />
| 0x08330082<br />
|?<br />
| [[FS:EnumerateExtSaveData|EnumerateExtSaveData]]<br />
| 0x1005<br />
|-<br />
| 0x08340082<br />
|?<br />
| EnumerateSharedExtSaveData<br />
| 0x1005<br />
|-<br />
| 0x08350080<br />
|?<br />
| DeleteExtSaveData<br />
| 0x100D, for when the input extdataID doesn't match the exheader extdataID<br />
|-<br />
| 0x08360080<br />
|?<br />
| DeleteSharedExtSaveData<br />
| 0x1005<br />
|-<br />
| 0x08370040<br />
|?<br />
| SetCardSpiBaudRate<br />
| 0x2<br />
|-<br />
| 0x08380040<br />
|?<br />
| SetCardSpiBusMode<br />
| 0x2<br />
|-<br />
| 0x08390000<br />
|?<br />
| SendInitializeInfoTo9<br />
| None<br />
|-<br />
| 0x083A0100<br />
|?<br />
| GetSpecialContentIndex<br />
| 0x1005<br />
|-<br />
| 0x083B00C2<br />
|?<br />
| GetLegacyRomHeader<br />
| 0x1015<br />
|-<br />
| 0x083C00C2<br />
|?<br />
| GetLegacyBannerData<br />
| 0x1015<br />
|-<br />
| 0x083D0100<br />
|?<br />
| CheckAuthorityToAccessExtSaveData<br />
| 0x44<br />
|-<br />
| 0x083E00C2<br />
|?<br />
| QueryTotalQuotaSize<br />
| None<br />
|-<br />
| 0x083F00C0<br />
|?<br />
| GetExtDataBlockSize<br />
| None<br />
|-<br />
| 0x08400040<br />
|?<br />
| AbnegateAccessRight<br />
|?<br />
|-<br />
| 0x08410000<br />
|?<br />
| DeleteSdmcRoot<br />
| 0x1005<br />
|-<br />
| 0x08420040<br />
|?<br />
| DeleteAllExtSaveDataOnNand<br />
| 0x1005<br />
|-<br />
| 0x08430000<br />
|?<br />
| [[FS:InitializeCtrFileSystem|InitializeCtrFileSystem]]<br />
| None<br />
|-<br />
| 0x08440000<br />
|?<br />
| CreateSeed<br />
| 0x2<br />
|-<br />
| 0x084500C2<br />
|?<br />
| [[FS:GetFormatInfo|GetFormatInfo]]<br />
|?<br />
|-<br />
| 0x08460102<br />
|?<br />
| GetLegacyRomHeader2<br />
| 0x1015<br />
|-<br />
| 0x08470180<br />
|?<br />
| FormatCtrCardUserSaveData<br />
| 0x6<br />
|-<br />
| 0x08480042<br />
|?<br />
| GetSdmcCtrRootPath<br />
| 0x100D<br />
|-<br />
| 0x08490040<br />
|?<br />
| GetArchiveResource<br />
|?<br />
|-<br />
| 0x084A0002<br />
|?<br />
| ExportIntegrityVerificationSeed<br />
| 0x4000<br />
|-<br />
| 0x084B0002<br />
|?<br />
| ImportIntegrityVerificationSeed<br />
| 0x4000<br />
|-<br />
| 0x084C0242<br />
|?<br />
| [[FS:FormatSaveData|FormatSaveData]]<br />
| 0x6, in some cases this write isn't needed however<br />
|-<br />
| 0x084D0102<br />
|?<br />
| GetLegacySubBannerData<br />
| 0x1015<br />
|-<br />
| 0x084E0342<br />
|?<br />
| [[FS:UpdateSha256Context|UpdateSha256Context]]<br />
| 0x5<br />
|-<br />
| 0x084F0102<br />
|?<br />
| ReadSpecialFile<br />
| None<br />
|-<br />
| 0x08500040<br />
|?<br />
| GetSpecialFileSize<br />
| None<br />
|-<br />
| 0x08510242<br />
| [[3.0.0-5]]<br />
| [[FS:CreateExtSaveData|CreateExtSaveData]]<br />
| Shared extdata: 0x101005. Regular extdata in certain cases: 0xC<br />
|-<br />
| 0x08520100<br />
| [[3.0.0-5]]<br />
| DeleteExtSaveData (u32 flags, u64 extdataID)<br />
| Shared extdata: 0x101005. Regular extdata in certain cases: 0x10100D<br />
|-<br />
| 0x08530142<br />
| [[3.0.0-5]]<br />
| ReadExtSaveDataIcon<br />
| 0x10100D (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x085400C0<br />
| [[3.0.0-5]]<br />
| GetExtDataBlockSize?<br />
| 0x10100D (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x08550102<br />
| [[3.0.0-5]]<br />
| EnumerateExtSaveData<br />
| 0x101005<br />
|-<br />
| 0x08560200<br />
| [[3.0.0-5]]<br />
| FsCreateSystemSaveData?<br />
| 0x4 (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x08570080<br />
| [[3.0.0-5]]<br />
| DeleteSystemSaveData<br />
| 0x1004 (this doesn't apply in certain cases, however)<br />
|-<br />
| 0x08580000<br />
| [[3.0.0-5]]<br />
| [[FS:GetMovableSedHashedKeyYRandomData|GetMovableSedHashedKeyYRandomData]]<br />
| 0x2004<br />
|-<br />
| 0x08590200<br />
| [[3.0.0-5]]<br />
| SetMovableSedHashedKeyYRandomData?<br />
| 0x2004<br />
|-<br />
| 0x085A00C0<br />
| [[3.0.0-5]]<br />
| SetArchivePriority(u64 ID,u32 priority)<br />
| None<br />
|-<br />
| 0x085B0080<br />
| [[3.0.0-5]]<br />
| GetArchivePriority(u64 ID,u32 *priority)<br />
| None<br />
|-<br />
| 0x085C00C0<br />
| [[3.0.0-5]]<br />
| SetCtrCardLatencyParameter<br />
| 0xE<br />
|-<br />
| 0x085D0180<br />
| [[3.0.0-5]]<br />
|?<br />
| 0x100001<br />
|-<br />
| 0x085E0040<br />
| [[3.0.0-5]]<br />
| ResetCardCompatibilityParameter<br />
| 0xE<br />
|-<br />
| 0x085F0040<br />
| [[3.0.0-5]]<br />
| SwitchCleanupInvalidSaveData<br />
| 0x12004<br />
|-<br />
| 0x08600042<br />
| [[3.0.0-5]]<br />
| [[FS:EnumerateSystemSaveData|EnumerateSystemSaveData]]<br />
| 0x2004<br />
|-<br />
| 0x08610042<br />
| [[3.0.0-5]]<br />
| InitializeWithSdkVersion<br />
| None<br />
|-<br />
| 0x08620040<br />
| [[3.0.0-5]]<br />
| SetPriority<br />
| None<br />
|-<br />
| 0x08630000<br />
| [[3.0.0-5]]<br />
| GetPriority<br />
| None<br />
|-<br />
| 0x08640000<br />
| [[3.0.0-5]]<br />
| Obsoleted_4_0_GetNandInfo <br />
| Stubbed, this returns an error<br />
|-<br />
| 0x08650140<br />
| [[4.0.0-7]]<br />
| SetSaveDataSecureValue, this is used with [[Anti Savegame Restore]].<br />
| 0x121004 (in certain cases this doesn't apply, however)<br />
|-<br />
| 0x086600C0<br />
| [[4.0.0-7]]<br />
| GetSaveDataSecureValue, this is used with [[Anti Savegame Restore]].<br />
| 0x121004 (in certain cases this doesn't apply, however)<br />
|-<br />
| 0x086700C4<br />
| [[4.0.0-7]]<br />
| ControlSecureSave<br />
| 0x121004<br />
|-<br />
| 0x08680000<br />
| [[4.0.0-7]]<br />
| GetMediaType, This loads the u8 mediatype for the current application from already initialized state, this u8 was originally loaded from the same data used by [[FS:GetProgramLaunchInfo|GetProgramLaunchInfo]]. This then writes the u8 to response-word[2]. This is used with [[Anti Savegame Restore]]<br />
| None<br />
|-<br />
| 0x08690000<br />
| [[4.0.0-7]]<br />
| Obsoleted_4_0_GetNandEraseCount Stubbed, this returns an error.<br />
| None<br />
|-<br />
| 0x086A0082<br />
| [[4.0.0-7]]<br />
| ReadNandReport This is a wrapper for [[Filesystem_services_PXI|FSPXI]] command 0x00550082.<br />
| None<br />
|-<br />
| 0x086B00C2<br />
|?<br />
|?<br />
| 00121004<br />
|-<br />
| 0x086C00C2<br />
|?<br />
|?<br />
| 00121004<br />
|-<br />
| 0x086D0040<br />
|?<br />
|?<br />
| 00020004<br />
|-<br />
| 0x086E00C0<br />
|?<br />
|?<br />
|None?<br />
|-<br />
| 0x086F0040<br />
|?<br />
|?<br />
| 0xE<br />
|-<br />
| 0x087000C2<br />
|?<br />
|?<br />
|None?<br />
|-<br />
| 0x08710100<br />
|?<br />
|?<br />
| 0xC<br />
|-<br />
| 0x087201C0<br />
|?<br />
|?<br />
| 00080004<br />
|-<br />
| 0x087300C0<br />
|?<br />
|?<br />
| 00080004<br />
|-<br />
| 0x08740000<br />
|?<br />
|?<br />
| 00080004<br />
|-<br />
| 0x08750140<br />
|?<br />
|?<br />
|None?<br />
|-<br />
| 0x087600C0<br />
|?<br />
|?<br />
|None?<br />
|-<br />
| 0x08770100<br />
|?<br />
|?<br />
|?<br />
|-<br />
| 0x087800C0<br />
|?<br />
|?<br />
|?<br />
|-<br />
| 0x087900C2<br />
| ?<br />
| Same as GetLegacyBannerData, except for the last parameter this passes u8 value 0x1 instead of 0x0, for the FSPXI command.<br />
| 0x00101015<br />
|-<br />
| 0x087A....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| ?<br />
| 0x00200000<br />
|-<br />
| 0x087B....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Wrapper for the code internally used for command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x087C....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x087D0000<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Writes an u32 from state to cmdreply[2]. Probably the total number of titles in the SEEDDB?<br />
| 0x00200000<br />
|-<br />
| 0x087E0042<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>. Writes a list of titleIDs to the outbuf, this is for titles with content-lock-seed(s) stored in SEEDDB. (u32 total_titleids_probably, ((Size<<4) <nowiki>|</nowiki> 12), outbufptr)<br />
| 0x00200000<br />
|-<br />
| 0x087F....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| ?<br />
| 0x00200000<br />
|-<br />
| 0x0880....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x0881....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x0882....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x08830000<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Writes an output value to cmdreply[2].<br />
| 0x00200000<br />
|-<br />
| 0x0884....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| Eventually calls same code as command <0x087A....>.<br />
| 0x00200000<br />
|-<br />
| 0x0885....<br />
| [[9.6.0-24|9.6.0-X]]<br />
| ?<br />
| 0x00200000<br />
|}<br />
<br />
Note: The question marks from Dummy1 to GetSpecialFileSize on the "available since system version" field are mainly there because I think that most of these are necessary for the main system to function, so theoretically that would mean that since the creation of the 3DS these were available, or since launch if that makes more sense. But because of the peculiar nature of some of the functions, they will remain question marks until they can be confirmed 100%.<br />
<br />
When access rights are required for a command, at least one of the bits in the process access info specified in the above table for the command must be set. Error 0xD9004676 is returned when a process attempts to use a command which it doesn't have access rights for the command. The exheader access info field is all zero's for most applications. Note that the permissions listed in the above table is for system-version v2.x, therefore permission bit(s) added with newer FIRM may be missing from this.<br />
<br />
Each session for fs:USER has separate permissions, initially these are set to all zero's for new fs:USER sessions. The permissions/etc for fs:USER sessions are initialized via [[FS:Initialize]](loaded from the user process exheader).<br />
<br />
=File service=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x000100C6<br />
| Dummy1<br />
|-<br />
| 0x040100C4<br />
| Control<br />
|-<br />
| 0x08010100<br />
| OpenSubFile<br />
|-<br />
| 0x080200C2<br />
| [[FSFile:Read|Read]]<br />
|-<br />
| 0x08030102<br />
| [[FSFile:Write|Write]]<br />
|-<br />
| 0x08040000<br />
| [[FSFile:GetSize|GetSize]]<br />
|-<br />
| 0x08050080<br />
| [[FSFile:SetSize|SetSize]]<br />
|-<br />
| 0x08060000<br />
| GetAttributes<br />
|-<br />
| 0x08070040<br />
| SetAttributes<br />
|-<br />
| 0x08080000<br />
| [[FSFile:Close|Close]]<br />
|-<br />
| 0x08090000<br />
| Flush<br />
|-<br />
| 0x080A0040<br />
| SetPriority<br />
|-<br />
| 0x080B0000<br />
| GetPriority<br />
|-<br />
| 0x080C0000<br />
| OpenLinkFile<br />
|-<br />
| 0x0C010100<br />
| ?<br />
|}<br />
<br />
=Directory service=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Available since system version<br />
! Description<br />
|-<br />
| 0x000100C6<br />
| [[1.0.0-0]]<br />
| Dummy1<br />
|-<br />
| 0x040100C4<br />
| [[1.0.0-0]]<br />
| Control<br />
|-<br />
| 0x08010042<br />
| [[1.0.0-0]]<br />
| [[FSDir:Read|Read]]<br />
|-<br />
| 0x08020000<br />
| [[1.0.0-0]]<br />
| [[FSDir:Close|Close]]<br />
|-<br />
| 0x08030040<br />
| ?<br />
| SetPriority<br />
|-<br />
| 0x08040000<br />
| ?<br />
| GetPriority<br />
|}<br />
<br />
= Filesystem service "fs:LDR" =<br />
This service is identical to fs:USER, except [[FS:OpenArchive]] archive 0x2345678E can only be accessed with fs:LDR.<br />
<br />
= ProgramRegistry service "fs:REG" =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x000100C6<br />
| Dummy1<br />
|-<br />
| 0x040103C0<br />
| [[FSReg:Register|Register]]<br />
|-<br />
| 0x04020040<br />
| [[FSReg:Unregister|Unregister]]<br />
|-<br />
| 0x040300C0<br />
| GetProgramInfo<br />
|-<br />
| 0x04040100<br />
| LoadProgram<br />
|-<br />
| 0x04050080<br />
| UnloadProgram<br />
|-<br />
| 0x04060080<br />
| CheckHostLoadId<br />
|}<br />
<br />
Only one session can be opened for this service at a time, hence no other processes can use this due to [[Process_Manager_Services|pm-module]] using this.<br />
<br />
=SEEDDB=<br />
With [[9.6.0-24|9.6.0-X]] new [[System_SaveData]] with saveID 0001000F was added, this seems to be handled by FS-module itself, probably via the new service-cmds added to fsuser. [[Home Menu]] and [[NIM_Services|NIM]] module have access to those commands.<br />
<br />
The SEEDDB savedata contains the title-unique seed-data used for the new [[NCCH]] keyY generation added with FIRM [[9.6.0-24|9.6.0-X]].<br />
<br />
=Errors=<br />
See [[Filesystem_services_PXI]].</div>Subvhttps://www.3dbrew.org/w/index.php?title=FS:CreateExtSaveData&diff=12740FS:CreateExtSaveData2015-06-02T02:36:33Z<p>Subv: Created page with "=Request= {| class="wikitable" border="1" |- ! Index Word ! Description |- | 0 | Header code [0x08510242] |- | 1 | Media type (NAND / SDMC) |- | 2 | Low word of the saveid |- |..."</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x08510242]<br />
|-<br />
| 1<br />
| Media type (NAND / SDMC)<br />
|-<br />
| 2<br />
| Low word of the saveid<br />
|-<br />
| 3<br />
| High word of the saveid<br />
|-<br />
| 4<br />
| Unknown<br />
|-<br />
| 5<br />
| Unknown<br />
|-<br />
| 6<br />
| Unknown<br />
|-<br />
| 7<br />
| Unknown<br />
|-<br />
| 8<br />
| Unknown<br />
|-<br />
| 9<br />
| Size of the SMDH icon<br />
|-<br />
| 10<br />
| (SMDH Size << 4) <nowiki>|</nowiki> 0x0000000A<br />
|-<br />
| 11<br />
| Pointer to the SMDH buffer<br />
|}<br />
<br />
=Description=<br />
This creates the ExtSaveData with the specified saveid in the specified media type. It stores the SMDH as "icon" in the root of the created directory. For more information see [[Extdata#VSXE_Filesystem_structure]]</div>Subvhttps://www.3dbrew.org/w/index.php?title=Services_API&diff=12733Services API2015-06-01T20:53:16Z<p>Subv: </p>
<hr />
<div>Nintendo provides application developers with an API, which communicate with certain services. Services, in this sense, are system processes running in the background which wait for incoming requests. When a process wants to communicate with a service, it first needs to get a handle to the named service, and then it can communicate with the service via interprocess communication. Each service has a name up to 8 characters, for example "nim:u".<br />
<br />
Handles for services are retrieved from the service manager port, "srv:". Services are an abstraction of ports, they operate the same way except regular ports can have their handles retrieved directly from a SVC.<br />
<br />
For a description of how commands and arguments are passed to services, see [[IPC Command Structure]].<br />
<br />
List of services:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Old3ds<br />
! Services<br />
! Service names<br />
! scope="col" width="200" | Notes<br />
|-<br />
| style="background: green" | Yes<br />
| [[Filesystem services]]<br />
| fs:USER, fs:LDR, fs:REG<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Process Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[PXI Services]]<br />
| PxiFS0, PxiFS1, PxiFSB, PxiFSR, PxiPM, pxi:am9, pxi:dev, pxi:mc, pxi:ps9<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Application Manager Services]]<br />
| am:app, am:net, am:u, am:sys, am:pipe<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Process Manager Services]]<br />
| pm:app, pm:dbg<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[NIM Services]]<br />
| nim:aoc, nim:ndm, nim:s, nim:u<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Config Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[NS|NS and APT Services]]<br />
| ns:s, ns:p, ns:c, APT:A, APT:S, APT:U<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[RO Services]]<br />
| ldr:ro<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[NDM Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[CSND Services]]<br />
| csnd:SND<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Camera Services]]<br />
| cam:u, y2r:u, cam:s, cam:c, cam:q (New3DS only)<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Codec Services]]<br />
| cdc:HID, cdc:MIC, cdc:CSN, cdc:DSP, cdc:LGY, cdc:CHK<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[DSP Services]]<br />
| dsp::DSP<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[GSP Services]]<br />
| gsp::Lcd, gsp::Gpu<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[BOSS Services]]<br />
| boss:U<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[IR Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[I2C Services]]<br />
| i2c::MCU, i2c::CAM, i2c::LCD, i2c::DEB, i2c::HID, i2c::IR, i2c::EEP<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[GPIO Services]]<br />
| gpio:CDC, gpio:MCU, gpio:HID, gpio:NWM, gpio:IR<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[HID Services]]<br />
| hid:NFC, hid:QTM, hid:SPVR, hid:USER <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[PTM Services]]<br />
| ptm:gets, ptm:play, ptm:s, ptm:sets, ptm:sysm, ptm:u<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[NWM Services]]<br />
| nwm::UDS<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[HTTP Services]]<br />
| http:C<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[SSL Services]]<br />
| ssl:C<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Socket Services]]<br />
| soc:P, soc:U<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[AC Services]]<br />
| ac:i, ac:u<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Friend Services]]<br />
| frd:a, frd:u<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[News Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[PDN Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[SPI Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[Loader Services]]<br />
| <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[MCU Services]]<br />
| mcu::CAM, mcu::GPU, mcu::HID, mcu::RTC, mcu::SND, mcu::NWM, mcu::HWC, mcu::PLS, mcu::CDC<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[MIC Services]]<br />
| mic:u<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[ACT Services]]<br />
| act:a, act:u<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[NFC Services]]<br />
| <br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[MVD Services]]<br />
| <br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[QTM Services]]<br />
| <br />
|<br />
|}<br />
<br />
List of PXI services:<br />
* [[Filesystem services PXI]]<br />
* [[Process Services PXI]]<br />
* [[Application Manager Services PXI]]<br />
* [[Process Manager Services PXI]]<br />
* [[Development Services PXI]]<br />
* [[Gamecard Services PXI]]<br />
* [[Legacy FIRM PXI]] (TWL_FIRM/AGB_FIRM)<br />
<br />
List of ports:<br />
* [[ErrDisp]]<br />
* [[Services]]<br />
<br />
<br />
See [[Error codes]].</div>Subvhttps://www.3dbrew.org/w/index.php?title=CRO0&diff=12732CRO02015-06-01T18:58:21Z<p>Subv: </p>
<hr />
<div>[[Category:File formats]]<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x80<br />
| SHA-256 hash-table, verified by [[CRR0|CRR]]<br />
|-<br />
| 0x80<br />
| 0x04<br />
| Magic "CRO0"<br />
|-<br />
| 0x84<br />
| 0x04<br />
| Name offset<br />
|-<br />
| 0x88<br />
| 0x04<br />
| Next loaded CRO pointer, set by RO during loading (Usually zero when the CRO is being loaded)<br />
|-<br />
| 0x8C<br />
| 0x04<br />
| Previous loaded CRO pointer, set by RO during loading<br />
|-<br />
| 0x90<br />
| 0x04<br />
| File size<br />
|-<br />
| 0x94<br />
| 0x18<br />
| Unknown<br />
|-<br />
| 0xAC<br />
| 0x04<br />
| "Segment offset", symbols are loaded relative to this. Probably filled by dynamic linker, set to 0xFFFFFFFF in file.<br />
|-<br />
| 0xB0<br />
| 0x04<br />
| Code offset<br />
|-<br />
| 0xB4<br />
| 0x04<br />
| Code size<br />
|-<br />
| 0xB8<br />
| 0x04<br />
| unk1 offset<br />
|-<br />
| 0xBC<br />
| 0x04<br />
| unk1 size<br />
|-<br />
| 0xC0<br />
| 0x04<br />
| Module Name offset<br />
|-<br />
| 0xC4<br />
| 0x04<br />
| Module Name size<br />
|-<br />
| 0xC8<br />
| 0x04<br />
| Segment Table offset<br />
|-<br />
| 0xCC<br />
| 0x04<br />
| Segment Table num (size = num*12)<br />
|-<br />
| 0xD0<br />
| 0x04<br />
| Export Table offset<br />
|-<br />
| 0xD4<br />
| 0x04<br />
| Export Table num (size = num * 8)<br />
|-<br />
| 0xD8<br />
| 0x04<br />
| unk3 offset<br />
|-<br />
| 0xDC<br />
| 0x04<br />
| unk3 num<br />
|-<br />
| 0xE0<br />
| 0x04<br />
| Export Strings offset<br />
|-<br />
| 0xE4<br />
| 0x04<br />
| Export Strings size<br />
|-<br />
| 0xE8<br />
| 0x04<br />
| Export Tree offset (fast lookups based on strlen)<br />
|-<br />
| 0xEC<br />
| 0x04<br />
| Export Tree num (size = num * 8)<br />
|-<br />
| 0xF0<br />
| 0x04<br />
| unk4 offset<br />
|-<br />
| 0xF4<br />
| 0x04<br />
| unk4 num<br />
|-<br />
| 0xF8<br />
| 0x04<br />
| Import Patches offset<br />
|-<br />
| 0xFC<br />
| 0x04<br />
| Import Patches num (size = num * 12)<br />
|-<br />
| 0x100<br />
| 0x04<br />
| Import Table 1 offset<br />
|-<br />
| 0x104<br />
| 0x04<br />
| Import Table 1 num (size = num * 8)<br />
|-<br />
| 0x108<br />
| 0x04<br />
| Import Table 2 offset<br />
|-<br />
| 0x10C<br />
| 0x04<br />
| Import Table 2 num (size = num * 8)<br />
|-<br />
| 0x110<br />
| 0x04<br />
| Import Table 3 offset<br />
|-<br />
| 0x114<br />
| 0x04<br />
| Import Table 3 num (size = num * 8)<br />
|-<br />
| 0x118<br />
| 0x04<br />
| Import Strings offset<br />
|-<br />
| 0x11C<br />
| 0x04<br />
| Import Strings size<br />
|-<br />
| 0x120<br />
| 0x04<br />
| unk8 offset<br />
|-<br />
| 0x124<br />
| 0x04<br />
| unk8 num<br />
|-<br />
| 0x128<br />
| 0x04<br />
| Relocation Patches offset<br />
|-<br />
| 0x12C<br />
| 0x04<br />
| Relocation Patches num (size = num * 12)<br />
|-<br />
| 0x130<br />
| 0x04<br />
| unk9 offset<br />
|-<br />
| 0x134<br />
| 0x04<br />
| unk9 num<br />
|}<br />
<br />
Segment offset (4 bytes)<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-3<br />
| Segment index for table<br />
|-<br />
| 4-31<br />
| Offset into segment<br />
|}<br />
<br />
Segment Table entry (12 bytes)<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Segment offset <br />
|-<br />
| 0x4<br />
| 0x4<br />
| Segment size<br />
|-<br />
| 0x8<br />
| 0x4<br />
| Segment id (0, 1, 2..)<br />
|}<br />
<br />
Export Table entry (8 bytes)<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Name offset<br />
|-<br />
| 0x4<br />
| 0x4<br />
| "Segment offset" for export<br />
|}<br />
<br />
Import Table entry (8 bytes)<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Name offset<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Offset of the head of a linear list that contains the patches for this import<br />
|}<br />
<br />
Patch entry (12 bytes)<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| "Segment offset" for output.<br />
|-<br />
| 0x4<br />
| 0x1<br />
| Patch type (0=nothing/ignore, 2=38=write u32 absolute (base+X), 3=write u32 relative (base+X-in_ptr), 10=THUMB branch, 28=ARM32 branch, 29=modify ARM32 branch offset, 42=write u32 relative (((signed int)base*2)/2+X-in_ptr), otherwise err)<br />
|-<br />
| 0x5<br />
| 0x1<br />
| Non-zero if last entry.<br />
|-<br />
| 0x6<br />
| 0x1<br />
| 1 is written to last entry if all symbols loaded successfully.<br />
|-<br />
| 0x7<br />
| 0x1<br />
| Unknown<br />
|-<br />
| 0x8<br />
| 0x4<br />
| X (00's in file, probably set by dynamic linker)<br />
|}<br />
<br />
ARM32 branch instruction is constructed as follows:<br />
If X > 0x2000000 or X < 0xFE000000, then skip.<br />
If (X&1) == 1 then write "b +4" (nop).<br />
Else write as normal.<br />
<br />
----<br />
<br />
CRO with extension .cro is used for "DLLs". CRS with extension .crs can be used for storing "DLL" symbols as well. The end of the file is aligned to a 0x1000-byte boundary with 0xCC bytes.<br />
CRO0 files are usually stored under "romfs:/cro/".<br />
<br />
The first hash-table entry hashes the 0x100-byte header following the hash-table. The following hash-table entries hash the sections specified in the header.<br />
<br />
When the RO module loads the entire CRO into process memory(mapped in the 0x00100000-0x04000000 region), it modifies the mapped CRO data. The magic field is also changed to "FIXD".<br />
<br />
Upon loading, the RO module will look for symbol "__aeabi_atexit" or "nnroAeabiAtexit_".<br />
<br />
For dumping symbols and loading a CRO into IDA, see [https://github.com/plutooo/ctr/].</div>Subv