├── CMakeLists.txt ├── Readme.md └── source ├── AmiiboUtil.cpp ├── AmiiboUtil.h ├── amiibo_map.h ├── amiibo_structs.h ├── bswap.h ├── communicator.cpp ├── communicator.h ├── cpu_guess.h ├── main.cpp └── main_non_gui.cpp /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | set(PROJECT Wumiibo) 4 | project(${PROJECT}) 5 | set(CMAKE_CXX_STANDARD 17) 6 | add_compile_options(-Wall -Wextra) 7 | 8 | 9 | set(NO_GUI "OFF" CACHE BOOL 10 | "Set to ON to build the non gui version of Wumiibo-Client") 11 | 12 | if(NO_GUI) 13 | set(SOURCES 14 | source/main_non_gui.cpp 15 | source/communicator.cpp 16 | source/AmiiboUtil.cpp 17 | ) 18 | 19 | else(NO_GUI) 20 | set(SOURCES 21 | source/main.cpp 22 | source/communicator.cpp 23 | source/AmiiboUtil.cpp 24 | ) 25 | endif(NO_GUI) 26 | 27 | set(HEADERS 28 | source/amiibo_map.h 29 | source/amiibo_structs.h 30 | source/communicator.h 31 | source/AmiiboUtil.h 32 | source/cpu_guess.h 33 | source/bswap.h 34 | ) 35 | 36 | add_executable(${PROJECT} ${SOURCES} ${HEADERS}) 37 | if(NO_GUI) 38 | target_link_libraries(${PROJECT} ws2_32 -static) 39 | else(NO_GUI) 40 | target_link_libraries(${PROJECT} nana jpeg png z gdi32 comdlg32 ws2_32 -static) 41 | endif(NO_GUI) -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Wumiibo-Client 2 | This is the source code for the client/companion app for [wumiibo](https://github.com/hax0kartik/wumiibo)(amiibo emulation for 3ds over network) 3 | 4 | ## How To Use 5 | 6 | * Decrypt your amiibo dumps using [amiitool](https://github.com/socram8888/amiitool) 7 | * Select your encrypted and decrypted amiibo bins 8 | * Enter 3ds's IP and press on `Emulate` -------------------------------------------------------------------------------- /source/AmiiboUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "AmiiboUtil.h" 2 | #include "amiibo_map.h" 3 | #include 4 | 5 | std::string AmiiboUtil::GetNameForID(uint64_t id) 6 | { 7 | return amiibo_map[id]; 8 | }; -------------------------------------------------------------------------------- /source/AmiiboUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | class AmiiboUtil 5 | { 6 | public: 7 | std::string GetNameForID(uint64_t id); 8 | }; -------------------------------------------------------------------------------- /source/amiibo_map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | std::map amiibo_map = { 7 | {0x0000000000000002, "Mario" }, 8 | {0x0000000000340102, "Mario" }, 9 | {0x00000000003c0102, "Mario - Gold Edition" }, 10 | {0x00000000003d0102, "Mario - Silver Edition" }, 11 | {0x0000000002380602, "8-Bit Mario Classic Color" }, 12 | {0x0000000002390602, "8-Bit Mario Modern Color" }, 13 | {0x0000000003710102, "Mario - Wedding" }, 14 | {0x0000010000190002, "Dr. Mario" }, 15 | {0x00010000000c0002, "Luigi" }, 16 | {0x0001000000350102, "Luigi" }, 17 | {0x0002000000010002, "Peach" }, 18 | {0x0002000000360102, "Peach" }, 19 | {0x0002000003720102, "Peach - Wedding" }, 20 | {0x0003000000020002, "Yoshi" }, 21 | {0x0003000000370102, "Yoshi" }, 22 | {0x0003010200410302, "Green Yarn Yoshi" }, 23 | {0x0003010200420302, "Pink Yarn Yoshi" }, 24 | {0x0003010200430302, "Light Blue Yarn Yoshi" }, 25 | {0x00030102023e0302, "Mega Yarn Yoshi" }, 26 | {0x0004000002620102, "Rosalina" }, 27 | {0x0004010000130002, "Rosalina & Luma" }, 28 | {0x0005000000140002, "Bowser" }, 29 | {0x0005000000390102, "Bowser" }, 30 | {0x0005000003730102, "Bowser - Wedding" }, 31 | {0x0005ff00023a0702, "Hammer Slam Bowser" }, 32 | {0x0006000000150002, "Bowser Jr." }, 33 | {0x00070000001a0002, "Wario" }, 34 | {0x0007000002630102, "Wario" }, 35 | {0x0008000000030002, "Donkey Kong" }, 36 | {0x0008000002640102, "Donkey Kong" }, 37 | {0x0008ff00023b0702, "Turbo Charge Donkey Kong" }, 38 | {0x00090000000d0002, "Diddy Kong" }, 39 | {0x0009000002650102, "Diddy Kong" }, 40 | {0x000a000000380102, "Toad" }, 41 | {0x0013000002660102, "Daisy" }, 42 | {0x00130000037a0002, "Daisy" }, 43 | {0x0014000002670102, "Waluigi" }, 44 | {0x0017000002680102, "Boo" }, 45 | {0x00800102035d0302, "Poochy" }, 46 | {0x0100000000040002, "Link" }, 47 | {0x01000000034b0902, "Link - Ocarina of Time" }, 48 | {0x01000000034c0902, "Link - Majora's Mask" }, 49 | {0x01000000034d0902, "Link - Twilight Princess" }, 50 | {0x01000000034e0902, "Link - Skyward Sword" }, 51 | {0x01000000034f0902, "8-Bit Link" }, 52 | {0x0100000003530902, "Link - Archer" }, 53 | {0x0100000003540902, "Link - Rider" }, 54 | {0x01000000037c0002, "Young Link" }, 55 | {0x0100000003990902, "Link - Link's Awakening" }, 56 | {0x0100010000160002, "Toon Link" }, 57 | {0x0100010003500902, "Toon Link - The Wind Waker" }, 58 | {0x01010000000e0002, "Zelda" }, 59 | {0x0101000003520902, "Toon Zelda - The Wind Waker" }, 60 | {0x0101000003560902, "Zelda" }, 61 | {0x0101010000170002, "Sheik" }, 62 | {0x01020100001b0002, "Ganondorf" }, 63 | {0x01030000024f0902, "Midna & Wolf Link" }, 64 | {0x0105000003580902, "Daruk" }, 65 | {0x0106000003590902, "Urbosa" }, 66 | {0x01070000035a0902, "Mipha" }, 67 | {0x01080000035b0902, "Revali" }, 68 | {0x0140000003550902, "Guardian" }, 69 | {0x01410000035c0902, "Bokoblin" }, 70 | {0x0180000000080002, "Villager" }, 71 | {0x01810000024b0502, "Isabelle - Summer Outfit" }, 72 | {0x0181000100440502, "Isabelle" }, 73 | {0x01810000037d0002, "Isabelle" }, 74 | {0x0181000101d40502, "Isabelle - Character Parfait" }, 75 | {0x01810100023f0502, "Isabelle - Winter" }, 76 | {0x0181010100b40502, "Isabelle - Winter" }, 77 | {0x01810201011a0502, "Isabelle - Kimono" }, 78 | {0x0181030101700502, "Isabelle - Dress" }, 79 | {0x0182000002400502, "K. K. Slider" }, 80 | {0x0182000100a80502, "K.K. Slider" }, 81 | {0x0182000101d80502, "K. K. Slider - Pikopuri" }, 82 | {0x0182010100460502, "DJ KK" }, 83 | {0x0183000002420502, "Tom Nook" }, 84 | {0x0183000100450502, "Tom Nook" }, 85 | {0x01830101010e0502, "Tom Nook - Jacket" }, 86 | {0x01840000024d0502, "Timmy & Tommy" }, 87 | {0x01850001004b0502, "Timmy" }, 88 | {0x0185020101170502, "Timmy - Full Apron" }, 89 | {0x0185040101790502, "Timmy - Suit" }, 90 | {0x0186010100af0502, "Tommy - Uniform" }, 91 | {0x0186030101750502, "Tommy - Suit" }, 92 | {0x0187000100470502, "Sable" }, 93 | {0x0188000002410502, "Mabel" }, 94 | {0x0188000101120502, "Mabel" }, 95 | {0x0189000100ab0502, "Labelle" }, 96 | {0x018a000002450502, "Reese" }, 97 | {0x018a000100a90502, "Reese" }, 98 | {0x018b000002460502, "Cyrus" }, 99 | {0x018b000101150502, "Cyrus" }, 100 | {0x018c000002430502, "Digby" }, 101 | {0x018c0001004c0502, "Digby" }, 102 | {0x018c010101180502, "Digby - Raincoat" }, 103 | {0x018d0000024c0502, "Rover" }, 104 | {0x018d0001010c0502, "Rover" }, 105 | {0x018e000002490502, "Resetti" }, 106 | {0x018e000100490502, "Resetti" }, 107 | {0x018e010101780502, "Resetti - Without Hat" }, 108 | {0x018f000100b30502, "Don Resetti" }, 109 | {0x018f010101190502, "Don Resetti - Without Hat" }, 110 | {0x0190000101710502, "Brewster" }, 111 | {0x01910001004e0502, "Harriet" }, 112 | {0x0192000002470502, "Blathers" }, 113 | {0x01920001010d0502, "Blathers" }, 114 | {0x0193000002480502, "Celeste" }, 115 | {0x0193000101740502, "Celeste" }, 116 | {0x01940000024a0502, "Kicks" }, 117 | {0x0194000100aa0502, "Kicks" }, 118 | {0x0195000100b00502, "Porter" }, 119 | {0x01960000024e0502, "Kapp'n" }, 120 | {0x0196000100480502, "Kapp'n" }, 121 | {0x0197000101770502, "Leilani" }, 122 | {0x0198000100b10502, "Lelia" }, 123 | {0x0199000101160502, "Grams" }, 124 | {0x019a000100b70502, "Chip" }, 125 | {0x019b000100b60502, "Nat" }, 126 | {0x019c000101730502, "Phineas" }, 127 | {0x019d000100ac0502, "Copper" }, 128 | {0x019e000100ad0502, "Booker" }, 129 | {0x019f000101110502, "Pete" }, 130 | {0x01a00001010f0502, "Pelly" }, 131 | {0x01a1000101100502, "Phyllis" }, 132 | {0x01a20001017d0502, "Gulliver" }, 133 | {0x01a30001004a0502, "Joan" }, 134 | {0x01a40001004d0502, "Pascal" }, 135 | {0x01a5000101720502, "Katrina" }, 136 | {0x01a6000100500502, "Sahara" }, 137 | {0x01a7000101140502, "Wendell" }, 138 | {0x01a80001004f0502, "Redd" }, 139 | {0x01a80101017e0502, "Redd - Shirt" }, 140 | {0x01a9000101760502, "Gracie" }, 141 | {0x01aa000100530502, "Lyle" }, 142 | {0x01ab0001017c0502, "Pave" }, 143 | {0x01ac0001017f0502, "Zipper" }, 144 | {0x01ad000100b80502, "Jack" }, 145 | {0x01ae0001011b0502, "Franklin" }, 146 | {0x01af0001011c0502, "Jingle" }, 147 | {0x01b0000100520502, "Tortimer" }, 148 | {0x01b1000100b20502, "Shrunk" }, 149 | {0x01b10101017b0502, "Shrunk - Loud Jacket" }, 150 | {0x01b3000100b50502, "Blanca" }, 151 | {0x01b4000101130502, "Leif" }, 152 | {0x01b5000100510502, "Luna" }, 153 | {0x01b6000100ae0502, "Katie" }, 154 | {0x01c1000002440502, "Lottie" }, 155 | {0x01c1000100540502, "Lottie" }, 156 | {0x01c10101017a0502, "Lottie - Black Skirt And Bow" }, 157 | {0x0200000100a10502, "Cyrano" }, 158 | {0x02010001016a0502, "Antonio" }, 159 | {0x0202000101030502, "Pango" }, 160 | {0x02030001019a0502, "Anabelle" }, 161 | {0x0206000103120502, "Snooty" }, 162 | {0x0208000100960502, "Annalisa" }, 163 | {0x02090001019f0502, "Olaf" }, 164 | {0x0214000100e40502, "Teddy" }, 165 | {0x0215000101820502, "Pinky" }, 166 | {0x0216000100570502, "Curt" }, 167 | {0x0217000101b30502, "Chow" }, 168 | {0x02190001007e0502, "Nate" }, 169 | {0x021a000100da0502, "Groucho" }, 170 | {0x021b000100800502, "Tutu" }, 171 | {0x021c000102f70502, "Ursala" }, 172 | {0x021d000101cd0502, "Grizzly" }, 173 | {0x021e000101230502, "Paula" }, 174 | {0x021f000103170502, "Ike" }, 175 | {0x0220000100fd0502, "Charlise" }, 176 | {0x02210001013c0502, "Beardo" }, 177 | {0x0222000101440502, "Klaus" }, 178 | {0x022d000100f20502, "Jay" }, 179 | {0x022e000101d30502, "Robin" }, 180 | {0x022f0001011e0502, "Anchovy" }, 181 | {0x0230000101d20502, "Twiggy" }, 182 | {0x02310001006a0502, "Jitters" }, 183 | {0x0232000102ea0502, "Piper" }, 184 | {0x0233000103060502, "Admiral" }, 185 | {0x0235000100840502, "Midge" }, 186 | {0x0238000102f80502, "Jacob" }, 187 | {0x023c000100bd0502, "Lucha" }, 188 | {0x023d000101b50502, "Jacques" }, 189 | {0x023e000100d10502, "Peck" }, 190 | {0x023f000101660502, "Sparro" }, 191 | {0x024a000101d10502, "Angus" }, 192 | {0x024b000101260502, "Rodeo" }, 193 | {0x024d000102f60502, "Stu" }, 194 | {0x024f000100810502, "T-Bone" }, 195 | {0x0251000100c10502, "Coach" }, 196 | {0x0252000100fe0502, "Vic" }, 197 | {0x025d000100550502, "Bob" }, 198 | {0x025e000101250502, "Mitzi" }, 199 | {0x025f000101c50502, "Rosie" }, 200 | {0x025f000101d70502, "Rosie - Amiibo Festival" }, 201 | {0x0260000100d20502, "Olivia" }, 202 | {0x0261000100650502, "Kiki" }, 203 | {0x0262000101370502, "Tangy" }, 204 | {0x0263000100750502, "Punchy" }, 205 | {0x0264000101ac0502, "Purrl" }, 206 | {0x0265000101540502, "Moe" }, 207 | {0x0266000100680502, "Kabuki" }, 208 | {0x0267000101080502, "Kid Cat" }, 209 | {0x02680001007d0502, "Monique" }, 210 | {0x02690001011f0502, "Tabby" }, 211 | {0x026a000101460502, "Stinky" }, 212 | {0x026b000100e90502, "Kitty" }, 213 | {0x026c000100c30502, "Tom" }, 214 | {0x026d0001013f0502, "Merry" }, 215 | {0x026e000100ba0502, "Felicity" }, 216 | {0x026f000101900502, "Lolly" }, 217 | {0x0270000100ff0502, "Ankha" }, 218 | {0x02710001019b0502, "Rudy" }, 219 | {0x0272000101860502, "Katt" }, 220 | {0x027d000100630502, "Bluebear" }, 221 | {0x027e000101690502, "Maple" }, 222 | {0x027f000100b90502, "Poncho" }, 223 | {0x0280000100830502, "Pudge" }, 224 | {0x0281000101200502, "Kody" }, 225 | {0x0282000101810502, "Stitches" }, 226 | {0x0282000101d60502, "Stitches - Amiibo Festival" }, 227 | {0x0283000100c70502, "Vladimir" }, 228 | {0x0284000102fe0502, "Murphy" }, 229 | {0x0286000103130502, "Olive" }, 230 | {0x02870001005a0502, "Cheri" }, 231 | {0x028a000102e90502, "June" }, 232 | {0x028b000100e30502, "Pekoe" }, 233 | {0x028c0001013e0502, "Chester" }, 234 | {0x028d000101bd0502, "Barold" }, 235 | {0x028e0001019e0502, "Tammy" }, 236 | {0x028f0101031a0502, "Marty" }, 237 | {0x0299000100950502, "Goose" }, 238 | {0x029a000100ee0502, "Benedict" }, 239 | {0x029b000100cb0502, "Egbert" }, 240 | {0x029e0001013d0502, "Ava" }, 241 | {0x02a2000101ba0502, "Becky" }, 242 | {0x02a3000102ff0502, "Plucky" }, 243 | {0x02a4000100720502, "Knox" }, 244 | {0x02a50001018c0502, "Broffina" }, 245 | {0x02a6000101240502, "Ken" }, 246 | {0x02b1000100690502, "Patty" }, 247 | {0x02b2000100c40502, "Tipper" }, 248 | {0x02b70001030f0502, "Norma" }, 249 | {0x02b80001019c0502, "Naomi" }, 250 | {0x02c3000100dc0502, "Alfonso" }, 251 | {0x02c4000100670502, "Alli" }, 252 | {0x02c5000103080502, "Boots" }, 253 | {0x02c7000101220502, "Del" }, 254 | {0x02c9000100cd0502, "Sly" }, 255 | {0x02ca000101ca0502, "Gayle" }, 256 | {0x02cb000101360502, "Drago" }, 257 | {0x02d6000100560502, "Fauna" }, 258 | {0x02d7000101300502, "Bam" }, 259 | {0x02d8000100e20502, "Zell" }, 260 | {0x02d9000101c80502, "Bruce" }, 261 | {0x02da000101330502, "Deirdre" }, 262 | {0x02db0001005e0502, "Lopez" }, 263 | {0x02dc000100be0502, "Fuchsia" }, 264 | {0x02dd000100ea0502, "Beau" }, 265 | {0x02de0001009c0502, "Diana" }, 266 | {0x02df000101910502, "Erik" }, 267 | {0x02e00101031d0502, "Chelsea" }, 268 | {0x02ea000101800502, "Goldie" }, 269 | {0x02ea000101d50502, "Goldie - Amiibo Festival" }, 270 | {0x02eb000100de0502, "Butch" }, 271 | {0x02ec000101c40502, "Lucky" }, 272 | {0x02ed0001015a0502, "Biskit" }, 273 | {0x02ee000101990502, "Bones" }, 274 | {0x02ef000100580502, "Portia" }, 275 | {0x02f0000100a70502, "Walker" }, 276 | {0x02f1000101450502, "Daisy" }, 277 | {0x02f2000100cc0502, "Cookie" }, 278 | {0x02f3000102f90502, "Maddie" }, 279 | {0x02f4000103050502, "Bea" }, 280 | {0x02f8000101380502, "Mac" }, 281 | {0x02f9000101020502, "Marcel" }, 282 | {0x02fa000100970502, "Benjamin" }, 283 | {0x02fb000100900502, "Cherry" }, 284 | {0x02fc0001018f0502, "Shep" }, 285 | {0x0307000100640502, "Bill" }, 286 | {0x03080001014d0502, "Joey" }, 287 | {0x0309000100c60502, "Pate" }, 288 | {0x030a000101c70502, "Maelle" }, 289 | {0x030b000100790502, "Deena" }, 290 | {0x030c000101b80502, "Pompom" }, 291 | {0x030d000101840502, "Mallary" }, 292 | {0x030e0001012f0502, "Freckles" }, 293 | {0x030f0001016d0502, "Derwin" }, 294 | {0x0310000100f80502, "Drake" }, 295 | {0x0311000100d60502, "Scoot" }, 296 | {0x0312000103090502, "Weber" }, 297 | {0x0313000101210502, "Miranda" }, 298 | {0x0314000102f40502, "Ketchup" }, 299 | {0x0316000101c00502, "Gloria" }, 300 | {0x0317000100a60502, "Molly" }, 301 | {0x03180001006c0502, "Quillson" }, 302 | {0x0323000100760502, "Opal" }, 303 | {0x0324000101890502, "Dizzy" }, 304 | {0x03250001010a0502, "Big Top" }, 305 | {0x0326000101390502, "Eloise" }, 306 | {0x0327000101c30502, "Margie" }, 307 | {0x0328000102eb0502, "Paolo" }, 308 | {0x03290001009d0502, "Axel" }, 309 | {0x032a000103070502, "Ellie" }, 310 | {0x032c000101480502, "Tucker" }, 311 | {0x032d000100bc0502, "Tia" }, 312 | {0x032e0101031c0502, "Chai" }, 313 | {0x03380001011d0502, "Lily" }, 314 | {0x0339000101b10502, "Ribbot" }, 315 | {0x033a000101cc0502, "Frobert" }, 316 | {0x033b000100fa0502, "Camofrog" }, 317 | {0x033c000101000502, "Drift" }, 318 | {0x033d0001013a0502, "Wart Jr." }, 319 | {0x033e000101a20502, "Puddles" }, 320 | {0x033f0001008f0502, "Jeremiah" }, 321 | {0x03410001030e0502, "Tad" }, 322 | {0x0342000101280502, "Cousteau" }, 323 | {0x0343000102ef0502, "Huck" }, 324 | {0x0344000100c50502, "Prince" }, 325 | {0x03450001005f0502, "Jambette" }, 326 | {0x0347000103020502, "Raddle" }, 327 | {0x03480001006b0502, "Gigi" }, 328 | {0x03490001018d0502, "Croque" }, 329 | {0x034a000101430502, "Diva" }, 330 | {0x034b0001009f0502, "Henry" }, 331 | {0x0356000101350502, "Chevre" }, 332 | {0x0357000100eb0502, "Nan" }, 333 | {0x0358000102fa0502, "Billy" }, 334 | {0x035a000100850502, "Gruff" }, 335 | {0x035c000101290502, "Velma" }, 336 | {0x035d000100c90502, "Kidd" }, 337 | {0x035e0001018e0502, "Pashmina" }, 338 | {0x0369000100d30502, "Cesar" }, 339 | {0x036a0001019d0502, "Peewee" }, 340 | {0x036b0001018b0502, "Boone" }, 341 | {0x036d000103040502, "Louie" }, 342 | {0x036e000102fb0502, "Boyd" }, 343 | {0x03700001015d0502, "Violet" }, 344 | {0x03710001005c0502, "Al" }, 345 | {0x03720001010b0502, "Rocket" }, 346 | {0x0373000101340502, "Hans" }, 347 | {0x0374010103190502, "Rilla" }, 348 | {0x037e000101560502, "Hamlet" }, 349 | {0x037f000101aa0502, "Apple" }, 350 | {0x0380000101870502, "Graham" }, 351 | {0x0381000100d50502, "Rodney" }, 352 | {0x03820001016b0502, "Soleil" }, 353 | {0x03830001009b0502, "Clay" }, 354 | {0x0384000100860502, "Flurry" }, 355 | {0x0385000101060502, "Hamphrey" }, 356 | {0x0390000101850502, "Rocco" }, 357 | {0x0392000101270502, "Bubbles" }, 358 | {0x0393000100a00502, "Bertha" }, 359 | {0x0394000100890502, "Biff" }, 360 | {0x0395000102fc0502, "Bitty" }, 361 | {0x0398000100bf0502, "Harry" }, 362 | {0x0399000101c20502, "Hippeux" }, 363 | {0x03a40001014f0502, "Buck" }, 364 | {0x03a50001015b0502, "Victoria" }, 365 | {0x03a6000100c80502, "Savannah" }, 366 | {0x03a7000101a10502, "Elmer" }, 367 | {0x03a8000100910502, "Rosco" }, 368 | {0x03a9000100710502, "Winnie" }, 369 | {0x03aa000100e60502, "Ed" }, 370 | {0x03ab000103160502, "Cleo" }, 371 | {0x03ac000101880502, "Peaches" }, 372 | {0x03ad000101b20502, "Annalise" }, 373 | {0x03ae000100870502, "Clyde" }, 374 | {0x03af0001012c0502, "Colton" }, 375 | {0x03b0000101a90502, "Papi" }, 376 | {0x03b1000100f00502, "Julian" }, 377 | {0x03bc0001008a0502, "Yuka" }, 378 | {0x03bd000100f90502, "Alice" }, 379 | {0x03be000101980502, "Melba" }, 380 | {0x03bf000101bc0502, "Sydney" }, 381 | {0x03c0000103100502, "Gonzo" }, 382 | {0x03c1000100bb0502, "Ozzie" }, 383 | {0x03c40001012b0502, "Canberra" }, 384 | {0x03c50001015c0502, "Lyman" }, 385 | {0x03c6000100930502, "Eugene" }, 386 | {0x03d1000100c20502, "Kitt" }, 387 | {0x03d2000100e50502, "Mathilda" }, 388 | {0x03d3000102f30502, "Carrie" }, 389 | {0x03d6000101570502, "Astrid" }, 390 | {0x03d7000101b40502, "Sylvia" }, 391 | {0x03d9000101a50502, "Walt" }, 392 | {0x03da000101510502, "Rooney" }, 393 | {0x03db0001006d0502, "Marcie" }, 394 | {0x03e6000100ec0502, "Bud" }, 395 | {0x03e70001012a0502, "Elvis" }, 396 | {0x03e8000102f50502, "Rex" }, 397 | {0x03ea0001030b0502, "Leopold" }, 398 | {0x03ec000101830502, "Mott" }, 399 | {0x03ed000101a30502, "Rory" }, 400 | {0x03ee0001008b0502, "Lionel" }, 401 | {0x03fa000100d00502, "Nana" }, 402 | {0x03fb000101cf0502, "Simon" }, 403 | {0x03fc000101470502, "Tammi" }, 404 | {0x03fd000101580502, "Monty" }, 405 | {0x03fe000101a40502, "Elise" }, 406 | {0x03ff000100f40502, "Flip" }, 407 | {0x04000001006f0502, "Shari" }, 408 | {0x0401000100660502, "Deli" }, 409 | {0x040c000101590502, "Dora" }, 410 | {0x040d000100780502, "Limberg" }, 411 | {0x040e000100880502, "Bella" }, 412 | {0x040f000101500502, "Bree" }, 413 | {0x04100001007f0502, "Samson" }, 414 | {0x0411000101ab0502, "Rod" }, 415 | {0x04140001030a0502, "Candi" }, 416 | {0x0415000101bb0502, "Rizzo" }, 417 | {0x0416000100fb0502, "Anicotti" }, 418 | {0x0418000100d80502, "Broccolo" }, 419 | {0x041a000100e00502, "Moose" }, 420 | {0x041b000100f10502, "Bettina" }, 421 | {0x041c000101410502, "Greta" }, 422 | {0x041d0001018a0502, "Penelope" }, 423 | {0x041e0001015f0502, "Chadder" }, 424 | {0x0429000100700502, "Octavian" }, 425 | {0x042a0001012d0502, "Marina" }, 426 | {0x042b000101af0502, "Zucker" }, 427 | {0x0436000101940502, "Queenie" }, 428 | {0x0437000101050502, "Gladys" }, 429 | {0x0438000103000502, "Sandy" }, 430 | {0x0439000103110502, "Sprocket" }, 431 | {0x043b000103030502, "Julia" }, 432 | {0x043c000101cb0502, "Cranston" }, 433 | {0x043d0001007c0502, "Phil" }, 434 | {0x043e000101490502, "Blanche" }, 435 | {0x043f000101550502, "Flora" }, 436 | {0x0440000100ca0502, "Phoebe" }, 437 | {0x044b0001016c0502, "Apollo" }, 438 | {0x044c0001008e0502, "Amelia" }, 439 | {0x044d000101930502, "Pierce" }, 440 | {0x044e000103150502, "Buzz" }, 441 | {0x0450000100cf0502, "Avery" }, 442 | {0x04510001015e0502, "Frank" }, 443 | {0x0452000100730502, "Sterling" }, 444 | {0x0453000101040502, "Keaton" }, 445 | {0x0454000101ae0502, "Celia" }, 446 | {0x045f000101a80502, "Aurora" }, 447 | {0x0460000100a50502, "Roald" }, 448 | {0x0461000101610502, "Cube" }, 449 | {0x0462000100f60502, "Hopper" }, 450 | {0x0463000101310502, "Friga" }, 451 | {0x0464000100c00502, "Gwen" }, 452 | {0x04650001006e0502, "Puck" }, 453 | {0x0468000102f20502, "Wade" }, 454 | {0x0469000101640502, "Boomer" }, 455 | {0x046a000101d00502, "Iggly" }, 456 | {0x046b000101970502, "Tex" }, 457 | {0x046c0001008c0502, "Flo" }, 458 | {0x046d000100f30502, "Sprinkle" }, 459 | {0x0478000101630502, "Curly" }, 460 | {0x0479000100920502, "Truffles" }, 461 | {0x047a000100600502, "Rasher" }, 462 | {0x047b000100f50502, "Hugh" }, 463 | {0x047c000101a00502, "Lucy" }, 464 | {0x047d0001012e0502, "Spork/Crackle" }, 465 | {0x04800001008d0502, "Cobb" }, 466 | {0x0481000102f10502, "Boris" }, 467 | {0x0482000102fd0502, "Maggie" }, 468 | {0x0483000101b00502, "Peggy" }, 469 | {0x04850001014c0502, "Gala" }, 470 | {0x0486000100fc0502, "Chops" }, 471 | {0x0487000101bf0502, "Kevin" }, 472 | {0x0488000100980502, "Pancetti" }, 473 | {0x0489000100ef0502, "Agnes" }, 474 | {0x04940001009a0502, "Bunnie" }, 475 | {0x0495000101920502, "Dotty" }, 476 | {0x0496000100d90502, "Coco" }, 477 | {0x04970001007a0502, "Snake" }, 478 | {0x04980001014a0502, "Gaston" }, 479 | {0x0499000100df0502, "Gabi" }, 480 | {0x049a0001014e0502, "Pippy" }, 481 | {0x049b000100610502, "Tiffany" }, 482 | {0x049c000101400502, "Genji" }, 483 | {0x049d000100ed0502, "Ruby" }, 484 | {0x049e000101b70502, "Doc" }, 485 | {0x049f000103010502, "Claude" }, 486 | {0x04a00001016e0502, "Francine" }, 487 | {0x04a10001016f0502, "Chrissy" }, 488 | {0x04a2000102e80502, "Hopkins" }, 489 | {0x04a3000101c90502, "OHare" }, 490 | {0x04a4000100d40502, "Carmen" }, 491 | {0x04a5000100740502, "Bonbon" }, 492 | {0x04a6000100a30502, "Cole" }, 493 | {0x04a7000101a60502, "Mira" }, 494 | {0x04a80101031e0502, "Toby" }, 495 | {0x04b2000101b90502, "Tank" }, 496 | {0x04b3000100dd0502, "Rhonda" }, 497 | {0x04b40001030c0502, "Spike" }, 498 | {0x04b6000102ec0502, "Hornsby" }, 499 | {0x04b9000101600502, "Merengue" }, 500 | {0x04ba0001005d0502, "Ren�e" }, 501 | {0x04c5000101010502, "Vesta" }, 502 | {0x04c6000101670502, "Baabara" }, 503 | {0x04c7000100940502, "Eunice" }, 504 | {0x04c8000102ed0502, "Stella" }, 505 | {0x04c90001030d0502, "Cashmere" }, 506 | {0x04cc000100a40502, "Willow" }, 507 | {0x04cd000101520502, "Curlos" }, 508 | {0x04ce000100db0502, "Wendy" }, 509 | {0x04cf000100e10502, "Timbra" }, 510 | {0x04d0000101960502, "Frita" }, 511 | {0x04d10001009e0502, "Muffy" }, 512 | {0x04d2000101a70502, "Pietro" }, 513 | {0x04d30101031b0502, "�toile" }, 514 | {0x04dd000100a20502, "Peanut" }, 515 | {0x04de000100ce0502, "Blaire" }, 516 | {0x04df000100e80502, "Filbert" }, 517 | {0x04e0000100f70502, "Pecan" }, 518 | {0x04e1000101be0502, "Nibbles" }, 519 | {0x04e2000101090502, "Agent S" }, 520 | {0x04e3000101650502, "Caroline" }, 521 | {0x04e4000101b60502, "Sally" }, 522 | {0x04e5000101ad0502, "Static" }, 523 | {0x04e6000100820502, "Mint" }, 524 | {0x04e7000101320502, "Ricky" }, 525 | {0x04e8000101ce0502, "Cally" }, 526 | {0x04ea000103180502, "Tasha" }, 527 | {0x04eb000102f00502, "Sylvana" }, 528 | {0x04ec000100770502, "Poppy" }, 529 | {0x04ed000100620502, "Sheldon" }, 530 | {0x04ee0001014b0502, "Marshal" }, 531 | {0x04ef0001013b0502, "Hazel" }, 532 | {0x04fa000101680502, "Rolf" }, 533 | {0x04fb000101c60502, "Rowan" }, 534 | {0x04fc000102ee0502, "Tybalt" }, 535 | {0x04fd0001007b0502, "Bangle" }, 536 | {0x04fe000100590502, "Leonardo" }, 537 | {0x04ff000101620502, "Claudia" }, 538 | {0x0500000100e70502, "Bianca" }, 539 | {0x050b000100990502, "Chief" }, 540 | {0x050c000101c10502, "Lobo" }, 541 | {0x050d000101420502, "Wolfgang" }, 542 | {0x050e000100d70502, "Whitney" }, 543 | {0x050f000103140502, "Dobie" }, 544 | {0x0510000101070502, "Freya" }, 545 | {0x0511000101950502, "Fang" }, 546 | {0x0513000102e70502, "Vivian" }, 547 | {0x0514000101530502, "Skye" }, 548 | {0x05150001005b0502, "Kyle" }, 549 | {0x0580000000050002, "Fox" }, 550 | {0x05810000001c0002, "Falco" }, 551 | {0x05840000037e0002, "Wolf" }, 552 | {0x05c0000000060002, "Samus" }, 553 | {0x05c0000003651302, "Samus Aran" }, 554 | {0x05c00100001d0002, "Zero Suit Samus" }, 555 | {0x05c1000003661302, "Metroid" }, 556 | {0x05c20000037f0002, "Ridley" }, 557 | {0x05c3000003800002, "Dark Samus" }, 558 | {0x0600000000120002, "Captain Falcon" }, 559 | {0x06400100001e0002, "Olimar" }, 560 | {0x06c00000000f0002, "Little Mac" }, 561 | {0x0700000000070002, "Wii Fit Trainer" }, 562 | {0x0740000000100002, "Pit" }, 563 | {0x0741000000200002, "Dark Pit" }, 564 | {0x07420000001f0002, "Palutena" }, 565 | {0x07800000002d0002, "Mr. Game & Watch" }, 566 | {0x07810000002e0002, "R.O.B - Famicom" }, 567 | {0x0781000000330002, "R.O.B. - NES" }, 568 | {0x07820000002f0002, "Duck Hunt" }, 569 | {0x07c0000000210002, "Mii Brawler" }, 570 | {0x07c0010000220002, "Mii Swordfighter" }, 571 | {0x07c0020000230002, "Mii Gunner" }, 572 | {0x08000100003e0402, "Inkling Girl" }, 573 | {0x08000100025f0402, "Inkling Girl - Lime Green" }, 574 | {0x0800010003690402, "Inkling Girl - Neon Pink" }, 575 | {0x0800010003820002, "Inkling" }, 576 | {0x08000200003f0402, "Inkling Boy" }, 577 | {0x0800020002600402, "Inkling Boy - Purple" }, 578 | {0x08000200036a0402, "Inkling Boy - Neon Green" }, 579 | {0x0800030000400402, "Inkling Squid" }, 580 | {0x0800030002610402, "Inkling Squid - Orange" }, 581 | {0x08000300036b0402, "Inkling Squid - Neon Purple" }, 582 | {0x08010000025d0402, "Callie" }, 583 | {0x08020000025e0402, "Marie" }, 584 | {0x0803000003760402, "Pearl" }, 585 | {0x0804000003770402, "Marina" }, 586 | {0x08050100038e0402, "Octoling Girl" }, 587 | {0x08050200038f0402, "Octoling Boy" }, 588 | {0x0805030003900402, "Octoling Octopus" }, 589 | {0x09c0010102690e02, "Mario - Soccer" }, 590 | {0x09c00201026a0e02, "Mario - Baseball" }, 591 | {0x09c00301026b0e02, "Mario - Tennis" }, 592 | {0x09c00401026c0e02, "Mario - Golf" }, 593 | {0x09c00501026d0e02, "Mario - Horse Racing" }, 594 | {0x09c10101026e0e02, "Luigi - Soccer" }, 595 | {0x09c10201026f0e02, "Luigi - Baseball" }, 596 | {0x09c1030102700e02, "Luigi - Tennis" }, 597 | {0x09c1040102710e02, "Luigi - Golf" }, 598 | {0x09c1050102720e02, "Luigi - Horse Racing" }, 599 | {0x09c2010102730e02, "Peach - Soccer" }, 600 | {0x09c2020102740e02, "Peach - Baseball" }, 601 | {0x09c2030102750e02, "Peach - Tennis" }, 602 | {0x09c2040102760e02, "Peach - Golf" }, 603 | {0x09c2050102770e02, "Peach - Horse Racing" }, 604 | {0x09c3010102780e02, "Daisy - Soccer" }, 605 | {0x09c3020102790e02, "Daisy - Baseball" }, 606 | {0x09c30301027a0e02, "Daisy - Tennis" }, 607 | {0x09c30401027b0e02, "Daisy - Golf" }, 608 | {0x09c30501027c0e02, "Daisy - Horse Racing" }, 609 | {0x09c40101027d0e02, "Yoshi - Soccer" }, 610 | {0x09c40201027e0e02, "Yoshi - Baseball" }, 611 | {0x09c40301027f0e02, "Yoshi - Tennis" }, 612 | {0x09c4040102800e02, "Yoshi - Golf" }, 613 | {0x09c4050102810e02, "Yoshi - Horse Racing" }, 614 | {0x09c5010102820e02, "Wario - Soccer" }, 615 | {0x09c5020102830e02, "Wario - Baseball" }, 616 | {0x09c5030102840e02, "Wario - Tennis" }, 617 | {0x09c5040102850e02, "Wario - Golf" }, 618 | {0x09c5050102860e02, "Wario - Horse Racing" }, 619 | {0x09c6010102870e02, "Waluigi - Soccer" }, 620 | {0x09c6020102880e02, "Waluigi - Baseball" }, 621 | {0x09c6030102890e02, "Waluigi - Tennis" }, 622 | {0x09c60401028a0e02, "Waluigi - Golf" }, 623 | {0x09c60501028b0e02, "Waluigi - Horse Racing" }, 624 | {0x09c70101028c0e02, "Donkey Kong - Soccer" }, 625 | {0x09c70201028d0e02, "Donkey Kong - Baseball" }, 626 | {0x09c70301028e0e02, "Donkey Kong - Tennis" }, 627 | {0x09c70401028f0e02, "Donkey Kong - Golf" }, 628 | {0x09c7050102900e02, "Donkey Kong - Horse Racing" }, 629 | {0x09c8010102910e02, "Diddy Kong - Soccer" }, 630 | {0x09c8020102920e02, "Diddy Kong - Baseball" }, 631 | {0x09c8030102930e02, "Diddy Kong - Tennis" }, 632 | {0x09c8040102940e02, "Diddy Kong - Golf" }, 633 | {0x09c8050102950e02, "Diddy Kong - Horse Racing" }, 634 | {0x09c9010102960e02, "Bowser - Soccer" }, 635 | {0x09c9020102970e02, "Bowser - Baseball" }, 636 | {0x09c9030102980e02, "Bowser - Tennis" }, 637 | {0x09c9040102990e02, "Bowser - Golf" }, 638 | {0x09c90501029a0e02, "Bowser - Horse Racing" }, 639 | {0x09ca0101029b0e02, "Bowser Jr. - Soccer" }, 640 | {0x09ca0201029c0e02, "Bowser Jr. - Baseball" }, 641 | {0x09ca0301029d0e02, "Bowser Jr. - Tennis" }, 642 | {0x09ca0401029e0e02, "Bowser Jr. - Golf" }, 643 | {0x09ca0501029f0e02, "Bowser Jr. - Horse Racing" }, 644 | {0x09cb010102a00e02, "Boo - Soccer" }, 645 | {0x09cb020102a10e02, "Boo - Baseball" }, 646 | {0x09cb030102a20e02, "Boo - Tennis" }, 647 | {0x09cb040102a30e02, "Boo - Golf" }, 648 | {0x09cb050102a40e02, "Boo - Horse Racing" }, 649 | {0x09cc010102a50e02, "Baby Mario - Soccer" }, 650 | {0x09cc020102a60e02, "Baby Mario - Baseball" }, 651 | {0x09cc030102a70e02, "Baby Mario - Tennis" }, 652 | {0x09cc040102a80e02, "Baby Mario - Golf" }, 653 | {0x09cc050102a90e02, "Baby Mario - Horse Racing" }, 654 | {0x09cd010102aa0e02, "Baby Luigi - Soccer" }, 655 | {0x09cd020102ab0e02, "Baby Luigi - Baseball" }, 656 | {0x09cd030102ac0e02, "Baby Luigi - Tennis" }, 657 | {0x09cd040102ad0e02, "Baby Luigi - Golf" }, 658 | {0x09cd050102ae0e02, "Baby Luigi - Horse Racing" }, 659 | {0x09ce010102af0e02, "Birdo - Soccer" }, 660 | {0x09ce020102b00e02, "Birdo - Baseball" }, 661 | {0x09ce030102b10e02, "Birdo - Tennis" }, 662 | {0x09ce040102b20e02, "Birdo - Golf" }, 663 | {0x09ce050102b30e02, "Birdo - Horse Racing" }, 664 | {0x09cf010102b40e02, "Rosalina - Soccer" }, 665 | {0x09cf020102b50e02, "Rosalina - Baseball" }, 666 | {0x09cf030102b60e02, "Rosalina - Tennis" }, 667 | {0x09cf040102b70e02, "Rosalina - Golf" }, 668 | {0x09cf050102b80e02, "Rosalina - Horse Racing" }, 669 | {0x09d0010102b90e02, "Metal Mario - Soccer" }, 670 | {0x09d0020102ba0e02, "Metal Mario - Baseball" }, 671 | {0x09d0030102bb0e02, "Metal Mario - Tennis" }, 672 | {0x09d0040102bc0e02, "Metal Mario - Golf" }, 673 | {0x09d0050102bd0e02, "Metal Mario - Horse Racing" }, 674 | {0x09d1010102be0e02, "Pink Gold Peach - Soccer" }, 675 | {0x09d1020102bf0e02, "Pink Gold Peach - Baseball" }, 676 | {0x09d1030102c00e02, "Pink Gold Peach - Tennis" }, 677 | {0x09d1040102c10e02, "Pink Gold Peach - Golf" }, 678 | {0x09d1050102c20e02, "Pink Gold Peach - Horse Racing" }, 679 | {0x1902000003830002, "Ivysaur" }, 680 | {0x1906000000240002, "Charizard" }, 681 | {0x1907000003840002, "Squirtle" }, 682 | {0x1919000000090002, "Pikachu" }, 683 | {0x1927000000260002, "Jigglypuff" }, 684 | {0x19960000023d0002, "Mewtwo" }, 685 | {0x19ac000003850002, "Pichu" }, 686 | {0x1ac0000000110002, "Lucario" }, 687 | {0x1b92000000250002, "Greninja" }, 688 | {0x1bd7000003860002, "Incineroar" }, 689 | {0x1d000001025c0d02, "Shadow Mewtwo" }, 690 | {0x1d01000003750d02, "Detective Pikachu" }, 691 | {0x1d40000003870002, "Pokemon Trainer" }, 692 | {0x1f000000000a0002, "Kirby" }, 693 | {0x1f00000002540c02, "Kirby" }, 694 | {0x1f01000000270002, "Meta Knight" }, 695 | {0x1f01000002550c02, "Meta Knight" }, 696 | {0x1f02000000280002, "King Dedede" }, 697 | {0x1f02000002560c02, "King Dedede" }, 698 | {0x1f03000002570c02, "Waddle Dee" }, 699 | {0x1f400000035e1002, "Qbby" }, 700 | {0x21000000000b0002, "Marth" }, 701 | {0x2101000000180002, "Ike" }, 702 | {0x2102000000290002, "Lucina" }, 703 | {0x21030000002a0002, "Robin" }, 704 | {0x2104000002520002, "Roy" }, 705 | {0x21050000025a0002, "Corrin" }, 706 | {0x2105010003630002, "Corrin - Player 2" }, 707 | {0x2106000003601202, "Alm" }, 708 | {0x2107000003611202, "Celica" }, 709 | {0x2108000003880002, "Chrom" }, 710 | {0x21080000036f1202, "Chrom" }, 711 | {0x2109000003701202, "Tiki" }, 712 | {0x22400000002b0002, "Shulk" }, 713 | {0x22800000002c0002, "Ness" }, 714 | {0x2281000002510002, "Lucas" }, 715 | {0x22c00000003a0202, "Chibi Robo" }, 716 | {0x3200000000300002, "Sonic" }, 717 | {0x32400000025b0002, "Bayonetta" }, 718 | {0x3240010003640002, "Bayonetta - Player 2" }, 719 | {0x3340000000320002, "Pac-Man" }, 720 | {0x3380000003781402, "Solaire of Astora" }, 721 | {0x3480000000310002, "Mega Man" }, 722 | {0x3480000002580002, "Mega Man - Gold Edition" }, 723 | {0x3480000003791502, "Mega Man" }, 724 | {0x34c0000002530002, "Ryu" }, 725 | {0x34c1000003890002, "Ken" }, 726 | {0x3500010002e10f02, "One-Eyed Rathalos and Rider - Male" }, 727 | {0x3500020002e20f02, "One-Eyed Rathalos and Rider - Female" }, 728 | {0x3501000002e30f02, "Nabiru" }, 729 | {0x3502010002e40f02, "Rathian and Cheval" }, 730 | {0x3503010002e50f02, "Barioth and Ayuria" }, 731 | {0x3504010002e60f02, "Qurupeco and Dan" }, 732 | {0x35c0000002500a02, "Shovel Knight" }, 733 | {0x35c0000003920a02, "Shovel Knight - Gold Edition" }, 734 | {0x35c10000036c0a02, "Plague Knight" }, 735 | {0x35c20000036d0a02, "Specter Knight" }, 736 | {0x35c30000036e0a02, "King Knight" }, 737 | {0x3600000002590002, "Cloud" }, 738 | {0x3600010003620002, "Cloud - Player 2" }, 739 | {0x06420000035f1102, "Pikmin" }, 740 | {0x0015000003670102, "Goomba" }, 741 | {0x0023000003680102, "Koopa Troopa" }, 742 | {0x3740000103741402, "Super Mario Cereal" }, 743 | {0x37800000038a0002, "Snake" }, 744 | {0x37c00000038b0002, "Simon" }, 745 | {0x37c10000038c0002, "Richter" }, 746 | {0x3800000103931702, "Pawapuro" }, 747 | {0x3801000103941702, "Ikari" }, 748 | {0x3802000103951702, "Daijobu" }, 749 | {0x3803000103961702, "Hayakawa" }, 750 | {0x3804000103971702, "Yabe" }, 751 | {0x3805000103981702, "Ganda" }, 752 | {0x38c0000003911602, "Loot Goblin" }, 753 | {0x00c00000037b0002, "King K. Rool" }, 754 | {0x00240000038d0002, "Piranha Plant" }, 755 | {0x078f000003810002, "Ice Climbers" } 756 | }; 757 | -------------------------------------------------------------------------------- /source/amiibo_structs.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct NFC_IdentificationBlock 5 | { 6 | uint8_t id[2]; 7 | uint8_t char_variant; 8 | uint8_t series; 9 | uint8_t model_no[2]; 10 | uint8_t figure_type; 11 | uint8_t pad[0x2F]; 12 | }; 13 | 14 | typedef struct{ 15 | uint16_t id_offset_size;/// "uint16_t size/offset of the below ID data. Normally this is 0x7. When this is <=10, this field is the size of the below ID data. When this is >10, this is the offset of the 10-byte ID data, relative to structstart+4+. It's unknown in what cases this 10-byte ID data is used." 16 | uint8_t unk_x2;//"Unknown uint8_t, normally 0x0." 17 | uint8_t unk_x3;//"Unknown uint8_t, normally 0x2." 18 | uint8_t id[0x28];//"ID data. When the above size field is 0x7, this is the 7-byte NFC tag UID, followed by all-zeros." 19 | }NFC_TagInfo; 20 | 21 | struct Date 22 | { 23 | uint16_t year; 24 | uint8_t month; 25 | uint8_t day; 26 | Date() 27 | { 28 | year = 0; month = 0; day = 0; 29 | } 30 | Date(uint16_t _year, uint8_t _month, uint8_t _day) 31 | { 32 | year = _year; 33 | month = _month; 34 | day = _day; 35 | } 36 | Date(uint16_t raw) 37 | { 38 | year = (raw >> 9) + 2000; 39 | month = (raw << 23 >> 28) & 0xF; 40 | day = raw & 0x1F; 41 | }; 42 | 43 | uint16_t getraw() 44 | { 45 | return (((year << 9) + 0x6000) | 0x20 * month) | day; 46 | } 47 | }; 48 | 49 | /// AmiiboSettings structure, see also here: https://3dbrew.org/wiki/NFC:GetAmiiboSettings 50 | typedef struct { 51 | uint8_t mii[0x60];/// "Owner Mii." 52 | uint16_t nickname[11];/// "UTF-16BE Amiibo nickname." 53 | uint8_t flags;/// "This is plaintext_amiibosettingsdata[0] & 0xF." See also the NFC_amiiboFlag enums. 54 | uint8_t countrycodeid;/// "This is plaintext_amiibosettingsdata[1]." "Country Code ID, from the system which setup this amiibo." 55 | Date setupdate; 56 | uint8_t unk_x7c[0x2c];//Normally all-zero? 57 | } NFC_AmiiboSettings; 58 | 59 | /// AmiiboConfig structure, see also here: https://3dbrew.org/wiki/NFC:GetAmiiboConfig 60 | typedef struct { 61 | Date lastwritedate; 62 | uint16_t write_counter; 63 | uint8_t characterID[3];/// the first element is the collection ID, the second the character in this collection, the third the variant 64 | uint8_t series;/// ID of the series 65 | uint8_t amiiboID[2];/// ID shared by all exact same amiibo. Some amiibo are only distinguished by this one like regular SMB Series Mario and the gold one 66 | uint8_t type;/// Type of amiibo 0 = figure, 1 = card, 2 = plush 67 | uint8_t pagex4_byte3; 68 | uint16_t appdata_size;/// "NFC module writes hard-coded uint8_t value 0xD8 here. This is the size of the Amiibo AppData, apps can use this with the AppData R/W commands. ..." 69 | uint8_t zeros[0x30];/// "Unused / reserved: this is cleared by NFC module but never written after that." 70 | } NFC_AmiiboConfig; 71 | 72 | typedef struct 73 | { 74 | uint64_t titleid; // TitleID 75 | uint32_t appid; // AppID 76 | uint16_t counter; // Counter 77 | uint8_t unk; // this is plaintextamiibosettingsdata >> 4 78 | uint8_t unk2; // this is always set to 2 79 | uint8_t tid_related; // this is tid related. set to 0. 80 | uint8_t unk3[0x2F]; // More unknown fields 81 | }NFC_AppDataConfig; 82 | 83 | 84 | typedef struct 85 | { 86 | uint8_t pagex4_byte3; 87 | uint8_t flag; 88 | Date lastwritedate; 89 | uint16_t writecounter; 90 | NFC_AmiiboSettings settings; 91 | NFC_AppDataConfig appDataConfig; 92 | uint8_t AppData[0xd8]; 93 | } NFC_PlainData; 94 | 95 | typedef enum { 96 | NFC_TagState_Uninitialized = 0, /// nfcInit() was not used yet. 97 | NFC_TagState_ScanningStopped = 1, /// Not currently scanning for NFC tags. Set by nfcStopScanning() and nfcInit(), when successful. 98 | NFC_TagState_Scanning = 2, /// Currently scanning for NFC tags. Set by nfcStartScanning() when successful. 99 | NFC_TagState_InRange = 3, /// NFC tag is in range. The state automatically changes to this when the state was previously value 2, without using any NFC service commands. 100 | NFC_TagState_OutOfRange = 4, /// NFC tag is now out of range, where the NFC tag was previously in range. This occurs automatically without using any NFC service commands. Once this state is entered, it won't automatically change to anything else when the tag is moved in range again. Hence, if you want to keep doing tag scanning after this, you must stop+start scanning. 101 | NFC_TagState_DataReady = 5 /// NFC tag data was successfully loaded. This is set by nfcLoadAmiiboData() when successful. 102 | } NFC_TagState; 103 | 104 | #define BSWAP_U32(num) ((num>>24)&0xff) | ((num<<8)&0xff0000) | ((num>>8)&0xff00) | ((num<<24)&0xff000000) 105 | 106 | static inline uint32_t IPC_MakeHeader(uint16_t command_id, unsigned normal_params, unsigned translate_params) 107 | { 108 | return ((uint32_t) command_id << 16) | (((uint32_t) normal_params & 0x3F) << 6) | (((uint32_t) translate_params & 0x3F) << 0); 109 | } 110 | 111 | static inline uint32_t IPC_Desc_StaticBuffer(size_t size, unsigned buffer_id) 112 | { 113 | return (size << 14) | ((buffer_id & 0xF) << 10) | 0x2; 114 | } -------------------------------------------------------------------------------- /source/bswap.h: -------------------------------------------------------------------------------- 1 | #ifndef bswap_h 2 | #define bswap_h 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "cpu_guess.h" 9 | 10 | #if defined _MSC_VER && defined CPU_GUESS_X86_64 11 | #include 12 | #endif 13 | 14 | static inline unsigned short bswap_16(unsigned short x) { 15 | #if defined _MSC_VER && defined CPU_GUESS_X86_64 16 | return _byteswap_ushort(x); 17 | #elif defined _MSC_VER && defined CPU_GUESS_X86 18 | __asm lea edx, [x] 19 | __asm mov ax, [edx] 20 | __asm xchg ah, al 21 | __asm mov [edx], ax 22 | return x; 23 | #elif defined CPU_GUESS_X86 24 | __asm__("rorw $8, %0" : "+r"(x)); 25 | return x; 26 | #elif defined CPU_GUESS_ARM_V6 || defined CPU_GUESS_ARM_V7 27 | __asm__("rev16 %0, %0" : "+r"(x)); 28 | return x; 29 | #else 30 | return (x >> 8) | (x << 8); 31 | #endif 32 | } 33 | 34 | static inline unsigned int bswap_32(unsigned int x) { 35 | #if defined _MSC_VER && defined CPU_GUESS_X86_64 36 | return _byteswap_ulong(x); 37 | #elif defined _MSC_VER && defined CPU_GUESS_X86 38 | __asm lea edx, [x] 39 | __asm mov eax, [edx] 40 | __asm bswap eax 41 | __asm mov [edx], eax 42 | return x; 43 | #elif defined CPU_GUESS_X86 44 | # if __CPU__ != 386 45 | __asm__("bswap %0" : "+r"(x)); 46 | return x; 47 | # else 48 | __asm__( 49 | "rorw $8, %w0 \n\t" 50 | "rorl $16, %0 \n\t" 51 | "rorw $8, %w0" 52 | : "+r"(x)); 53 | return x; 54 | # endif 55 | #elif defined CPU_GUESS_ARM_V6 || defined CPU_GUESS_ARM_V7 56 | __asm__("rev %0, %0" : "+r"(x)); 57 | return x; 58 | #elif defined CPU_GUESS_ARM 59 | unsigned int t; 60 | __asm__( 61 | "eor %1, %0, %0, ror #16 \n\t" 62 | "bic %1, %1, #0xFF0000 \n\t" 63 | "mov %0, %0, ror #8 \n\t" 64 | "eor %0, %0, %1, lsr #8 \n\t" 65 | : "+r"(x), "=&r"(t)); 66 | return x; 67 | #else 68 | x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF); 69 | return (x >> 16) | (x << 16); 70 | #endif 71 | } 72 | 73 | static inline unsigned long long bswap_64(unsigned long long x) { 74 | #if defined _MSC_VER && defined CPU_GUESS_X86_64 75 | return _byteswap_uint64(x); 76 | #elif defined _MSC_VER && defined CPU_GUESS_X86 77 | __asm lea edx, [x] 78 | __asm mov eax, [edx] 79 | __asm bswap eax 80 | __asm xchg eax, [edx+4] 81 | __asm bswap eax 82 | __asm mov [edx], eax 83 | return x; 84 | #elif defined CPU_GUESS_X86_64 85 | __asm__("bswap %0": "=r"(x) : "0"(x)); 86 | return x; 87 | #else 88 | union { 89 | unsigned long long ll; 90 | unsigned int l[2]; 91 | } w, r; 92 | w.ll = x; 93 | r.l[0] = bswap_32(w.l[1]); 94 | r.l[1] = bswap_32(w.l[0]); 95 | return r.ll; 96 | #endif 97 | } 98 | 99 | #ifdef __cplusplus 100 | } 101 | #endif 102 | 103 | #endif /* bswap_h */ 104 | -------------------------------------------------------------------------------- /source/communicator.cpp: -------------------------------------------------------------------------------- 1 | #include "communicator.h" 2 | #include 3 | #include 4 | #define SA struct sockaddr 5 | #define WIN32_LEAN_AND_MEAN 6 | #include 7 | #include 8 | #include 9 | 10 | static int readFile(std::string filename, uint8_t *data) 11 | { 12 | std::ifstream is(filename, std::ifstream::binary); 13 | if(is) 14 | { 15 | is.seekg (0, is.end); 16 | int length = is.tellg(); 17 | is.seekg (0, is.beg); 18 | if(length > 540) 19 | return -1; // decrypted file is not usually bigger than 540 bytes. 20 | is.read((char*)data, length); 21 | is.close(); 22 | return 0; 23 | } 24 | return -1; 25 | } 26 | 27 | static int writeFile(std::string filename, uint8_t *data, int length) 28 | { 29 | std::ofstream is(filename, std::ofstream::binary); 30 | if(is) 31 | { 32 | is.write((char*)data, length); 33 | is.close(); 34 | return 0; 35 | } 36 | return -1; 37 | } 38 | 39 | int Communicator::ReadFiles() 40 | { 41 | int r1 = readFile(m_decryptedfile, m_decrypteddata); 42 | int r2 = readFile(m_encryptedfile, m_encrypteddata); 43 | return r1 && r2; 44 | } 45 | 46 | int Communicator::ParseEncryptedFile() 47 | { 48 | if(m_encrypteddata[0xC] != 0xF1 && m_encrypteddata[0xD] != 0x10) // signature fail 49 | return -1; 50 | memcpy((uint8_t*)&m_taginfo.id[0], (uint8_t*)&m_encrypteddata[0], 7); 51 | memcpy((uint8_t*)&m_identityblock, (uint8_t*)&m_encrypteddata[0x54], 8); 52 | return 0; 53 | } 54 | 55 | int Communicator::ParseDecryptedFile() 56 | { 57 | if(m_decrypteddata[0x02] != 0xF && m_decrypteddata[0x3] != 0xE0) 58 | return -1; 59 | 60 | m_plaindata.pagex4_byte3 = m_decrypteddata[0x2B]; 61 | m_plaindata.flag = m_decrypteddata[0x2C]; 62 | m_plaindata.lastwritedate = Date(bswap_16(*(uint16_t*)&m_decrypteddata[0x32])); 63 | m_plaindata.writecounter = bswap_16((m_decrypteddata[0xB4] << 8) | m_decrypteddata[0xB5]); 64 | if(m_plaindata.flag << 27 >> 31) 65 | { 66 | memcpy(m_plaindata.settings.mii, &m_decrypteddata[0x4C], 0x60); 67 | memcpy(m_plaindata.settings.nickname, &m_decrypteddata[0x38], 2*10); 68 | m_plaindata.settings.flags = m_decrypteddata[0x2C] & 0xF; 69 | m_plaindata.settings.countrycodeid = m_decrypteddata[0x2D]; 70 | m_plaindata.settings.setupdate = Date(bswap_16(*(uint16_t*)&m_decrypteddata[0x30])); 71 | if(m_plaindata.flag << 26 >> 31) 72 | { 73 | memcpy((uint8_t*)&m_plaindata.appDataConfig.appid, (uint8_t*)&m_decrypteddata[0xB6], 4); 74 | memcpy((uint8_t*)&m_plaindata.appDataConfig.titleid, (uint8_t*)&m_decrypteddata[0xAC], 8); 75 | m_plaindata.appDataConfig.titleid = bswap_64(m_plaindata.appDataConfig.titleid); 76 | m_plaindata.appDataConfig.counter = bswap_16(*((uint16_t*)&m_decrypteddata[0xB4])); 77 | m_plaindata.appDataConfig.unk = m_plaindata.flag >> 4; 78 | memcpy((uint8_t*)&m_plaindata.AppData[0], (uint8_t*)&m_decrypteddata[0xDC], 0xD8); 79 | } 80 | } 81 | return 0; 82 | } 83 | 84 | int Communicator::ParseFiles() 85 | { 86 | int p1 = ParseEncryptedFile(); 87 | int p2 = ParseDecryptedFile(); 88 | return p1 && p2; 89 | } 90 | 91 | void Communicator::FlushToFileIfRequired() 92 | { 93 | if(!m_flush) return; 94 | m_decrypteddata[0x2B] = m_plaindata.pagex4_byte3; 95 | m_decrypteddata[0x2C] = m_plaindata.flag; 96 | // memcpy(&m_decrypteddata[0x32], &m_plaindata.lastwritedate.getraw(), 2); //TODO fix this 97 | m_plaindata.writecounter = bswap_16(m_plaindata.writecounter += 1); 98 | memcpy(&m_decrypteddata[0xB4], &m_plaindata.writecounter, 2); 99 | if(m_plaindata.flag << 27 >> 31) 100 | { 101 | memcpy(&m_decrypteddata[0x4C], m_plaindata.settings.mii, 0x60); 102 | memcpy(&m_decrypteddata[0x38], m_plaindata.settings.nickname, 2*10); 103 | m_decrypteddata[0x2D] = m_plaindata.settings.countrycodeid; 104 | uint16_t date = bswap_16(m_plaindata.settings.setupdate.getraw()); 105 | memcpy(&m_decrypteddata[0x30], &date, 2); 106 | if(m_plaindata.flag << 26 >> 31) 107 | { 108 | memcpy((uint8_t*)&m_decrypteddata[0xB6], (uint8_t*)&m_plaindata.appDataConfig.appid, 4); 109 | memcpy((uint8_t*)&m_decrypteddata[0xAC], (uint8_t*)&m_plaindata.appDataConfig.titleid, 8); 110 | //m_plaindata.appDataConfig.counter = bswap_16(*((uint16_t*)&m_decrypteddata[0xB4])); 111 | //m_plaindata.appDataConfig.unk = m_plaindata.flag >> 4; 112 | memcpy((uint8_t*)&m_decrypteddata[0xDC], (uint8_t*)&m_plaindata.AppData[0], 0xD8); 113 | } 114 | } 115 | writeFile(m_decryptedfile, m_decrypteddata, 532); 116 | } 117 | 118 | int Communicator::ConnectTo3DS() 119 | { 120 | WSADATA wsaData; 121 | int winsock_res = WSAStartup(MAKEWORD(2, 2), &wsaData); 122 | if (winsock_res != 0) 123 | { 124 | printf("Failed WSAStartup()\n"); 125 | return 1; 126 | } 127 | struct sockaddr_in servaddr, cli; 128 | // socket create and varification 129 | m_sockfd = socket(AF_INET, SOCK_STREAM, 0); 130 | if (m_sockfd == -1) 131 | { 132 | printf("Socket creation failed\n"); 133 | return -1; 134 | } 135 | servaddr.sin_family = AF_INET; 136 | servaddr.sin_addr.s_addr = inet_addr(m_addr.c_str()); 137 | servaddr.sin_port = htons(8001); 138 | 139 | if (connect(m_sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) { 140 | printf("Connect failed\n"); 141 | return -1; 142 | } 143 | printf("Connect succeeded\n"); 144 | return 0; 145 | } 146 | 147 | void Communicator::DisconnectFrom3DS() 148 | { 149 | closesocket(m_sockfd); 150 | m_sockfd = -1; 151 | WSACleanup(); 152 | } 153 | 154 | void Communicator::IPCServer() 155 | { 156 | uint8_t buff[256]; 157 | for (;;) 158 | { 159 | int res = recv(m_sockfd, (char*)buff, 256, 0); 160 | if(res == SOCKET_ERROR) break; 161 | uint32_t *cmdbuf = (uint32_t*)buff; 162 | uint16_t cmdid = cmdbuf[0] >> 16; 163 | printf("Cmdid recieved %08X\n", cmdbuf[0]); 164 | switch(cmdid) 165 | { 166 | case 1: 167 | case 2: 168 | case 3: 169 | case 4: 170 | { 171 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 172 | cmdbuf[1] = 0; 173 | break; 174 | } 175 | 176 | case 5: // StartTagScanning 177 | { 178 | m_tagstate = NFC_TagState_Scanning; 179 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 180 | cmdbuf[1] = 0; 181 | break; 182 | } 183 | 184 | case 6: // StopTagScanning 185 | { 186 | m_tagstate = NFC_TagState_ScanningStopped; 187 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 188 | cmdbuf[1] = 0; 189 | break; 190 | } 191 | 192 | case 7: // LoadAmiiboData 193 | { 194 | m_tagstate = NFC_TagState_DataReady; 195 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 196 | cmdbuf[1] = 0; 197 | break; 198 | } 199 | 200 | case 8: // ResetTagState 201 | { 202 | m_tagstate = NFC_TagState_OutOfRange; 203 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 204 | cmdbuf[1] = 0; 205 | break; 206 | } 207 | 208 | case 9: // UpdateStoredAmiiboData 209 | { 210 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 211 | cmdbuf[1] = 0; 212 | break; 213 | } 214 | 215 | case 0xB: // TagInRangeEvent 216 | { 217 | printf("GetTagInRangeEvent\n"); 218 | break; 219 | } 220 | 221 | case 0xC: /// TagOutOfRangeEvent 222 | { 223 | printf("TagOutOfRangeEvent\n"); 224 | break; 225 | } 226 | 227 | case 0xD: // GetTagState 228 | { 229 | if(cmdbuf[1] == 1) 230 | { 231 | printf("TagState changed by module\n"); 232 | m_tagstate = cmdbuf[2]; 233 | } 234 | cmdbuf[2] = m_tagstate; 235 | printf("TagState %d\n", m_tagstate); 236 | if(m_tagstate == NFC_TagState_Scanning) m_tagstate = NFC_TagState_InRange; 237 | cmdbuf[0] = IPC_MakeHeader(cmdid, 2, 0); 238 | cmdbuf[1] = 0; 239 | break; 240 | } 241 | 242 | case 0xF: // CommunicationGetStatus 243 | { 244 | cmdbuf[2] = 2; // Hardcode to "communication established successfully" 245 | cmdbuf[0] = IPC_MakeHeader(cmdid, 2, 0); 246 | cmdbuf[1] = 0; 247 | break; 248 | } 249 | 250 | case 0x11: // GetTagInfo 251 | { 252 | m_taginfo.id_offset_size = 7; 253 | m_taginfo.unk_x2 = 0; 254 | m_taginfo.unk_x3 = 2; 255 | memcpy(&cmdbuf[2], &m_taginfo, sizeof(NFC_TagInfo)); 256 | cmdbuf[0] = IPC_MakeHeader(cmdid, 12, 0); 257 | cmdbuf[1] = 0; 258 | break; 259 | } 260 | 261 | case 0x13: //OpenAppData 262 | { 263 | uint32_t appid = bswap_32(cmdbuf[1]); 264 | printf("Expected AppID %X: Our AppID %X\n", appid, m_plaindata.appDataConfig.appid); 265 | if(m_plaindata.flag << 26 >> 31) 266 | { 267 | if(appid == m_plaindata.appDataConfig.appid) 268 | cmdbuf[1] = 0; 269 | else 270 | { 271 | printf("0x13 AppID was incorrect\n"); 272 | cmdbuf[1] = 0xC8A17638; // AppId incorrect 273 | } 274 | } 275 | else 276 | { 277 | cmdbuf[1] = 0xC8A17620; // Not Initialized 278 | printf("0x13 Not Initialized\n"); 279 | } 280 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 281 | break; 282 | } 283 | 284 | case 0x14: //InitializeAppData 285 | { 286 | uint32_t appid = cmdbuf[1]; 287 | uint32_t size = cmdbuf[2]; 288 | send(m_sockfd, (char*)cmdbuf, 256, 0); 289 | recv(m_sockfd, (char*)buff, 256, 0); 290 | uint64_t pid = 0; 291 | memcpy((uint8_t*)&pid, (uint8_t*)&buff[0], 8); 292 | printf("TitleID %llX\n", pid); 293 | pid = bswap_64(pid); 294 | printf("TitleID after swap %llX\n", pid); 295 | m_plaindata.appDataConfig.titleid = pid; 296 | m_plaindata.appDataConfig.appid = bswap_32(appid); 297 | m_plaindata.flag |= 0x20u; 298 | memcpy((uint8_t*)&m_plaindata.AppData[0], (uint8_t*)&cmdbuf[2], 0xD8); 299 | 300 | m_flush = true; 301 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 302 | break; 303 | } 304 | 305 | case 0x15: //GetAppdata 306 | { 307 | //uint32_t size = cmdbuf[2]; 308 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 2); 309 | cmdbuf[1] = 0; 310 | cmdbuf[2] = IPC_Desc_StaticBuffer(0xd8, 0); 311 | memcpy((uint8_t*)&cmdbuf[3], (uint8_t*)&m_plaindata.AppData[0], 0xD8); 312 | break; 313 | } 314 | 315 | case 0x16: // WriteAppData 316 | { 317 | uint32_t size = cmdbuf[1]; 318 | struct cmdbuf_struct 319 | { 320 | uint8_t uid[7]; 321 | uint16_t unk; 322 | uint8_t uid_size; 323 | uint8_t unk2[0x15]; 324 | }; 325 | struct cmdbuf_struct cmdbuf_0x16; 326 | memcpy((uint8_t*)&cmdbuf_0x16, (uint8_t*)&cmdbuf[2], sizeof(struct cmdbuf_struct)); 327 | send(m_sockfd, (char*)cmdbuf, 256, 0); 328 | recv(m_sockfd, (char*)buff, 256, 0); 329 | memcpy((uint8_t*)&m_plaindata.AppData[0], (uint8_t*)&buff[0], 0xD8); 330 | 331 | m_flush = true; 332 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 333 | cmdbuf[1] = 0; 334 | break; 335 | } 336 | 337 | 338 | case 0x17: // GetAmiiboSettings 339 | { 340 | if (!(m_plaindata.flag & 0x10)) 341 | { 342 | memset(&m_plaindata.settings, 0, sizeof(m_plaindata.settings)); 343 | printf("0x17 UNINITITIALIZED\n"); 344 | cmdbuf[1] = 0xC8A17628; //uninitialised 345 | } 346 | else 347 | cmdbuf[1] = 0; 348 | 349 | cmdbuf[0] = IPC_MakeHeader(cmdid, 0x2B, 0); 350 | memcpy(&cmdbuf[2], &m_plaindata.settings, sizeof(m_plaindata.settings)); 351 | break; 352 | } 353 | 354 | case 0x18: // GetAmiiboConfig 355 | { 356 | printf("Cmdid 0x18 recieved"); 357 | NFC_AmiiboConfig config; 358 | config.lastwritedate.year = m_plaindata.lastwritedate.year; 359 | config.lastwritedate.month = m_plaindata.lastwritedate.month; 360 | config.lastwritedate.day = m_plaindata.lastwritedate.day; 361 | config.write_counter = m_plaindata.writecounter; 362 | config.characterID[0] = m_identityblock.id[0]; 363 | config.characterID[1] = m_identityblock.id[1]; 364 | config.characterID[2] = m_identityblock.char_variant; 365 | config.series = m_identityblock.series; 366 | config.amiiboID[0] = m_identityblock.model_no[0]; 367 | config.amiiboID[1] = m_identityblock.model_no[1]; 368 | config.type = m_identityblock.figure_type; 369 | config.pagex4_byte3 = m_plaindata.pagex4_byte3; //raw page 0x4 byte 0x3, dec byte 370 | config.appdata_size = 0xD8; 371 | memcpy((uint8_t*)&cmdbuf[2], (uint8_t*)&config, 0x40); 372 | cmdbuf[0] = IPC_MakeHeader(cmdid, 17, 0); 373 | cmdbuf[1] = 0; 374 | break; 375 | } 376 | 377 | case 0x19: //GetAppDataInitStruct IDA decompilation shows that this function just returns a 0x3c empty struct 378 | // We will do the same 379 | { 380 | uint8_t data[0x3c]; 381 | memset(data, 0, 0x3c); 382 | memcpy((uint8_t*)&cmdbuf[2], (uint8_t*)&data[0], 0x3c); 383 | cmdbuf[0] = IPC_MakeHeader(cmdid, 16 ,0); 384 | cmdbuf[1] = 0; 385 | break; 386 | } 387 | 388 | case 0x1A: // Unknown1A 389 | { 390 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 391 | cmdbuf[1] = 0; 392 | break; 393 | } 394 | 395 | case 0x1B: // GetAmiiboIdentificationBlock 396 | { 397 | memcpy((uint8_t*)&cmdbuf[2], (uint8_t*)&m_identityblock, 0x36); 398 | cmdbuf[0] = IPC_MakeHeader(cmdid, 15, 0); 399 | cmdbuf[1] = 0; 400 | break; 401 | } 402 | 403 | case 0x401: //Reset 404 | { 405 | m_plaindata.flag = 0; 406 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 407 | cmdbuf[1] = 0; 408 | break; 409 | } 410 | 411 | case 0x402: //GetAppDataConfig 412 | { 413 | m_plaindata.appDataConfig.unk2 = 2; 414 | m_plaindata.appDataConfig.tid_related = -1; 415 | if(m_plaindata.flag << 26 >> 31) 416 | { 417 | switch(m_plaindata.appDataConfig.titleid >> 28) 418 | { 419 | case 0: 420 | case 2: 421 | m_plaindata.appDataConfig.tid_related = 0; 422 | break; 423 | case 1: 424 | m_plaindata.appDataConfig.tid_related = 1; 425 | } 426 | } 427 | memcpy((uint8_t*)&cmdbuf[2], (uint8_t*)&m_plaindata.appDataConfig, sizeof(m_plaindata.appDataConfig)); 428 | cmdbuf[0] = IPC_MakeHeader(cmdid, 16, 0); 429 | cmdbuf[1] = 0; 430 | break; 431 | } 432 | 433 | case 0x404: //SetAmiiboSettings 434 | { 435 | memcpy((uint8_t*)&m_plaindata.settings, &cmdbuf[1], sizeof(NFC_AmiiboSettings)); 436 | if(!(m_plaindata.flag << 27 >> 31) & 0xF) 437 | { 438 | printf("0x404 Doing first time initialization"); 439 | time_t now = time(0); 440 | struct tm *aTime = localtime(&now); 441 | Date date(aTime->tm_mday, aTime->tm_mon + 1, aTime->tm_year + 1900); 442 | uint16_t raw = date.getraw(); 443 | m_plaindata.settings.setupdate = Date(raw); 444 | m_plaindata.settings.countrycodeid = cmdbuf[43] >> 24; // Set countrycode 445 | } 446 | m_plaindata.flag = ((m_plaindata.flag & 0xF0) | (m_plaindata.settings.flags & 0xF) | 0x10); 447 | m_flush = true; 448 | cmdbuf[0] = IPC_MakeHeader(cmdid, 1, 0); 449 | cmdbuf[1] = 0; 450 | break; 451 | } 452 | 453 | case 0x407: 454 | { 455 | uint32_t isSet = (m_plaindata.flag << 26 >> 31) & 1; 456 | printf("IsSet %d\n", isSet); 457 | cmdbuf[0] = IPC_MakeHeader(cmdid, 2, 0); 458 | cmdbuf[1] = 0; 459 | cmdbuf[2] = isSet; 460 | break; 461 | } 462 | 463 | default: 464 | printf("Unimplemented command %08x\n", cmdbuf[0]); 465 | } 466 | send(m_sockfd, (char*)cmdbuf, 256, 0); 467 | } 468 | printf("Disconnected\n"); 469 | } -------------------------------------------------------------------------------- /source/communicator.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "amiibo_structs.h" 5 | #include "bswap.h" 6 | class Communicator 7 | { 8 | public: 9 | void SetDecryptedFile(const std::string filename) { 10 | m_decryptedfile = filename; 11 | }; 12 | 13 | void SetEncryptedFile(const std::string filename) { 14 | m_encryptedfile = filename; 15 | }; 16 | 17 | void SetIPAddr(const std::string addr){ 18 | m_addr = addr; 19 | } 20 | 21 | const std::string &GetEncryptedFile() { 22 | return m_encryptedfile; 23 | }; 24 | 25 | const std::string &GetDecryptedFile() { 26 | return m_decryptedfile; 27 | }; 28 | 29 | uint64_t GetAmiiboID() { 30 | uint64_t val; 31 | memcpy(&val, &m_identityblock, 8); 32 | val = bswap_64(val); 33 | return val; 34 | } 35 | 36 | bool Is3DSConnected() { 37 | return m_sockfd != -1 ? true : false; 38 | } 39 | 40 | void DisconnectFrom3DS(); 41 | int ReadFiles(); 42 | int ParseFiles(); 43 | void FlushToFileIfRequired(); 44 | int ConnectTo3DS(); 45 | void IPCServer(); 46 | 47 | protected: 48 | int ParseEncryptedFile(); 49 | int ParseDecryptedFile(); 50 | 51 | private: 52 | std::string m_decryptedfile; 53 | std::string m_encryptedfile; 54 | std::string m_addr; 55 | uint8_t m_decrypteddata[540]; 56 | uint8_t m_encrypteddata[540]; 57 | 58 | NFC_PlainData m_plaindata; 59 | NFC_IdentificationBlock m_identityblock; 60 | NFC_TagInfo m_taginfo; 61 | 62 | int m_sockfd = -1; 63 | uint8_t m_tagstate = NFC_TagState_ScanningStopped; // By default we should send the state as tag in range 64 | bool m_flush; 65 | }; -------------------------------------------------------------------------------- /source/cpu_guess.h: -------------------------------------------------------------------------------- 1 | #ifndef cpu_guess_h 2 | #define cpu_guess_h 3 | 4 | /* ARM detection */ 5 | #if defined ARM || defined __arm__ || defined _ARM 6 | # define CPU_GUESS_ARM 7 | #endif 8 | 9 | /* x86, x86-64 detection */ 10 | #if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64 11 | # define CPU_GUESS_X86 12 | # if defined __x86_64__ || defined _M_X64 13 | # define CPU_GUESS_X86_64 14 | # endif 15 | #endif 16 | 17 | /* ARMv6 detection */ 18 | #if defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6Z__ || defined __ARM_ARCH_6ZK__ || defined __ARM_ARCH_6T2__ 19 | # define CPU_GUESS_ARM_V6 20 | #endif 21 | 22 | /* ARMv7 detection */ 23 | #if defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__ 24 | # define CPU_GUESS_ARM_V7 25 | #endif 26 | 27 | #endif /* cpu_guess_h */ 28 | -------------------------------------------------------------------------------- /source/main.cpp: -------------------------------------------------------------------------------- 1 | #include // always include this 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "communicator.h" 12 | #include "AmiiboUtil.h" 13 | 14 | void start(Communicator *comm, nana::form *fm, nana::textbox *box) 15 | { 16 | AmiiboUtil util; 17 | auto error = [](nana::form *fm, std::string message) -> void { 18 | nana::msgbox m(*fm, "Error"); 19 | m.icon(m.icon_error); 20 | m << message; 21 | auto response = m(); 22 | }; 23 | 24 | printf("Reading Files.\n"); 25 | if(comm->ReadFiles() != 0) 26 | { 27 | error(fm, "An Error occured while reading files"); 28 | return; 29 | } 30 | 31 | printf("Files parsed successfully.\n"); 32 | if(comm->ParseFiles() != 0) 33 | { 34 | error(fm, "Files are invalid"); 35 | return; 36 | } 37 | 38 | box->append("Figurine: " + util.GetNameForID(comm->GetAmiiboID()), false); 39 | 40 | printf("Connecting to 3DS.\n"); 41 | if(comm->ConnectTo3DS() != 0) 42 | { 43 | error(fm, "Could not connect to 3DS, check IP Address and the internet connection."); 44 | return; 45 | } 46 | 47 | printf("Connected.\n"); 48 | comm->IPCServer(); 49 | comm->FlushToFileIfRequired(); 50 | } 51 | 52 | int main() 53 | { 54 | using namespace nana; 55 | Communicator comm; 56 | AmiiboUtil webutil; 57 | form fm {API::make_center(300, 200), appearance{true, true, false, false, true, false, false}}; 58 | nana::filebox picker{nullptr, true}; 59 | fm.caption("Wumiibo"); 60 | 61 | label enc_label{fm, rectangle{10, 10, 110, 30}}; // pos x:y:width:height 62 | label dec_label{fm, rectangle{10, 40, 110, 30}}; 63 | label ip_addr{fm, rectangle{10, 70, 110, 30}}; 64 | enc_label.caption("Enc amiibo file:"); 65 | dec_label.caption("Dec amiibo file:"); 66 | ip_addr .caption("3DS IP Address:"); 67 | 68 | textbox enc_loc {fm, rectangle{100, 4, 150, 25}, true}; 69 | textbox dec_loc {fm, rectangle{100, 34, 150, 25}, true}; 70 | textbox ip_loc {fm, rectangle{100, 64, 150, 25}, true}; 71 | textbox debug_loc {fm, rectangle{10, 160, 280, 30}, true}; 72 | enc_loc.editable(false); 73 | dec_loc.editable(false); 74 | debug_loc.editable(false); 75 | 76 | button enc_button {fm, rectangle{260, 4, 30, 25}}; 77 | enc_button.caption("..."); 78 | button dec_button {fm, rectangle{260, 34, 30, 25}}; 79 | dec_button.caption("..."); 80 | button set_ip {fm, rectangle{260, 64, 30, 25}}; 81 | set_ip.caption("set"); 82 | 83 | button emulate {fm, rectangle {110, 120, 90, 30}}; 84 | emulate.caption("Emulate"); 85 | 86 | enc_button.events().click([&]() { 87 | auto paths = picker.show(); 88 | if(!paths.empty()){ 89 | enc_loc.select(true); 90 | enc_loc.del(); 91 | enc_loc.append(paths[0].filename(), true); 92 | comm.SetEncryptedFile(paths[0].u8string()); 93 | } 94 | }); 95 | 96 | dec_button.events().click([&]() { 97 | auto paths = picker.show(); 98 | if(!paths.empty()){ 99 | dec_loc.select(true); 100 | dec_loc.del(); 101 | dec_loc.append(paths[0].filename(), true); 102 | comm.SetDecryptedFile(paths[0].u8string()); 103 | } 104 | }); 105 | 106 | set_ip.events().click([&]() { 107 | std::string ip; 108 | if(ip_loc.getline(0, ip)) 109 | comm.SetIPAddr(ip); 110 | }); 111 | 112 | emulate.events().click([&]() { 113 | if(comm.Is3DSConnected()) { 114 | comm.DisconnectFrom3DS(); 115 | emulate.caption("Emulate"); 116 | } 117 | else 118 | { 119 | debug_loc.select(true); 120 | debug_loc.del(); 121 | std::thread(start, &comm, &fm, &debug_loc).detach(); 122 | emulate.caption("Stop"); 123 | } 124 | }); 125 | 126 | // fm_place.collocate(); // and collocate all in place 127 | fm.show(); 128 | exec(); 129 | } -------------------------------------------------------------------------------- /source/main_non_gui.cpp: -------------------------------------------------------------------------------- 1 | #include "communicator.h" 2 | #include "AmiiboUtil.h" 3 | 4 | 5 | int main(int argc, char **argv) 6 | { 7 | Communicator comm; 8 | AmiiboUtil util; 9 | comm.SetEncryptedFile(argv[1]); 10 | comm.SetDecryptedFile(argv[2]); 11 | comm.SetIPAddr(argv[3]); 12 | 13 | if(comm.ReadFiles() != 0) 14 | { 15 | printf("An error occured while reading the files\n"); 16 | return -1; 17 | } 18 | 19 | if(comm.ParseFiles() != 0) 20 | { 21 | printf("Files are invalid\n"); 22 | return -2; 23 | } 24 | printf("Files parsed successfully.\n"); 25 | printf("Figurine: %s\n", util.GetNameForID(comm.GetAmiiboID()).c_str()); 26 | printf("Connecting to 3ds.\n"); 27 | if(comm.ConnectTo3DS() != 0) 28 | { 29 | printf("Could not connect to 3ds\n"); 30 | return -3; 31 | } 32 | printf("Connected.\n"); 33 | comm.IPCServer(); 34 | comm.FlushToFileIfRequired(); 35 | return 0; 36 | } --------------------------------------------------------------------------------