https://www.3dbrew.org/w/api.php?action=feedcontributions&user=Xerpi&feedformat=atom
3dbrew - User contributions [en]
2024-03-29T13:03:20Z
User contributions
MediaWiki 1.35.8
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20814
SPI Registers
2018-08-18T07:03:27Z
<p>Xerpi: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-5<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
When the transfer is finished, a 0 has to be written to this register.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Services&diff=17780
GPIO Services
2016-07-19T12:01:47Z
<p>Xerpi: /* GPIO Services */</p>
<hr />
<div>[[Category:Services]]<br />
= GPIO Service Names =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Service name<br />
! Permitted interrupts bitmasks<br />
|-<br />
| gpio:CDC<br />
| 0x48<br />
|-<br />
| gpio:MCU<br />
| 0x48020<br />
|-<br />
| gpio:HID<br />
| 0x4301<br />
|-<br />
| gpio:NWM<br />
| 0x40020<br />
|-<br />
| gpio:IR<br />
| 0xEC0<br />
|-<br />
| gpio:NFC<br />
| 0x13000<br />
|-<br />
| gpio:QTM<br />
| 0x20000<br />
|}<br />
<br />
For the mapping between interrupts bitmasks and IRQs see: [[GPIO:BindInterrupt#Supported_values]].<br />
<br />
The commands for these services are identical.<br />
<br />
= GPIO Services =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
! Uses [[GPIO_Registers|GPIO Regs]]<br />
|-<br />
| 0x0001....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x00020080<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x0003....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x00040080<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0005....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x00060080<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x00070040<br />
| GetIRGPIO(u32 unk1,u32* ret)<br />
| 0x10147000, 0x10147010, 0x10147014, 0x10147020, 0x10147028<br />
|-<br />
| 0x00080080<br />
| SetIRGPIO(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147014, 0x10147020, 0x10147028<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
| None<br />
|-<br />
| 0x000A0042<br />
| [[GPIO:UnbindInterrupt|UnbindInterrupt]]<br />
| None<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO:BindInterrupt&diff=17779
GPIO:BindInterrupt
2016-07-19T12:01:44Z
<p>Xerpi: /* Interrupts binded by modules */</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x00090082]<br />
|-<br />
| 1<br />
| u32, interrupt bitmask<br />
|-<br />
| 2<br />
| s32, priority<br />
|-<br />
| 3<br />
| Must be value [[IPC#Message_Structure|0x00000000]], otherwise error 0xD9001830<br />
|-<br />
| 4<br />
| Handle syncObject<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 binds an interrupt in gpio-module's [[NCCH/Extended Header#ARM11_Kernel_Capabilities|interrupt ACL]] to the specified syncObject (using [[SVC|svcBindInterrupt]]).<br />
<br />
=Supported values=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bitmask<br />
! Interrupt<br />
|-<br />
| 0x2<br />
| 0x63<br />
|-<br />
| 0x4<br />
| 0x60<br />
|-<br />
| 0x8<br />
| 0x64<br />
|-<br />
| 0x10<br />
| 0x66<br />
|-<br />
| 0x40<br />
| 0x68<br />
|-<br />
| 0x80<br />
| 0x69<br />
|-<br />
| 0x100<br />
| 0x6A<br />
|-<br />
| 0x200<br />
| 0x6B<br />
|-<br />
| 0x400<br />
| 0x6C<br />
|-<br />
| 0x800<br />
| 0x6D<br />
|-<br />
| 0x1000<br />
| 0x6E<br />
|-<br />
| 0x2000<br />
| 0x6F<br />
|-<br />
| 0x4000<br />
| 0x70<br />
|-<br />
| 0x8000<br />
| 0x71<br />
|-<br />
| 0x10000<br />
| 0x72<br />
|-<br />
| 0x20000<br />
| 0x73<br />
|}<br />
<br />
See also [[ARM11 Interrupts]].<br />
<br />
=Interrupts binded by modules=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Module<br />
! Binded interrupts (bitmask)<br />
|-<br />
| [[Codec_Services|cdc]]<br />
| 0x8<br />
|-<br />
| [[HID_Services|hid]]<br />
| 0x100<br />
|-<br />
| [[IR_Services|ir]]<br />
| 0x40<br />
|-<br />
| [[MCU_Services|mcu]]<br />
| 0x8000<br />
|}<br />
<br />
See [[GPIO:BindInterrupt#Supported_values]] for the bitmask <-> IRQ number correspondence table.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO:BindInterrupt&diff=17778
GPIO:BindInterrupt
2016-07-19T11:43:39Z
<p>Xerpi: /* Interrupts binded by modules */</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x00090082]<br />
|-<br />
| 1<br />
| u32, interrupt bitmask<br />
|-<br />
| 2<br />
| s32, priority<br />
|-<br />
| 3<br />
| Must be value [[IPC#Message_Structure|0x00000000]], otherwise error 0xD9001830<br />
|-<br />
| 4<br />
| Handle syncObject<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 binds an interrupt in gpio-module's [[NCCH/Extended Header#ARM11_Kernel_Capabilities|interrupt ACL]] to the specified syncObject (using [[SVC|svcBindInterrupt]]).<br />
<br />
=Supported values=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bitmask<br />
! Interrupt<br />
|-<br />
| 0x2<br />
| 0x63<br />
|-<br />
| 0x4<br />
| 0x60<br />
|-<br />
| 0x8<br />
| 0x64<br />
|-<br />
| 0x10<br />
| 0x66<br />
|-<br />
| 0x40<br />
| 0x68<br />
|-<br />
| 0x80<br />
| 0x69<br />
|-<br />
| 0x100<br />
| 0x6A<br />
|-<br />
| 0x200<br />
| 0x6B<br />
|-<br />
| 0x400<br />
| 0x6C<br />
|-<br />
| 0x800<br />
| 0x6D<br />
|-<br />
| 0x1000<br />
| 0x6E<br />
|-<br />
| 0x2000<br />
| 0x6F<br />
|-<br />
| 0x4000<br />
| 0x70<br />
|-<br />
| 0x8000<br />
| 0x71<br />
|-<br />
| 0x10000<br />
| 0x72<br />
|-<br />
| 0x20000<br />
| 0x73<br />
|}<br />
<br />
See also [[ARM11 Interrupts]].<br />
<br />
=Interrupts binded by modules=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Module<br />
! Binded interrupts (bitmask)<br />
|-<br />
| [[Codec_Services|cdc]]<br />
| 0x8<br />
|-<br />
| [[HID_Services|hid]]<br />
| 0x100<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Services&diff=17777
GPIO Services
2016-07-19T11:40:30Z
<p>Xerpi: /* GPIO Services */</p>
<hr />
<div>[[Category:Services]]<br />
= GPIO Service Names =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Service name<br />
! Permitted interrupts bitmasks<br />
|-<br />
| gpio:CDC<br />
| 0x48<br />
|-<br />
| gpio:MCU<br />
| 0x48020<br />
|-<br />
| gpio:HID<br />
| 0x4301<br />
|-<br />
| gpio:NWM<br />
| 0x40020<br />
|-<br />
| gpio:IR<br />
| 0xEC0<br />
|-<br />
| gpio:NFC<br />
| 0x13000<br />
|-<br />
| gpio:QTM<br />
| 0x20000<br />
|}<br />
<br />
For the mapping between interrupts bitmasks and IRQs see: [[GPIO:BindInterrupt#Supported_values]].<br />
<br />
The commands for these services are identical.<br />
<br />
= GPIO Services =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
! Uses [[GPIO_Registers|GPIO Regs]]<br />
|-<br />
| 0x0001....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x00020080<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x0003....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x00040080<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0005....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x00060080<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x00070040<br />
| GetIRGPIO(u32 unk1,u32* ret)<br />
| 0x10147000, 0x10147010, 0x10147014, 0x10147020, 0x10147028<br />
|-<br />
| 0x0008....<br />
| SetIRGPIO(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147014, 0x10147020, 0x10147028<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
| None<br />
|-<br />
| 0x000A0042<br />
| [[GPIO:UnbindInterrupt|UnbindInterrupt]]<br />
| None<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO:BindInterrupt&diff=17776
GPIO:BindInterrupt
2016-07-19T11:35:55Z
<p>Xerpi: </p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0x00090082]<br />
|-<br />
| 1<br />
| u32, interrupt bitmask<br />
|-<br />
| 2<br />
| s32, priority<br />
|-<br />
| 3<br />
| Must be value [[IPC#Message_Structure|0x00000000]], otherwise error 0xD9001830<br />
|-<br />
| 4<br />
| Handle syncObject<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 binds an interrupt in gpio-module's [[NCCH/Extended Header#ARM11_Kernel_Capabilities|interrupt ACL]] to the specified syncObject (using [[SVC|svcBindInterrupt]]).<br />
<br />
=Supported values=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bitmask<br />
! Interrupt<br />
|-<br />
| 0x2<br />
| 0x63<br />
|-<br />
| 0x4<br />
| 0x60<br />
|-<br />
| 0x8<br />
| 0x64<br />
|-<br />
| 0x10<br />
| 0x66<br />
|-<br />
| 0x40<br />
| 0x68<br />
|-<br />
| 0x80<br />
| 0x69<br />
|-<br />
| 0x100<br />
| 0x6A<br />
|-<br />
| 0x200<br />
| 0x6B<br />
|-<br />
| 0x400<br />
| 0x6C<br />
|-<br />
| 0x800<br />
| 0x6D<br />
|-<br />
| 0x1000<br />
| 0x6E<br />
|-<br />
| 0x2000<br />
| 0x6F<br />
|-<br />
| 0x4000<br />
| 0x70<br />
|-<br />
| 0x8000<br />
| 0x71<br />
|-<br />
| 0x10000<br />
| 0x72<br />
|-<br />
| 0x20000<br />
| 0x73<br />
|}<br />
<br />
See also [[ARM11 Interrupts]].<br />
<br />
=Interrupts binded by modules=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Module<br />
! Binded interrupts bitmask<br />
|-<br />
| [[Codec_Services|cdc]]<br />
| 0x8<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Registers&diff=17775
GPIO Registers
2016-07-19T10:59:32Z
<p>Xerpi: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Address<br />
! Width<br />
! Interrupt bitmasks associated to this register<br />
|-<br />
| ??<br />
| 0x10147000<br />
| 2??<br />
| 0x1, 0x2, 0x4<br />
|-<br />
| ??<br />
| [[#0x10147010|0x10147010]]<br />
| 4<br />
| 0x8, 0x10<br />
|-<br />
| ??<br />
| 0x10147014<br />
| 2??<br />
| 0x20<br />
|-<br />
| ??<br />
| 0x10147020<br />
| 4<br />
| 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000<br />
|-<br />
| ??<br />
| 0x10147024<br />
| 4<br />
| 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000<br />
|-<br />
| ??<br />
| 0x10147028<br />
| 2??<br />
| 0x40000<br />
|}<br />
<br />
== 0x10147010 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 24<br />
| Enable/disable? GPIO interrupt 0x64 (bitmask 0x8)<br />
|-<br />
| 25<br />
| Enable/disable? GPIO interrupt 0x66 (bitmask 0x10)<br />
|}<br />
<br />
= Default values =<br />
<br />
After bootrom initialization, these are the values of the registers:<br />
<br />
{| class="wikitable" border="1"<br />
! Address<br />
! Value<br />
|-<br />
| 0x10147000<br />
| 0x0003<br />
|-<br />
| 0x10147010<br />
| 0x00000002<br />
|-<br />
| 0x10147014<br />
| 0x0000<br />
|-<br />
| 0x10147020<br />
| 0x00000DFB<br />
|-<br />
| 0x10147024<br />
| 0x00000000<br />
|-<br />
| 0x10147028<br />
| 0x0000<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Services&diff=17774
GPIO Services
2016-07-19T10:54:30Z
<p>Xerpi: /* GPIO Services */</p>
<hr />
<div>[[Category:Services]]<br />
= GPIO Service Names =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Service name<br />
! Permitted interrupts bitmasks<br />
|-<br />
| gpio:CDC<br />
| 0x48<br />
|-<br />
| gpio:MCU<br />
| 0x48020<br />
|-<br />
| gpio:HID<br />
| 0x4301<br />
|-<br />
| gpio:NWM<br />
| 0x40020<br />
|-<br />
| gpio:IR<br />
| 0xEC0<br />
|-<br />
| gpio:NFC<br />
| 0x13000<br />
|-<br />
| gpio:QTM<br />
| 0x20000<br />
|}<br />
<br />
For the mapping between interrupts bitmasks and IRQs see: [[GPIO:BindInterrupt#Supported_values]].<br />
<br />
The commands for these services are identical.<br />
<br />
= GPIO Services =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
! Uses [[GPIO_Registers|GPIO Regs]]<br />
|-<br />
| 0x0001....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x0002....<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x0003....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0004....<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0005....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0006....<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0007....<br />
| GetIRGPIO(u32 unk1,u32* ret)<br />
| 0x10147000, 0x10147010, 0x10147014, 0x10147020, 0x10147028<br />
|-<br />
| 0x0008....<br />
| SetIRGPIO(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147014, 0x10147020, 0x10147028<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
| None<br />
|-<br />
| 0x000A0042<br />
| [[GPIO:UnbindInterrupt|UnbindInterrupt]]<br />
| None<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Services&diff=17773
GPIO Services
2016-07-19T10:53:37Z
<p>Xerpi: </p>
<hr />
<div>[[Category:Services]]<br />
= GPIO Service Names =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Service name<br />
! Permitted interrupts bitmasks<br />
|-<br />
| gpio:CDC<br />
| 0x48<br />
|-<br />
| gpio:MCU<br />
| 0x48020<br />
|-<br />
| gpio:HID<br />
| 0x4301<br />
|-<br />
| gpio:NWM<br />
| 0x40020<br />
|-<br />
| gpio:IR<br />
| 0xEC0<br />
|-<br />
| gpio:NFC<br />
| 0x13000<br />
|-<br />
| gpio:QTM<br />
| 0x20000<br />
|}<br />
<br />
For the mapping between interrupts bitmasks and IRQs see: [[GPIO:BindInterrupt#Supported_values]].<br />
<br />
The commands for these services are identical.<br />
<br />
= GPIO Services =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
! Uses [[GPIO_Registers|GPIO Regs]]<br />
|-<br />
| 0x0001....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x0002....<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147020<br />
|-<br />
| 0x0003....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0004....<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0005....<br />
| ?(u32 unk1,u32* ret)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0006....<br />
| ?(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147024<br />
|-<br />
| 0x0007....<br />
| GetIRGPIO(u32 unk1,u32* ret)<br />
| 0x10147000, 0x10147010, 0x10147014, 0x10147020, 0x10147018<br />
|-<br />
| 0x0008....<br />
| SetIRGPIO(u32 unk1,u32 unk2)<br />
| 0x10147010, 0x10147014, 0x10147020, 0x10147028<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
| None<br />
|-<br />
| 0x000A0042<br />
| [[GPIO:UnbindInterrupt|UnbindInterrupt]]<br />
| None<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Services&diff=17772
GPIO Services
2016-07-19T10:28:04Z
<p>Xerpi: </p>
<hr />
<div>[[Category:Services]]<br />
= GPIO Service Names =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Service name<br />
! Permitted interrupts bitmasks<br />
|-<br />
| gpio:CDC<br />
| 0x48<br />
|-<br />
| gpio:MCU<br />
| 0x48020<br />
|-<br />
| gpio:HID<br />
| 0x4301<br />
|-<br />
| gpio:NWM<br />
| 0x40020<br />
|-<br />
| gpio:IR<br />
| 0xEC0<br />
|-<br />
| gpio:NFC<br />
| 0x13000<br />
|-<br />
| gpio:QTM<br />
| 0x20000<br />
|}<br />
<br />
For the mapping between interrupts bitmasks and IRQs see: [[GPIO:BindInterrupt#Supported_values]].<br />
<br />
The commands for these services are identical.<br />
<br />
= CDC Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00020080<br />
| void unknown_0x2(u32 unk, u32 unk)<br />
|-<br />
| 0x00040080<br />
| void unknown_0x4(u32 unk, u32 unk)<br />
|-<br />
| 0x00060080<br />
| void unknown_0x6(u32 unk, u32 unk)<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
|}<br />
<br />
= HID Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00020080<br />
| void unknown_0x2(u32 unk, u32 unk)<br />
|-<br />
| 0x00040080<br />
| void unknown_0x4(u32 unk, u32 unk)<br />
|-<br />
| 0x00060080<br />
| void unknown_0x6(u32 unk, u32 unk)<br />
|-<br />
| 0x00070040<br />
| u32 unknown_0x7(u32 unk). Parameter and return value might be some mask of the same kind?<br />
|}<br />
<br />
= I2C Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| ?(u32 unk1,u32* ret) //reads from 0x1ec47020<br />
|-<br />
| 0x0002....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0003....<br />
| ?(u32 unk1,u32* ret)<br />
|-<br />
| 0x0004....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0005....<br />
| ?(u32 unk1,u32* ret)<br />
|-<br />
| 0x0006....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0007....<br />
| GetIRGPIO(u32 unk1,u32* ret)<br />
|-<br />
| 0x0008....<br />
| SetIRGPIO(u32 unk1,u32 unk2)<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
|-<br />
| 0x000A0042<br />
| [[GPIO:UnbindInterrupt|UnbindInterrupt]]<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Services&diff=17771
GPIO Services
2016-07-19T10:25:58Z
<p>Xerpi: Add permitted interrupts bitmask</p>
<hr />
<div>[[Category:Services]]<br />
= GPIO Service Names =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Service name<br />
! Permitted interrupts bitmasks<br />
|-<br />
! gpio:CDC<br />
! 0x48<br />
|-<br />
! gpio:MCU<br />
! 0x48020<br />
|-<br />
! gpio:HID<br />
! 0x4301<br />
|-<br />
! gpio:NWM<br />
! 0x40020<br />
|-<br />
! gpio:IR<br />
! 0xEC0<br />
|-<br />
! gpio:NFC<br />
! 0x13000<br />
|-<br />
! gpio:QTM<br />
! 0x20000<br />
|}<br />
<br />
For the mapping between interrupts bitmasks and IRQs see: [[GPIO:BindInterrupt#Supported_values]].<br />
<br />
The commands for these services are identical.<br />
<br />
= CDC Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00020080<br />
| void unknown_0x2(u32 unk, u32 unk)<br />
|-<br />
| 0x00040080<br />
| void unknown_0x4(u32 unk, u32 unk)<br />
|-<br />
| 0x00060080<br />
| void unknown_0x6(u32 unk, u32 unk)<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
|}<br />
<br />
= HID Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00020080<br />
| void unknown_0x2(u32 unk, u32 unk)<br />
|-<br />
| 0x00040080<br />
| void unknown_0x4(u32 unk, u32 unk)<br />
|-<br />
| 0x00060080<br />
| void unknown_0x6(u32 unk, u32 unk)<br />
|-<br />
| 0x00070040<br />
| u32 unknown_0x7(u32 unk). Parameter and return value might be some mask of the same kind?<br />
|}<br />
<br />
= I2C Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| ?(u32 unk1,u32* ret) //reads from 0x1ec47020<br />
|-<br />
| 0x0002....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0003....<br />
| ?(u32 unk1,u32* ret)<br />
|-<br />
| 0x0004....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0005....<br />
| ?(u32 unk1,u32* ret)<br />
|-<br />
| 0x0006....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0007....<br />
| GetIRGPIO(u32 unk1,u32* ret)<br />
|-<br />
| 0x0008....<br />
| SetIRGPIO(u32 unk1,u32 unk2)<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
|-<br />
| 0x000A0042<br />
| [[GPIO:UnbindInterrupt|UnbindInterrupt]]<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=17704
ARM11 Interrupts
2016-07-16T20:38:37Z
<p>Xerpi: /* Hardware Interrupts */</p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0-0x5<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt.<br />
|-<br />
| 0x7<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9-0xE<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0xF<br />
| dmnt/debugger<br />
| MPCore software-interrupt. Used to abstract FIQ (debug).<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog.<br />
|}<br />
<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| PSC0?<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| PSC1?<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| PDC0?<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| PDC1?<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| PPF?<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| ?<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x58<br />
| Kernel<br />
| PDN<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Asserted when shell is opened?<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Asserted when shell is closed?<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| IR?<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| Headphone jack plugged out<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU (HOME/POWER pressed)<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| Gamecard related<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|}<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt data object for interrupt number <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt is pending<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is enabled, about to execute<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
The interrupt data pointer is a pointer to the object that handles that interrupt. The first first word in the object is a pointer to the object's vtable and the first function in the vtable is the interrupt handler for that interrupt number. When an interrupt runs, the function is passed its object in r0 and the interrupt number in r1.<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptEvent[224]<br />
| Table of interrupt event objects for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| KThread*<br />
| Thread currently acting on the interrupt table<br />
|-<br />
| 0x704<br />
| s16<br />
| Error tracker for thread above<br />
|-<br />
| 0x706<br />
| u16<br />
| Alignment<br />
|}<br />
<br />
<br />
= InterruptEvent =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt event object <br />
|-<br />
| 0x4<br />
| u32<br />
| Interrupt flags<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Services&diff=17695
GPIO Services
2016-07-16T11:55:34Z
<p>Xerpi: </p>
<hr />
<div>[[Category:Services]]<br />
= GPIO Service Names =<br />
* "gpio:CDC"<br />
* "gpio:MCU"<br />
* "gpio:HID"<br />
* "gpio:NWM"<br />
* "gpio:IR"<br />
* "gpio:NFC"<br />
<br />
The commands for these services are identical.<br />
<br />
= CDC Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00020080<br />
| void unknown_0x2(u32 unk, u32 unk)<br />
|-<br />
| 0x00040080<br />
| void unknown_0x4(u32 unk, u32 unk)<br />
|-<br />
| 0x00060080<br />
| void unknown_0x6(u32 unk, u32 unk)<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
|}<br />
<br />
= HID Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00020080<br />
| void unknown_0x2(u32 unk, u32 unk)<br />
|-<br />
| 0x00040080<br />
| void unknown_0x4(u32 unk, u32 unk)<br />
|-<br />
| 0x00060080<br />
| void unknown_0x6(u32 unk, u32 unk)<br />
|-<br />
| 0x00070040<br />
| u32 unknown_0x7(u32 unk). Parameter and return value might be some mask of the same kind?<br />
|}<br />
<br />
= I2C Service =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| ?(u32 unk1,u32* ret) //reads from 0x1ec47020<br />
|-<br />
| 0x0002....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0003....<br />
| ?(u32 unk1,u32* ret)<br />
|-<br />
| 0x0004....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0005....<br />
| ?(u32 unk1,u32* ret)<br />
|-<br />
| 0x0006....<br />
| ?(u32 unk1,u32 unk2)<br />
|-<br />
| 0x0007....<br />
| GetIRGPIO(u32 unk1,u32* ret)<br />
|-<br />
| 0x0008....<br />
| SetIRGPIO(u32 unk1,u32 unk2)<br />
|-<br />
| 0x00090082<br />
| [[GPIO:BindInterrupt|BindInterrupt]]<br />
|-<br />
| 0x000A0042<br />
| [[GPIO:UnbindInterrupt|UnbindInterrupt]]<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=16630
ARM11 Interrupts
2016-04-09T20:09:05Z
<p>Xerpi: /* Hardware Interrupts */</p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0-0x5<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt.<br />
|-<br />
| 0x7<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9-0xE<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0xF<br />
| dmnt/debugger<br />
| MPCore software-interrupt. Used to abstract FIQ (debug).<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog.<br />
|}<br />
<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| PSC0?<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| PSC1?<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| PDC0?<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| PDC1?<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| PPF?<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| ?<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x58<br />
| Kernel<br />
| New3DS MPCore clock interface?<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Asserted when shell is opened?<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Asserted when shell is closed?<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in/out<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| IR?<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU HID events<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| Gamecard related<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|}<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt data object for interrupt number <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt is pending<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is enabled, about to execute<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
The interrupt data pointer is a pointer to the object that handles that interrupt. The first first word in the object is a pointer to the object's vtable and the first function in the vtable is the interrupt handler for that interrupt number. When an interrupt runs, the function is passed its object in r0 and the interrupt number in r1.<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptEvent[224]<br />
| Table of interrupt event objects for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| KThread*<br />
| Thread currently acting on the interrupt table<br />
|-<br />
| 0x704<br />
| s16<br />
| Error tracker for thread above<br />
|-<br />
| 0x706<br />
| u16<br />
| Alignment<br />
|}<br />
<br />
<br />
= InterruptEvent =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt event object <br />
|-<br />
| 0x4<br />
| u32<br />
| Interrupt flags<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Codec_Services&diff=16526
Codec Services
2016-04-06T14:12:43Z
<p>Xerpi: /* Touchscreen */</p>
<hr />
<div>=HID Codec "cdc:HID"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| GetTouchData<br />
|-<br />
| 0x00020000<br />
| Initialize<br />
|-<br />
| 0x00030000<br />
| Finalize<br />
|}<br />
<br />
== Touchscreen ==<br />
The touchscreen is the SPI [[SPI_Registers#SPI_NEW_CNT|device number 3]], so it uses the [[SPI_Services|0x10142XXX]] SPI registers. It is initialized by issuing the following SPI commands:<br />
spi_select_reg(3, 0x67);<br />
spi_offset_mask(3, 0x26, 0x80, 0x80);<br />
spi_select_reg(3, 0x67);<br />
spi_offset_mask(3, 0x24, 0, 0x80);<br />
spi_select_reg(3, 0x67);<br />
spi_offset_mask(3, 0x25, 0x10, 0x3C);<br />
<br />
Once the touchscreen is initialized, you can start polling touch data:<br />
u8 raw_touchdata[0x40];<br />
spi_select_reg(3, 0x67);<br />
spi_read_offset(3, 0x26); //The return value of this is checked against "& 2"<br />
spi_select_reg(3, 0xFB);<br />
spi_read_offset_array(3, 1, raw_touchdata, 0x34);<br />
<br />
This is the format of the touchdata report:<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Width<br />
! Description<br />
|-<br />
| 0x00<br />
| 2*5<br />
| Five Touchscreen X Coordinates (big-endian MSB,LSB each. 12 bits number)<br />
|-<br />
| 0x0A<br />
| 2*5<br />
| Five Touchscreen Y Coordinates (big-endian MSB,LSB each. 12 bits number)<br />
|-<br />
| 0x20<br />
| ??<br />
| ??<br />
|}<br />
<br />
When the touchscreen is not touched, all the coordinates report 0xFFFF, and since touch coordinates have only 12 bits, you can check if the touchscreen is pressed by checking the 4th bit of the MSB. For example: pendown = !(raw_touchdata[0] & BIT(4))<br />
<br />
=MIC Codec "cdc:MIC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=CSN Codec "cdc:CSN"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=DSP Codec "cdc:DSP"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=Legacy Codec "cdc:LGY"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=CHK Codec "cdc:CHK"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Codec_Services&diff=16525
Codec Services
2016-04-06T13:19:10Z
<p>Xerpi: /* HID Codec "cdc:HID" */</p>
<hr />
<div>=HID Codec "cdc:HID"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| GetTouchData<br />
|-<br />
| 0x00020000<br />
| Initialize<br />
|-<br />
| 0x00030000<br />
| Finalize<br />
|}<br />
<br />
== Touchscreen ==<br />
The touchscreen is the SPI [[SPI_Registers#SPI_NEW_CNT|device number 3]], so it uses the [[SPI_Services|0x10142XXX]] SPI registers. It is initialized by issuing the following SPI commands:<br />
spi_select_reg(3, 0x67);<br />
spi_offset_mask(3, 0x26, 0x80, 0x80);<br />
spi_select_reg(3, 0x67);<br />
spi_offset_mask(3, 0x24, 0, 0x80);<br />
spi_select_reg(3, 0x67);<br />
spi_offset_mask(3, 0x25, 0x10, 0x3C);<br />
<br />
=MIC Codec "cdc:MIC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=CSN Codec "cdc:CSN"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=DSP Codec "cdc:DSP"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=Legacy Codec "cdc:LGY"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}<br />
<br />
=CHK Codec "cdc:CHK"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=MCU_Services&diff=16388
MCU Services
2016-04-02T13:02:41Z
<p>Xerpi: /* MCU HID service "mcu::HID" */</p>
<hr />
<div>Only one session can be open per service at a time. If a session is already open for a service, MCU module will wait for the thread handling the session to terminate(triggered by the session being closed by the user process), then it accepts the new session. The commands for each service are handled by separate threads.<br />
<br />
=MCU camera service "mcu::CAM"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| ?<br />
|-<br />
| 0x0002....<br />
| ?<br />
|}<br />
<br />
=MCU GPU service "mcu::GPU"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| GetLcdPowerState. This writes the value of I2C-MCU register 0xf bit6 to u8 cmdreply[2], and the value of bit5 from that register to u8 cmdreply[3].<br />
|-<br />
| 0x00020080<br />
| SetLcdPowerState. This writes the upper LCD bits of MCU register 0x22.<br />
|-<br />
| 0x00030000<br />
| GetGpuLcdInterfaceState. This writes the value of I2C-MCU register 0xf bit7 to u8 cmdreply[2].<br />
|-<br />
| 0x0004....<br />
| SetGpuLcdInterfaceState. This writes the lower two bits of MCU register 0x22.<br />
|-<br />
| 0x0005....<br />
| ?<br />
|-<br />
| 0x0006....<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
|-<br />
| 0x00090000<br />
| GetMcuFwVerHigh. Called by GSP module<br />
|-<br />
| 0x000A0000<br />
| GetMcuFwVerLow. Called by GSP module<br />
|-<br />
| 0x000B....<br />
| Set3dLedState<br />
|-<br />
| 0x000C....<br />
| Get3dLedState<br />
|-<br />
| 0x000D....<br />
| GetMcuGpuEventHandle. Event handle written to TLS+0x8c. MCU notifications 24 to 29 signal this.<br />
|-<br />
| 0x000E0000<br />
| GetMcuGpuEventReason. Writes some value to TLS+0x88. Called by GSP module<br />
|}<br />
<br />
=MCU HID service "mcu::HID"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|-<br />
| 0x0002....<br />
| ?<br />
|-<br />
| 0x0003....<br />
| ?<br />
|-<br />
| 0x0004....<br />
| ?<br />
|-<br />
| 0x0005....<br />
| ?<br />
|-<br />
| 0x0006....<br />
| ?<br />
|-<br />
| 0x0007....<br />
| Get3dSliderState<br />
|-<br />
| 0x0008....<br />
| ?<br />
|-<br />
| 0x00090000<br />
| ?<br />
|-<br />
| 0x000A0000<br />
| ?<br />
|-<br />
| 0x000B....<br />
| ?<br />
|-<br />
| 0x000C....<br />
| GetMcuHidEventHandle. MCU notifications 11 and 12 signal this.<br />
|-<br />
| 0x000D0000<br />
| GetMcuHidEventReason<br />
|-<br />
| 0x000E0000<br />
| [[MCUHID:GetSoundVolume|GetSoundVolume]]<br />
|-<br />
| 0x000F0040<br />
| SetAccelerometerState(int enable). 1 = enable, 0 = disable accelerometer<br />
|}<br />
<br />
=MCU service "mcu::RTC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| SetSystemClock (RTC)<br />
|-<br />
| 0x0002....<br />
| GetSystemClock (RTC)<br />
|-<br />
| 0x0003....<br />
| ?<br />
|-<br />
| 0x0004....<br />
| ?<br />
|-<br />
| 0x0005....<br />
| ?<br />
|-<br />
| 0x0006....<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
|-<br />
| 0x0009....<br />
| ?<br />
|-<br />
| 0x000A....<br />
| ?<br />
|-<br />
| 0x000B....<br />
| ?<br />
|-<br />
| 0x000C....<br />
| ?<br />
|-<br />
| 0x000D....<br />
| ?<br />
|-<br />
| 0x000E....<br />
| ?<br />
|-<br />
| 0x000F....<br />
| ?<br />
|-<br />
| 0x0010....<br />
| ?<br />
|-<br />
| 0x0011....<br />
| ?<br />
|-<br />
| 0x0012....<br />
| ?<br />
|-<br />
| 0x0013....<br />
| ?<br />
|-<br />
| 0x0014....<br />
| ?<br />
|-<br />
| 0x0015....<br />
| ?<br />
|-<br />
| 0x0016....<br />
| ?<br />
|-<br />
| 0x0017....<br />
| ?<br />
|-<br />
| 0x0018....<br />
| ?<br />
|-<br />
| 0x0019....<br />
| ?<br />
|-<br />
| 0x001A....<br />
| ?<br />
|-<br />
| 0x001B....<br />
| ?<br />
|-<br />
| 0x001C....<br />
| ?<br />
|-<br />
| 0x001D....<br />
| ?<br />
|-<br />
| 0x001E....<br />
| ?<br />
|-<br />
| 0x001F0040<br />
| SetPedometerRecordingMode<br />
|-<br />
| 0x00200000<br />
| GetPedometerState<br />
|-<br />
| 0x0021....<br />
| ?<br />
|-<br />
| 0x0022....<br />
| ?<br />
|-<br />
| 0x0023....<br />
| ?<br />
|-<br />
| 0x0024....<br />
| GetMcuRtcEventHandle. MCU notifications 1, 8, 9, 10, 13, 14 and 15 signal this.<br />
|-<br />
| 0x0025....<br />
| GetMcuRtcEventReason<br />
|-<br />
| 0x0026....<br />
| ?<br />
|-<br />
| 0x0027....<br />
| ?<br />
|-<br />
| 0x0028....<br />
| ?<br />
|-<br />
| 0x0029....<br />
| ?<br />
|-<br />
| 0x002A0000<br />
| GetShellState. This writes the value of I2C-MCU register 0xf bit1 to u8 cmdreply[2].<br />
|-<br />
| 0x002B0000<br />
| GetAdapterState. This writes the value of I2C-MCU register 0xf bit3 to u8 cmdreply[2].<br />
|-<br />
| 0x002C0000<br />
| GetBatteryChargeState. This writes the value of I2C-MCU register 0xf bit4 to u8 cmdreply[2].<br />
|-<br />
| 0x002D0000<br />
| [[MCURTC:GetBatteryLevel|GetBatteryLevel]]<br />
|-<br />
| 0x002E....<br />
| ?<br />
|-<br />
| 0x002F....<br />
| ?<br />
|-<br />
| 0x0030....<br />
| ?<br />
|-<br />
| 0x0031....<br />
| ?<br />
|-<br />
| 0x0032....<br />
| [[MCURTC:PowerOff|PowerOff]] (writes 0x1 to i2c MCU device, reg 0x20)<br />
|-<br />
| 0x0033....<br />
| [[MCURTC:HardwareReboot|HardwareReboot]] (writes 0x4 to i2c MCU device, reg 0x20)<br />
|-<br />
| 0x0034....<br />
| ?<br />
|-<br />
| 0x0035....<br />
| Writes 0x10 to i2c MCU device, reg 0x20<br />
|-<br />
| 0x0036....<br />
| SetWatchdogTimer<br />
|-<br />
| 0x0037....<br />
| GetWatchdogTimer<br />
|-<br />
| 0x0038....<br />
| ?<br />
|-<br />
| 0x0039....<br />
| ?<br />
|-<br />
| 0x003A....<br />
| ?<br />
|-<br />
| 0x003B0640<br />
| [[MCURTC:SetInfoLEDPattern|SetInfoLEDPattern]]<br />
|-<br />
| 0x003C0040<br />
| [[MCURTC:SetInfoLEDPatternHeader|SetInfoLEDPatternHeader]]<br />
|-<br />
| 0x003D0000<br />
| [[MCURTC:GetInfoLEDStatus|GetInfoLEDStatus]]<br />
|-<br />
| 0x003E....<br />
| ?<br />
|-<br />
| 0x003F....<br />
| ?<br />
|-<br />
| 0x0040....<br />
| ?<br />
|-<br />
| 0x0041....<br />
| ?<br />
|-<br />
| 0x00420040<br />
| [[MCURTC:SetBatteryEmptyLEDPattern|SetBatteryEmptyLEDPattern]]<br />
|-<br />
| 0x0043....<br />
| ?<br />
|-<br />
| 0x0044....<br />
| ?<br />
|-<br />
| 0x0045....<br />
| ?<br />
|-<br />
| 0x0046....<br />
| ?<br />
|-<br />
| 0x0047....<br />
| ?<br />
|-<br />
| 0x0048....<br />
| ?<br />
|-<br />
| 0x0049....<br />
| ?<br />
|-<br />
| 0x004A....<br />
| ?<br />
|-<br />
| 0x004B....<br />
| ?<br />
|-<br />
| 0x004C....<br />
| ?<br />
|-<br />
| 0x004D....<br />
| [[MCURTC:ReadHidFlagRegister|ReadHidFlagRegister]] (reads i2c MCU device, reg 0x10)<br />
|-<br />
| 0x004E....<br />
| [[MCURTC:PublishNotifications|PublishNotifications]]<br />
|-<br />
| 0x004F....<br />
| Sets some flag (otherwise set when uploading MCU firmware)<br />
|-<br />
| 0x0050....<br />
| Returns the above flag<br />
|-<br />
| 0x0051....<br />
| SetLegacyPoweroff<br />
|-<br />
| 0x00520000<br />
| IsLegacyPoweroff<br />
|-<br />
| 0x0053....<br />
| ?<br />
|-<br />
| 0x0054....<br />
| ?<br />
|-<br />
| 0x0055....<br />
| ?<br />
|-<br />
| 0x0056....<br />
| ?<br />
|-<br />
| 0x0057....<br />
| ?<br />
|-<br />
| 0x0058....<br />
| ?<br />
|-<br />
| 0x0059....<br />
| SetLegacyJumpProhibitedFlag<br />
|-<br />
| 0x005A....<br />
| GetLegacyJumpProhibitedFlag<br />
|}<br />
<br />
Note that using invalid input with these InfoLED/SetBatteryEmptyLEDPattern commands(especially SetInfoLEDPattern) can cause the system to be bricked(however the boot failure may not begin immediately after using the invalid parameters). For the bitmasks controlling these LEDs, bit clear = LED enable, bit set = LED disable? These notification LEDs(red LED, green LED, blue LED, ...) can only be enabled/disabled, nothing more.<br />
<br />
=MCU sound service "mcu::SND"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| GetSoundVolume<br />
|-<br />
| 0x0002....<br />
| ?<br />
|-<br />
| 0x0003....<br />
| ?<br />
|}<br />
<br />
=MCU wifi service "mcu::NWM"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| SetWiFiLedState<br />
|-<br />
| 0x0002....<br />
| GetWiFiLedState<br />
|-<br />
| 0x0003....<br />
| Sets GPIO 0x20 high/low?<br />
|-<br />
| 0x0004....<br />
| Gets GPIO 0x20 high/low?<br />
|-<br />
| 0x0005....<br />
| Sets GPIO 0x40000 high/low?<br />
|-<br />
| 0x0006....<br />
| Gets GPIO 0x40000 high/low?<br />
|-<br />
| 0x0007....<br />
| Sets a FIRM WiFi-state-related flag?<br />
|-<br />
| 0x0008....<br />
| Gets the above flag<br />
|}<br />
<br />
=MCU service "mcu::HWC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| GetMcuRegister? Seems to read an arbitrary register (by parameter)<br />
|-<br />
| 0x0002....<br />
| SetMcuRegister?<br />
|-<br />
| 0x0003....<br />
| ?<br />
|-<br />
| 0x0004....<br />
| ?<br />
|-<br />
| 0x0005....<br />
| GetBatteryLevel<br />
|-<br />
| 0x0006....<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
|-<br />
| 0x0009....<br />
| Set3dLedState<br />
|-<br />
| 0x000A0640<br />
| This is the same as [[MCURTC:SetInfoLEDPattern]].<br />
|-<br />
| 0x000B....<br />
| GetSoundVolume<br />
|-<br />
| 0x000C....<br />
| ?<br />
|-<br />
| 0x000D....<br />
| ?<br />
|-<br />
| 0x000E....<br />
| ?<br />
|-<br />
| 0x000F....<br />
| GetRtcTime<br />
|-<br />
| 0x00100000<br />
| GetMcuFwVerHigh<br />
|-<br />
| 0x00110000<br />
| GetMcuFwVerLow<br />
|}<br />
<br />
=MCU service "mcu::PLS"=<br />
<br />
RTC-related? Each of these seems to retrieve a second counter from a different RTC register.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x0001....<br />
| ?<br />
|-<br />
| 0x0002....<br />
| ?<br />
|-<br />
| 0x0003....<br />
| ?<br />
|-<br />
| 0x0004....<br />
| ?<br />
|-<br />
| 0x0005....<br />
| ?<br />
|-<br />
| 0x0006....<br />
| ?<br />
|-<br />
| 0x0007....<br />
| ?<br />
|-<br />
| 0x0008....<br />
| ?<br />
|-<br />
| 0x0009....<br />
| ?<br />
|}<br />
<br />
=MCU codec service "mcu::CDC"=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Command Header<br />
! Description<br />
|-<br />
| 0x00010000<br />
| ?<br />
|}<br />
<br />
=New3DS=<br />
The Old3DS/New3DS MCU sysmodules are identical except that the MCU firmware binary written via I2C is different. The size of that binary is the same. The only different words in .text are for the version of that MCU fw binary.<br />
<br />
=MCU firmware versions=<br />
<br />
These reside in mcu-module .rodata, are uploaded to MCU register 0x05 and are usually size 0x4003 bytes. (0x4000 bytes with 3 byte magic "jhl"?)<br />
<br />
There exists an alternate code path where uploading is done using register 0x3B (decided by making some nonsense conclusions about registers 0x0F and 0x10). This may be a "hack" around early versions of MCU? Register 0x3B is RTC-related on recent versions of MCU, and the "nonsense" condition is not met even on factory MCU firmware.<br />
<br />
On dev-units, the user-facing representation of this firmware version is displayed by first subtracting 0x10 from the major field (raw register 0x00). It is these user-facing versions that are displayed in the table below. It is unknown what bit4 (0x10) actually represents, but it is seemingly always set.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Title version<br />
! Firmware<br />
|-<br />
| New3DS v8192/safe v9217 (latest)<br />
| 3.56<br />
|-<br />
| Old3DS v6145 to v8192 (latest)<br />
| 2.37<br />
|-<br />
| Old3DS v5122<br />
| 2.35<br />
|-<br />
| Old3DS v4102<br />
| 2.30<br />
|-<br />
| Old3DS v3072<br />
| 2.16<br />
|-<br />
| Old3DS v2048<br />
| 1.52<br />
|-<br />
| Old3DS v1026<br />
| 1.51<br />
|-<br />
| Old3DS v0/safe v0<br />
| 1.20<br />
|-<br />
| Old3DS factory<br />
| 1.07<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=16367
SPI Registers
2016-04-01T07:52:08Z
<p>Xerpi: /* SPI_NEW_CNT */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz/Firmware, 1=2MHz/Touchscr, 2=1MHz/Powerman., 3=512KHz)<br />
|-<br />
| 2-6<br />
| Not used (Zero)<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0-3)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 0-5<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
When the transfer is finished, a 0 has to be written to this register.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=16346
SPI Registers
2016-03-30T23:09:37Z
<p>Xerpi: /* SPI_NEW_DONE */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz/Firmware, 1=2MHz/Touchscr, 2=1MHz/Powerman., 3=512KHz)<br />
|-<br />
| 2-6<br />
| Not used (Zero)<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0-3)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 0-5<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
When the transfer is finished, a 0 has to be written to this register.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Registers&diff=16314
GPIO Registers
2016-03-29T21:54:23Z
<p>Xerpi: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Address<br />
! Width<br />
! Interrupt bitmasks associated to this register<br />
|-<br />
| ??<br />
| 0x10147000<br />
| 2??<br />
| 0x1, 0x2, 0x4<br />
|-<br />
| ??<br />
| [[#0x10147010|0x10147010]]<br />
| 4<br />
| 0x8, 0x10<br />
|-<br />
| ??<br />
| 0x10147014<br />
| 2??<br />
| 0x20<br />
|-<br />
| ??<br />
| 0x10147020<br />
| 4<br />
| 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000<br />
|-<br />
| ??<br />
| 0x10147024<br />
| 4<br />
| 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000<br />
|-<br />
| ??<br />
| 0x10147028<br />
| 2??<br />
| 0x40000<br />
|}<br />
<br />
== 0x10147010 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 24<br />
| Enable/disable? GPIO interrupt 0x64 (bitmask 0x8)<br />
|-<br />
| 25<br />
| Enable/disable? GPIO interrupt 0x66 (bitmask 0x10)<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=16313
ARM11 Interrupts
2016-03-29T21:48:37Z
<p>Xerpi: </p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0-0x5<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt.<br />
|-<br />
| 0x7<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9-0xF<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog.<br />
|}<br />
<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| ?<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x58<br />
| Kernel<br />
| New3DS MPCore clock interface?<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Asserted when shell is opened?<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Asserted when shell is closed?<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in/out<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU HID events<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| Gamecard related<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|}<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt data object for interrupt number <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt is pending<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is enabled, about to execute<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
The interrupt data pointer is a pointer to the object that handles that interrupt. The first first word in the object is a pointer to the object's vtable and the first function in the vtable is the interrupt handler for that interrupt number. When an interrupt runs, the function is passed its object in r0 and the interrupt number in r1.<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptEvent[224]<br />
| Table of interrupt event objects for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| KThread*<br />
| Thread currently acting on the interrupt table<br />
|-<br />
| 0x704<br />
| s16<br />
| Error tracker for thread above<br />
|-<br />
| 0x706<br />
| u16<br />
| Alignment<br />
|}<br />
<br />
<br />
= InterruptEvent =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt event object <br />
|-<br />
| 0x4<br />
| u32<br />
| Interrupt flags<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Registers&diff=16310
GPIO Registers
2016-03-29T20:26:13Z
<p>Xerpi: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Address<br />
! Width<br />
! Interrupt bitmasks associated to this register<br />
|-<br />
| ??<br />
| 0x10147000<br />
| 2??<br />
| 0x1, 0x2, 0x4<br />
|-<br />
| ??<br />
| 0x10147010<br />
| 4<br />
| 0x8, 0x10<br />
|-<br />
| ??<br />
| 0x10147014<br />
| 2??<br />
| 0x20<br />
|-<br />
| ??<br />
| 0x10147020<br />
| 4<br />
| 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000<br />
|-<br />
| ??<br />
| 0x10147024<br />
| 4<br />
| 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000<br />
|-<br />
| ??<br />
| 0x10147028<br />
| 2??<br />
| 0x40000<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=16268
ARM11 Interrupts
2016-03-28T21:16:51Z
<p>Xerpi: </p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0-0x5<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt.<br />
|-<br />
| 0x7<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9-0xF<br />
| <br />
| MPCore software-interrupt.<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog.<br />
|}<br />
<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| ?<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| ?<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x58<br />
| Kernel<br />
| New3DS MPCore clock interface?<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| ?<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Asserted when shell is opened?<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Asserted when shell is closed?<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU HID events<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| ?<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|}<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt data object for interrupt number <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt is pending<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is enabled, about to execute<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
The interrupt data pointer is a pointer to the object that handles that interrupt. The first first word in the object is a pointer to the object's vtable and the first function in the vtable is the interrupt handler for that interrupt number. When an interrupt runs, the function is passed its object in r0 and the interrupt number in r1.<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptEvent[224]<br />
| Table of interrupt event objects for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| KThread*<br />
| Thread currently acting on the interrupt table<br />
|-<br />
| 0x704<br />
| s16<br />
| Error tracker for thread above<br />
|-<br />
| 0x706<br />
| u16<br />
| Alignment<br />
|}<br />
<br />
<br />
= InterruptEvent =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Pointer to interrupt event object <br />
|-<br />
| 0x4<br />
| u32<br />
| Interrupt flags<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO:UnbindInterrupt&diff=16236
GPIO:UnbindInterrupt
2016-03-27T09:36:40Z
<p>Xerpi: Created page with "=Request= {| class="wikitable" border="1" |- ! Index Word ! Description |- | 0 | Header code [0xA0042] |- | 1 | u32, interrupt bitmask |- | 2 | Handle syncObject |} =Respon..."</p>
<hr />
<div>=Request=<br />
{| class="wikitable" border="1"<br />
|-<br />
! Index Word<br />
! Description<br />
|-<br />
| 0<br />
| Header code [0xA0042]<br />
|-<br />
| 1<br />
| u32, interrupt bitmask<br />
|-<br />
| 2<br />
| Handle syncObject<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 />
<br />
See also [[GPIO:BindInterrupt]] and [[ARM11 Interrupts]].</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Registers&diff=16235
GPIO Registers
2016-03-27T07:25:18Z
<p>Xerpi: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Address<br />
! Width<br />
|-<br />
| ??<br />
| 0x10147000<br />
| 2??<br />
|-<br />
| ??<br />
| 0x10147010<br />
| 4<br />
|-<br />
| ??<br />
| 0x10147014<br />
| 2??<br />
|-<br />
| ??<br />
| 0x10147020<br />
| 4<br />
|-<br />
| ??<br />
| 0x10147024<br />
| 4<br />
|-<br />
| ??<br />
| 0x10147028<br />
| 2??<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=GPIO_Registers&diff=16231
GPIO Registers
2016-03-26T13:26:00Z
<p>Xerpi: Created page with "= Registers = {| class="wikitable" border="1" ! Name ! Address ! Width |- | ?? | 0x10147010 | 4?? |- | ?? | 0x10147014 | 2?? |- | ?? | 0x10147020 | 4?? |- | ?? | 0x10147028..."</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Address<br />
! Width<br />
|-<br />
| ??<br />
| 0x10147010<br />
| 4??<br />
|-<br />
| ??<br />
| 0x10147014<br />
| 2??<br />
|-<br />
| ??<br />
| 0x10147020<br />
| 4??<br />
|-<br />
| ??<br />
| 0x10147028<br />
| 2??<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=SVC&diff=16200
SVC
2016-03-25T15:40:24Z
<p>Xerpi: Undo revision 16199 by Xerpi (talk)</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 ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size, [[#enum_MemoryOperation|MemoryOperation]] operation, [[#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 QueryMemory(MemoryInfo* info, 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, 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 CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, [[#enum_MemoryPermission|MemoryPermission]] mypermission, [[#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 MapMemoryBlock(Handle memblock, u32 addr, [[#enum_MemoryPermission|MemoryPermission]] mypermissions, [[#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 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 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 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 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 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)<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 CreatePort(Handle* portServer, Handle* portClient, const char* name, s32 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 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 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 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 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 BindInterrupt(Interrupt name, Handle syncObject, s32 priority, bool isManualClear)<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 syncObject)<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 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(nn::Handle, void *, void const*, unsigned int, signed char)<br />
|<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, 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 process, 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]](long long *, int *, nn::Handle, unsigned int, nn::dmnt::DebugThreadParam)<br />
| Disabled on regular kernel.<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 MapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr)<br />
|<br />
|-<br />
| 0x72<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result UnmapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr)<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. No ARM11 processes have access to it without some form of kernelhax.<br />
|-<br />
| 0x7C<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| KernelSetState(unsigned int Type, unsigned int Param0, unsigned int Param1, unsigned int Param2)<br />
| The type determines the meaning of each param<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 />
| ???<br />
| Debug related? The svcaccesscontrol mask doesn't apply for this SVC. 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 MemoryState ==<br />
{| class="wikitable" border="1"<br />
! Memory state flags<br />
! Value<br />
|-<br />
| FREE<br />
| 0<br />
|-<br />
| RESERVED<br />
| 1<br />
|-<br />
| IO<br />
| 2<br />
|-<br />
| STATIC<br />
| 3<br />
|-<br />
| CODE<br />
| 4<br />
|-<br />
| PRIVATE<br />
| 5<br />
|-<br />
| SHARED<br />
| 6<br />
|-<br />
| CONTINUOUS<br />
| 7<br />
|-<br />
| ALIASED<br />
| 8<br />
|-<br />
| ALIAS<br />
| 9<br />
|-<br />
| ALIAS CODE<br />
| 10<br />
|-<br />
| LOCKED<br />
| 11<br />
|}<br />
<br />
== enum PageFlags ==<br />
{| class="wikitable" border="1"<br />
! Page flags<br />
! Bit<br />
|-<br />
| LOCKED<br />
| 0<br />
|-<br />
| CHANGED<br />
| 1<br />
|}<br />
<br />
== enum MemoryOperation ==<br />
<br />
{| class="wikitable" border="1"<br />
! Memory operation<br />
! Id<br />
|-<br />
| FREE<br />
| 1<br />
|-<br />
| RESERVE<br />
| 2<br />
|-<br />
| COMMIT<br />
| 3<br />
|-<br />
| MAP<br />
| 4<br />
|-<br />
| UNMAP<br />
| 5<br />
|-<br />
| PROTECT<br />
| 6<br />
|-<br />
| REGION APP<br />
| 0x100<br />
|-<br />
| REGION SYSTEM<br />
| 0x200<br />
|-<br />
| REGION BASE<br />
| 0x300<br />
|-<br />
| LINEAR<br />
| 0x10000<br />
|}<br />
<br />
The LINEAR memory-operation indicates that the mapped physical address is always MappedVAddr+0x0C000000, thus this memory can be used for hardware devices' DMA(such as the [[GPU]]). Addr0+size for this must be within the 0x14000000-0x1C000000 range when Addr0 is non-zero(Addr1 must be zero), Addr0 isn't actually used by svcControlMemory for mapping memory: Addr0 is not used by the kernel after doing address-range checks. The kernel determines what physical-address to use by allocating memory from FCRAM(about the same way as other memory), which is then used to determine the virtual-address.<br />
<br />
[[8.0.0-18]] added a new memory mapping(0x30000000-0x38000000) for LINEAR memory, this replaces the original mapping for newer titles. The kernel uses the new mapping when the process memory-region is BASE, or when the process kernel-release-version field is >=0x022c(2.44 / system-version [[8.0.0-18]]).<br />
<br />
The input mem-region value for svcControlMemory is only used(when non-zero) when the PID is value 1, for the [[FIRM]] ARM11 "loader" module.<br />
<br />
== enum MemoryPermission ==<br />
<br />
{| class="wikitable" border="1"<br />
! Memory permission<br />
! Id<br />
|-<br />
| NONE<br />
| 0<br />
|-<br />
| R<br />
| 1<br />
|-<br />
| W<br />
| 2<br />
|-<br />
| RW<br />
| 3<br />
|-<br />
| X<br />
| 4<br />
|-<br />
| RX<br />
| 5<br />
|-<br />
| WX<br />
| 6<br />
|-<br />
| RWX<br />
| 7<br />
|-<br />
| DONTCARE<br />
| 0x10000000<br />
|}<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 />
== struct MemoryInfo ==<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Base process virtual address<br />
|-<br />
| u32<br />
| Size<br />
|-<br />
| u32<br />
| Permission<br />
|-<br />
| enum MemoryState<br />
| State<br />
|}<br />
<br />
== struct PageInfo ==<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Flags<br />
|}<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 />
<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[2]<br />
| Unknown/padding<br />
|-<br />
| u32[6]<br />
| Event-specific data (see below)<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Event type<br />
! Id<br />
|-<br />
| PROCESS<br />
| 0<br />
|-<br />
| CREATE THREAD<br />
| 1<br />
|-<br />
| EXIT THREAD<br />
| 2<br />
|-<br />
| EXIT PROCESS<br />
| 3<br />
|-<br />
| EXCEPTION<br />
| 4<br />
|-<br />
| DLL LOAD<br />
| 5<br />
|-<br />
| DLL UNLOAD<br />
| 6<br />
|-<br />
| SCHEDULE IN<br />
| 7<br />
|-<br />
| SCHEDULE OUT<br />
| 8<br />
|-<br />
| SYSCALL IN<br />
| 9<br />
|-<br />
| SYSCALL OUT<br />
| 10<br />
|-<br />
| OUTPUT STRING<br />
| 11<br />
|-<br />
| MAP<br />
| 12<br />
|}<br />
<br />
=== 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 />
| 0 = newly created process, 1 = attached process<br />
|}<br />
<br />
=== CREATE THREAD event ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Creator thread ID<br />
|-<br />
| u32<br />
| Base address (?)<br />
|-<br />
| u32<br />
| Entrypoint<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 />
| UNHANDLED EXCEPTION<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<br />
| Argument (type-specific)<br />
|}<br />
<br />
Exception types:<br />
{| class="wikitable" border="1"<br />
! Reason<br />
! Id<br />
! Argument<br />
|-<br />
| UNDEFINED INSTRUCTION<br />
| 0<br />
| (None)<br />
|-<br />
| (Unknown)<br />
| 1<br />
| (None)<br />
|-<br />
| (Unknown, mem-related)<br />
| 2<br />
| Address<br />
|-<br />
| (Unknown, mem-related)<br />
| 3<br />
| Address<br />
|-<br />
| ATTACH BREAK<br />
| 4<br />
| (None)<br />
|-<br />
| BREAKPOINT<br />
| 5<br />
| (None)<br />
|-<br />
| USER BREAK<br />
| 6<br />
| User break type<br />
|-<br />
| DEBUGGER BREAK<br />
| 7<br />
| (None)<br />
|-<br />
| UNDEFINED SYSCALL<br />
| 8<br />
| Attempted syscall ID<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 />
<br />
=== SCHEDULER/SYSCALL IN/OUT events ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u64<br />
| Clock tick<br />
|-<br />
| u32<br />
| Syscall (only for 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 />
== 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 />
= Processes =<br />
Each process is given an array of [[NCCH/Extended_Header#ARM11_Kernel_Capabilities|kernel capability descriptors]] upon creation (see CreateProcess). Official software forwards the descriptors specified in the [[NCCH#Extended_Header|NCCH exheader]].<br />
<br />
Any process can only use SVCs which are enabled in its kernel capability descriptors. This is enforced by the ARM11 kernel SVC handler by checking the syscall access control mask stored on the SVC-mode stack. If the SVC isn't enabled, a kernelpanic() is triggered. Each process has a separate SVC-mode stack; this stack and the syscall access mask stored here are initialized when the process is started. Applications normally only have access to SVCs <=0x3D, however not all SVCs <=0x3D are accessible to the application. The majority of the SVCs accessible to applications are unused by the application.<br />
<br />
Each process has a separate handle-table, the size of which is stored in the kernel capability descriptor. The handles in a handle-table can't be used in the context of other processes, since those handles don't exist in other handle-tables.<br />
<br />
0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for the current KThread.<br />
<br />
Calling svcBreak on retail will only terminate the process which called this SVC.<br />
<br />
= Threads =<br />
For svcCreateThread the input address used for Entrypoint_Param and StackTop are normally the same, however these can be arbitrary. For the main thread the Entrypoint_Param is value 0.<br />
<br />
Using CloseHandle() with a KThread handle will terminate the specified thread, only if the reference count reaches 0.<br />
<br />
Lower priority values give the thread higher priority. For userland apps, priorities between 0x18 and 0x3F are allowed. The priority of the app's main thread seems to be 0x30.<br />
<br />
The thread scheduler is cooperative, therefore if a thread takes up all the CPU time (for example if it enters an endless loop), all the other threads that run on the same CPU core won't get a chance to run. The main way of yielding another thread is using an address arbiter.<br />
<br />
= Memory Mapping =<br />
ControlMemory and MapMemoryBlock can be used to map memory pages, these two SVCs only support mapping execute-never R/W pages. The input permissions parameter for these SVCs must therefore be <=3, where value zero is used when un-mapping memory. Furthermore it appears that only regular heap pages can be mirrored (it won't work for TLS, stack, .data, .text, for example).<br />
<br />
Bitmask 0xF00 for ControlMemory parameter MemoryType is the memory-type, when this is zero the memory-type is loaded from the kernel flags stored in the exheader ARM11 kernel descriptors, for the process using the SVC.<br />
<br />
ControlMemory parameter MemoryType with value 0x10003 is used for mapping the GSP [[Memory_layout|heap]]. The low 8-bits are the type: 1 is for un-mapping memory, 3 for mapping memory. Type4 is used to mirror the RW memory at Addr1, to Addr0. Type4 will return an error if Addr1 is located in read-only memory. Addr1 is not used for type1 and type3.<br />
<br />
The ARM11 kernel does not allow processes to create shared memory blocks via svcCreateMemoryBlock, when the process memorytype (from the kernel flags stored in the exheader kernel descriptor) is the application memorytype, and when addr=0. When the memorytype is not the application memorytype and addr=0, the kernel allocates new memory for the calling process and turns it into a shared memory block. When addr is non-zero, it must be located in memory which is already mapped. Furthermore, it appears that only regular heap pages (allocated using svcControlMemory op=COMMIT) are accepted as valid addrs.<br />
<br />
ControlProcessMemory maps memory in the specified process, this is the only SVC which allows mapping executable memory. Format of the permissions field for memory mapping SVCs: bit0=R, bit1=W, bit2=X. Type6 sets the Addr0 memory permissions to the input permissions, for already mapped memory. Type is the MemoryOperation enum, without the memory-type/memory-region. ControlProcessMemory only supports type4, type5, and type6. ControlProcessMemory does not support using the current KProcess handle alias.<br />
<br />
MapProcessMemory maps RW memory starting at address 0x00100000 in the specified KProcess, at the specified StartAddr in the current process. MapProcessMemory then maps 0x08000000 in the specified process, to StartAddr+0x7f00000 in the current process. UnmapProcessMemory unmaps the memory which was mapped by MapProcessMemory.<br />
<br />
Note that with the MAP MemoryOperation, the kernel will refuse to MAP memory for the specified addr1, when addr1 was already used with another MAP operation as addr1. The kernel also doesn't allow memory to be freed via the FREE MemoryOperation, when other virtual-memory is mapped to this same memory(when the MAP MemoryOperation was used with this memory with addr1).<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 />
= 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 />
= KernelSetState =<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 />
| This initializes the programID for launching [[FIRM]], then triggers launching [[FIRM]]. Param0 is unused. Param1 is the programID-low, and the programID-high is 0x00040138. Param2 is used only with the [[New_3DS]] kernel, pm-module uses value 0 with this. With New3DS kernel, it forces the programIDlow to be the New3DS NATIVE_FIRM, when the input programIDlow is for the Old3DS NATIVE_FIRM and Param2==0.<br />
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 />
| Unknown, does nothing with the TWL_FIRM ARM11 kernel.<br />
|-<br />
| 2<br />
| Yes<br />
| Yes<br />
| Unknown.<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 />
| This used for initializing the 0x1000-byte buffer used by the launched [[FIRM]]. Param2 is unused. When Param0 is value 1, this buffer is copied to the beginning of FCRAM at 0xF0000000, and Param1 is unused. When Param0 is value 0, this kernel buffer is mapped to process address Param1.<br />
|-<br />
| 4<br />
| No<br />
| Yes<br />
| Param0-Param3 are unused. 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 />
| ?<br />
|-<br />
| 6<br />
| Yes<br />
| No<br />
| Debug related?<br />
|-<br />
| 7<br />
| Yes<br />
| No<br />
| This triggers an MCU (hard) reboot. Param0-3 are unused. 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 unused FIRM launch code-path, with different [[PXI]] FIFO word constants.<br />
|-<br />
| 9<br />
| Yes, implemented at some point after system-version v4.5.<br />
| ?<br />
| Unknown<br />
|-<br />
| 10<br />
| Yes<br />
| ?<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. Param0 = input value. Only bit0-1 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 />
| 9-19<br />
| [[8.0.0-18]]<br />
| This only returns error 0xD8E007ED.<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-23<br />
| [[8.0.0-18]]<br />
| This only returns error 0xE0E01BF4.<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-1 for kernel object (u32), and also a boolean if the refcount-1 is negative (u32).<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 />
= 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 />
| 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>
Xerpi
https://www.3dbrew.org/w/index.php?title=SVC&diff=16199
SVC
2016-03-25T15:37:06Z
<p>Xerpi: Add Interrupts</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 ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size, [[#enum_MemoryOperation|MemoryOperation]] operation, [[#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 QueryMemory(MemoryInfo* info, 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, 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 CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, [[#enum_MemoryPermission|MemoryPermission]] mypermission, [[#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 MapMemoryBlock(Handle memblock, u32 addr, [[#enum_MemoryPermission|MemoryPermission]] mypermissions, [[#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 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 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 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 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 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)<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 CreatePort(Handle* portServer, Handle* portClient, const char* name, s32 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 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 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 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 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 [[SVC#Interrupts|BindInterrupt]](Interrupt name, Handle syncObject, s32 priority, bool isManualClear)<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 syncObject)<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 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(nn::Handle, void *, void const*, unsigned int, signed char)<br />
|<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, 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 process, 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]](long long *, int *, nn::Handle, unsigned int, nn::dmnt::DebugThreadParam)<br />
| Disabled on regular kernel.<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 MapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr)<br />
|<br />
|-<br />
| 0x72<br />
| style="background: green" | Yes<br />
| style="background: red" | No<br />
| style="background: red" | No<br />
| Result UnmapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr)<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. No ARM11 processes have access to it without some form of kernelhax.<br />
|-<br />
| 0x7C<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| style="background: green" | Yes<br />
| KernelSetState(unsigned int Type, unsigned int Param0, unsigned int Param1, unsigned int Param2)<br />
| The type determines the meaning of each param<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 />
| ???<br />
| Debug related? The svcaccesscontrol mask doesn't apply for this SVC. 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 MemoryState ==<br />
{| class="wikitable" border="1"<br />
! Memory state flags<br />
! Value<br />
|-<br />
| FREE<br />
| 0<br />
|-<br />
| RESERVED<br />
| 1<br />
|-<br />
| IO<br />
| 2<br />
|-<br />
| STATIC<br />
| 3<br />
|-<br />
| CODE<br />
| 4<br />
|-<br />
| PRIVATE<br />
| 5<br />
|-<br />
| SHARED<br />
| 6<br />
|-<br />
| CONTINUOUS<br />
| 7<br />
|-<br />
| ALIASED<br />
| 8<br />
|-<br />
| ALIAS<br />
| 9<br />
|-<br />
| ALIAS CODE<br />
| 10<br />
|-<br />
| LOCKED<br />
| 11<br />
|}<br />
<br />
== enum PageFlags ==<br />
{| class="wikitable" border="1"<br />
! Page flags<br />
! Bit<br />
|-<br />
| LOCKED<br />
| 0<br />
|-<br />
| CHANGED<br />
| 1<br />
|}<br />
<br />
== enum MemoryOperation ==<br />
<br />
{| class="wikitable" border="1"<br />
! Memory operation<br />
! Id<br />
|-<br />
| FREE<br />
| 1<br />
|-<br />
| RESERVE<br />
| 2<br />
|-<br />
| COMMIT<br />
| 3<br />
|-<br />
| MAP<br />
| 4<br />
|-<br />
| UNMAP<br />
| 5<br />
|-<br />
| PROTECT<br />
| 6<br />
|-<br />
| REGION APP<br />
| 0x100<br />
|-<br />
| REGION SYSTEM<br />
| 0x200<br />
|-<br />
| REGION BASE<br />
| 0x300<br />
|-<br />
| LINEAR<br />
| 0x10000<br />
|}<br />
<br />
The LINEAR memory-operation indicates that the mapped physical address is always MappedVAddr+0x0C000000, thus this memory can be used for hardware devices' DMA(such as the [[GPU]]). Addr0+size for this must be within the 0x14000000-0x1C000000 range when Addr0 is non-zero(Addr1 must be zero), Addr0 isn't actually used by svcControlMemory for mapping memory: Addr0 is not used by the kernel after doing address-range checks. The kernel determines what physical-address to use by allocating memory from FCRAM(about the same way as other memory), which is then used to determine the virtual-address.<br />
<br />
[[8.0.0-18]] added a new memory mapping(0x30000000-0x38000000) for LINEAR memory, this replaces the original mapping for newer titles. The kernel uses the new mapping when the process memory-region is BASE, or when the process kernel-release-version field is >=0x022c(2.44 / system-version [[8.0.0-18]]).<br />
<br />
The input mem-region value for svcControlMemory is only used(when non-zero) when the PID is value 1, for the [[FIRM]] ARM11 "loader" module.<br />
<br />
== enum MemoryPermission ==<br />
<br />
{| class="wikitable" border="1"<br />
! Memory permission<br />
! Id<br />
|-<br />
| NONE<br />
| 0<br />
|-<br />
| R<br />
| 1<br />
|-<br />
| W<br />
| 2<br />
|-<br />
| RW<br />
| 3<br />
|-<br />
| X<br />
| 4<br />
|-<br />
| RX<br />
| 5<br />
|-<br />
| WX<br />
| 6<br />
|-<br />
| RWX<br />
| 7<br />
|-<br />
| DONTCARE<br />
| 0x10000000<br />
|}<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 />
== struct MemoryInfo ==<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Base process virtual address<br />
|-<br />
| u32<br />
| Size<br />
|-<br />
| u32<br />
| Permission<br />
|-<br />
| enum MemoryState<br />
| State<br />
|}<br />
<br />
== struct PageInfo ==<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Flags<br />
|}<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 />
<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[2]<br />
| Unknown/padding<br />
|-<br />
| u32[6]<br />
| Event-specific data (see below)<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Event type<br />
! Id<br />
|-<br />
| PROCESS<br />
| 0<br />
|-<br />
| CREATE THREAD<br />
| 1<br />
|-<br />
| EXIT THREAD<br />
| 2<br />
|-<br />
| EXIT PROCESS<br />
| 3<br />
|-<br />
| EXCEPTION<br />
| 4<br />
|-<br />
| DLL LOAD<br />
| 5<br />
|-<br />
| DLL UNLOAD<br />
| 6<br />
|-<br />
| SCHEDULE IN<br />
| 7<br />
|-<br />
| SCHEDULE OUT<br />
| 8<br />
|-<br />
| SYSCALL IN<br />
| 9<br />
|-<br />
| SYSCALL OUT<br />
| 10<br />
|-<br />
| OUTPUT STRING<br />
| 11<br />
|-<br />
| MAP<br />
| 12<br />
|}<br />
<br />
=== 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 />
| 0 = newly created process, 1 = attached process<br />
|}<br />
<br />
=== CREATE THREAD event ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u32<br />
| Creator thread ID<br />
|-<br />
| u32<br />
| Base address (?)<br />
|-<br />
| u32<br />
| Entrypoint<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 />
| UNHANDLED EXCEPTION<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<br />
| Argument (type-specific)<br />
|}<br />
<br />
Exception types:<br />
{| class="wikitable" border="1"<br />
! Reason<br />
! Id<br />
! Argument<br />
|-<br />
| UNDEFINED INSTRUCTION<br />
| 0<br />
| (None)<br />
|-<br />
| (Unknown)<br />
| 1<br />
| (None)<br />
|-<br />
| (Unknown, mem-related)<br />
| 2<br />
| Address<br />
|-<br />
| (Unknown, mem-related)<br />
| 3<br />
| Address<br />
|-<br />
| ATTACH BREAK<br />
| 4<br />
| (None)<br />
|-<br />
| BREAKPOINT<br />
| 5<br />
| (None)<br />
|-<br />
| USER BREAK<br />
| 6<br />
| User break type<br />
|-<br />
| DEBUGGER BREAK<br />
| 7<br />
| (None)<br />
|-<br />
| UNDEFINED SYSCALL<br />
| 8<br />
| Attempted syscall ID<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 />
<br />
=== SCHEDULER/SYSCALL IN/OUT events ===<br />
<br />
{| class="wikitable" border="1"<br />
! Type<br />
! Field<br />
|-<br />
| u64<br />
| Clock tick<br />
|-<br />
| u32<br />
| Syscall (only for 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 />
== 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 />
= Processes =<br />
Each process is given an array of [[NCCH/Extended_Header#ARM11_Kernel_Capabilities|kernel capability descriptors]] upon creation (see CreateProcess). Official software forwards the descriptors specified in the [[NCCH#Extended_Header|NCCH exheader]].<br />
<br />
Any process can only use SVCs which are enabled in its kernel capability descriptors. This is enforced by the ARM11 kernel SVC handler by checking the syscall access control mask stored on the SVC-mode stack. If the SVC isn't enabled, a kernelpanic() is triggered. Each process has a separate SVC-mode stack; this stack and the syscall access mask stored here are initialized when the process is started. Applications normally only have access to SVCs <=0x3D, however not all SVCs <=0x3D are accessible to the application. The majority of the SVCs accessible to applications are unused by the application.<br />
<br />
Each process has a separate handle-table, the size of which is stored in the kernel capability descriptor. The handles in a handle-table can't be used in the context of other processes, since those handles don't exist in other handle-tables.<br />
<br />
0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for the current KThread.<br />
<br />
Calling svcBreak on retail will only terminate the process which called this SVC.<br />
<br />
= Threads =<br />
For svcCreateThread the input address used for Entrypoint_Param and StackTop are normally the same, however these can be arbitrary. For the main thread the Entrypoint_Param is value 0.<br />
<br />
Using CloseHandle() with a KThread handle will terminate the specified thread, only if the reference count reaches 0.<br />
<br />
Lower priority values give the thread higher priority. For userland apps, priorities between 0x18 and 0x3F are allowed. The priority of the app's main thread seems to be 0x30.<br />
<br />
The thread scheduler is cooperative, therefore if a thread takes up all the CPU time (for example if it enters an endless loop), all the other threads that run on the same CPU core won't get a chance to run. The main way of yielding another thread is using an address arbiter.<br />
<br />
= Memory Mapping =<br />
ControlMemory and MapMemoryBlock can be used to map memory pages, these two SVCs only support mapping execute-never R/W pages. The input permissions parameter for these SVCs must therefore be <=3, where value zero is used when un-mapping memory. Furthermore it appears that only regular heap pages can be mirrored (it won't work for TLS, stack, .data, .text, for example).<br />
<br />
Bitmask 0xF00 for ControlMemory parameter MemoryType is the memory-type, when this is zero the memory-type is loaded from the kernel flags stored in the exheader ARM11 kernel descriptors, for the process using the SVC.<br />
<br />
ControlMemory parameter MemoryType with value 0x10003 is used for mapping the GSP [[Memory_layout|heap]]. The low 8-bits are the type: 1 is for un-mapping memory, 3 for mapping memory. Type4 is used to mirror the RW memory at Addr1, to Addr0. Type4 will return an error if Addr1 is located in read-only memory. Addr1 is not used for type1 and type3.<br />
<br />
The ARM11 kernel does not allow processes to create shared memory blocks via svcCreateMemoryBlock, when the process memorytype (from the kernel flags stored in the exheader kernel descriptor) is the application memorytype, and when addr=0. When the memorytype is not the application memorytype and addr=0, the kernel allocates new memory for the calling process and turns it into a shared memory block. When addr is non-zero, it must be located in memory which is already mapped. Furthermore, it appears that only regular heap pages (allocated using svcControlMemory op=COMMIT) are accepted as valid addrs.<br />
<br />
ControlProcessMemory maps memory in the specified process, this is the only SVC which allows mapping executable memory. Format of the permissions field for memory mapping SVCs: bit0=R, bit1=W, bit2=X. Type6 sets the Addr0 memory permissions to the input permissions, for already mapped memory. Type is the MemoryOperation enum, without the memory-type/memory-region. ControlProcessMemory only supports type4, type5, and type6. ControlProcessMemory does not support using the current KProcess handle alias.<br />
<br />
MapProcessMemory maps RW memory starting at address 0x00100000 in the specified KProcess, at the specified StartAddr in the current process. MapProcessMemory then maps 0x08000000 in the specified process, to StartAddr+0x7f00000 in the current process. UnmapProcessMemory unmaps the memory which was mapped by MapProcessMemory.<br />
<br />
Note that with the MAP MemoryOperation, the kernel will refuse to MAP memory for the specified addr1, when addr1 was already used with another MAP operation as addr1. The kernel also doesn't allow memory to be freed via the FREE MemoryOperation, when other virtual-memory is mapped to this same memory(when the MAP MemoryOperation was used with this memory with addr1).<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 />
= 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 />
= KernelSetState =<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 />
| This initializes the programID for launching [[FIRM]], then triggers launching [[FIRM]]. Param0 is unused. Param1 is the programID-low, and the programID-high is 0x00040138. Param2 is used only with the [[New_3DS]] kernel, pm-module uses value 0 with this. With New3DS kernel, it forces the programIDlow to be the New3DS NATIVE_FIRM, when the input programIDlow is for the Old3DS NATIVE_FIRM and Param2==0.<br />
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 />
| Unknown, does nothing with the TWL_FIRM ARM11 kernel.<br />
|-<br />
| 2<br />
| Yes<br />
| Yes<br />
| Unknown.<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 />
| This used for initializing the 0x1000-byte buffer used by the launched [[FIRM]]. Param2 is unused. When Param0 is value 1, this buffer is copied to the beginning of FCRAM at 0xF0000000, and Param1 is unused. When Param0 is value 0, this kernel buffer is mapped to process address Param1.<br />
|-<br />
| 4<br />
| No<br />
| Yes<br />
| Param0-Param3 are unused. 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 />
| ?<br />
|-<br />
| 6<br />
| Yes<br />
| No<br />
| Debug related?<br />
|-<br />
| 7<br />
| Yes<br />
| No<br />
| This triggers an MCU (hard) reboot. Param0-3 are unused. 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 unused FIRM launch code-path, with different [[PXI]] FIFO word constants.<br />
|-<br />
| 9<br />
| Yes, implemented at some point after system-version v4.5.<br />
| ?<br />
| Unknown<br />
|-<br />
| 10<br />
| Yes<br />
| ?<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. Param0 = input value. Only bit0-1 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 />
| 9-19<br />
| [[8.0.0-18]]<br />
| This only returns error 0xD8E007ED.<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-23<br />
| [[8.0.0-18]]<br />
| This only returns error 0xE0E01BF4.<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-1 for kernel object (u32), and also a boolean if the refcount-1 is negative (u32).<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 />
= Interrupts =<br />
<br />
{| class="wikitable" border="1"<br />
! Interrupt numbers<br />
! Module using it<br />
|-<br />
| 0x54, 0x55, 0x5C<br />
| I2C<br />
|}<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 />
| 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>
Xerpi
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=16195
SPI Registers
2016-03-25T12:30:37Z
<p>Xerpi: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz/Firmware, 1=2MHz/Touchscr, 2=1MHz/Powerman., 3=512KHz)<br />
|-<br />
| 2-6<br />
| Not used (Zero)<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0-3)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 0-5<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
When the transfer is finished, a 0 is written to this register.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=16194
SPI Registers
2016-03-25T12:19:42Z
<p>Xerpi: Update SPI_NEW_DONE</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz/Firmware, 1=2MHz/Touchscr, 2=1MHz/Powerman., 3=512KHz)<br />
|-<br />
| 2-6<br />
| Not used (Zero)<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0-3)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
When the transfer is finished, a 0 is written to this register.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=16193
CONFIG11 Registers
2016-03-25T12:14:18Z
<p>Xerpi: Update PDN_SPI_CNT</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_SHAREDWRAM_32K_DATA|PDN_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_SHAREDWRAM_32K_CODE|PDN_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| ARM11 interrupt related.<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x1014010C<br />
| 2<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140140<br />
| 2<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_WIFI_CNT|PDN_WIFI_CNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_SPI_CNT|PDN_SPI_CNT]]<br />
| 0x101401C0<br />
| 4<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
| <br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewProcess11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewProcess11<br />
|-<br />
| style="background: red" | No<br />
| [[#PDN_BOOTROM_OVERLAY_CNT|PDN_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 4<br />
| NewProcess11<br />
|-<br />
| style="background: red" | No<br />
| [[#PDN_BOOTROM_OVERLAY_VAL|PDN_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewProcess11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
| <br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#PDN_MPCORE_CFG|PDN_MPCORE_CFG]]<br />
| 0x10140FFC<br />
| 1<br />
| Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| PDN_GPU_STATUS?<br />
| 0x10141000<br />
| 4<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| PDN_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| PDN_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#PDN_TWLMODE_0|PDN_TWLMODE_0]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_TWLMODE_1|PDN_TWLMODE_1]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_TWLMODE_2|PDN_TWLMODE_2]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| <br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| PDN_WIFI?<br />
| 0x1014110C<br />
| 1<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_CODEC|PDN_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[CODEC Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_CODEC|PDN_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[CODEC Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#PDN_GPU_CNT|PDN_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_GPU_CNT2|PDN_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| PDN_GPU_CNT3<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_CODEC_CNT|PDN_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#PDN_CAMERA_CNT|PDN_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| PDN_DSP_CNT<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#PDN_MPCORE_CLKCNT|PDN_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewProcess11<br />
|-<br />
| style="background: red" | No<br />
| [[#PDN_MPCORE_CNT|PDN_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewProcess11<br />
|-<br />
| style="background: red" | No<br />
| [[#PDN_MPCORE_BOOTCNT<0-3>|PDN_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewProcess11<br />
|}<br />
<br />
== PDN_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== PDN_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== PDN_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160000.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142000.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143000.<br />
|}<br />
<br />
== PDN_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== PDN_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#PDN_MPCORE_BOOTCNT|PDN_MPCORE_BOOTCNT]].<br />
<br />
== PDN_MPCORE_CFG ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Always set to 1 on both Old3DS and New3DS.<br />
|-<br />
| 1<br />
| 3rd ARM11 MPCore available maybe?<br />
|-<br />
| 2<br />
| 4th ARM11 MPCore available maybe?<br />
|}<br />
<br />
== PDN_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of PDN_MPCORE_CFG:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! PDN_MPCORE_CFG bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above PDN_MPCORE_CFG bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== PDN_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Power on 3rd ARM11 MPCore maybe?<br />
|-<br />
| 8<br />
| Power on 4th ARM11 MPCore maybe?<br />
|}<br />
<br />
== PDN_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#PDN_BOOTROM_OVERLAY_VAL|PDN_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#PDN_BOOTROM_OVERLAY_VAL|PDN_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==PDN_WIFI_CNT==<br />
Bit0: Enable wifi.<br />
<br />
==PDN_TWLMODE_0==<br />
Observed 0x8001 when running under TWL_ and AGB_FIRM, 0 NATIVE_FIRM.<br />
<br />
This address is poked from ARM7 to signal that it has booted and begun executing code. The ARM7-mode address for this register is 0x4700000.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
Writing 0x8000 to here from the ARM9 with NATIVE_FIRM running doesn't seem to do anything, other reg-pokes likely need done first.<br />
<br />
==PDN_TWLMODE_1==<br />
Observed 0x8000 when running under TWL_FIRM, 0 NATIVE_FIRM.<br />
<br />
==PDN_GPU_CNT==<br />
This one seems to control the LCD/GPU/Backlight.<br />
<br />
Bit0: Enable GPU registers at 0x10400000+.<br />
Bit16: Turn on LCD backlight.<br />
<br />
==PDN_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==PDN_GPU_CNT3==<br />
Bit1: FCRAM access from ARM11? Clearing this bit in 3DS-mode causes the ARM11 and ARM9 to hang/crash.<br />
<br />
==PDN_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==PDN_CODEC_CNT==<br />
This is the power register used for the [[PDN_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==PDN_CAMERA_CNT==<br />
This is the power register used for the [[PDN_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Homebrew_Applications&diff=10760
Homebrew Applications
2014-11-19T21:42:13Z
<p>Xerpi: </p>
<hr />
<div>{| class="wikitable" border="1"<br />
! Category<br />
! Name<br />
! Description<br />
! Author<br />
! Download<br />
! Open-Source<br />
|-<br />
| Game<br />
| [https://github.com/smealum/yeti3DS Yeti3DS]<br />
| A quick and dirty port of Derek Evans' Yeti3D software rendering engine.<br />
| [[User:smea|smea]]<br />
| N/A<br />
| Yes<br />
|-<br />
| Game<br />
| [https://github.com/smealum/3dscraft 3DSCraft]<br />
| Minecraft clone.<br />
| [[User:smea|smea]]<br />
| N/A<br />
| Yes<br />
|-<br />
| Emulator<br />
| [https://github.com/StapleButter/blargSnes blargSnes]<br />
| A Super Nintendo emulator.<br />
| StapleButter<br />
| N/A<br />
| Yes<br />
|-<br />
| Emulator<br />
| [https://github.com/Drenn1/GameYob/tree/master/platform/3ds GameYob]<br />
| A Game Boy (Color) emulator.<br />
| Drenn<br />
| N/A<br />
| Yes<br />
|-<br />
| Emulator<br />
| [https://github.com/st4rk/3DNES 3DNES]<br />
| An NES emulator.<br />
| St4rk<br />
| N/A<br />
| Yes<br />
|-<br />
|-<br />
| Emulator<br />
| [https://github.com/xerpi/CHIP-3DS CHIP-3DS]<br />
| A simple and slow CHIP-8 emulator.<br />
| xerpi<br />
| N/A<br />
| Yes<br />
|-<br />
| Application<br />
| [https://github.com/smealum/ftPONY ftPONY]<br />
| A basic FTP server, useful for testing new homebrew versions without swapping the SD card.<br />
| [[User:smea|smea]]<br />
| N/A<br />
| Yes<br />
|-<br />
| Application<br />
| [https://github.com/plutooo/ctrrpc ctrrpc]<br />
| A small and easily extensible RPC server/client written in C/Python. Allows you to quickly poke service-commands and syscalls over wifi from a Python shell on your PC. Useful during reverse-engineering.<br />
| [[User:plutooo|plutoo]]<br />
| N/A<br />
| Yes<br />
|-<br />
| Application<br />
| [https://github.com/yellows8/ctr-streaming-server ctr-streaming-server]<br />
| This is a server which runs on a 3DS, which receives audio/video for playback. This can also send [[HID_Shared_Memory|HID]] state to the client (see the README) when enabled. The included parse_hidstream tool can be used to parse that HID data to simulate keyboard/mouse input events, via Linux uinput.<br />
| [[User:yellows8|yellows8]]<br />
| N/A<br />
| Yes<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=3DSX_Format&diff=10698
3DSX Format
2014-11-15T13:11:24Z
<p>Xerpi: </p>
<hr />
<div>The 3DSX format is an executable file-format designed for homebrew applications on the 3DS.<br />
<br />
The file is structured like this:<br />
* Header<br />
* Code relocation table header<br />
* Rodata relocation table header<br />
* Data relocation table header<br />
* Code segment<br />
* Rodata segment<br />
* Data segment<br />
* Code relocation table<br />
* Rodata relocation table<br />
* Data relocation table<br />
<br />
== Header ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 4<br />
| Magic (3DSX)<br />
|-<br />
| 0x4<br />
| 2<br />
| Header size<br />
|-<br />
| 0x6<br />
| 2<br />
| Relocation Header size<br />
|-<br />
| 0x8<br />
| 4<br />
| Format version<br />
|-<br />
| 0xC<br />
| 4<br />
| Flags<br />
|-<br />
| 0x10<br />
| 4<br />
| Code segment size<br />
|-<br />
| 0x14<br />
| 4<br />
| Rodata segment size<br />
|-<br />
| 0x18<br />
| 4<br />
| Data segment size (including bss)<br />
|-<br />
| 0x1C<br />
| 4<br />
| Bss segment size<br />
|}<br />
<br />
== Relocation Header ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 4<br />
| Number of absolute relocations<br />
|-<br />
| 0x4<br />
| 4<br />
| Number of relative relocations<br />
|}<br />
<br />
== Relocation ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 2<br />
| Number of words to skip<br />
|-<br />
| 0x2<br />
| 2<br />
| Number of words to patch<br />
|}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=User:Xerpi&diff=8342
User:Xerpi
2013-12-28T15:01:46Z
<p>Xerpi: </p>
<hr />
<div>* Twitter: @xerpi<br />
* e-mail: xerpi.g.12@gmail.com</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=EShop/es&diff=2111
EShop/es
2012-01-01T09:42:33Z
<p>Xerpi: </p>
<hr />
<div>La Nintendo 3DS eShop fue añadida en la actualización de junio de 2011 para JP/EUR/USA.<br />
<br />
Permite descargar juegos de la Consola Virtual, 3D Classics, software de DSi y ver imágenes y tráilers 3D de futuros títulos de Nintendo 3DS.<br />
<br />
Al conectar con los servidores, la eShop realiza las siguientes peticiones sobre HTTPS: nus.c.shop.nintendowifi.net, ecs.c.shop.nintendowifi.net, cp3s-auth.c.shop.nintendowifi.net, cas.c.shop.nintendowifi.net, y a248.e.akamai.net.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Savegames/es&diff=2094
Savegames/es
2011-12-30T13:34:14Z
<p>Xerpi: </p>
<hr />
<div>Esta página describe el formato, la des/encriptación, etc de las partidas guardadas de los cartuchos de los juegos de la 3DS. Puedes encontrar partidas guardadas de varios juegos de la 3DS en la página de [[Games/es|Juegos]].<br />
<br />
<br />
=== Encriptación ===<br />
<br />
En la 3DS las partidas se almacenan de una forma similar a la DS, en un chip FLASH en el cartucho del juego. En la DS estas partidas están en formato de texto plano pero en la 3DS se añade una capa de encriptación. Esto se parece mucho a un flujo de cifrado, donde los contenidos de algunas partidas tienen un comportamiento extraño cuando se XORean algunas partes juntas de la partida y da como resultado un archivo de texto plano.<br />
<br />
La razón por la que esto funciona es porque el cifrado usado tiene un tamaño de 512 bytes. Que es lo mismo, se va repitiendo la misma clave cada 512 bytes. La forma de encriptar con un cifrado es la producida por una clave XOR. Por desgracia, si se repite la clave y estás encriptando un texto plano conocido (en nuestro caso, ceros) básicamente estás “regalando” tu clave.<br />
<br />
Entonces, ¿cómo puedo utilizar esto para desencriptar una partida guardada en una 3DS? En primer lugar, tienes que dividir la partida en chunks (trozos) de 512 bytes. Entonces, debes seleccionar los chunks por su contenido, descartando los que solo contengan FF. Ahora debes buscar el chunk más común. Esta es la clave. Ahora XORea con la clave que acabas de encontrar la partida original y deberías obtener la partida completamente desencriptada. Si vuelves a XORear con la clave a la partida desencriptada volverás a obtener la partida completamente encriptada. <br />
<br />
Actualización:<br />
<br />
Desde el firmware 2.0.0-4 Nintendo ha introducido una nueva forma de encriptación (podría ser una solución para la exploit de más arriba). El xorpad parece repetirse en el archivo pero no cada 0x200 bytes. Así que por ahora no se sabe cómo descifrar las nuevas partidas.<br />
<br />
'''Juegos que usan la nueva encriptación:'''<br />
* Super Mario 3D Land<br />
* Mario Kart 7<br />
* Need for Speed - The Run<br />
<br />
'''Más información:'''<br />
*Los juegos viejos aún usan el antiguo xorpad de 0x200 bytes.<br />
*Los juegos nuevos puedes ser copiados y restaurados (se usa la misma clava tanto una partida como para otra)<br />
* El wearleveling sigue siendo el mismo.<br />
*XOReando dos archivos juntos puede producir algo de texto claro.<br />
*Se ha observado que el xorpad se repite cada 0x1000 bytes (podría ser la longitud máxima pero aún no se ha probado).<br />
<br />
=== Nivel de desgaste ===<br />
<br />
La 3DS utiliza un esquema para prevenir el nivel de desgaste de los chips FLASH de las partidas. Eso lo consigue utilizando blockmaps i un journal. El blockmap se encuentra en el offset 0 del chip, y es seguido inmediatamente por el journal. El estado inicial es dictado por el blockmap, y el journal es entonces aplicado.<br />
<br />
Primero hay 8 bytes cuyos fines se desconocen aún. Luego viene el blockmap.<br />
La estructura del blockmap es simple:<br />
<pre><br />
struct header_entry {<br />
uint8_t phys_sec; // cuando se establece el sépitmo bit, el bloque tiene checksums, de lo contrario los checksums son cero<br />
uint8_t alloc_cnt;<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
</pre><br />
<br />
Hay un journal por sector, contando desde el sector físico 1(el sector 0 contiene el blockmap/journal).<br />
Los siguientes dos bytes que siguen al blockmap son el CRC16 (con 0xFFFF como valor inicial (como el modbus)) de los primeros 8 bytes del blockmap.<br />
<br />
Entonces hay el journal.<br />
La estructura del journal es:<br />
<pre><br />
struct sector_entry {<br />
uint8_t virt_sec; // Asignado al sector<br />
uint8_t prev_virt_sec; // Sector físico previamente asignado<br />
uint8_t phys_sec; // Asignado desde el sector<br />
uint8_t prev_phys_sec; // Sector virtual previamente asignado<br />
uint8_t phys_realloc_cnt; // Cantidas de veces que el sector físico ha sido reasignado<br />
uint8_t virt_realloc_cnt; // Cantidas de veces que el sector virtual ha sido reasignado<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
<br />
struct long_sector_entry{<br />
struct sector_entry sector;<br />
struct sector_entry dupe;<br />
uint32_t magic;<br />
}__attribute__((__packed__));<br />
</pre><br />
<br />
Con la constante mágica 0x080d6ce0.<br />
<br />
Los checksums de las entradas del blockmap/journal trabajan de la siguiente forma:<br />
* cada byte es el checksum de un bloque de tamaño 0x200 bytes encriptado<br />
* para calcular el checksum, el CRC16 del bloque ( con el valor iniciar 0xFFFF) es calculado, y los dos bytes del CRC16 son XOReados juntos para producir un checksum de 8 bits.<br />
<br />
=== Particiones===<br />
<br />
Puede haber múltiples particiones en el chip. <br />
Las particiones están representadas por tablas de manchas del DIFI dentro de la estructura DISA.<br />
El orden de las manchas del DIFI es el orden de las particiones del chip.<br />
<br />
'''DISA'''<br />
<br />
* If the uint32 @ 0x168 into the image in the DISA is a %1=1, then first table is is hashed, otherwise the second DIFI table is hashed. <br />
* If the table has more then 1 DIFI then the uint32 @ 0x168 is the offset from the DATA partition to the file base (masked with 0xFFFFFFFE).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Principio<br />
! Longitud<br />
! Descripción<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DISA")<br />
|-<br />
| 0x04<br />
| 4<br />
| Desconocido (puede ser mágico, puede ser el mismo que todas las partidas)<br />
|-<br />
| 0x08<br />
| 8<br />
| Tamaño de la tabla de particiones<br />
|-<br />
| 0x10<br />
| 8<br />
| Offset a la partición primaria de la tabla del DISA<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset a la partición secundaria de la tabla del DISA<br />
|-<br />
| 0x20<br />
| 8<br />
| Longitud de la tabla de particiones<br />
|-<br />
| 0x28<br />
| 8<br />
| Offset de la entrada de guardado en la tabla de particiones<br />
|-<br />
| 0x30<br />
| 8<br />
| Longitud de la entrada de guardado en la tabla de particiones<br />
|-<br />
| 0x38<br />
| 8<br />
| Offset de la entrada de datos en la tabla de particiones<br />
|-<br />
| 0x40<br />
| 8<br />
| Longitud de la entrada de datos en la tabla de particiones<br />
|-<br />
| 0x48<br />
| 8<br />
| Offset de la partición de guardado<br />
|-<br />
| 0x50<br />
| 8<br />
| Longitud de la partición de guardado<br />
|-<br />
| 0x58<br />
| 8<br />
| Offset de la partición de datos<br />
|-<br />
| 0x60<br />
| 8<br />
| Longitud de la partición de datos<br />
|-<br />
| 0x68<br />
| 4<br />
| Tabla activa (y el offset hacia la filebase)<br />
|-<br />
| 0x6C<br />
| 0x20<br />
| Hash desde la partición activa<br />
|-<br />
| 0x8C<br />
| 4*29<br />
| Desconocido<br />
|}<br />
<br />
* The hash in the DISA hashes the Active Table (starting from tables's offset to tables's offset + table length) with SHA256.<br />
<br />
* The partitions offsets points to a 0x1000 long block which isn't understood yet. The actual information starts after that block.<br />
<br />
The DIFIs table @ 0x200 (into the image) is written twice, (Meaning, if there's 4 DIFI blobs then the table is 2 DIFIs long).<br />
<br />
The second table is for backup. The active table is mentioned at 0x13C into the image (1=First table, other=Second Table)<br />
<br />
'''DIFI'''<br />
<br />
These 0x130 large blobs describe the partitions. Every DIFI blob describes a partition. Partitions are catted together, so after the end of one partition is the beginning of the next.<br />
<br />
Actually DIFI blobs are 0x12C large because the last 4 are not used and appear 0xFFFFFFFF at the encrypted image.<br />
<br />
For most games there's only 1 partition (The SAVE partition) and some (like Asphalt 3D, Steel Diver & Lego Star Wars III) has 2 partitions.<br />
<br />
* 2 Partitions means that the files inside the SAVE partition is on the other partition (we would call it DATA partition).<br />
<br />
* No more than 2 partitions have been seen yet (and can't be becuase of the DISA known structure).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DIFI")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset to "IVFC" blob in DIFI (usually 0x44)<br />
|-<br />
| 0x10<br />
| 8<br />
| Size of "IVFC" blob<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset to "DPFS" blob in DIFI (usually 0xBC)<br />
|-<br />
| 0x20<br />
| 8<br />
| Size of "DPFS" blob<br />
|-<br />
| 0x28<br />
| 8<br />
| Offset to the hash in DIFI (usually 0x010C)<br />
|-<br />
| 0x30<br />
| 8<br />
| Size of this hash<br />
|-<br />
| 0x38<br />
| 4<br />
| Flags (1 means DATA partition)<br />
|-<br />
| 0x3C<br />
| 8<br />
| File base offset (for DATA partitions)<br />
|}<br />
<br />
'''IVFC'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("IVFC")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x20000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown (0x20?)<br />
|-<br />
| 0x10<br />
| 8<br />
| First Hash Offset<br />
|-<br />
| 0x18<br />
| 8<br />
| First Hash Length<br />
|-<br />
| 0x20<br />
| 8<br />
| First Hash Block Size (1<<value)<br />
|-<br />
| 0x28<br />
| 8<br />
| Second Hash Offset<br />
|-<br />
| 0x30<br />
| 8<br />
| Second Hash Length<br />
|-<br />
| 0x38<br />
| 8<br />
| Second Hash Block Size (1<<value)<br />
|-<br />
| 0x40<br />
| 8<br />
| HashTable Offset<br />
|-<br />
| 0x48<br />
| 8<br />
| HashTable Length<br />
|-<br />
| 0x50<br />
| 8<br />
| HashTable Block Size (1<<value)<br />
|-<br />
| 0x58<br />
| 8<br />
| FileSystem Offset<br />
|-<br />
| 0x60<br />
| 8<br />
| FileSystem Length<br />
|-<br />
| 0x68<br />
| 8<br />
| FileSystem Block Size (1<<value)<br />
|-<br />
| 0x70<br />
| 8<br />
| Unknown (usually 0x78=120)<br />
|-<br />
|}<br />
<br />
* First & Second hash are not understood yet.<br />
<br />
'''DPFS'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DPFS")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset To First table<br />
|-<br />
| 0x10<br />
| 8<br />
| First table length<br />
|-<br />
| 0x18<br />
| 8<br />
| First table block size (1<<value)<br />
|-<br />
| 0x20<br />
| 8<br />
| Offset To Second table<br />
|-<br />
| 0x28<br />
| 8<br />
| Second table length<br />
|-<br />
| 0x30<br />
| 8<br />
| Second table block size (1<<value)<br />
|-<br />
| 0x38<br />
| 8<br />
| Offset to Data<br />
|-<br />
| 0x40<br />
| 8<br />
| Data Length<br />
|-<br />
| 0x48<br />
| 8<br />
| Data block size (1<<value)<br />
|-<br />
|}<br />
<br />
* Every block this table point to is written twice (concatenated). You can see that the offset to the next block is twice the length (except the data which always begin after 0x1000).<br />
<br />
The first partition's data starts at 0x2000. First comes the hashtable (usually start @ 0x40 into the partition) and then the filesystem.<br />
<br />
The hashtable entries' size is 2^x where x is the 'Hashed block size' from the IVFC block.<br />
<br />
'''Hash'''<br />
<br />
After the DIFI,IVFC & DPFS comes a 0x20 long hash, it is unknown what it's hashing.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfimg_drawing.png]]<br />
<br />
==== The SAVE partition ====<br />
<br />
* The SAVE filesystem works with a backup. There are two SAVE blocks inside the partition concatenated. Which SAVE block is the updated one is unknown yet.. (I'm guessing from experience that (image[0x100B] & 0x20) == 0x20 --> 1st SAVE --[[User:Elisherer|Elisherer]] 01:30, 18 October 2011 (CEST))<br />
<br />
'''Finding the folders table:'''<br />
* If DATA partition exists: At folder table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'folder table offset' * 'folder table media' (=0x200) from the 'filestore offset'. (usually 0 from filebase)<br />
<br />
'''Finding the files table:'''<br />
* If DATA partition exists: At file table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'file table offset' * 'file table media' (=0x200) from the 'filestore offset'.<br />
<br />
'''Detemining the filestore base:'''<br />
* If DATA partition exists: At file base from the DATA's DIFI struct into the DATA partition.<br />
* Otherwise: At the 'filestore offset' from the beginning of the SAVE struct.<br />
<br />
Folder's entry structure:<br />
<pre><br />
struct folder_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 folder_index;<br />
u32 unk1; <br />
u32 last_file_index;<br />
u32 unk3; <br />
u32 unk4;<br />
}<br />
</pre><br />
<br />
File's entry structure:<br />
<pre><br />
struct file_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 index;<br />
u32 unk1; // magic?<br />
u32 block_offset;<br />
u64 file_size;<br />
u32 unk2; // flags?<br />
u32 unk3;<br />
}<br />
</pre><br />
<br />
The first entry in both tables is the count of the table, the parent directory index will be the amount of table rows. The root includes itself, so there are the amount - 1 (minus one) folders in the root directory (or files). The entries that follow after the root are the actual folders/files.<br />
<br />
Reading the files out is as simple as taking the file base offset and adding (block_offset * 0x200) to it.<br />
<br />
Here's a follow-up example from the Legend of Zelda: Ocarina of Time 3D:<br />
<pre><br />
//FST entry = SAVE base + File base + (FST offset * 0x200) + (FST entry # * 0x30)<br />
//0x2600 = 0x2000 + 0x400 + (0x1 * 0x200) + (0x0 * 0x30)<br />
<br />
00002600: 03000000 09000000 00000000 00000000 ................<br />
00002610: 00000000 00000000 00000000 00000000 ................<br />
00002620: 00000000 00000000 00000000 00000000 ................<br />
00002630: 01000000 73797374 656D2E64 61740000 ....system.dat..<br />
00002640: 00000000 00000000 D57B1100 02000000 ........Õ{......<br />
00002650: 22000000 00000000 E8121500 00000000 ".......è.......<br />
00002660: 01000000 73617665 30302E62 696E0000 ....save00.bin..<br />
00002670: 00000000 01000000 69921100 03000000 ........i’......<br />
00002680: DC140000 00000000 04000000 00000000 Ü...............<br />
</pre><br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("SAVE")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic padding<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 8<br />
| Partition Size [medias]<br />
|-<br />
| 0x18<br />
| 4<br />
| Partition Media Size<br />
|-<br />
| 0x1C<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x24<br />
| 4<br />
| Unknown<br />
|-<br />
| 0x28<br />
| 8<br />
| FolderMap Offset<br />
|-<br />
| 0x30<br />
| 4<br />
| FolderMap Size<br />
|-<br />
| 0x34<br />
| 4<br />
| FolderMap Media Size<br />
|-<br />
| 0x38<br />
| 8<br />
| FileMap Offset<br />
|-<br />
| 0x40<br />
| 4<br />
| FileMap Size<br />
|-<br />
| 0x44<br />
| 4<br />
| FileMap Media Size<br />
|-<br />
| 0x48<br />
| 8<br />
| BlockMap Offset<br />
|-<br />
| 0x50<br />
| 4<br />
| BlockMap Size<br />
|-<br />
| 0x54<br />
| 4<br />
| BlockMap Media Size<br />
|-<br />
| 0x58<br />
| 8<br />
| File store offset (from SAVE)<br />
|-<br />
| 0x60<br />
| 4<br />
| File store length [medias]<br />
|-<br />
| 0x64<br />
| 4<br />
| File store media size<br />
|-<br />
| 0x68<br />
| 4/8<br />
| Folders Table offset (8 bytes in DATA)<br />
|-<br />
| 0x6C<br />
| 4<br />
| Folders Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x70<br />
| 4<br />
| Folders Table unknown<br />
|-<br />
| 0x74<br />
| 4<br />
| Folders Table Media size<br />
|-<br />
| 0x78<br />
| 4/8<br />
| Files Table offset (8 bytes in DATA)<br />
|-<br />
| 0x7C<br />
| 4<br />
| Files Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x80<br />
| 4<br />
| Files Table unknown<br />
|-<br />
| 0x84<br />
| 4<br />
| Files Table Media size<br />
|-<br />
|}<br />
<br />
* The FolderMap and FileMap still unknown. They are tables of uint32.<br />
* The BlockMap is a map of the blocks in the filestore. An entry in the BlockMap is 2 uint32: {uint32 start_block; uint32 end_block; }. This is still being researched. (You can use [[3DSExplorer]] to see those maps.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfsave_drawing.png]]<br />
<br />
=== Initialization ===<br />
<br />
When a save EEPROM contains all xFFFF blocks it's assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. <br />
<br />
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter 'Z' (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)<br />
<br />
=== Fun Facts ===<br />
<br />
If you have facts that you found out by looking at the binary files please share them here:<br />
<br />
* From one save to another the game backups the last files that were in the partition and the entire image header in "random" locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Savegames/es&diff=2093
Savegames/es
2011-12-30T13:06:46Z
<p>Xerpi: </p>
<hr />
<div>Esta página describe el formato, la des/encriptación, etc de las partidas guardadas de los cartuchos de los juegos de la 3DS. Puedes encontrar partidas guardadas de varios juegos de la 3DS en la página de [[Games/es|Juegos]].<br />
<br />
<br />
=== Encriptación ===<br />
<br />
En la 3DS las partidas se almacenan de una forma similar a la DS, en un chip FLASH en el cartucho del juego. En la DS estas partidas están en formato de texto plano pero en la 3DS se añade una capa de encriptación. Esto se parece mucho a un flujo de cifrado, donde los contenidos de algunas partidas tienen un comportamiento extraño cuando se XORean algunas partes juntas de la partida y da como resultado un archivo de texto plano.<br />
<br />
La razón por la que esto funciona es porque el cifrado usado tiene un tamaño de 512 bytes. Que es lo mismo, se va repitiendo la misma clave cada 512 bytes. La forma de encriptar con un cifrado es la producida por una clave XOR. Por desgracia, si se repite la clave y estás encriptando un texto plano conocido (en nuestro caso, ceros) básicamente estás “regalando” tu clave.<br />
<br />
Entonces, ¿cómo puedo utilizar esto para desencriptar una partida guardada en una 3DS? En primer lugar, tienes que dividir la partida en chunks (trozos) de 512 bytes. Entonces, debes seleccionar los chunks por su contenido, descartando los que solo contengan FF. Ahora debes buscar el chunk más común. Esta es la clave. Ahora XORea con la clave que acabas de encontrar la partida original y deberías obtener la partida completamente desencriptada. Si vuelves a XORear con la clave a la partida desencriptada volverás a obtener la partida completamente encriptada. <br />
<br />
Actualización:<br />
<br />
Desde el firmware 2.0.0-4 Nintendo ha introducido una nueva forma de encriptación (podría ser una solución para la exploit de más arriba). El xorpad parece repetirse en el archivo pero no cada 0x200 bytes. Así que por ahora no se sabe cómo descifrar las nuevas partidas.<br />
<br />
'''Juegos que usan la nueva encriptación:'''<br />
* Super Mario 3D Land<br />
* Mario Kart 7<br />
* Need for Speed - The Run<br />
<br />
'''Más información:'''<br />
*Los juegos viejos aún usan el antiguo xorpad de 0x200 bytes.<br />
*Los juegos nuevos puedes ser copiados y restaurados (se usa la misma clava tanto una partida como para otra)<br />
* El wearleveling sigue siendo el mismo.<br />
*XOReando dos archivos juntos puede producir algo de texto claro.<br />
*Se ha observado que el xorpad se repite cada 0x1000 bytes (podría ser la longitud máxima pero aún no se ha probado).<br />
<br />
=== Nivel de desgaste ===<br />
<br />
La 3DS utiliza un esquema para prevenir el nivel de desgaste de los chips FLASH de las partidas. Eso lo consigue utilizando blockmaps i un journal. El blockmap se encuentra en el offset 0 del chip, y es seguido inmediatamente por el journal. El estado inicial es dictado por el blockmap, y el journal es entonces aplicado.<br />
<br />
Primero hay 8 bytes cuyos fines se desconocen aún. Luego viene el blockmap.<br />
La estructura del blockmap es simple:<br />
<pre><br />
struct header_entry {<br />
uint8_t phys_sec; // cuando se establece el sépitmo bit, el bloque tiene checksums, de lo contrario los checksums son cero<br />
uint8_t alloc_cnt;<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
</pre><br />
<br />
Hay un journal por sector, contando desde el sector físico 1(el sector 0 contiene el blockmap/journal).<br />
Los siguientes dos bytes que siguen al blockmap son el CRC16 (con 0xFFFF como valor inicial (como el modbus)) de los primeros 8 bytes del blockmap.<br />
<br />
Then comes the journal.<br />
The journal structure is as follows:<br />
<pre><br />
struct sector_entry {<br />
uint8_t virt_sec; // Mapped to sector<br />
uint8_t prev_virt_sec; // Physical sector previously mapped to<br />
uint8_t phys_sec; // Mapped from sector<br />
uint8_t prev_phys_sec; // Virtual sector previously mapped to<br />
uint8_t phys_realloc_cnt; // Amount of times physical sector has been remapped<br />
uint8_t virt_realloc_cnt; // Amount of times virtual sector has been remapped<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
<br />
struct long_sector_entry{<br />
struct sector_entry sector;<br />
struct sector_entry dupe;<br />
uint32_t magic;<br />
}__attribute__((__packed__));<br />
</pre><br />
<br />
With magic being a constant 0x080d6ce0.<br />
<br />
The checksums in the blockmap/journal entries work as follows:<br />
* each byte is the checksum of an encrypted 0x200 bytes large block<br />
* to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum<br />
<br />
=== Partitions ===<br />
<br />
There can be multiple partitions on the chip. <br />
The partitions are represented by tables of DIFI blobs inside a DISA structure.<br />
The order of the DIFI blobs is the order of the partitions in the chip.<br />
<br />
'''DISA'''<br />
<br />
* If the uint32 @ 0x168 into the image in the DISA is a %1=1, then first table is is hashed, otherwise the second DIFI table is hashed. <br />
* If the table has more then 1 DIFI then the uint32 @ 0x168 is the offset from the DATA partition to the file base (masked with 0xFFFFFFFE).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DISA")<br />
|-<br />
| 0x04<br />
| 4<br />
| Unknown (maybe magic, the same in all the save files so far)<br />
|-<br />
| 0x08<br />
| 8<br />
| Partition table size<br />
|-<br />
| 0x10<br />
| 8<br />
| Offset to primary partition table in DISA<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset to secondary partition table in DISA<br />
|-<br />
| 0x20<br />
| 8<br />
| Partition table's length<br />
|-<br />
| 0x28<br />
| 8<br />
| SAVE Partition entry offset in the partition table<br />
|-<br />
| 0x30<br />
| 8<br />
| SAVE Partition entry length in the partition table<br />
|-<br />
| 0x38<br />
| 8<br />
| DATA Partition entry offset in the partition table<br />
|-<br />
| 0x40<br />
| 8<br />
| DATA Partition entry length in the partition table<br />
|-<br />
| 0x48<br />
| 8<br />
| SAVE Partition offset<br />
|-<br />
| 0x50<br />
| 8<br />
| SAVE Partition length<br />
|-<br />
| 0x58<br />
| 8<br />
| DATA Partition offset<br />
|-<br />
| 0x60<br />
| 8<br />
| DATA Partition length<br />
|-<br />
| 0x68<br />
| 4<br />
| Active table (and the offset to the filebase)<br />
|-<br />
| 0x6C<br />
| 0x20<br />
| Hash from active table<br />
|-<br />
| 0x8C<br />
| 4*29<br />
| Unknown<br />
|}<br />
<br />
* The hash in the DISA hashes the Active Table (starting from tables's offset to tables's offset + table length) with SHA256.<br />
<br />
* The partitions offsets points to a 0x1000 long block which isn't understood yet. The actual information starts after that block.<br />
<br />
The DIFIs table @ 0x200 (into the image) is written twice, (Meaning, if there's 4 DIFI blobs then the table is 2 DIFIs long).<br />
<br />
The second table is for backup. The active table is mentioned at 0x13C into the image (1=First table, other=Second Table)<br />
<br />
'''DIFI'''<br />
<br />
These 0x130 large blobs describe the partitions. Every DIFI blob describes a partition. Partitions are catted together, so after the end of one partition is the beginning of the next.<br />
<br />
Actually DIFI blobs are 0x12C large because the last 4 are not used and appear 0xFFFFFFFF at the encrypted image.<br />
<br />
For most games there's only 1 partition (The SAVE partition) and some (like Asphalt 3D, Steel Diver & Lego Star Wars III) has 2 partitions.<br />
<br />
* 2 Partitions means that the files inside the SAVE partition is on the other partition (we would call it DATA partition).<br />
<br />
* No more than 2 partitions have been seen yet (and can't be becuase of the DISA known structure).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DIFI")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset to "IVFC" blob in DIFI (usually 0x44)<br />
|-<br />
| 0x10<br />
| 8<br />
| Size of "IVFC" blob<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset to "DPFS" blob in DIFI (usually 0xBC)<br />
|-<br />
| 0x20<br />
| 8<br />
| Size of "DPFS" blob<br />
|-<br />
| 0x28<br />
| 8<br />
| Offset to the hash in DIFI (usually 0x010C)<br />
|-<br />
| 0x30<br />
| 8<br />
| Size of this hash<br />
|-<br />
| 0x38<br />
| 4<br />
| Flags (1 means DATA partition)<br />
|-<br />
| 0x3C<br />
| 8<br />
| File base offset (for DATA partitions)<br />
|}<br />
<br />
'''IVFC'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("IVFC")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x20000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown (0x20?)<br />
|-<br />
| 0x10<br />
| 8<br />
| First Hash Offset<br />
|-<br />
| 0x18<br />
| 8<br />
| First Hash Length<br />
|-<br />
| 0x20<br />
| 8<br />
| First Hash Block Size (1<<value)<br />
|-<br />
| 0x28<br />
| 8<br />
| Second Hash Offset<br />
|-<br />
| 0x30<br />
| 8<br />
| Second Hash Length<br />
|-<br />
| 0x38<br />
| 8<br />
| Second Hash Block Size (1<<value)<br />
|-<br />
| 0x40<br />
| 8<br />
| HashTable Offset<br />
|-<br />
| 0x48<br />
| 8<br />
| HashTable Length<br />
|-<br />
| 0x50<br />
| 8<br />
| HashTable Block Size (1<<value)<br />
|-<br />
| 0x58<br />
| 8<br />
| FileSystem Offset<br />
|-<br />
| 0x60<br />
| 8<br />
| FileSystem Length<br />
|-<br />
| 0x68<br />
| 8<br />
| FileSystem Block Size (1<<value)<br />
|-<br />
| 0x70<br />
| 8<br />
| Unknown (usually 0x78=120)<br />
|-<br />
|}<br />
<br />
* First & Second hash are not understood yet.<br />
<br />
'''DPFS'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DPFS")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset To First table<br />
|-<br />
| 0x10<br />
| 8<br />
| First table length<br />
|-<br />
| 0x18<br />
| 8<br />
| First table block size (1<<value)<br />
|-<br />
| 0x20<br />
| 8<br />
| Offset To Second table<br />
|-<br />
| 0x28<br />
| 8<br />
| Second table length<br />
|-<br />
| 0x30<br />
| 8<br />
| Second table block size (1<<value)<br />
|-<br />
| 0x38<br />
| 8<br />
| Offset to Data<br />
|-<br />
| 0x40<br />
| 8<br />
| Data Length<br />
|-<br />
| 0x48<br />
| 8<br />
| Data block size (1<<value)<br />
|-<br />
|}<br />
<br />
* Every block this table point to is written twice (concatenated). You can see that the offset to the next block is twice the length (except the data which always begin after 0x1000).<br />
<br />
The first partition's data starts at 0x2000. First comes the hashtable (usually start @ 0x40 into the partition) and then the filesystem.<br />
<br />
The hashtable entries' size is 2^x where x is the 'Hashed block size' from the IVFC block.<br />
<br />
'''Hash'''<br />
<br />
After the DIFI,IVFC & DPFS comes a 0x20 long hash, it is unknown what it's hashing.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfimg_drawing.png]]<br />
<br />
==== The SAVE partition ====<br />
<br />
* The SAVE filesystem works with a backup. There are two SAVE blocks inside the partition concatenated. Which SAVE block is the updated one is unknown yet.. (I'm guessing from experience that (image[0x100B] & 0x20) == 0x20 --> 1st SAVE --[[User:Elisherer|Elisherer]] 01:30, 18 October 2011 (CEST))<br />
<br />
'''Finding the folders table:'''<br />
* If DATA partition exists: At folder table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'folder table offset' * 'folder table media' (=0x200) from the 'filestore offset'. (usually 0 from filebase)<br />
<br />
'''Finding the files table:'''<br />
* If DATA partition exists: At file table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'file table offset' * 'file table media' (=0x200) from the 'filestore offset'.<br />
<br />
'''Detemining the filestore base:'''<br />
* If DATA partition exists: At file base from the DATA's DIFI struct into the DATA partition.<br />
* Otherwise: At the 'filestore offset' from the beginning of the SAVE struct.<br />
<br />
Folder's entry structure:<br />
<pre><br />
struct folder_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 folder_index;<br />
u32 unk1; <br />
u32 last_file_index;<br />
u32 unk3; <br />
u32 unk4;<br />
}<br />
</pre><br />
<br />
File's entry structure:<br />
<pre><br />
struct file_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 index;<br />
u32 unk1; // magic?<br />
u32 block_offset;<br />
u64 file_size;<br />
u32 unk2; // flags?<br />
u32 unk3;<br />
}<br />
</pre><br />
<br />
The first entry in both tables is the count of the table, the parent directory index will be the amount of table rows. The root includes itself, so there are the amount - 1 (minus one) folders in the root directory (or files). The entries that follow after the root are the actual folders/files.<br />
<br />
Reading the files out is as simple as taking the file base offset and adding (block_offset * 0x200) to it.<br />
<br />
Here's a follow-up example from the Legend of Zelda: Ocarina of Time 3D:<br />
<pre><br />
//FST entry = SAVE base + File base + (FST offset * 0x200) + (FST entry # * 0x30)<br />
//0x2600 = 0x2000 + 0x400 + (0x1 * 0x200) + (0x0 * 0x30)<br />
<br />
00002600: 03000000 09000000 00000000 00000000 ................<br />
00002610: 00000000 00000000 00000000 00000000 ................<br />
00002620: 00000000 00000000 00000000 00000000 ................<br />
00002630: 01000000 73797374 656D2E64 61740000 ....system.dat..<br />
00002640: 00000000 00000000 D57B1100 02000000 ........Õ{......<br />
00002650: 22000000 00000000 E8121500 00000000 ".......è.......<br />
00002660: 01000000 73617665 30302E62 696E0000 ....save00.bin..<br />
00002670: 00000000 01000000 69921100 03000000 ........i’......<br />
00002680: DC140000 00000000 04000000 00000000 Ü...............<br />
</pre><br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("SAVE")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic padding<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 8<br />
| Partition Size [medias]<br />
|-<br />
| 0x18<br />
| 4<br />
| Partition Media Size<br />
|-<br />
| 0x1C<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x24<br />
| 4<br />
| Unknown<br />
|-<br />
| 0x28<br />
| 8<br />
| FolderMap Offset<br />
|-<br />
| 0x30<br />
| 4<br />
| FolderMap Size<br />
|-<br />
| 0x34<br />
| 4<br />
| FolderMap Media Size<br />
|-<br />
| 0x38<br />
| 8<br />
| FileMap Offset<br />
|-<br />
| 0x40<br />
| 4<br />
| FileMap Size<br />
|-<br />
| 0x44<br />
| 4<br />
| FileMap Media Size<br />
|-<br />
| 0x48<br />
| 8<br />
| BlockMap Offset<br />
|-<br />
| 0x50<br />
| 4<br />
| BlockMap Size<br />
|-<br />
| 0x54<br />
| 4<br />
| BlockMap Media Size<br />
|-<br />
| 0x58<br />
| 8<br />
| File store offset (from SAVE)<br />
|-<br />
| 0x60<br />
| 4<br />
| File store length [medias]<br />
|-<br />
| 0x64<br />
| 4<br />
| File store media size<br />
|-<br />
| 0x68<br />
| 4/8<br />
| Folders Table offset (8 bytes in DATA)<br />
|-<br />
| 0x6C<br />
| 4<br />
| Folders Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x70<br />
| 4<br />
| Folders Table unknown<br />
|-<br />
| 0x74<br />
| 4<br />
| Folders Table Media size<br />
|-<br />
| 0x78<br />
| 4/8<br />
| Files Table offset (8 bytes in DATA)<br />
|-<br />
| 0x7C<br />
| 4<br />
| Files Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x80<br />
| 4<br />
| Files Table unknown<br />
|-<br />
| 0x84<br />
| 4<br />
| Files Table Media size<br />
|-<br />
|}<br />
<br />
* The FolderMap and FileMap still unknown. They are tables of uint32.<br />
* The BlockMap is a map of the blocks in the filestore. An entry in the BlockMap is 2 uint32: {uint32 start_block; uint32 end_block; }. This is still being researched. (You can use [[3DSExplorer]] to see those maps.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfsave_drawing.png]]<br />
<br />
=== Initialization ===<br />
<br />
When a save EEPROM contains all xFFFF blocks it's assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. <br />
<br />
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter 'Z' (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)<br />
<br />
=== Fun Facts ===<br />
<br />
If you have facts that you found out by looking at the binary files please share them here:<br />
<br />
* From one save to another the game backups the last files that were in the partition and the entire image header in "random" locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Savegames/es&diff=2092
Savegames/es
2011-12-30T12:48:14Z
<p>Xerpi: </p>
<hr />
<div>Esta página describe el formato, la des/encriptación, etc de las partidas guardadas de los cartuchos de los juegos de la 3DS. Puedes encontrar partidas guardadas de varios juegos de la 3DS en la página de [[Games/es|Juegos]].<br />
<br />
<br />
=== Encriptación ===<br />
<br />
En la 3DS las partidas se almacenan de una forma similar a la DS, en un chip FLASH en el cartucho del juego. En la DS estas partidas están en formato de texto plano pero en la 3DS se añade una capa de encriptación. Esto se parece mucho a un flujo de cifrado, donde los contenidos de algunas partidas tienen un comportamiento extraño cuando se XORean algunas partes juntas de la partida y da como resultado un archivo de texto plano.<br />
<br />
La razón por la que esto funciona es porque el cifrado usado tiene un tamaño de 512 bytes. Que es lo mismo, se va repitiendo la misma clave cada 512 bytes. La forma de encriptar con un cifrado es la producida por una clave XOR. Por desgracia, si se repite la clave y estás encriptando un texto plano conocido (en nuestro caso, ceros) básicamente estás “regalando” tu clave.<br />
<br />
Entonces, ¿cómo puedo utilizar esto para desencriptar una partida guardada en una 3DS? En primer lugar, tienes que dividir la partida en chunks (trozos) de 512 bytes. Entonces, debes seleccionar los chunks por su contenido, descartando los que solo contengan FF. Ahora debes buscar el chunk más común. Esta es la clave. Ahora XORea con la clave que acabas de encontrar la partida original y deberías obtener la partida completamente desencriptada. Si vuelves a XORear con la clave a la partida desencriptada volverás a obtener la partida completamente encriptada. <br />
<br />
Actualización:<br />
<br />
Desde el firmware 2.0.0-4 Nintendo ha introducido una nueva forma de encriptación (podría ser una solución para la exploit de más arriba). El xorpad parece repetirse en el archivo pero no cada 0x200 bytes. Así que por ahora no se sabe cómo descifrar las nuevas partidas.<br />
<br />
'''Juegos que usan la nueva encriptación:'''<br />
* Super Mario 3D Land<br />
* Mario Kart 7<br />
* Need for Speed - The Run<br />
<br />
'''Más información:'''<br />
*Los juegos viejos aún usan el antiguo xorpad de 0x200 bytes.<br />
*Los juegos nuevos puedes ser copiados y restaurados (se usa la misma clava tanto una partida como para otra)<br />
* El wearleveling sigue siendo el mismo.<br />
*XOReando dos archivos juntos puede producir algo de texto claro.<br />
*Se ha observado que el xorpad se repite cada 0x1000 bytes (podría ser la longitud máxima pero aún no se ha probado).<br />
<br />
=== Wear leveling ===<br />
<br />
The 3DS employs a wear leveling scheme on the savegame FLASH chips. This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.<br />
<br />
First, there are 8 bytes whose purposes are currently unknown. Then comes the actual blockmap.<br />
The blockmap structure is simple:<br />
<pre><br />
struct header_entry {<br />
uint8_t phys_sec; // when bit7 is set, block has checksums, otherwise checksums are all zero<br />
uint8_t alloc_cnt;<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
</pre><br />
<br />
There's one entry per sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).<br />
<br />
The 2 bytes that follow the blockmap are the CRC16 (with starting value 0xFFFF (like modbus)) of the first 8 bytes and the blockmap.<br />
<br />
Then comes the journal.<br />
The journal structure is as follows:<br />
<pre><br />
struct sector_entry {<br />
uint8_t virt_sec; // Mapped to sector<br />
uint8_t prev_virt_sec; // Physical sector previously mapped to<br />
uint8_t phys_sec; // Mapped from sector<br />
uint8_t prev_phys_sec; // Virtual sector previously mapped to<br />
uint8_t phys_realloc_cnt; // Amount of times physical sector has been remapped<br />
uint8_t virt_realloc_cnt; // Amount of times virtual sector has been remapped<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
<br />
struct long_sector_entry{<br />
struct sector_entry sector;<br />
struct sector_entry dupe;<br />
uint32_t magic;<br />
}__attribute__((__packed__));<br />
</pre><br />
<br />
With magic being a constant 0x080d6ce0.<br />
<br />
The checksums in the blockmap/journal entries work as follows:<br />
* each byte is the checksum of an encrypted 0x200 bytes large block<br />
* to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum<br />
<br />
=== Partitions ===<br />
<br />
There can be multiple partitions on the chip. <br />
The partitions are represented by tables of DIFI blobs inside a DISA structure.<br />
The order of the DIFI blobs is the order of the partitions in the chip.<br />
<br />
'''DISA'''<br />
<br />
* If the uint32 @ 0x168 into the image in the DISA is a %1=1, then first table is is hashed, otherwise the second DIFI table is hashed. <br />
* If the table has more then 1 DIFI then the uint32 @ 0x168 is the offset from the DATA partition to the file base (masked with 0xFFFFFFFE).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DISA")<br />
|-<br />
| 0x04<br />
| 4<br />
| Unknown (maybe magic, the same in all the save files so far)<br />
|-<br />
| 0x08<br />
| 8<br />
| Partition table size<br />
|-<br />
| 0x10<br />
| 8<br />
| Offset to primary partition table in DISA<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset to secondary partition table in DISA<br />
|-<br />
| 0x20<br />
| 8<br />
| Partition table's length<br />
|-<br />
| 0x28<br />
| 8<br />
| SAVE Partition entry offset in the partition table<br />
|-<br />
| 0x30<br />
| 8<br />
| SAVE Partition entry length in the partition table<br />
|-<br />
| 0x38<br />
| 8<br />
| DATA Partition entry offset in the partition table<br />
|-<br />
| 0x40<br />
| 8<br />
| DATA Partition entry length in the partition table<br />
|-<br />
| 0x48<br />
| 8<br />
| SAVE Partition offset<br />
|-<br />
| 0x50<br />
| 8<br />
| SAVE Partition length<br />
|-<br />
| 0x58<br />
| 8<br />
| DATA Partition offset<br />
|-<br />
| 0x60<br />
| 8<br />
| DATA Partition length<br />
|-<br />
| 0x68<br />
| 4<br />
| Active table (and the offset to the filebase)<br />
|-<br />
| 0x6C<br />
| 0x20<br />
| Hash from active table<br />
|-<br />
| 0x8C<br />
| 4*29<br />
| Unknown<br />
|}<br />
<br />
* The hash in the DISA hashes the Active Table (starting from tables's offset to tables's offset + table length) with SHA256.<br />
<br />
* The partitions offsets points to a 0x1000 long block which isn't understood yet. The actual information starts after that block.<br />
<br />
The DIFIs table @ 0x200 (into the image) is written twice, (Meaning, if there's 4 DIFI blobs then the table is 2 DIFIs long).<br />
<br />
The second table is for backup. The active table is mentioned at 0x13C into the image (1=First table, other=Second Table)<br />
<br />
'''DIFI'''<br />
<br />
These 0x130 large blobs describe the partitions. Every DIFI blob describes a partition. Partitions are catted together, so after the end of one partition is the beginning of the next.<br />
<br />
Actually DIFI blobs are 0x12C large because the last 4 are not used and appear 0xFFFFFFFF at the encrypted image.<br />
<br />
For most games there's only 1 partition (The SAVE partition) and some (like Asphalt 3D, Steel Diver & Lego Star Wars III) has 2 partitions.<br />
<br />
* 2 Partitions means that the files inside the SAVE partition is on the other partition (we would call it DATA partition).<br />
<br />
* No more than 2 partitions have been seen yet (and can't be becuase of the DISA known structure).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DIFI")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset to "IVFC" blob in DIFI (usually 0x44)<br />
|-<br />
| 0x10<br />
| 8<br />
| Size of "IVFC" blob<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset to "DPFS" blob in DIFI (usually 0xBC)<br />
|-<br />
| 0x20<br />
| 8<br />
| Size of "DPFS" blob<br />
|-<br />
| 0x28<br />
| 8<br />
| Offset to the hash in DIFI (usually 0x010C)<br />
|-<br />
| 0x30<br />
| 8<br />
| Size of this hash<br />
|-<br />
| 0x38<br />
| 4<br />
| Flags (1 means DATA partition)<br />
|-<br />
| 0x3C<br />
| 8<br />
| File base offset (for DATA partitions)<br />
|}<br />
<br />
'''IVFC'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("IVFC")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x20000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown (0x20?)<br />
|-<br />
| 0x10<br />
| 8<br />
| First Hash Offset<br />
|-<br />
| 0x18<br />
| 8<br />
| First Hash Length<br />
|-<br />
| 0x20<br />
| 8<br />
| First Hash Block Size (1<<value)<br />
|-<br />
| 0x28<br />
| 8<br />
| Second Hash Offset<br />
|-<br />
| 0x30<br />
| 8<br />
| Second Hash Length<br />
|-<br />
| 0x38<br />
| 8<br />
| Second Hash Block Size (1<<value)<br />
|-<br />
| 0x40<br />
| 8<br />
| HashTable Offset<br />
|-<br />
| 0x48<br />
| 8<br />
| HashTable Length<br />
|-<br />
| 0x50<br />
| 8<br />
| HashTable Block Size (1<<value)<br />
|-<br />
| 0x58<br />
| 8<br />
| FileSystem Offset<br />
|-<br />
| 0x60<br />
| 8<br />
| FileSystem Length<br />
|-<br />
| 0x68<br />
| 8<br />
| FileSystem Block Size (1<<value)<br />
|-<br />
| 0x70<br />
| 8<br />
| Unknown (usually 0x78=120)<br />
|-<br />
|}<br />
<br />
* First & Second hash are not understood yet.<br />
<br />
'''DPFS'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DPFS")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset To First table<br />
|-<br />
| 0x10<br />
| 8<br />
| First table length<br />
|-<br />
| 0x18<br />
| 8<br />
| First table block size (1<<value)<br />
|-<br />
| 0x20<br />
| 8<br />
| Offset To Second table<br />
|-<br />
| 0x28<br />
| 8<br />
| Second table length<br />
|-<br />
| 0x30<br />
| 8<br />
| Second table block size (1<<value)<br />
|-<br />
| 0x38<br />
| 8<br />
| Offset to Data<br />
|-<br />
| 0x40<br />
| 8<br />
| Data Length<br />
|-<br />
| 0x48<br />
| 8<br />
| Data block size (1<<value)<br />
|-<br />
|}<br />
<br />
* Every block this table point to is written twice (concatenated). You can see that the offset to the next block is twice the length (except the data which always begin after 0x1000).<br />
<br />
The first partition's data starts at 0x2000. First comes the hashtable (usually start @ 0x40 into the partition) and then the filesystem.<br />
<br />
The hashtable entries' size is 2^x where x is the 'Hashed block size' from the IVFC block.<br />
<br />
'''Hash'''<br />
<br />
After the DIFI,IVFC & DPFS comes a 0x20 long hash, it is unknown what it's hashing.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfimg_drawing.png]]<br />
<br />
==== The SAVE partition ====<br />
<br />
* The SAVE filesystem works with a backup. There are two SAVE blocks inside the partition concatenated. Which SAVE block is the updated one is unknown yet.. (I'm guessing from experience that (image[0x100B] & 0x20) == 0x20 --> 1st SAVE --[[User:Elisherer|Elisherer]] 01:30, 18 October 2011 (CEST))<br />
<br />
'''Finding the folders table:'''<br />
* If DATA partition exists: At folder table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'folder table offset' * 'folder table media' (=0x200) from the 'filestore offset'. (usually 0 from filebase)<br />
<br />
'''Finding the files table:'''<br />
* If DATA partition exists: At file table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'file table offset' * 'file table media' (=0x200) from the 'filestore offset'.<br />
<br />
'''Detemining the filestore base:'''<br />
* If DATA partition exists: At file base from the DATA's DIFI struct into the DATA partition.<br />
* Otherwise: At the 'filestore offset' from the beginning of the SAVE struct.<br />
<br />
Folder's entry structure:<br />
<pre><br />
struct folder_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 folder_index;<br />
u32 unk1; <br />
u32 last_file_index;<br />
u32 unk3; <br />
u32 unk4;<br />
}<br />
</pre><br />
<br />
File's entry structure:<br />
<pre><br />
struct file_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 index;<br />
u32 unk1; // magic?<br />
u32 block_offset;<br />
u64 file_size;<br />
u32 unk2; // flags?<br />
u32 unk3;<br />
}<br />
</pre><br />
<br />
The first entry in both tables is the count of the table, the parent directory index will be the amount of table rows. The root includes itself, so there are the amount - 1 (minus one) folders in the root directory (or files). The entries that follow after the root are the actual folders/files.<br />
<br />
Reading the files out is as simple as taking the file base offset and adding (block_offset * 0x200) to it.<br />
<br />
Here's a follow-up example from the Legend of Zelda: Ocarina of Time 3D:<br />
<pre><br />
//FST entry = SAVE base + File base + (FST offset * 0x200) + (FST entry # * 0x30)<br />
//0x2600 = 0x2000 + 0x400 + (0x1 * 0x200) + (0x0 * 0x30)<br />
<br />
00002600: 03000000 09000000 00000000 00000000 ................<br />
00002610: 00000000 00000000 00000000 00000000 ................<br />
00002620: 00000000 00000000 00000000 00000000 ................<br />
00002630: 01000000 73797374 656D2E64 61740000 ....system.dat..<br />
00002640: 00000000 00000000 D57B1100 02000000 ........Õ{......<br />
00002650: 22000000 00000000 E8121500 00000000 ".......è.......<br />
00002660: 01000000 73617665 30302E62 696E0000 ....save00.bin..<br />
00002670: 00000000 01000000 69921100 03000000 ........i’......<br />
00002680: DC140000 00000000 04000000 00000000 Ü...............<br />
</pre><br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("SAVE")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic padding<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 8<br />
| Partition Size [medias]<br />
|-<br />
| 0x18<br />
| 4<br />
| Partition Media Size<br />
|-<br />
| 0x1C<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x24<br />
| 4<br />
| Unknown<br />
|-<br />
| 0x28<br />
| 8<br />
| FolderMap Offset<br />
|-<br />
| 0x30<br />
| 4<br />
| FolderMap Size<br />
|-<br />
| 0x34<br />
| 4<br />
| FolderMap Media Size<br />
|-<br />
| 0x38<br />
| 8<br />
| FileMap Offset<br />
|-<br />
| 0x40<br />
| 4<br />
| FileMap Size<br />
|-<br />
| 0x44<br />
| 4<br />
| FileMap Media Size<br />
|-<br />
| 0x48<br />
| 8<br />
| BlockMap Offset<br />
|-<br />
| 0x50<br />
| 4<br />
| BlockMap Size<br />
|-<br />
| 0x54<br />
| 4<br />
| BlockMap Media Size<br />
|-<br />
| 0x58<br />
| 8<br />
| File store offset (from SAVE)<br />
|-<br />
| 0x60<br />
| 4<br />
| File store length [medias]<br />
|-<br />
| 0x64<br />
| 4<br />
| File store media size<br />
|-<br />
| 0x68<br />
| 4/8<br />
| Folders Table offset (8 bytes in DATA)<br />
|-<br />
| 0x6C<br />
| 4<br />
| Folders Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x70<br />
| 4<br />
| Folders Table unknown<br />
|-<br />
| 0x74<br />
| 4<br />
| Folders Table Media size<br />
|-<br />
| 0x78<br />
| 4/8<br />
| Files Table offset (8 bytes in DATA)<br />
|-<br />
| 0x7C<br />
| 4<br />
| Files Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x80<br />
| 4<br />
| Files Table unknown<br />
|-<br />
| 0x84<br />
| 4<br />
| Files Table Media size<br />
|-<br />
|}<br />
<br />
* The FolderMap and FileMap still unknown. They are tables of uint32.<br />
* The BlockMap is a map of the blocks in the filestore. An entry in the BlockMap is 2 uint32: {uint32 start_block; uint32 end_block; }. This is still being researched. (You can use [[3DSExplorer]] to see those maps.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfsave_drawing.png]]<br />
<br />
=== Initialization ===<br />
<br />
When a save EEPROM contains all xFFFF blocks it's assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. <br />
<br />
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter 'Z' (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)<br />
<br />
=== Fun Facts ===<br />
<br />
If you have facts that you found out by looking at the binary files please share them here:<br />
<br />
* From one save to another the game backups the last files that were in the partition and the entire image header in "random" locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Gamecards/es&diff=2091
Gamecards/es
2011-12-30T12:36:46Z
<p>Xerpi: /* Formato */</p>
<hr />
<div>[[File:Gamecard.jpg|thumb|right|Una tarjeta 3DS]] <br />
[[File:GamecardPhy.jpg|thumb|right|Primer plano del PCB]] <br />
<br />
===Interfaz física===<br />
Las tarjetas 3DS tienen la misma interfaz física que las tarjetas DS y DSi. Sólo hay una pequeña diferencia de diseño en la carcasa de plástico, que tiene un pequeño saliente en la esquina superior derecha. De este modo se impide la inserción de la tarjeta en las antiguas consolas Nintendo DS o Nintendo DSi.<br />
<br />
Si se modifica la carcasa para que una tarjeta 3DS encaje en una consola Nintendo DS o Nintendo DSi, ésta se negará a leer los datos de la tarjeta y no mostrará icono alguno.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Conector<br />
! Nombre<br />
! Descripción<br />
|-<br />
| 1<br />
| GND<br />
| Tierra<br />
|-<br />
| 2<br />
| CLK<br />
| Reloj. Frecuencias 6.7MHz y 4.2MHz para tarjetas DS/DSi, hasta 16.6MHz en tarjetas 3DS (para transferencias SPI y ROM).<br />
|-<br />
| 3<br />
| NC<br />
| No conectado. Posiblemente usado para programar las tarjetas.<br />
|-<br />
| 4<br />
| RCS<br />
| Selección de ROM, activo a nivel bajo. Al pasar a nivel bajo se inicia la transferencia del ROM.<br />
|-<br />
| 5<br />
| RST<br />
| Reinicio, activo a nivel bajo. <br />
|-<br />
| 6<br />
| ECS<br />
| Selección del chip de partidas guardadas, activo a nivel bajo. Al pasar a nivel bajo se inicia la transferencia SPI de la partida guardada.<br />
|-<br />
| 7<br />
| IRQ<br />
| Detección de extracción de la tarjeta.<br />
|-<br />
| 8<br />
| VCC<br />
| Alimentación 3.3V.<br />
|-<br />
| 9<br />
| DAT0<br />
| Bus de datos bidireccional.<br />
|-<br />
| 10<br />
| DAT1<br />
| Bus de datos bidireccional.<br />
|-<br />
| 11<br />
| DAT2<br />
| Bus de datos bidireccional.<br />
|-<br />
| 12<br />
| DAT3<br />
| Bus de datos bidireccional.<br />
|-<br />
| 13<br />
| DAT4<br />
| Bus de datos bidireccional / Conector NC/SIO3 en el chip de partidas guardadas.<br />
|-<br />
| 14<br />
| DAT5<br />
| Bus de datos bidireccional / Conector WP#/SIO2 en el chip de partidas guardadas.<br />
|-<br />
| 15<br />
| DAT6<br />
| Bus de datos bidireccional / Conector SO/SIO1 en el chip de partidas guardadas.<br />
|-<br />
| 16<br />
| DAT7<br />
| Bus de datos bidireccional / Conector SI/SIO0 en el chip de partidas guardadas.<br />
|-<br />
| 17<br />
| GND<br />
| Tierra<br />
|}<br />
<br />
===Flash SPI===<br />
De momento, sólo se ha identificado un chip flash de partidas guardadas. El chip se identifica como 0xC22211. La ID del fabricante JEDEC es Macronix, y a pesar que la etiqueta del chip dice 25L1001, la ID JEDEC corresponde con el MX25L1021E. Hoja de datos ent: http://www.macronix.com/QuickPlace/hq/PageLibrary4825740B00298A3B.nsf/h_Index/3F21BAC2E121E17848257639003A3146/$File/MX25L1021E,%203V,%201Mb,%20v0.01.pdf. Sin embargo, el MX25L1021E no soporta la transmisión ancha de 4 bit que la Nintendo 3DS usa para comunicarse con la flash SPI. Entonces es posible que sea un chip personalizado.<br />
<br />
===Formato===<br />
Las tarjetas pueden venir en distintos tamaños e incluyen actualizaciones del sistema en una región reservada para ello. En las ROMs de menos de 1GB se puede encontrar esta región con:<br />
CART_SIZE_MAX-( 0x280000*(CART_SIZE_MAX/CART_SIZE_128MB) )-0x2000000. La región es entonces de 0x2000000 bytes.<br />
<br />
===Protocolo===<br />
El protocolo de comunicación entre la consola Nintendo 3DS y las tarjetas 3DS ha cambiado casi completamente en comparación al protocolo de comunicación de las tarjetas DS y DSi.<br />
<br />
Después de la sexta transferencia, los comandos cambian de tamaño, pasando de ser de 8 bytes a 16 bytes. Posiblemente se usa una nueva encriptación, como AES CTR.<br />
Cuando se usan comandos de 16 bytes, el bus de datos mantiene el valor 0x00 hasta que la tarjeta señala que está lista enviando un simple byte 0x01, seguido de los datos. Después de cada bloque de datos de 0x200 bytes, se envían (antes de ser encriptados) 4 bytes CRC32 estándar de los datos de bloque.<br />
<br />
Esto es un set de comandos de muestra que una Nintendo 3DS envía a una tarjeta 3DS:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Tamaño<br />
! Comando<br />
! Comando desencriptado<br />
! Descripción<br />
|-<br />
|<tt>2000</tt><br />
|<tt>9F00000000000000</tt><br />
|<br />
|Reinicio<br />
|-<br />
|<tt>0000</tt><br />
|<tt>71C93FE9BB0A3B18</tt><br />
|<br />
|Desconocido<br />
|-<br />
|<tt>0004</tt><br />
|<tt>9000000000000000</tt><br />
|<br />
|Obtener ID de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>9000000000000000</tt><br />
|<br />
| Obtener ID de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>A000000000000000</tt><br />
|<br />
| Desconocido, respuesta=00000000<br />
|-<br />
|<tt>0000</tt><br />
|<tt>3E00000000000000</tt><br />
| <br />
| Entrar modo de comandos de 16 bytes.<br />
|-<br />
|<tt>0200</tt><br />
|<tt>82000000000000000000000000000000</tt><br />
| <br />
| Obtener cabecera<br />
|-<br />
|<tt>0000</tt><br />
|<tt>F32C92D85C9D44DED3E0E41DBE7C90D9</tt><br />
|<tt>8300000000000000708DF1A731717D0B</tt> <br />
| Semilla<br />
|-<br />
|<tt>0004</tt><br />
|<tt>696B9D8582FB55D31B68CAFE70C74A95</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Obtener ID protegida de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>BAA4812CA0AC9C5D19399530E3ACCCAB</tt><br />
|<tt>A300000000000000708DF1A731717D0B</tt><br />
| Desconocido<br />
|-<br />
|<tt>0000</tt><br />
|<tt>178E427C22D87ADB86387249A97D321A</tt><br />
|<tt>C500000000000000708DF1A731717D0B</tt><br />
| Desconocido<br />
|-<br />
|<tt>0004</tt><br />
|<tt>E06019B1BD5C9130ED6A4D9F4A9E7193</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Obtener ID protegida de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>4E0D224862523BBFE2E6255F80E15F37</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Obtener ID protegida de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>4CDF93D319FB62D0DB632A45E3E8D84C</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Obtener ID protegida de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>9AA5D80551002F955546D296A57F0FEF</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Obtener ID protegida de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>C12BA81AEF30DDDBD93FAD5D544C6334</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Obtener ID protegida de la tarjeta, respuesta=9000FEC2<br />
|-<br />
|<tt>0200</tt><br />
|<tt>62EC5FB7F420AE1DC6253AE18AFA5BB3</tt><br />
|<tt>BF000000000000000000000000000000</tt><br />
| Leer dirección 0<br />
|-<br />
|<tt>0200</tt><br />
|<tt>E3FA23AA016BE0C93430D1F42FF41324</tt><br />
|<tt>BF000000000040000000000000000000</tt><br />
| Leer dirección 0x4000<br />
|}<br />
<br />
El comando de la cabecera tiene algunos falsos bytes iniciales, y finalmente responde con una cabecera de 0x200 bytes. Esto es un ejemplo de Lego Starwars 3:<br />
0000000: 00 8c 03 00 00 00 04 00 00 00 00 00 00 00 00 00 ................<br />
0000010: b3 cf fb c6 6a b1 cb 20 32 af ce 35 d4 1c 74 c9 ....j.. 2..5..t.<br />
0000020: 8e 6b 27 2f 08 01 28 3b d4 30 de 44 37 f5 b0 46 .k'/..(;.0.D7..F<br />
0000030: 91 59 d7 38 33 48 df 83 fd 71 84 2c 00 00 00 00 .Y.83H...q.,....<br />
0000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000100: 4e 43 43 48 7a 7f 0e 00 00 8c 03 00 00 00 04 00 NCCHz...........<br />
0000110: 36 34 02 00 00 00 00 00 00 8c 03 00 00 00 04 00 64..............<br />
0000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000150: 43 54 52 2d 50 2d 41 4c 47 50 00 00 00 00 00 00 CTR-P-ALGP......<br />
0000160: 0c 27 e3 c1 de 7b 2a e2 d3 11 4f 32 a4 ee bf 46 .'...{*...O2...F<br />
0000170: 9a fd 0c f3 52 c1 1d 49 84 c2 a9 f1 d2 14 4c 63 ....R..I......Lc<br />
0000180: 00 04 00 00 00 00 00 00 00 00 00 00 01 03 00 00 ................<br />
0000190: 05 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00001a0: 06 00 00 00 1c 0a 00 00 01 00 00 00 00 00 00 00 ................<br />
00001b0: 22 0a 00 00 58 75 0e 00 01 00 00 00 00 00 00 00 "...Xu..........<br />
00001c0: 13 0c 04 26 15 f6 47 c4 c6 32 25 ea 9e 67 f8 a2 ...&..G..2%..g..<br />
00001d0: 7b 15 24 6b 88 fb c7 a9 27 25 7b 84 97 7b 78 7b {.$k....'%{..{x{<br />
00001e0: a6 5b ee 10 60 bb 6a 68 21 bb ce c6 00 03 5b 7e .[..`.jh!.....[~<br />
00001f0: 64 fb 6e ac a7 f0 96 0c fb 1f 5a 37 08 77 28 f7 d.n.......Z7.w(.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Traductores&diff=2090
Traductores
2011-12-30T12:36:11Z
<p>Xerpi: </p>
<hr />
<div>Esta lista incluye todos los colaboradores de la traducción española de 3DBrew<br />
<br />
''En la columna de "Contribuciones", añadir el enlace a cada página traducida (ya sea en su totalidad o en parte)''<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! width="32%" | Nombre<br />
! width="8%" |Región<br />
! width="60%" |Contribuciones<br />
! |Retrato Mii<br />
|-<br />
| <center>[[user:Xerpi|xerpi]]</center><br />
| <center>España</center><br />
|<br />
-[[Main_Page/es|Página principal]]<br><br />
-[[News/Archive/es|Archivos]]<br><br />
-[[Glossary/es|Glosario]]<br><br />
-[[Hardware/es|Hardware]]<br><br />
-[[FAQ/es|Preguntas frecuentes]]<br><br />
-[[Savegames/es|Partidas guardadas]]<br />
|[[File:MiiXerpi.jpg|120px]]<br />
|-<br />
| <center>[[user:Markitus95|Markitus95]]</center><br />
| <center>España</center><br />
| -[[Circle Pad Pro/Es|Circle Pad Pro]]<br />
-[[Gamecards/es|Tarjetas 3DS]]<br />
| [[File:MiiMarkitus95.jpg|120px]]<br />
|-</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Savegames/es&diff=2089
Savegames/es
2011-12-30T11:56:19Z
<p>Xerpi: Created page with "Esta página describe el formato, la des/encriptación, etc de las partidas guardadas de los cartuchos de los juegos de la 3DS. Puedes encontrar partidas guardadas de varios jueg..."</p>
<hr />
<div>Esta página describe el formato, la des/encriptación, etc de las partidas guardadas de los cartuchos de los juegos de la 3DS. Puedes encontrar partidas guardadas de varios juegos de la 3DS en la página de [[Games/es|Juegos]].<br />
<br />
<br />
=== Encriptación ===<br />
<br />
En la 3DS las partidas se almacenan de una forma similar a la DS, en un chip FLASH en el cartucho del juego. En la DS estas partidas están en formato de texto plano pero en la 3DS se añade una capa de encriptación. Esto se parece mucho a un flujo de cifrado, donde los contenidos de algunas partidas tienen un comportamiento extraño cuando se XORean algunas partes juntas de la partida y da como resultado un archivo de texto plano.<br />
<br />
La razón por la que esto funciona es porque el cifrado usado tiene un tamaño de 512 bytes. Que es lo mismo, se va repitiendo la misma clave cada 512 bytes. La forma de encriptar con un cifrado es la producida por una clave XOR. Por desgracia, si se repite la clave y estás encriptando un texto plano conocido (en nuestro caso, ceros) básicamente estás “regalando” tu clave.<br />
<br />
Entonces, ¿cómo puedo utilizar esto para desencriptar una partida guardada en una 3DS? En primer lugar, tienes que dividir la partida en chunks (trozos) de 512 bytes. Entonces, debes seleccionar los chunks por su contenido, descartando los que solo contengan FF. Ahora debes buscar el chunk más común. Esta es la clave. Ahora XORea con la clave que acabas de encontrar la partida original y deberías obtener la partida completamente desencriptada. Si vuelves a XORear con la clave a la partida desencriptada volverás a obtener la partida completamente encriptada. <br />
<br />
Actualización:<br />
<br />
Desde el firmware 2.0.0-4 Nintendo ha introducido una nueva forma de encriptación (podría ser una solución para la exploit de más arriba). El xorpad parece repetirse en el archivo pero no cada 0x200 bytes. Así que por ahora no se sabe cómo descifrar las nuevas partidas.<br />
<br />
'''Juegos que usan la nueva encriptación:'''<br />
* Super Mario 3D Land<br />
* Mario Kart 7<br />
* Need for Speed - The Run<br />
<br />
'''Más información:'''<br />
*Los juegos viejos aún usan el antiguo xorpad de 0x200 bytes.<br />
* New games saves can be backed-up and restored (same key is used from one save to another).<br />
*Los juegos nuevos puedes ser copiados y restaurados (se usa la misma clava tanto una partida como para otra)<br />
* El wearleveling sigue siendo el mismo.<br />
*XOReando dos archivos juntos puede producir algo de texto claro.<br />
*Se ha observado que el xorpad se repite cada 0x1000 bytes (podría ser la longitud máxima pero aún no se ha probado).<br />
<br />
=== Wear leveling ===<br />
<br />
The 3DS employs a wear leveling scheme on the savegame FLASH chips. This is done through the usage of blockmaps and a journal. The blockmap is located at offset 0 of the flash chip, and is immediately followed by the journal. The initial state is dictated by the blockmap, and the journal is then applied to that.<br />
<br />
First, there are 8 bytes whose purposes are currently unknown. Then comes the actual blockmap.<br />
The blockmap structure is simple:<br />
<pre><br />
struct header_entry {<br />
uint8_t phys_sec; // when bit7 is set, block has checksums, otherwise checksums are all zero<br />
uint8_t alloc_cnt;<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
</pre><br />
<br />
There's one entry per sector, counting from physical sector 1 (sector 0 contains the blockmap/journal).<br />
<br />
The 2 bytes that follow the blockmap are the CRC16 (with starting value 0xFFFF (like modbus)) of the first 8 bytes and the blockmap.<br />
<br />
Then comes the journal.<br />
The journal structure is as follows:<br />
<pre><br />
struct sector_entry {<br />
uint8_t virt_sec; // Mapped to sector<br />
uint8_t prev_virt_sec; // Physical sector previously mapped to<br />
uint8_t phys_sec; // Mapped from sector<br />
uint8_t prev_phys_sec; // Virtual sector previously mapped to<br />
uint8_t phys_realloc_cnt; // Amount of times physical sector has been remapped<br />
uint8_t virt_realloc_cnt; // Amount of times virtual sector has been remapped<br />
uint8_t chksums[8];<br />
} __attribute__((__packed__));<br />
<br />
struct long_sector_entry{<br />
struct sector_entry sector;<br />
struct sector_entry dupe;<br />
uint32_t magic;<br />
}__attribute__((__packed__));<br />
</pre><br />
<br />
With magic being a constant 0x080d6ce0.<br />
<br />
The checksums in the blockmap/journal entries work as follows:<br />
* each byte is the checksum of an encrypted 0x200 bytes large block<br />
* to calculate the checksum, a CRC16 of the block (with starting value 0xFFFF) is calculated, and the two bytes of the CRC16 are XORed together to produce the 8bit checksum<br />
<br />
=== Partitions ===<br />
<br />
There can be multiple partitions on the chip. <br />
The partitions are represented by tables of DIFI blobs inside a DISA structure.<br />
The order of the DIFI blobs is the order of the partitions in the chip.<br />
<br />
'''DISA'''<br />
<br />
* If the uint32 @ 0x168 into the image in the DISA is a %1=1, then first table is is hashed, otherwise the second DIFI table is hashed. <br />
* If the table has more then 1 DIFI then the uint32 @ 0x168 is the offset from the DATA partition to the file base (masked with 0xFFFFFFFE).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DISA")<br />
|-<br />
| 0x04<br />
| 4<br />
| Unknown (maybe magic, the same in all the save files so far)<br />
|-<br />
| 0x08<br />
| 8<br />
| Partition table size<br />
|-<br />
| 0x10<br />
| 8<br />
| Offset to primary partition table in DISA<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset to secondary partition table in DISA<br />
|-<br />
| 0x20<br />
| 8<br />
| Partition table's length<br />
|-<br />
| 0x28<br />
| 8<br />
| SAVE Partition entry offset in the partition table<br />
|-<br />
| 0x30<br />
| 8<br />
| SAVE Partition entry length in the partition table<br />
|-<br />
| 0x38<br />
| 8<br />
| DATA Partition entry offset in the partition table<br />
|-<br />
| 0x40<br />
| 8<br />
| DATA Partition entry length in the partition table<br />
|-<br />
| 0x48<br />
| 8<br />
| SAVE Partition offset<br />
|-<br />
| 0x50<br />
| 8<br />
| SAVE Partition length<br />
|-<br />
| 0x58<br />
| 8<br />
| DATA Partition offset<br />
|-<br />
| 0x60<br />
| 8<br />
| DATA Partition length<br />
|-<br />
| 0x68<br />
| 4<br />
| Active table (and the offset to the filebase)<br />
|-<br />
| 0x6C<br />
| 0x20<br />
| Hash from active table<br />
|-<br />
| 0x8C<br />
| 4*29<br />
| Unknown<br />
|}<br />
<br />
* The hash in the DISA hashes the Active Table (starting from tables's offset to tables's offset + table length) with SHA256.<br />
<br />
* The partitions offsets points to a 0x1000 long block which isn't understood yet. The actual information starts after that block.<br />
<br />
The DIFIs table @ 0x200 (into the image) is written twice, (Meaning, if there's 4 DIFI blobs then the table is 2 DIFIs long).<br />
<br />
The second table is for backup. The active table is mentioned at 0x13C into the image (1=First table, other=Second Table)<br />
<br />
'''DIFI'''<br />
<br />
These 0x130 large blobs describe the partitions. Every DIFI blob describes a partition. Partitions are catted together, so after the end of one partition is the beginning of the next.<br />
<br />
Actually DIFI blobs are 0x12C large because the last 4 are not used and appear 0xFFFFFFFF at the encrypted image.<br />
<br />
For most games there's only 1 partition (The SAVE partition) and some (like Asphalt 3D, Steel Diver & Lego Star Wars III) has 2 partitions.<br />
<br />
* 2 Partitions means that the files inside the SAVE partition is on the other partition (we would call it DATA partition).<br />
<br />
* No more than 2 partitions have been seen yet (and can't be becuase of the DISA known structure).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DIFI")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset to "IVFC" blob in DIFI (usually 0x44)<br />
|-<br />
| 0x10<br />
| 8<br />
| Size of "IVFC" blob<br />
|-<br />
| 0x18<br />
| 8<br />
| Offset to "DPFS" blob in DIFI (usually 0xBC)<br />
|-<br />
| 0x20<br />
| 8<br />
| Size of "DPFS" blob<br />
|-<br />
| 0x28<br />
| 8<br />
| Offset to the hash in DIFI (usually 0x010C)<br />
|-<br />
| 0x30<br />
| 8<br />
| Size of this hash<br />
|-<br />
| 0x38<br />
| 4<br />
| Flags (1 means DATA partition)<br />
|-<br />
| 0x3C<br />
| 8<br />
| File base offset (for DATA partitions)<br />
|}<br />
<br />
'''IVFC'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("IVFC")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x20000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown (0x20?)<br />
|-<br />
| 0x10<br />
| 8<br />
| First Hash Offset<br />
|-<br />
| 0x18<br />
| 8<br />
| First Hash Length<br />
|-<br />
| 0x20<br />
| 8<br />
| First Hash Block Size (1<<value)<br />
|-<br />
| 0x28<br />
| 8<br />
| Second Hash Offset<br />
|-<br />
| 0x30<br />
| 8<br />
| Second Hash Length<br />
|-<br />
| 0x38<br />
| 8<br />
| Second Hash Block Size (1<<value)<br />
|-<br />
| 0x40<br />
| 8<br />
| HashTable Offset<br />
|-<br />
| 0x48<br />
| 8<br />
| HashTable Length<br />
|-<br />
| 0x50<br />
| 8<br />
| HashTable Block Size (1<<value)<br />
|-<br />
| 0x58<br />
| 8<br />
| FileSystem Offset<br />
|-<br />
| 0x60<br />
| 8<br />
| FileSystem Length<br />
|-<br />
| 0x68<br />
| 8<br />
| FileSystem Block Size (1<<value)<br />
|-<br />
| 0x70<br />
| 8<br />
| Unknown (usually 0x78=120)<br />
|-<br />
|}<br />
<br />
* First & Second hash are not understood yet.<br />
<br />
'''DPFS'''<br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("DPFS")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic Number (0x10000)<br />
|-<br />
| 0x08<br />
| 8<br />
| Offset To First table<br />
|-<br />
| 0x10<br />
| 8<br />
| First table length<br />
|-<br />
| 0x18<br />
| 8<br />
| First table block size (1<<value)<br />
|-<br />
| 0x20<br />
| 8<br />
| Offset To Second table<br />
|-<br />
| 0x28<br />
| 8<br />
| Second table length<br />
|-<br />
| 0x30<br />
| 8<br />
| Second table block size (1<<value)<br />
|-<br />
| 0x38<br />
| 8<br />
| Offset to Data<br />
|-<br />
| 0x40<br />
| 8<br />
| Data Length<br />
|-<br />
| 0x48<br />
| 8<br />
| Data block size (1<<value)<br />
|-<br />
|}<br />
<br />
* Every block this table point to is written twice (concatenated). You can see that the offset to the next block is twice the length (except the data which always begin after 0x1000).<br />
<br />
The first partition's data starts at 0x2000. First comes the hashtable (usually start @ 0x40 into the partition) and then the filesystem.<br />
<br />
The hashtable entries' size is 2^x where x is the 'Hashed block size' from the IVFC block.<br />
<br />
'''Hash'''<br />
<br />
After the DIFI,IVFC & DPFS comes a 0x20 long hash, it is unknown what it's hashing.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfimg_drawing.png]]<br />
<br />
==== The SAVE partition ====<br />
<br />
* The SAVE filesystem works with a backup. There are two SAVE blocks inside the partition concatenated. Which SAVE block is the updated one is unknown yet.. (I'm guessing from experience that (image[0x100B] & 0x20) == 0x20 --> 1st SAVE --[[User:Elisherer|Elisherer]] 01:30, 18 October 2011 (CEST))<br />
<br />
'''Finding the folders table:'''<br />
* If DATA partition exists: At folder table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'folder table offset' * 'folder table media' (=0x200) from the 'filestore offset'. (usually 0 from filebase)<br />
<br />
'''Finding the files table:'''<br />
* If DATA partition exists: At file table exact offset from the SAVE struct (from the beginning of the struct).<br />
* Otherwise: The 'file table offset' * 'file table media' (=0x200) from the 'filestore offset'.<br />
<br />
'''Detemining the filestore base:'''<br />
* If DATA partition exists: At file base from the DATA's DIFI struct into the DATA partition.<br />
* Otherwise: At the 'filestore offset' from the beginning of the SAVE struct.<br />
<br />
Folder's entry structure:<br />
<pre><br />
struct folder_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 folder_index;<br />
u32 unk1; <br />
u32 last_file_index;<br />
u32 unk3; <br />
u32 unk4;<br />
}<br />
</pre><br />
<br />
File's entry structure:<br />
<pre><br />
struct file_entry {<br />
u32 parent_folder_index;<br />
u8 filename[0x10];<br />
u32 index;<br />
u32 unk1; // magic?<br />
u32 block_offset;<br />
u64 file_size;<br />
u32 unk2; // flags?<br />
u32 unk3;<br />
}<br />
</pre><br />
<br />
The first entry in both tables is the count of the table, the parent directory index will be the amount of table rows. The root includes itself, so there are the amount - 1 (minus one) folders in the root directory (or files). The entries that follow after the root are the actual folders/files.<br />
<br />
Reading the files out is as simple as taking the file base offset and adding (block_offset * 0x200) to it.<br />
<br />
Here's a follow-up example from the Legend of Zelda: Ocarina of Time 3D:<br />
<pre><br />
//FST entry = SAVE base + File base + (FST offset * 0x200) + (FST entry # * 0x30)<br />
//0x2600 = 0x2000 + 0x400 + (0x1 * 0x200) + (0x0 * 0x30)<br />
<br />
00002600: 03000000 09000000 00000000 00000000 ................<br />
00002610: 00000000 00000000 00000000 00000000 ................<br />
00002620: 00000000 00000000 00000000 00000000 ................<br />
00002630: 01000000 73797374 656D2E64 61740000 ....system.dat..<br />
00002640: 00000000 00000000 D57B1100 02000000 ........Õ{......<br />
00002650: 22000000 00000000 E8121500 00000000 ".......è.......<br />
00002660: 01000000 73617665 30302E62 696E0000 ....save00.bin..<br />
00002670: 00000000 01000000 69921100 03000000 ........i’......<br />
00002680: DC140000 00000000 04000000 00000000 Ü...............<br />
</pre><br />
<br />
{| class="wikitable"<br />
|-<br />
! Start<br />
! Length<br />
! Description<br />
|-<br />
| 0x00<br />
| 4<br />
| Magic ("SAVE")<br />
|-<br />
| 0x04<br />
| 4<br />
| Magic padding<br />
|-<br />
| 0x08<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x10<br />
| 8<br />
| Partition Size [medias]<br />
|-<br />
| 0x18<br />
| 4<br />
| Partition Media Size<br />
|-<br />
| 0x1C<br />
| 8<br />
| Unknown<br />
|-<br />
| 0x24<br />
| 4<br />
| Unknown<br />
|-<br />
| 0x28<br />
| 8<br />
| FolderMap Offset<br />
|-<br />
| 0x30<br />
| 4<br />
| FolderMap Size<br />
|-<br />
| 0x34<br />
| 4<br />
| FolderMap Media Size<br />
|-<br />
| 0x38<br />
| 8<br />
| FileMap Offset<br />
|-<br />
| 0x40<br />
| 4<br />
| FileMap Size<br />
|-<br />
| 0x44<br />
| 4<br />
| FileMap Media Size<br />
|-<br />
| 0x48<br />
| 8<br />
| BlockMap Offset<br />
|-<br />
| 0x50<br />
| 4<br />
| BlockMap Size<br />
|-<br />
| 0x54<br />
| 4<br />
| BlockMap Media Size<br />
|-<br />
| 0x58<br />
| 8<br />
| File store offset (from SAVE)<br />
|-<br />
| 0x60<br />
| 4<br />
| File store length [medias]<br />
|-<br />
| 0x64<br />
| 4<br />
| File store media size<br />
|-<br />
| 0x68<br />
| 4/8<br />
| Folders Table offset (8 bytes in DATA)<br />
|-<br />
| 0x6C<br />
| 4<br />
| Folders Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x70<br />
| 4<br />
| Folders Table unknown<br />
|-<br />
| 0x74<br />
| 4<br />
| Folders Table Media size<br />
|-<br />
| 0x78<br />
| 4/8<br />
| Files Table offset (8 bytes in DATA)<br />
|-<br />
| 0x7C<br />
| 4<br />
| Files Table Length (medias) (Only in no DATA)<br />
|-<br />
| 0x80<br />
| 4<br />
| Files Table unknown<br />
|-<br />
| 0x84<br />
| 4<br />
| Files Table Media size<br />
|-<br />
|}<br />
<br />
* The FolderMap and FileMap still unknown. They are tables of uint32.<br />
* The BlockMap is a map of the blocks in the filestore. An entry in the BlockMap is 2 uint32: {uint32 start_block; uint32 end_block; }. This is still being researched. (You can use [[3DSExplorer]] to see those maps.<br />
<br />
'''Summary Drawing'''<br />
<br />
[[File:Sfsave_drawing.png]]<br />
<br />
=== Initialization ===<br />
<br />
When a save EEPROM contains all xFFFF blocks it's assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. <br />
<br />
I got a new game SplinterCell3D-Pal and I downloaded the save and it was 128KB of 0xFF, except the first 0x10 bytes which were the letter 'Z' (uppercase) --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)<br />
<br />
=== Fun Facts ===<br />
<br />
If you have facts that you found out by looking at the binary files please share them here:<br />
<br />
* From one save to another the game backups the last files that were in the partition and the entire image header in "random" locations.. --[[User:Elisherer|Elisherer]] 22:41, 15 October 2011 (CEST)</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Traductores&diff=2087
Traductores
2011-12-29T23:00:05Z
<p>Xerpi: </p>
<hr />
<div>Esta lista incluye todos los colaboradores de la traducción española de 3DBrew<br />
<br />
''En la columna de "Contribuciones", añadir el enlace a cada página traducida (ya sea en su totalidad o en parte)''<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! width="32%" | Nombre<br />
! width="8%" |Región<br />
! width="60%" |Contribuciones<br />
! |Retrato Mii<br />
|-<br />
| <center>[[user:Xerpi|xerpi]]</center><br />
| <center>España</center><br />
|<br />
-[[Main_Page/es|Página principal]]<br><br />
-[[News/Archive/es|Archivos]]<br><br />
-[[Glossary/es|Glosario]]<br><br />
-[[Hardware/es|Hardware]]<br><br />
-[[FAQ/es|Preguntas frecuentes]]<br />
|[[File:MiiXerpi.jpg|120px]]<br />
|-<br />
| <center>[[user:Markitus95|Markitus95]]</center><br />
| <center>España</center><br />
| -[[Circle Pad Pro/Es|Circle Pad Pro]]<br />
-[[Gamecards/es|Tarjetas 3DS]]<br />
| [[File:MiiMarkitus95.jpg|120px]]<br />
|-</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=FAQ/es&diff=2086
FAQ/es
2011-12-29T22:55:52Z
<p>Xerpi: Created page with "===== Preguntas Generales ===== '''P:''' ¿Algún progreso? '''R:''' Mira en las últimas noticias de la página principal, si hay algún progreso estará allí. '''P:''' ¿S..."</p>
<hr />
<div>===== Preguntas Generales =====<br />
<br />
'''P:''' ¿Algún progreso?<br />
<br />
'''R:''' Mira en las últimas noticias de la página principal, si hay algún progreso estará allí.<br />
<br />
<br />
'''P:''' ¿Se ha dumpeado ya la NAND?<br />
<br />
'''R:''' Si, el dumpeo de la NAND se ha realizado con éxito , aunque la imagen está encriptada. Por internet hay un dump falso, como broma del dia del pescado de abril.<br />
<br />
<br />
===== Contribuciones =====<br />
<br />
'''P:''' ¿Qué puedo hacer para ayudar?<br />
<br />
'''R:''' Trata de mantener la información de este wiki actualizada. Tratar de corregir o aclarar cualquier información poco clara. Intente documentar información útil sobre la Nintendo 3DS.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Traductores&diff=2085
Traductores
2011-12-29T22:49:09Z
<p>Xerpi: </p>
<hr />
<div>Esta lista incluye todos los colaboradores de la traducción española de 3DBrew<br />
<br />
''En la columna de "Contribuciones", añadir el enlace a cada página traducida (ya sea en su totalidad o en parte)''<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! width="32%" | Nombre<br />
! width="8%" |Región<br />
! width="60%" |Contribuciones<br />
! |Retrato Mii<br />
|-<br />
| <center>[[user:Xerpi|xerpi]]</center><br />
| <center>España</center><br />
|<br />
-[[Main_Page/es|Página principal]]<br><br />
-[[News/Archive/es|Archivos]]<br><br />
-[[Glossary/es|Glosario]]<br><br />
-[[Hardware/es|Hardware]]<br />
|[[File:MiiXerpi.jpg|120px]]<br />
|-<br />
| <center>[[user:Markitus95|Markitus95]]</center><br />
| <center>España</center><br />
| -[[Circle Pad Pro/Es|Circle Pad Pro]]<br />
-[[Gamecards/es|Tarjetas 3DS]]<br />
| [[File:MiiMarkitus95.jpg|120px]]<br />
|-</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Hardware/es&diff=2084
Hardware/es
2011-12-29T22:48:24Z
<p>Xerpi: Created page with "{{stub}} En esta página se enumera y describe el hardware que se encuentra dentro de la Nintendo 3DS. Muchas de estas partes han sido hechas manualmente y se amplían aquí o e..."</p>
<hr />
<div>{{stub}}<br />
<br />
En esta página se enumera y describe el hardware que se encuentra dentro de la Nintendo 3DS. Muchas de estas partes han sido hechas manualmente y se amplían aquí o en otras páginas.<br />
<br />
== Especificaciones ==<br />
<br />
{| class="wikitable"<br />
! Tipo!! Nombre !! Hoja de datos !! fuente<br />
|-<br />
| SoC || Nintendo 1048 0H (Modificado): CPU, GPU, VRAM & DSP todo en un chip. || N/A || N/A<br />
|-<br />
| Núcleo procesador || ARM11 MPCore 2x 268MHz & 2x VFP Co-Processor || [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360f/index.html] || [11] <br />
|-<br />
| GPU || [http://en.wikipedia.org/wiki/PICA200 DMP PICA] 268MHz || N/A || [11] <br />
|-<br />
| DSP || 134Mhz. 24ch 32728Hz frecuencias de muestreo. || N/A || [11]<br />
|-<br />
| VRAM || 6 MB en SoC. Independiente de la memoria del sistema (FCRAM). || N/A || [11]<br />
|-<br />
| FCRAM || 2x64MB Fujitsu MB82M8080-07L ||[http://crediar.no-ip.com/sg_/download.php?id=d67d1c][http://edevice.fujitsu.com/fj/DATASHEET/e-ds/e511463.pdf][http://edevice.fujitsu.com/jp/datasheet/j-ds/j511463.pdf]|| [5]<br />
|-<br />
| Almacenamiento || Toshiba THGBM2G3P1FBAI8 1GB NAND Flash || N/A || N/A<br />
|-<br />
| Administración de energía || Texas Instruments PAIC3010B 0AA37DW || N/A || FCC filing<br />
|-<br />
| Giroscopio || Invensense ITG-3270 MEMS Gyroscope || [http://dl-web.dropbox.com/u/20520664/references/PS-ITG-3200-00-01.4.pdf] || N/A<br />
|-<br />
| Acelerómetro || ST Micro 2048 33DH X1MAQ Modelo LIS331DH || [http://dl.dropbox.com/u/20520664/references/CD00213470.pdf] || N/A<br />
|-<br />
| Wifi || 802.11b/g Atheros AR6014 || [http://www.db.pokestation.net/3DS/Wi-Fi%20module%20pinouts.pdf] || N/A<br />
|-<br />
| IC Infrarrojo || NXP infrared IC, "S750 0803 TSD031C" || N/A || [10]<br />
|-<br />
| Microcontrolador auxiliar || UC CTR, microcontrolador personalizado|| N/A || N/A<br />
|}<br />
<br />
* [11] Documentación oficial<br />
<br />
* [5],[10] Según iFixit.com ([http://www.ifixit.com/Teardown/Nintendo-3DS-Teardown/5029/1#s22696 source]):<br />
<br />
* La hoja de datos de la memoria es para un chip de la misma serie, que tiene menos memoria que el de la 3DS (128mbits vs 512mbits).<br />
<br />
* Hay mucha información en [https://fjallfoss.fcc.gov/oetcf/eas/reports/ViewExhibitReport.cfm?mode=Exhibits&RequestTimeout=500&calledFromFrame=N&application_id=462292&fcc_id=%27EW4DWMW028%27].<br />
<br />
== FCRAM ==<br />
Hay una FCRAM (RAM de Ciclo Rápido) IC en la 3DS, producida por Fujitsu, el modelo es MB82M8080-07L. Fujitsu MB82M8080-07L contiene internamente 2 dies, uno MB81EDS516545 y el otro MB82DBS08645.<br />
<br />
El die MB81EDS516545 es un CMOS FCRAM con la interfaz SDRAM de velocidad de datos de doble baja potencia (LPDDR) que contiene 512MBit de almacenamiento accesible en formato de 64-bit. El MB81EDS516545 es adecuado para aplicaciones que requieren un alto ancho de banda de datos con bajo consumo de energía.<br />
<br />
<br />
== SoC ==<br />
<br />
La 3DS tiene gran parte de su funcionamiento interno ubicado en un SoC (System on Chip) al igual que sus predecesores. Esto se hace para reducir los costos de fabricación, reducir el consumo de energía, así como hacer el diseño de la PCB de menor complejidad y que el sistema sea más difícil de manipular. El SoC, calificado como el Nintendo 0H 1048, contiene la CPU, GPU, DSP y VRAM.<br />
De acuerdo con documentos oficiales, la CPU usa una CPU de doble núcleo ARM11, a velocidad de reloj de 268MHz. Un núcleo está dedicado al software del sistema, mientras que el otro se utiliza para la programación de aplicaciones, cada uno conocido como la syscore y AppCore, respectivamente.<br />
<br />
== Imágenes ==<br />
<br />
=== Delante ===<br />
<br />
[[Image:CTR_Front.jpg|600px]]<br />
<br />
[http://guide-images.ifixit.net/igi/ishJaSCOwLkvbLYK Alta resolución]<br />
<br />
=== Detrás ===<br />
<br />
[[Image:CTR_Back.jpg]]<br />
<br />
[http://guide-images.ifixit.net/igi/n1CKAdbPrHyNPNuW Alta resolución]<br />
<br />
=== Pinout de la NAND ===<br />
[[Image:CTR_NAND_pinout.png]]<br />
<br />
Se ha realizado con éxito el dumpeo de la NAND, pero la imagen está encriptada.<br />
=== Pinout del dongle WiFi ===<br />
[[Image:CTR_WiFiDongle_pinout.png|600px]]<br />
<br />
La interfaz SDIO es de color rojo: <br />
* CLK<br />
* CMD<br />
* D0, D1, D2, D3<br />
Esta es la interfaz para el nuevo módulo Wifi (basado en un based on Atheros AR6002), ya incluido en la DSi.<br />
El antiguo WiFi de la DS es de color amarillo, los pins son por ahora desconocidos.<br />
<br />
La EEPROM I2C es de color azul:<br />
* SCL<br />
* SDA<br />
<br />
La Flash SPI es de color púrpura:<br />
* CLK<br />
* CS#<br />
* SI<br />
* SO<br />
* WP#<br />
* NC<br />
<br />
=== Microcontrolador auxiliar ===<br />
[[Image:CTR_UC.png|600px]]<br />
<br />
Gestiona el botón HOME, el interruptor WiFi, el regulador 3D y el regulador del control del volumen. Controla LEDs, varias fuentes de alimentación.<br />
<br />
Dispositivos conectados al bus I2C:<br />
* UC (master?)<br />
* Acelerómetro (slave address 0x18)<br />
* SoC (master? slave?)</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Main_Page/Navigation/es&diff=2081
Main Page/Navigation/es
2011-12-29T20:16:12Z
<p>Xerpi: </p>
<hr />
<div>{{Main page box|Navegación|Main Page/Navigation/es}}<br />
<div style="margin: -.3em -1em -1em -1em;"><br />
{| width="100%" bgcolor="#fff" border="0" cellpadding="2px" cellspacing="2px" style="margin:auto;"<br />
|- align="center" bgcolor="#e7eef6"<br />
! width="33%" | '''General'''<br />
! width="34%" | '''3DS hardware'''<br />
! width="33%" | '''3DS software'''<br />
|- valign="top" style="background: #F5FAFF;"<br />
| <br />
*[[3DS exploits/es|Exploits de la 3DS]]<br />
*[[Glossary/es|Glosario]]<br />
*[[FAQ/es|Preguntas frecuentes]]<br />
*[[Friend code/es|Códigos de amigo]]<br />
*[[Games/es|Juegos]]<br />
|<br />
*[[Hardware/es|Hardware]]<br />
*[[Circle Pad Pro/Es|Circle Pad Pro]]<br />
*[[Gamecards/es|Tarjetas 3DS]]<br />
|<br />
*[[Nintendo Software/es|Software de Nintendo]]<br />
*[[3DS Development Unit Software/es|Unidad de Desarrollo de Software 3DS]]<br />
*[[File Formats/es|Formatos de archivo]] ([[CCI/es|CCI]]/[[CXI/es|CXI]]/[[CIA/es|CIA]])<br />
*[[Title list/es|Lista de títulos]]<br />
*[[Title metadata/es|Metadatos de título]]<br />
*[[SD Filesystem/es|Sistema de archivos de la SD]]<br />
*[[Flash Filesystem/es|Sistema de archivos de la Flash]]<br />
*[[Bootloader/es|Bootloader]]<br />
*[[Savegames/es|Partidas guardadas]]<br />
|}<br />
</div><br />
{{box-footer-empty}}</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Traductores&diff=2080
Traductores
2011-12-29T20:00:45Z
<p>Xerpi: </p>
<hr />
<div>Esta lista incluye todos los colaboradores de la traducción española de 3DBrew<br />
<br />
''En la columna de "Contribuciones", añadir el enlace a cada página traducida (ya sea en su totalidad o en parte)''<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! width="32%" | Nombre<br />
! width="8%" |Región<br />
! width="60%" |Contribuciones<br />
! |Retrato Mii<br />
|-<br />
| <center>[[user:Xerpi|xerpi]]</center><br />
| <center>España</center><br />
|<br />
-[[Main_Page/es|Página principal]]<br><br />
-[[News/Archive/es|Archivos]]<br><br />
-[[Glossary/es|Glosario]]<br />
|[[File:MiiXerpi.jpg|120px]]<br />
|-<br />
| <center>[[user:Markitus95|Markitus95]]</center><br />
| <center>España</center><br />
| -[[Circle Pad Pro/Es|Circle Pad Pro]]<br />
| [[File:MiiMarkitus95.jpg|120px]]<br />
|-</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=File:MiiXerpi.jpg&diff=2079
File:MiiXerpi.jpg
2011-12-29T19:59:50Z
<p>Xerpi: </p>
<hr />
<div></div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Glossary/es&diff=2078
Glossary/es
2011-12-29T19:47:09Z
<p>Xerpi: </p>
<hr />
<div>Un pequeño diccionario de los términos que te puedes encontrar en 3DSBrew.<br />
<br />
== C ==<br />
<br />
=== C ===<br />
<br />
Es el lenguaje en que los desarrolladores de homebrew programan. También es un lenguaje de programación que se utiliza para hacer todo, desde su sistema operativo hasta su consola de videojuegos.<br />
<br />
=== C++ ===<br />
<br />
Es un lenguaje de programación orientado a objetos en que los desarrolladores de homebrew programan. Como su nombre indica, C + + es esencialmente una mejora respecto a C.<br />
<br />
== D ==<br />
=== Descarga DS ===<br />
<br />
Otra aplicación integrada en el firmware de Nintendo 3DS. Es un lugar donde la gente puede descargar los juegos multijugador desde otra DS o 3DS, con los juegos compatibles que son capaces de utilizar una sola tarjeta de juego para jugar contra varias personas.<br />
<br />
=== DSi ===<br />
<br />
Es consola portátil creada por Nintendo. Es la segunda sucesora de la Nintendo DS, y la 6 ª generación portátil de Nintendo. Cuenta con dos pantallas (más grandes), dos cámaras y un sistema de compras en línea. El menú también es diferente, ya que usa canales similares a los utilizados en la Wii. El brillo de la pantalla que se puede establecer más que la DS Lite.<br />
<br />
=== DS Lite ===<br />
<br />
La predecesora de la DSi. Llegó después de la original DS “Fat” y tiene 4 niveles de brillo de pantalla, como la DS “Fat”.<br />
<br />
=== DS "FAT" ===<br />
<br />
La Nintendo DS original. Terminó siendo la sucesora de la Game Boy, aunque Nintendo no tenía la intención de que esto sucediera. Tiene una pantalla táctil.<br />
=== DSiWare ===<br />
<br />
Una plataforma iniciada por Nintendo que permite a los desarrolladores crear de forma barata y después vender contenidos originales a bajo precio (en comparación con los precios de los juegos de nueva DSi). Todos los juegos de DSiWare están disponibles en el Canal Tienda DSi en el menú principal.<br />
<br />
=== Dump ===<br />
<br />
Extracción el contenido protegido de algo así como una unidad de chips NAND o el disco o que son inaccesibles y / o incomprensible, en circunstancias normales.<br />
<br />
== E ==<br />
<br />
=== Exploit ===<br />
<br />
Una elusión inteligente de seguridad que permite al usuario realizar tareas que normalmente no están permitidos. A menudo, algunos exploits son empleados en serie para que el usuario pueda ganar autoridad progresivamente sobre el sistema en cada paso, con el objetivo de conseguir el control y el acceso total al sistema.<br />
== F ==<br />
<br />
=== FCRAM ===<br />
FCRAM (RAM de ciclo rápido: Fast Cycle RAM) es una nueva tecnología desarrollada por Fujitsu Corporation que aborda el problema de la velocidad del DRAM / procesador de una manera diferente. Es uno de los componentes de hardware de 3DS.<br />
<br />
== H ==<br />
<br />
=== Hexadecimal (Hex) ===<br />
<br />
Es un término usado para describir el sistema de numeración de base 16, en el qual cada dígito representa cuatro bits. Después de los dígitos 0-9, se emplean las letras A-F para representar los valores del 10 al 15. Hexadecimal es el formato preferido para mostrar los datos binarios, ya que es fácil de convertir mentalmente a / desde binario y sólo utiliza dos caracteres por byte.<br />
<br />
== I ==<br />
<br />
=== IRC ===<br />
<br />
IRC (Internet Relay Chat); es un chat en tiempo real basado en texto a través de Internet.<br />
<br />
== M ==<br />
=== [[Menú Principal]] ===<br />
<br />
Interfaz principal de la 3DS, aparece después de la pantalla de advertencia de salud cuando el sistema está encendido. En la 3DS aquí es donde están todos los de juegos y los canales descargados.<br />
<br />
=== [[Title metadata/es|Metadatos de título]] ===<br />
Un formato que se utiliza para almacenar los metadatos de un título y su contenido instalado, incluyendo los contenidos que consisten en sus hash SHA1.<br />
=== [[MPO]] ===<br />
<br />
MPO (Multi-Picture Object), es un formato de archive abierto, usado por Nintendo para crear imágenes 3D. Usa etiquetas Exif y MP juntamente con JPG. Se puede leer un archivo MPO como si fuera dos JPG juntos.<br />
<br />
== S ==<br />
<br />
== T ==<br />
=== Tarjeta SD ===<br />
<br />
Un tipo común de tarjeta de memoria, utilizado por la 3DS, cámaras digitales, reproductores de música, etc. Significa SecureDigital. La tarjeta SD estándar tiene una capacidad máxima de 2 gigabytes (2.048 megabytes), sin embargo, algunas tarjetas de 4GB existen, pero son raras. Estas tarjetas no suelen tener una gran compatibilidad con los productos que no cuenten con SDHC , a pesar de que no son SDHC, 2 GB es el tamaño que deberías utilizar.<br />
=== Tarjeta SDHC ===<br />
<br />
ES para tarjeta SD de alta capacidad. Un tipo de tarjeta SD con una capacidad de almacenamiento superior a la normal de las tarjetas SD. Estos son teóricamente capaces de albergar hasta 2 terabytes de espacio, pero son políticamente limitadas por las normas vigentes a 32 gigabytes.<br />
<br />
=== [[TMD]] ===<br />
<br />
Ver [[Title metadata]].<br />
<br />
=== Título ===<br />
<br />
Un título es un juego de 3DS en una tarjeta o en una 3DS. Un título está identificado por un único ID, un código de 8 bytes (4 caracteres) utilizado para la identificación del título. Todos los títulos están cifrados por razones de seguridad.</div>
Xerpi
https://www.3dbrew.org/w/index.php?title=Glossary/es&diff=2077
Glossary/es
2011-12-29T19:46:45Z
<p>Xerpi: </p>
<hr />
<div>Un pequeño diccionario de los términos que te puedes encontrar en 3DSBrew.<br />
<br />
== C ==<br />
<br />
=== C ===<br />
<br />
Es el lenguaje en que los desarrolladores de homebrew programan. También es un lenguaje de programación que se utiliza para hacer todo, desde su sistema operativo hasta su consola de videojuegos.<br />
<br />
=== C++ ===<br />
<br />
Es un lenguaje de programación orientado a objetos en que los desarrolladores de homebrew programan. Como su nombre indica, C + + es esencialmente una mejora respecto a C.<br />
<br />
== D ==<br />
<br />
=== DSi ===<br />
<br />
Es consola portátil creada por Nintendo. Es la segunda sucesora de la Nintendo DS, y la 6 ª generación portátil de Nintendo. Cuenta con dos pantallas (más grandes), dos cámaras y un sistema de compras en línea. El menú también es diferente, ya que usa canales similares a los utilizados en la Wii. El brillo de la pantalla que se puede establecer más que la DS Lite.<br />
<br />
=== DS Lite ===<br />
<br />
La predecesora de la DSi. Llegó después de la original DS “Fat” y tiene 4 niveles de brillo de pantalla, como la DS “Fat”.<br />
<br />
=== DS "FAT" ===<br />
<br />
La Nintendo DS original. Terminó siendo la sucesora de la Game Boy, aunque Nintendo no tenía la intención de que esto sucediera. Tiene una pantalla táctil.<br />
=== DSiWare ===<br />
<br />
Una plataforma iniciada por Nintendo que permite a los desarrolladores crear de forma barata y después vender contenidos originales a bajo precio (en comparación con los precios de los juegos de nueva DSi). Todos los juegos de DSiWare están disponibles en el Canal Tienda DSi en el menú principal.<br />
<br />
=== Dump ===<br />
<br />
Extracción el contenido protegido de algo así como una unidad de chips NAND o el disco o que son inaccesibles y / o incomprensible, en circunstancias normales.<br />
=== Descarga DS ===<br />
<br />
Otra aplicación integrada en el firmware de Nintendo 3DS. Es un lugar donde la gente puede descargar los juegos multijugador desde otra DS o 3DS, con los juegos compatibles que son capaces de utilizar una sola tarjeta de juego para jugar contra varias personas.<br />
<br />
== E ==<br />
<br />
=== Exploit ===<br />
<br />
Una elusión inteligente de seguridad que permite al usuario realizar tareas que normalmente no están permitidos. A menudo, algunos exploits son empleados en serie para que el usuario pueda ganar autoridad progresivamente sobre el sistema en cada paso, con el objetivo de conseguir el control y el acceso total al sistema.<br />
== F ==<br />
<br />
=== FCRAM ===<br />
FCRAM (RAM de ciclo rápido: Fast Cycle RAM) es una nueva tecnología desarrollada por Fujitsu Corporation que aborda el problema de la velocidad del DRAM / procesador de una manera diferente. Es uno de los componentes de hardware de 3DS.<br />
<br />
== H ==<br />
<br />
=== Hexadecimal (Hex) ===<br />
<br />
Es un término usado para describir el sistema de numeración de base 16, en el qual cada dígito representa cuatro bits. Después de los dígitos 0-9, se emplean las letras A-F para representar los valores del 10 al 15. Hexadecimal es el formato preferido para mostrar los datos binarios, ya que es fácil de convertir mentalmente a / desde binario y sólo utiliza dos caracteres por byte.<br />
<br />
== I ==<br />
<br />
=== IRC ===<br />
<br />
IRC (Internet Relay Chat); es un chat en tiempo real basado en texto a través de Internet.<br />
<br />
== M ==<br />
=== [[Menú Principal]] ===<br />
<br />
Interfaz principal de la 3DS, aparece después de la pantalla de advertencia de salud cuando el sistema está encendido. En la 3DS aquí es donde están todos los de juegos y los canales descargados.<br />
<br />
=== [[Title metadata/es|Metadatos de título]] ===<br />
Un formato que se utiliza para almacenar los metadatos de un título y su contenido instalado, incluyendo los contenidos que consisten en sus hash SHA1.<br />
=== [[MPO]] ===<br />
<br />
MPO (Multi-Picture Object), es un formato de archive abierto, usado por Nintendo para crear imágenes 3D. Usa etiquetas Exif y MP juntamente con JPG. Se puede leer un archivo MPO como si fuera dos JPG juntos.<br />
<br />
== S ==<br />
<br />
== T ==<br />
=== Tarjeta SD ===<br />
<br />
Un tipo común de tarjeta de memoria, utilizado por la 3DS, cámaras digitales, reproductores de música, etc. Significa SecureDigital. La tarjeta SD estándar tiene una capacidad máxima de 2 gigabytes (2.048 megabytes), sin embargo, algunas tarjetas de 4GB existen, pero son raras. Estas tarjetas no suelen tener una gran compatibilidad con los productos que no cuenten con SDHC , a pesar de que no son SDHC, 2 GB es el tamaño que deberías utilizar.<br />
=== Tarjeta SDHC ===<br />
<br />
ES para tarjeta SD de alta capacidad. Un tipo de tarjeta SD con una capacidad de almacenamiento superior a la normal de las tarjetas SD. Estos son teóricamente capaces de albergar hasta 2 terabytes de espacio, pero son políticamente limitadas por las normas vigentes a 32 gigabytes.<br />
<br />
=== [[TMD]] ===<br />
<br />
Ver [[Title metadata]].<br />
<br />
=== Título ===<br />
<br />
Un título es un juego de 3DS en una tarjeta o en una 3DS. Un título está identificado por un único ID, un código de 8 bytes (4 caracteres) utilizado para la identificación del título. Todos los títulos están cifrados por razones de seguridad.</div>
Xerpi