diff --git a/config/SZBE69/flags.json b/config/SZBE69/flags.json index c31c34e7..18bf200b 100644 --- a/config/SZBE69/flags.json +++ b/config/SZBE69/flags.json @@ -29,6 +29,21 @@ "-d NDEBUG" ] }, + "main": { + "base": "base", + "flags": [ + "-sdata 2", + "-sdata2 2", + "-str reuse,pool", + + "-fp_contract on", + "-pragma \"merge_float_consts on\"", + + "-O4,p", + "-inline noauto", + "-func_align 4" + ] + }, "runtime": { "base": "base", "flags": [ @@ -48,7 +63,9 @@ "rvl_sdk": { "base": "base", "flags": [ - "-func_align 16" + "-func_align 16", + "-lang=c", + "-O4" ] }, "band3": { @@ -63,17 +80,21 @@ "-pragma \"merge_float_consts on\"", "-O4,s", - "-inline off", - "-ipa file" + "-ipa file", + "-inline off" ] }, "system": { "base": "band3", - "flags": [] + "flags": [ + "-func_align 4" + ] }, "network": { "base": "band3", - "flags": [] + "flags": [ + "-func_align 4" + ] }, "json_c": { "base": "base", @@ -102,7 +123,8 @@ "-pragma \"merge_float_consts on\"", "-lang=c99", - "-O4,p", + "-O4,s", + "-func_align 4", "-inline auto" ] }, diff --git a/config/SZBE69/objects.json b/config/SZBE69/objects.json index b6a0b269..82ac142d 100644 --- a/config/SZBE69/objects.json +++ b/config/SZBE69/objects.json @@ -1,13 +1,25 @@ { + "main": { + "mw_version": "Wii/1.3", + "cflags": "main", + "objects": { + "Main.cpp": "Matching", + "App.cpp": "NonMatching" + } + }, "band3": { "mw_version": "Wii/1.3", "cflags": "band3", - "objects": {} + "objects": { + "band3/bandtrack/TrackConfig.cpp": "Equivalent" + } }, "network": { "mw_version": "Wii/1.3", "cflags": "network", "objects": { + "network/Platform/BadEvents.cpp": "Matching", + "network/net/JsonUtils.cpp": "NonMatching" } }, @@ -22,15 +34,41 @@ "network/net/json-c/printbuf.c": "Matching" } }, + "zlib": { + "mw_version": "Wii/1.3", + "cflags": "zlib", + "objects": { + "system/zlib/adler32.c": "Matching", + "system/zlib/crc32.c": "Matching", + "system/zlib/deflate.c": "NonMatching", + "system/zlib/trees.c": "NonMatching", + "system/zlib/zutil.c": "Matching", + "system/zlib/inflate.c": "Matching", + "system/zlib/inftrees.c": "NonMatching", + "system/zlib/inffast.c": "Matching" + } + }, "system": { "mw_version": "Wii/1.3", "cflags": "system", "objects": { "system/math/Key.cpp": "NonMatching", + "system/math/Rand.cpp": "NonMatching", + "system/math/Rand2.cpp": "Matching", + + "system/midi/MidiParser.cpp": "NonMatching", + + "system/obj/DataArray.cpp": "NonMatching", + "system/obj/DataFile.cpp": "NonMatching", + "system/obj/DataFunc.cpp": "NonMatching", + "system/obj/DataNode.cpp": "NonMatching", + "system/obj/TextFile.cpp": "NonMatching", + "system/obj/TypeProps.cpp": "NonMatching", "system/rndobj/AmbientOcclusion.cpp": "NonMatching", "system/rndobj/Anim.cpp": "NonMatching", "system/rndobj/AnimFilter.cpp": "NonMatching", + "system/rndobj/Bitmap.cpp": "NonMatching", "system/rndobj/Cam.cpp": "NonMatching", "system/rndobj/CamAnim.cpp": "NonMatching", "system/rndobj/ColorXfm.cpp": "NonMatching", @@ -49,8 +87,9 @@ "system/rndobj/LitAnim.cpp": "NonMatching", "system/rndobj/Mat.cpp": "NonMatching", "system/rndobj/MatAnim.cpp": "NonMatching", + "system/rndobj/Mesh.cpp": "NonMatching", "system/rndobj/MotionBlur.cpp": "NonMatching", - "system/rndobj/Movie.cpp": "NonMatching", + "system/rndobj/Movie.cpp": "Equivalent", "system/rndobj/MultiMeshProxy.cpp": "NonMatching", "system/rndobj/Overlay.cpp": "NonMatching", "system/rndobj/Poll.cpp": "NonMatching", @@ -75,7 +114,24 @@ "system/synth/ADSR.cpp": "NonMatching", - "system/ui/UIPanel.cpp": "NonMatching" + "system/ui/UIButton.cpp": "NonMatching", + "system/ui/UIPanel.cpp": "NonMatching", + + "system/utl/Messages.cpp": "NonMatching", + "system/utl/Messages2.cpp": "NonMatching", + "system/utl/Messages3.cpp": "NonMatching", + "system/utl/Messages4.cpp": "NonMatching", + "system/utl/Symbols.cpp": "NonMatching", + "system/utl/Symbols2.cpp": "NonMatching", + "system/utl/Symbols3.cpp": "NonMatching", + "system/utl/Symbols4.cpp": "NonMatching" + } + }, + "RVL_SDK": { + "mw_version": "Wii/1.3", + "cflags": "rvl_sdk", + "objects": { + "sdk/RVL_SDK/revolution/os/OSSemaphore.c": "Matching" } } } diff --git a/config/SZBE69/splits.txt b/config/SZBE69/splits.txt index 04125b16..9da7eecb 100644 --- a/config/SZBE69/splits.txt +++ b/config/SZBE69/splits.txt @@ -16,21 +16,25 @@ Sections: rb3/unknown/800/unk_8000D980.cpp: .text start:0x8000D980 end:0x8000F364 -rb3/app.cpp: - .text start:0x8000F364 end:0x8000F804 - sdk/MSL_C/sdata_1.c: .sdata start:0x808E3270 end:0x808E3280 +App.cpp: + .text start:0x8000F364 end:0x8000F804 + rb3/stubs/stubone.cpp: .text start:0x8000F90C end:0x8000F914 -rb3/main.cpp: +Main.cpp: .text start:0x8000F96C end:0x8000F9B0 rb3/unknown/800/unk_8000F9B0.cpp: .text start:0x8000F9B0 end:0x80011714 +network/Platform/BadEvents.cpp: + .text start:0x80011754 end:0x80011778 + .bss start:0x808F0950 end:0x808F0954 + libs/quazal/datetime.cpp: .text start:0x800127E4 end:0x800129F4 @@ -78,8 +82,12 @@ libs/quazal/unknown/8007/unk_8007BF84.cpp: .text start:0x8007BF84 end:0x8007CA94 libs/quazal/unknown/800A/unk_800A515C.cpp: - .text start:0x800A515C end:0x800A5368 - .data start:0x8082A5C0 end:0x8082A678 + .text start:0x800A515C end:0x800A51AC + .data start:0x8082A5C0 end:0x8082A608 + +network/Products/NetZ.cpp: + .text start:0x800A51AC end:0x800A5278 + .data start:0x8082A608 end:0x8082A660 network/net/JsonUtils.cpp: .text start:0x800A6360 end:0x800A71BC @@ -128,7 +136,11 @@ rb3/unknown/800/unk_800C9D04.cpp: .text start:0x800C9D04 end:0x800DB158 rb3/unknown/800/unk_800DB160.cpp: - .text start:0x800DB160 end:0x800F6DE4 + .text start:0x800DB160 end:0x800E4020 + +band3/bandtrack/TrackConfig.cpp: + .text start:0x800E4020 end:0x800E43A0 + .data start:0x8082F9F8 end:0x8082FA28 rb3/unknown/800/unk_800F6DF8.cpp: .text start:0x800F6DF8 end:0x800FF880 @@ -374,7 +386,7 @@ rb3/unknown/802/unk_8022CD04.cpp: rb3/providers/outfitprovider.cpp: .text start:0x8023F918 end:0x8023FAF4 -rb3/panels/overshellpanel.cpp: +band3/meta_band/OvershellPanel.cpp: .text start:0x8023FAF4 end:0x802473C0 .ctors start:0x807EFE70 end:0x807EFE74 @@ -591,7 +603,7 @@ system/os/Joypad.cpp: .text start:0x80300F98 end:0x80303E44 .ctors start:0x807EFED8 end:0x807EFEDC -rb3/netstream.cpp: +system/os/NetStream.cpp: .text start:0x80308638 end:0x80308ACC rb3/wiinetworksocket.cpp: @@ -646,6 +658,8 @@ system/obj/DataFunc.cpp: .text start:0x8031B2B8 end:0x80322958 .ctors start:0x807EFF0C end:0x807EFF10 .data start:0x80854FA8 end:0x80855448 + .sbss start:0x808E4478 end:0x808E447C + .bss start:0x8091A518 end:0x8091A588 system/obj/DataNode.cpp: .text start:0x80322958 end:0x80324278 @@ -667,11 +681,15 @@ system/obj/DataFlex.c: .sbss start:0x808E4488 end:0x808E4490 .bss start:0x8091ABA8 end:0x8091ABD8 -rb3/objectdir.cpp: +system/obj/ObjectDir.cpp: .text start:0x8032553C end:0x8032DA70 .ctors start:0x807EFF18 end:0x807EFF1C -rb3/dirunloader.cpp: +system/obj/DirLoader.cpp: + .text start:0x8032DA70 end:0x8033106C + .ctors start:0x807EFF1C end:0x807EFF20 + +system/obj/DirUnloader.cpp: .text start:0x8033106C end:0x80331D40 rb3/msgsource.cpp: @@ -798,28 +816,28 @@ rb3/unknown/803/unk_80354A30.cpp: system/utl/MemStream.cpp: .text start:0x80354E6C end:0x80355190 -rb3/symbols/messageset1.cpp: +system/utl/Messages.cpp: .text start:0x80355190 end:0x80355E18 .ctors start:0x807EFF5C end:0x807EFF60 .data start:0x808572C8 end:0x808577C8 .sbss start:0x808E4528 end:0x808E4530 .bss start:0x8097CE08 end:0x8097D570 -rb3/symbols/messageset2.cpp: +system/utl/Messages2.cpp: .text start:0x80355E18 end:0x80356848 .ctors start:0x807EFF60 end:0x807EFF64 .data start:0x808577C8 end:0x80857C68 .sbss start:0x808E4530 end:0x808E4538 .bss start:0x8097D570 end:0x8097DB70 -rb3/symbols/messageset3.cpp: +system/utl/Messages3.cpp: .text start:0x80356848 end:0x803572F0 .ctors start:0x807EFF64 end:0x807EFF68 .data start:0x80857C68 end:0x80858080 .sbss start:0x808E4538 end:0x808E4540 .bss start:0x8097DB70 end:0x8097E1B8 -rb3/symbols/messageset4.cpp: +system/utl/Messages4.cpp: .text start:0x803572F0 end:0x80357E10 .ctors start:0x807EFF68 end:0x807EFF6C .data start:0x80858080 end:0x80858470 @@ -849,31 +867,28 @@ system/utl/StringTable.cpp: system/utl/Symbol.cpp: .text start:0x80363F60 end:0x803651B0 -rb3/stringtablelocks.cpp: - .text start:0x803651B0 end:0x80365214 - -rb3/symbols/symbolset1.cpp: - .text start:0x80365214 end:0x8036B5A0 +system/utl/Symbols.cpp: + .text start:0x803651B0 end:0x8036B5A0 .ctors start:0x807EFF6C end:0x807EFF70 .data start:0x80858D28 end:0x80861278 .sbss start:0x808E4568 end:0x808E4570 .bss start:0x8097E948 end:0x809809F8 -rb3/symbols/symbolset2.cpp: +system/utl/Symbols2.cpp: .text start:0x8036B5A0 end:0x803704DC .ctors start:0x807EFF70 end:0x807EFF74 .data start:0x80861278 end:0x80867580 .sbss start:0x808E4570 end:0x808E4578 .bss start:0x809809F8 end:0x80982448 -rb3/symbols/symbolset3.cpp: +system/utl/Symbols3.cpp: .text start:0x803704DC end:0x8037546C .ctors start:0x807EFF74 end:0x807EFF78 .data start:0x80867580 end:0x8086DE50 .sbss start:0x808E4578 end:0x808E4580 .bss start:0x80982448 end:0x80983EB8 -rb3/symbols/symbolset4.cpp: +system/utl/Symbols4.cpp: .text start:0x8037546C end:0x8037A3D8 .ctors start:0x807EFF78 end:0x807EFF7C .data start:0x8086DE50 end:0x80874468 @@ -903,37 +918,37 @@ system/utl/UTF8.cpp: rb3/unknown/803/unk_8037AD40.cpp: .text start:0x8037BE50 end:0x8037EB94 -libs/zlib/adler32.c: +system/zlib/adler32.c: .text start:0x8037EB94 end:0x8037ED1C -libs/zlib/crc32.c: +system/zlib/crc32.c: .text start:0x8037ED1C end:0x8037EE64 .rodata start:0x807F1E00 end:0x807F2200 -libs/zlib/deflate.c: +system/zlib/deflate.c: .text start:0x8037EE64 end:0x80380B78 .rodata start:0x807F2200 end:0x807F2280 -libs/zlib/trees.c: +system/zlib/trees.c: .text start:0x80380B78 end:0x80382960 .rodata start:0x807F2280 end:0x807F2CB8 .data start:0x80874690 end:0x808746D0 -libs/zlib/zutil.c: +system/zlib/zutil.c: .text start:0x80382960 end:0x80382998 .rodata start:0x807F2CB8 end:0x807F2CE0 .data start:0x808746D0 end:0x80874750 -libs/zlib/inflate.c: +system/zlib/inflate.c: .text start:0x80382998 end:0x80384248 .rodata start:0x807F2CE0 end:0x807F3588 .data start:0x80874750 end:0x80874978 -libs/zlib/inftrees.c: +system/zlib/inftrees.c: .text start:0x80384248 end:0x803846EC .rodata start:0x807F3588 end:0x807F36B8 -libs/zlib/inffast.c: +system/zlib/inffast.c: .text start:0x803846EC end:0x80384BA8 .data start:0x80874978 end:0x808749C8 @@ -978,7 +993,7 @@ rb3/unisonicon.cpp: rb3/songsectioncontroller.cpp: .text start:0x8044FAF4 end:0x8045593C -rb3/overshelldir.cpp: +system/bandobj/OvershellDir.cpp: .text start:0x8045593C end:0x804567C8 rb3/unknown/805/unk_8050FA30.cpp: @@ -1017,14 +1032,14 @@ rb3/panels/storepanel.cpp: rb3/unknown/805/unk_8052A44C.cpp: .text start:0x8052A44C end:0x8052D22C -rb3/midiparser.cpp: +system/midi/MidiParser.cpp: .text start:0x8052D22C end:0x80531574 .ctors start:0x807EFFBC end:0x807EFFC0 -rb3/labelnumberticker.cpp: +system/ui/LabelNumberTicker.cpp: .text start:0x80549150 end:0x8054A190 -rb3/labelshrinkwrapper.cpp: +system/ui/LabelShrinkWrapper.cpp: .text start:0x8054A190 end:0x8054AE78 system/ui/PanelDir.cpp: @@ -1038,6 +1053,7 @@ system/ui/UI.cpp: system/ui/UIButton.cpp: .text start:0x80552668 end:0x80552E80 + .sbss start:0x808E4A68 end:0x808E4A6C system/ui/UIColor.cpp: .text start:0x80552E80 end:0x80553260 @@ -1478,7 +1494,7 @@ libs/speex/libspeex/vbr.c: libs/speex/libspeex/vq.c: .text start:0x806A82E8 end:0x806A8550 -rb3/Rnd/wii/wiirnd.cpp: +system/wiirnd/WiiRnd.cpp: .text start:0x806B8438 end:0x806BDD84 .ctors start:0x807F0040 end:0x807F0044 .sbss start:0x808E4E70 end:0x808E4E74 @@ -1587,8 +1603,17 @@ libs/bt/stack/l2cap/l2c_utils.c: libs/bt/stack/rfcomm/port_api.c: .text start:0x807281FC end:0x8072A538 -sdk/Dolphin/pad/pad.c: +sdk/RVL_SDK/revolution/os/OSSemaphore.c: + .text start:0x8076B2A0 end:0x8076B3D0 + +sdk/RVL_SDK/revolution/pad/Pad.c: .text start:0x8076F4E0 end:0x8076F540 -sdk/Dolphin/rso/RSOLink.c: +sdk/RVL_SDK/revolution/rso/RSOLink.c: .text start:0x8076F540 end:0x807713F0 + +sdk/RVL_SDK/revolution/sc/scsystem.c: + .text start:0x807713F0 end:0x80772E80 + .data start:0x808D2AF8 end:0x808D2CF0 + .sdata start:0x808E35F8 end:0x808E3708 + .bss start:0x809ECC20 end:0x809F4DC0 diff --git a/config/SZBE69/symbols.txt b/config/SZBE69/symbols.txt index 46e3c2e0..b05e64eb 100644 --- a/config/SZBE69/symbols.txt +++ b/config/SZBE69/symbols.txt @@ -827,7 +827,7 @@ fn_8000DBB4 = .text:0x8000DBB4; // type:function size:0x8 fn_8000DBBC = .text:0x8000DBBC; // type:function size:0x4C fn_8000DC08 = .text:0x8000DC08; // type:function size:0x70 fn_8000DC78 = .text:0x8000DC78; // type:function size:0x30 -__as__6SymbolFRC6Symbol = .text:0x8000DCA8; // type:function size:0xC scope:weak noexport +__ct__6SymbolFRC6Symbol = .text:0x8000DCA8; // type:function size:0xC scope:weak noexport fn_8000DCB4 = .text:0x8000DCB4; // type:function size:0x30 fn_8000DCE4 = .text:0x8000DCE4; // type:function size:0x2C ~GenericDtor = .text:0x8000DD10; // type:function size:0x40 scope:weak noexport @@ -8164,28 +8164,28 @@ fn_800E3CF4 = .text:0x800E3CF4; // type:function size:0x8 Handle__5TrackFP9DataArrayb = .text:0x800E3CFC; // type:function size:0x318 fn_800E4014 = .text:0x800E4014; // type:function size:0xC __ct__11TrackConfigFP8BandUser = .text:0x800E4020; // type:function size:0x7C -fn_800E409C = .text:0x800E409C; // type:function size:0x30 -fn_800E40CC = .text:0x800E40CC; // type:function size:0x30 -fn_800E40FC = .text:0x800E40FC; // type:function size:0x40 -fn_800E413C = .text:0x800E413C; // type:function size:0x8 -fn_800E4144 = .text:0x800E4144; // type:function size:0x8 -fn_800E414C = .text:0x800E414C; // type:function size:0x8 -fn_800E4154 = .text:0x800E4154; // type:function size:0x8 -fn_800E415C = .text:0x800E415C; // type:function size:0x8 -fn_800E4164 = .text:0x800E4164; // type:function size:0x8 -fn_800E416C = .text:0x800E416C; // type:function size:0x8 -fn_800E4174 = .text:0x800E4174; // type:function size:0x8 -fn_800E417C = .text:0x800E417C; // type:function size:0x2C -fn_800E41A8 = .text:0x800E41A8; // type:function size:0x30 -fn_800E41D8 = .text:0x800E41D8; // type:function size:0x5C -fn_800E4234 = .text:0x800E4234; // type:function size:0x30 -fn_800E4264 = .text:0x800E4264; // type:function size:0x40 -fn_800E42A4 = .text:0x800E42A4; // type:function size:0xD4 -fn_800E4378 = .text:0x800E4378; // type:function size:0x8 -fn_800E4380 = .text:0x800E4380; // type:function size:0x8 -fn_800E4388 = .text:0x800E4388; // type:function size:0x8 -fn_800E4390 = .text:0x800E4390; // type:function size:0x8 -fn_800E4398 = .text:0x800E4398; // type:function size:0x8 +__ct__Q211stlpmtx_std45vector>FRCQ211stlpmtx_std15StlNodeAlloc = .text:0x800E409C; // type:function size:0x30 +__ct__Q211stlpmtx_std51_Vector_impl>FRCQ211stlpmtx_std15StlNodeAlloc = .text:0x800E40CC; // type:function size:0x30 +__ct__Q211stlpmtx_std51_Vector_base>FRCQ211stlpmtx_std15StlNodeAlloc = .text:0x800E40FC; // type:function size:0x40 +GetBandUser__11TrackConfigCFv = .text:0x800E413C; // type:function size:0x8 +TrackNum__11TrackConfigCFv = .text:0x800E4144; // type:function size:0x8 +GetMaxSlots__11TrackConfigCFv = .text:0x800E414C; // type:function size:0x8 +Type__11TrackConfigCFv = .text:0x800E4154; // type:function size:0x8 +IsLefty__11TrackConfigCFv = .text:0x800E415C; // type:function size:0x8 +GetGameCymbalLanes__11TrackConfigCFv = .text:0x800E4164; // type:function size:0x8 +GetDisableHopos__11TrackConfigCFv = .text:0x800E416C; // type:function size:0x8 +UseLeftyGems__11TrackConfigCFv = .text:0x800E4174; // type:function size:0x8 +IsDrumTrack__11TrackConfigCFv = .text:0x800E417C; // type:function size:0x2C +IsKeyboardTrack__11TrackConfigCFv = .text:0x800E41A8; // type:function size:0x30 +AllowsOverlappingGems__11TrackConfigCFv = .text:0x800E41D8; // type:function size:0x5C +AllowsPartialHits__11TrackConfigCFv = .text:0x800E4234; // type:function size:0x30 +IsRealGuitarTrack__11TrackConfigCFv = .text:0x800E4264; // type:function size:0x40 +GetSlotColor__11TrackConfigCFi = .text:0x800E42A4; // type:function size:0xD4 +SetMaxSlots__11TrackConfigFi = .text:0x800E4378; // type:function size:0x8 +SetLefty__11TrackConfigFb = .text:0x800E4380; // type:function size:0x8 +SetGameCymbalLanes__11TrackConfigFUi = .text:0x800E4388; // type:function size:0x8 +SetDisableHopos__11TrackConfigFb = .text:0x800E4390; // type:function size:0x8 +SetTrackNum__11TrackConfigFi = .text:0x800E4398; // type:function size:0x8 fn_800E43A0 = .text:0x800E43A0; // type:function size:0x4 fn_800E43A4 = .text:0x800E43A4; // type:function size:0x88 fn_800E442C = .text:0x800E442C; // type:function size:0x14 @@ -8986,7 +8986,7 @@ fn_800FBE2C = .text:0x800FBE2C; // type:function size:0x58 fn_800FBE84 = .text:0x800FBE84; // type:function size:0x44 fn_800FBEC8 = .text:0x800FBEC8; // type:function size:0x8 fn_800FBED0 = .text:0x800FBED0; // type:function size:0x58 -fn_800FBF28 = .text:0x800FBF28; // type:function size:0x8 +GetControllerType__8BandUserCFv = .text:0x800FBF28; // type:function size:0x8 fn_800FBF30 = .text:0x800FBF30; // type:function size:0x8 fn_800FBF38 = .text:0x800FBF38; // type:function size:0x58 fn_800FBF90 = .text:0x800FBF90; // type:function size:0x44 @@ -25751,7 +25751,7 @@ __rs__FR9BinStreamP8DataNode = .text:0x80317AE0; // type:function size:0x38 SaveGlob__9DataArrayCFR9BinStreamb = .text:0x80317B18; // type:function size:0x84 LoadGlob__9DataArrayFR9BinStreamb = .text:0x80317B9C; // type:function size:0xD0 SetFile__9DataArrayF6Symbol = .text:0x80317C6C; // type:function size:0x10 -RunCommandsFromIndex__9DataArrayFi = .text:0x80317C7C; // type:function size:0x8C +ExecuteBlock__9DataArrayFi = .text:0x80317C7C; // type:function size:0x8C ExecuteScript__9DataArrayFiPQ23Hmx6ObjectPC9DataArrayi = .text:0x80317D08; // type:function size:0x154 __ls__FR10TextStreamPC9DataArray = .text:0x80317E5C; // type:function size:0x5C __rs__FR9BinStreamRP9DataArray = .text:0x80317EB8; // type:function size:0x84 @@ -25852,7 +25852,7 @@ fn_8031B1C0 = .text:0x8031B1C0; // type:function size:0x30 fn_8031B1F0 = .text:0x8031B1F0; // type:function size:0x60 fn_8031B250 = .text:0x8031B250; // type:function size:0x68 DataRegisterFunc__F6SymbolPFP9DataArray_8DataNode = .text:0x8031B2B8; // type:function size:0x40 -fn_8031B2F8 = .text:0x8031B2F8; // type:function size:0xFC +__vc<6Symbol>__Q211stlpmtx_std154map<6Symbol,PFP9DataArray_8DataNode,Q211stlpmtx_std13less<6Symbol>,Q211stlpmtx_std69StlNodeAlloc>>FRC6Symbol_RPFP9DataArray_8DataNode = .text:0x8031B2F8; // type:function size:0xFC fn_8031B3F4 = .text:0x8031B3F4; // type:function size:0x58 fn_8031B44C = .text:0x8031B44C; // type:function size:0x4 fn_8031B450 = .text:0x8031B450; // type:function size:0x40 @@ -26008,7 +26008,7 @@ __ct__12DataArrayPtrFP9DataArray = .text:0x803207B0; // type:function size:0x5C DataQuasiquote__FP9DataArray = .text:0x8032080C; // type:function size:0x40 DataUnquote__FP9DataArray = .text:0x8032084C; // type:function size:0x40 DataGetDateTime__FP9DataArray = .text:0x8032088C; // type:function size:0x1C8 -fn_80320A54 = .text:0x80320A54; // type:function size:0xE0 +FileListCallBack__FPc = .text:0x80320A54; // type:function size:0xE0 DataFileList__FP9DataArray = .text:0x80320B34; // type:function size:0xA4 DataFileListPaths__FP9DataArray = .text:0x80320BD8; // type:function size:0x48 DataObjectList__FP9DataArray = .text:0x80320C20; // type:function size:0xAC @@ -26026,7 +26026,7 @@ fn_80322094 = .text:0x80322094; // type:function size:0x2C __dt__11DataFuncObjFv = .text:0x803220C0; // type:function size:0x70 PoolFree__11DataFuncObjFv = .text:0x80322130; // type:function size:0x10 Handle__11DataFuncObjFP9DataArrayb = .text:0x80322140; // type:function size:0x1C -Filter__15DataMergeFilterFPQ23Hmx6ObjectPQ23Hmx6Object = .text:0x8032215C; // type:function size:0x188 +Filter__15DataMergeFilterFPQ23Hmx6ObjectPQ23Hmx6ObjectP9ObjectDir = .text:0x8032215C; // type:function size:0x188 fn_803222E4 = .text:0x803222E4; // type:function size:0x10 fn_803222F4 = .text:0x803222F4; // type:function size:0x158 fn_8032244C = .text:0x8032244C; // type:function size:0x44 @@ -26058,7 +26058,7 @@ fn_80322C9C = .text:0x80322C9C; // type:function size:0x40 fn_80322CDC = .text:0x80322CDC; // type:function size:0xA0 DataVarName__FPC8DataNode = .text:0x80322D7C; // type:function size:0xB8 fn_80322E34 = .text:0x80322E34; // type:function size:0x4 -AddToBuffer__8DataNodeFv = .text:0x80322E38; // type:function size:0x64 +UseQueue__FRC8DataNode = .text:0x80322E38; // type:function size:0x64 Evaluate__8DataNodeCFv = .text:0x80322E9C; // type:function size:0x8C Int__8DataNodeCFPC9DataArray = .text:0x80322F28; // type:function size:0x24 LiteralInt__8DataNodeCFPC9DataArray = .text:0x80322F4C; // type:function size:0x8 @@ -26904,24 +26904,24 @@ SetType__8TextFileF6Symbol = .text:0x8033CE60; // type:function size:0x128 __dt__8TextFileFv = .text:0x8033CF88; // type:function size:0xA0 @28@Print__8TextFileFPCc = .text:0x8033D028; // type:function size:0x8 @28@__dt__8TextFileFv = .text:0x8033D030; // type:function size:0x8 -GetArray__9TypePropsF6SymbolP9DataArrayP6ObjRef = .text:0x8033D038; // type:function size:0xE4 -SetArrayValue__9TypePropsF6SymboliRC8DataNodeP9DataArrayP6ObjRef = .text:0x8033D11C; // type:function size:0xAC -RemoveArrayValue__9TypePropsF6SymboliP9DataArrayP6ObjRef = .text:0x8033D1C8; // type:function size:0x88 -InsertArrayValue__9TypePropsF6SymboliRC8DataNodeP9DataArrayP6ObjRef = .text:0x8033D250; // type:function size:0x80 -SetKeyValue__9TypePropsF6SymbolRC8DataNodebP6ObjRef = .text:0x8033D2D0; // type:function size:0x1B4 -KeyValue__9TypePropsF6Symbolb = .text:0x8033D484; // type:function size:0x90 -GetSaveSymbolInfo__FP9DataArrayRbRb = .text:0x8033D514; // type:function size:0xCC +GetArray__9TypePropsF6SymbolP9DataArrayPQ23Hmx6Object = .text:0x8033D038; // type:function size:0xE4 +SetArrayValue__9TypePropsF6SymboliRC8DataNodeP9DataArrayPQ23Hmx6Object = .text:0x8033D11C; // type:function size:0xAC +RemoveArrayValue__9TypePropsF6SymboliP9DataArrayPQ23Hmx6Object = .text:0x8033D1C8; // type:function size:0x88 +InsertArrayValue__9TypePropsF6SymboliRC8DataNodeP9DataArrayPQ23Hmx6Object = .text:0x8033D250; // type:function size:0x80 +SetKeyValue__9TypePropsF6SymbolRC8DataNodebPQ23Hmx6Object = .text:0x8033D2D0; // type:function size:0x1B4 +KeyValue__9TypePropsCF6Symbolb = .text:0x8033D484; // type:function size:0x90 +GetSaveFlags__FP9DataArrayRbRb = .text:0x8033D514; // type:function size:0xCC Save__9TypePropsFR9BinStreamPQ23Hmx6Object = .text:0x8033D5E0; // type:function size:0x234 -Load__9TypePropsFR9BinStreamb = .text:0x8033D814; // type:function size:0x198 -ReplaceObject__9TypePropsFR8DataNodePQ23Hmx6ObjectPQ23Hmx6ObjectP6ObjRef = .text:0x8033D9AC; // type:function size:0x84 -Replace__9TypePropsFPQ23Hmx6ObjectPQ23Hmx6ObjectP6ObjRef = .text:0x8033DA30; // type:function size:0x100 +Load__9TypePropsFR9BinStreambPQ23Hmx6Object = .text:0x8033D814; // type:function size:0x198 +ReplaceObject__9TypePropsFR8DataNodePQ23Hmx6ObjectPQ23Hmx6ObjectPQ23Hmx6Object = .text:0x8033D9AC; // type:function size:0x84 +Replace__9TypePropsFPQ23Hmx6ObjectPQ23Hmx6ObjectPQ23Hmx6Object = .text:0x8033DA30; // type:function size:0x100 Size__9TypePropsCFv = .text:0x8033DB30; // type:function size:0x3C -ReleaseObjects__9TypePropsFP6ObjRef = .text:0x8033DB6C; // type:function size:0xF0 -AddRefObjects__9TypePropsFP6ObjRef = .text:0x8033DC5C; // type:function size:0xF0 -Assign__9TypePropsFRC9TypePropsP6ObjRef = .text:0x8033DD4C; // type:function size:0x6C -fn_8033DDB8 = .text:0x8033DDB8; // type:function size:0x2C -fn_8033DDE4 = .text:0x8033DDE4; // type:function size:0x10 -ClearAll__9TypePropsFP6ObjRef = .text:0x8033DDF4; // type:function size:0x44 +ReleaseObjects__9TypePropsFPQ23Hmx6Object = .text:0x8033DB6C; // type:function size:0xF0 +AddRefObjects__9TypePropsFPQ23Hmx6Object = .text:0x8033DC5C; // type:function size:0xF0 +Copy__9TypePropsFRC9TypePropsPQ23Hmx6Object = .text:0x8033DD4C; // type:function size:0x6C +Key__9TypePropsCFi = .text:0x8033DDB8; // type:function size:0x2C +Value__9TypePropsCFi = .text:0x8033DDE4; // type:function size:0x10 +ClearAll__9TypePropsFPQ23Hmx6Object = .text:0x8033DDF4; // type:function size:0x44 InitObject__FPQ23Hmx6Object = .text:0x8033DE38; // type:function size:0xFC PathName__FPCQ23Hmx6Object = .text:0x8033DF34; // type:function size:0x28 SafeName__FPQ23Hmx6Object = .text:0x8033DF5C; // type:function size:0x1C @@ -27718,10 +27718,10 @@ ReadImpl__9MemStreamFPvi = .text:0x80354F78; // type:function size:0x8C WriteImpl__9MemStreamFPCvi = .text:0x80355004; // type:function size:0xAC SeekImpl__9MemStreamFiQ29BinStream8SeekType = .text:0x803550B0; // type:function size:0x9C fn_8035514C = .text:0x8035514C; // type:function size:0x44 -__sinit_\messageset1_cpp = .text:0x80355190; // type:function size:0xC88 -__sinit_\messageset2_cpp = .text:0x80355E18; // type:function size:0xA30 -__sinit_\messageset3_cpp = .text:0x80356848; // type:function size:0xAA8 -__sinit_\messageset4_cpp = .text:0x803572F0; // type:function size:0xB20 +__sinit_\Messages_cpp = .text:0x80355190; // type:function size:0xC88 +__sinit_\Messages2_cpp = .text:0x80355E18; // type:function size:0xA30 +__sinit_\Messages3_cpp = .text:0x80356848; // type:function size:0xAA8 +__sinit_\Messages4_cpp = .text:0x803572F0; // type:function size:0xB20 __ct__18MultiTempoTempoMapFv = .text:0x80357E10; // type:function size:0x64 fn_80357E74 = .text:0x80357E74; // type:function size:0x58 fn_80357ECC = .text:0x80357ECC; // type:function size:0x80 @@ -28218,12 +28218,12 @@ FirstFrom__20KeylessHashFPPCc = .text:0x80364E58; // type:function size Insert__20KeylessHashFRCPCc = .text:0x80364EAC; // type:function size:0x138 Find__20KeylessHashFRCPCc = .text:0x80364FE4; // type:function size:0xB0 Resize__20KeylessHashFiPPCc = .text:0x80365094; // type:function size:0x11C -__ct__20StringTableLockBeginFv = .text:0x803651B0; // type:function size:0x58 -__ct__18StringTableLockEndFv = .text:0x80365208; // type:function size:0xC -__sinit_\symbolset1_cpp = .text:0x80365214; // type:function size:0x638C scope:local -__sinit_\symbolset2_cpp = .text:0x8036B5A0; // type:function size:0x4F3C scope:local -__sinit_\symbolset3_cpp = .text:0x803704DC; // type:function size:0x4F90 scope:local -__sinit_\symbolset4_cpp = .text:0x8037546C; // type:function size:0x4F6C scope:local +__ct__19BeginLiteralSymbolsFv = .text:0x803651B0; // type:function size:0x58 +__ct__17EndLiteralSymbolsFv = .text:0x80365208; // type:function size:0xC +__sinit_\Symbols_cpp = .text:0x80365214; // type:function size:0x638C scope:local +__sinit_\Symbols2_cpp = .text:0x8036B5A0; // type:function size:0x4F3C scope:local +__sinit_\Symbols3_cpp = .text:0x803704DC; // type:function size:0x4F90 scope:local +__sinit_\Symbols4_cpp = .text:0x8037546C; // type:function size:0x4F6C scope:local fn_8037A3D8 = .text:0x8037A3D8; // type:function size:0x38 __dt__14SimpleTempoMapFv = .text:0x8037A410; // type:function size:0x58 scope:weak SetTheTempoMap__FP8TempoMap = .text:0x8037A468; // type:function size:0xC @@ -43145,8 +43145,8 @@ fn_805314FC = .text:0x805314FC; // type:function size:0x14 fn_80531510 = .text:0x80531510; // type:function size:0x14 fn_80531524 = .text:0x80531524; // type:function size:0x14 fn_80531538 = .text:0x80531538; // type:function size:0x14 -fn_8053154C = .text:0x8053154C; // type:function size:0x14 -fn_80531560 = .text:0x80531560; // type:function size:0x14 +@176@28@SetType__10MidiParserF6Symbol = .text:0x8053154C; // type:function size:0x14 +@176@28@ClassName__10MidiParserCFv = .text:0x80531560; // type:function size:0x14 fn_80531574 = .text:0x80531574; // type:function size:0x60 fn_805315D4 = .text:0x805315D4; // type:function size:0x178 fn_8053174C = .text:0x8053174C; // type:function size:0x58 @@ -44323,8 +44323,8 @@ StaticClassName__8UIButtonFv = .text:0x805527E8; // type:function size:0x4C Copy__8UIButtonFPCQ23Hmx6ObjectQ33Hmx6Object8CopyType = .text:0x80552834; // type:function size:0x68 Save__8UIButtonFR9BinStream = .text:0x8055289C; // type:function size:0x4 Load__8UIButtonFR9BinStream = .text:0x805528A0; // type:function size:0x5C -fn_805528FC = .text:0x805528FC; // type:function size:0x64 -fn_80552960 = .text:0x80552960; // type:function size:0x4 +PreLoad__8UIButtonFR9BinStream = .text:0x805528FC; // type:function size:0x64 +PostLoad__8UIButtonFR9BinStream = .text:0x80552960; // type:function size:0x4 Handle__8UIButtonFP9DataArrayb = .text:0x80552964; // type:function size:0x150 OnMsg__8UIButtonFRC13ButtonDownMsg = .text:0x80552AB4; // type:function size:0x8C SyncProperty__8UIButtonFR8DataNodeP9DataArrayi6PropOp = .text:0x80552B40; // type:function size:0x8C @@ -44348,14 +44348,14 @@ fn_80552DC0 = .text:0x80552DC0; // type:function size:0x14 fn_80552DD4 = .text:0x80552DD4; // type:function size:0x14 fn_80552DE8 = .text:0x80552DE8; // type:function size:0x14 fn_80552DFC = .text:0x80552DFC; // type:function size:0x14 -fn_80552E10 = .text:0x80552E10; // type:function size:0x14 -fn_80552E24 = .text:0x80552E24; // type:function size:0x14 -fn_80552E38 = .text:0x80552E38; // type:function size:0x14 -fn_80552E4C = .text:0x80552E4C; // type:function size:0x14 -fn_80552E60 = .text:0x80552E60; // type:function size:0x8 -fn_80552E68 = .text:0x80552E68; // type:function size:0x8 -fn_80552E70 = .text:0x80552E70; // type:function size:0x8 -fn_80552E78 = .text:0x80552E78; // type:function size:0x8 +@444@28@SyncProperty__8UIButtonFR8DataNodeP9DataArrayi6PropOp = .text:0x80552E10; // type:function size:0x14 +@444@28@Handle__8UIButtonFP9DataArrayb = .text:0x80552E24; // type:function size:0x14 +@444@28@SetType__8UIButtonF6Symbol = .text:0x80552E38; // type:function size:0x14 +@444@28@ClassName__8UIButtonCFv = .text:0x80552E4C; // type:function size:0x14 +@176@Poll__7UILabelFv = .text:0x80552E60; // type:function size:0x8 +@176@Handle__8UIButtonFP9DataArrayb = .text:0x80552E68; // type:function size:0x8 +@176@SetType__8UIButtonF6Symbol = .text:0x80552E70; // type:function size:0x8 +@176@ClassName__8UIButtonCFv = .text:0x80552E78; // type:function size:0x8 __ct__7UIColorFv = .text:0x80552E80; // type:function size:0x58 GetColor__7UIColorCFv = .text:0x80552ED8; // type:function size:0x8 __as__7UIColorFRCQ23Hmx5Color = .text:0x80552EE0; // type:function size:0x8 @@ -44482,8 +44482,8 @@ Copy__7UILabelFPCQ23Hmx6ObjectQ33Hmx6Object8CopyType = .text:0x8055656C; // type fn_805565E8 = .text:0x805565E8; // type:function size:0x1B0 Save__7UILabelFR9BinStream = .text:0x80556798; // type:function size:0x4 Load__7UILabelFR9BinStream = .text:0x8055679C; // type:function size:0x5C -fn_805567F8 = .text:0x805567F8; // type:function size:0x438 -fn_80556C30 = .text:0x80556C30; // type:function size:0x108 +PreLoad__7UILabelFR9BinStream = .text:0x805567F8; // type:function size:0x438 +PostLoad__7UILabelFR9BinStream = .text:0x80556C30; // type:function size:0x108 fn_80556D38 = .text:0x80556D38; // type:function size:0x70 fn_80556DA8 = .text:0x80556DA8; // type:function size:0x20 fn_80556DC8 = .text:0x80556DC8; // type:function size:0x204 @@ -48296,7 +48296,7 @@ ClassName__13RndAnimFilterCFv = .text:0x805C99C4; // type:function size:0x4 @64@28@Handle__13RndAnimFilterFP9DataArrayb = .text:0x805C9A2C; // type:function size:0x14 @64@28@SetType__13RndAnimFilterF6Symbol = .text:0x805C9A40; // type:function size:0x14 @64@28@ClassName__13RndAnimFilterCFv = .text:0x805C9A54; // type:function size:0x14 -Load__9RndBitmapFR9BinStreamRc = .text:0x805C9A68; // type:function size:0xCC +LoadHeader__9RndBitmapFR9BinStreamRUc = .text:0x805C9A68; // type:function size:0xCC fn_805C9B34 = .text:0x805C9B34; // type:function size:0x94 fn_805C9BC8 = .text:0x805C9BC8; // type:function size:0x54 fn_805C9C1C = .text:0x805C9C1C; // type:function size:0x8C @@ -50626,7 +50626,7 @@ Save__8RndMovieFR9BinStream = .text:0x80614468; // type:function size:0x4 Load__8RndMovieFR9BinStream = .text:0x8061446C; // type:function size:0x5C PreLoad__8RndMovieFR9BinStream = .text:0x806144C8; // type:function size:0xE4 PostLoad__8RndMovieFR9BinStream = .text:0x806145AC; // type:function size:0x74 -fn_80614620 = .text:0x80614620; // type:function size:0x40 +SetFile__8RndMovieFRC8FilePathb = .text:0x80614620; // type:function size:0x40 Copy__8RndMovieFPCQ23Hmx6ObjectQ33Hmx6Object8CopyType = .text:0x80614660; // type:function size:0xAC Replace__8RndMovieFPQ23Hmx6ObjectPQ23Hmx6Object = .text:0x8061470C; // type:function size:0x88 SetTex__8RndMovieFP6RndTex = .text:0x80614794; // type:function size:0x8 @@ -58183,7 +58183,7 @@ OSJoinThread = .text:0x8076C260; // type:function size:0x144 OSResumeThread = .text:0x8076C3B0; // type:function size:0x29C fn_8076C650 = .text:0x8076C650; // type:function size:0x18C OSSleepThread = .text:0x8076C7E0; // type:function size:0xF0 scope:global -fn_8076C8D0 = .text:0x8076C8D0; // type:function size:0xF8 +OSWakeupThread = .text:0x8076C8D0; // type:function size:0xF8 fn_8076C9D0 = .text:0x8076C9D0; // type:function size:0xEC OSGetThreadPriority = .text:0x8076CAC0; // type:function size:0x8 fn_8076CAD0 = .text:0x8076CAD0; // type:function size:0x30 @@ -58265,24 +58265,24 @@ SCInit = .text:0x807713F0; // type:function size:0xA0 scope:global SCCheckStatus = .text:0x80771490; // type:function size:0x11C scope:global SCReloadConfFileAsync = .text:0x807715B0; // type:function size:0x114 scope:local OpenCallbackFromReload = .text:0x807716D0; // type:function size:0xD0 scope:local -fn_807717A0 = .text:0x807717A0; // type:function size:0xE8 -fn_80771890 = .text:0x80771890; // type:function size:0x8C -fn_80771920 = .text:0x80771920; // type:function size:0x124 -fn_80771A50 = .text:0x80771A50; // type:function size:0x4 -fn_80771A60 = .text:0x80771A60; // type:function size:0x248 -fn_80771CB0 = .text:0x80771CB0; // type:function size:0x180 -fn_80771E30 = .text:0x80771E30; // type:function size:0x194 -fn_80771FD0 = .text:0x80771FD0; // type:function size:0x278 -fn_80772250 = .text:0x80772250; // type:function size:0xE0 -fn_80772330 = .text:0x80772330; // type:function size:0x124 -fn_80772460 = .text:0x80772460; // type:function size:0xD4 -fn_80772540 = .text:0x80772540; // type:function size:0xD4 -fn_80772620 = .text:0x80772620; // type:function size:0xD4 -fn_80772700 = .text:0x80772700; // type:function size:0x100 -fn_80772800 = .text:0x80772800; // type:function size:0x104 -fn_80772910 = .text:0x80772910; // type:function size:0xC -fn_80772920 = .text:0x80772920; // type:function size:0x21C -fn_80772B40 = .text:0x80772B40; // type:function size:0x338 +ReadCallbackFromReload = .text:0x807717A0; // type:function size:0xE8 +CloseCallbackFromReload = .text:0x80771890; // type:function size:0x8C +FinishFromReload = .text:0x80771920; // type:function size:0x124 +CloseCallbackFromReloadError = .text:0x80771A50; // type:function size:0x4 +ParseConfBuf = .text:0x80771A60; // type:function size:0x248 +UnpackItem = .text:0x80771CB0; // type:function size:0x180 +DeleteItemByID = .text:0x80771E30; // type:function size:0x194 +CreateItemByID = .text:0x80771FD0; // type:function size:0x278 +SCFindByteArrayItem = .text:0x80772250; // type:function size:0xE0 +SCReplaceByteArrayItem = .text:0x80772330; // type:function size:0x124 +SCFindU8Item = .text:0x80772460; // type:function size:0xD4 +SCFindS8Item = .text:0x80772540; // type:function size:0xD4 +SCFindU32Item = .text:0x80772620; // type:function size:0xD4 +SCFindBoolItem = .text:0x80772700; // type:function size:0x100 +SCReplaceU8Item = .text:0x80772800; // type:function size:0x104 +__SCFlushSyncCallback = .text:0x80772910; // type:function size:0xC +SCFlushAsync = .text:0x80772920; // type:function size:0x21C +MyNandCallback = .text:0x80772B40; // type:function size:0x338 SCGetAspectRatio = .text:0x80772E80; // type:function size:0x54 fn_80772EE0 = .text:0x80772EE0; // type:function size:0x74 fn_80772F60 = .text:0x80772F60; // type:function size:0xC @@ -60057,7 +60057,7 @@ lbl_807F03F0 = .rodata:0x807F03F0; // type:object size:0x4 data:float lbl_807F03F4 = .rodata:0x807F03F4; // type:object size:0x4 data:float @F_3333733f = .rodata:0x807F03F8; // type:object size:0x8 data:float lbl_807F0400 = .rodata:0x807F0400; // type:object size:0x78 data:4byte -lbl_807F0478 = .rodata:0x807F0478; // type:object size:0x4 data:float +@F_9a99993e = .rodata:0x807F0478; // type:object size:0x4 data:float lbl_807F047C = .rodata:0x807F047C; // type:object size:0x4 data:float @F_0060ea46 = .rodata:0x807F0480; // type:object size:0x8 data:float lbl_807F0488 = .rodata:0x807F0488; // type:object size:0x8 data:float @@ -64074,7 +64074,7 @@ __vt__Q26Quazal4NetZ = .data:0x8082A608; // type:object size:0xC lbl_8082A614 = .data:0x8082A614; // type:object size:0x10 lbl_8082A624 = .data:0x8082A624; // type:object size:0x24 __RTTI__Q26Quazal4NetZ = .data:0x8082A648; // type:object size:0x8 -lbl_8082A650 = .data:0x8082A650; // type:object size:0x10 +@stringBase0 = .data:0x8082A650; // type:object size:0x10 scope:local data:string_table __vt__Q26Quazal13NetZSpecifics = .data:0x8082A660; // type:object size:0x18 lbl_8082A678 = .data:0x8082A678; // type:object size:0x18 lbl_8082A690 = .data:0x8082A690; // type:object size:0x18 @@ -64754,7 +64754,7 @@ lbl_8082F9A0 = .data:0x8082F9A0; // type:object size:0xC data:string lbl_8082F9AC = .data:0x8082F9AC; // type:object size:0x34 __RTTI__11UIComponent = .data:0x8082F9E0; // type:object size:0x8 lbl_8082F9E8 = .data:0x8082F9E8; // type:object size:0x10 -lbl_8082F9F8 = .data:0x8082F9F8; // type:object size:0x30 +@stringBase0 = .data:0x8082F9F8; // type:object size:0x30 scope:local data:string_table lbl_8082FA28 = .data:0x8082FA28; // type:object size:0x14 lbl_8082FA3C = .data:0x8082FA3C; // type:object size:0x5C __RTTI__17TrackPanelDirBase = .data:0x8082FA98; // type:object size:0x8 @@ -68222,8 +68222,8 @@ lbl_80854FA8 = .data:0x80854FA8; // type:object size:0x4A0 jumptable_80855448 = .data:0x80855448; // type:object size:0x98 scope:local jumptable_808554E0 = .data:0x808554E0; // type:object size:0x98 scope:local jumptable_80855578 = .data:0x80855578; // type:object size:0x98 scope:local -lbl_80855610 = .data:0x80855610; // type:object size:0x8 -lbl_80855618 = .data:0x80855618; // type:object size:0x80 +@STRING@__ls__FR10TextStreamPCQ23Hmx6Object = .data:0x80855610; // type:object size:0x7 data:string +@stringBase0 = .data:0x80855618; // type:object size:0x80 scope:local data:string_table gVarStackPtr = .data:0x80855698; // type:object size:0x4 data:4byte sFile = .data:0x8085569C; // type:object size:0x8 @stringBase0 = .data:0x808556A4; // type:object size:0x1C scope:local data:string_table @@ -68295,9 +68295,9 @@ __vt__8TextFile = .data:0x80856610; // type:object size:0x70 lbl_80856680 = .data:0x80856680; // type:object size:0x9 data:string lbl_8085668C = .data:0x8085668C; // type:object size:0x14 __RTTI__8TextFile = .data:0x808566A8; // type:object size:0x8 -lbl_808566B0 = .data:0x808566B0; // type:object size:0x8 -lbl_808566B8 = .data:0x808566B8; // type:object size:0x8 data:string -lbl_808566C0 = .data:0x808566C0; // type:object size:0x8 +@STRING@SetType__8TextFileF6Symbol@0 = .data:0x808566B0; // type:object size:0x6 data:string +@STRING@SetType__8TextFileF6Symbol = .data:0x808566B8; // type:object size:0x8 data:string +@stringBase0 = .data:0x808566C0; // type:object size:0x7 scope:local data:string_table lbl_808566C8 = .data:0x808566C8; // type:object size:0x98 TheBeatMap = .data:0x80856760; // type:object size:0x8 data:4byte lbl_80856768 = .data:0x80856768; // type:object size:0x20 @@ -68403,10 +68403,10 @@ __vt__9MemStream = .data:0x80857270; // type:object size:0x34 lbl_808572A4 = .data:0x808572A4; // type:object size:0xC lbl_808572B0 = .data:0x808572B0; // type:object size:0x10 lbl_808572C0 = .data:0x808572C0; // type:object size:0x8 -lbl_808572C8 = .data:0x808572C8; // type:object size:0x4FA -lbl_808577C8 = .data:0x808577C8; // type:object size:0x4A0 -lbl_80857C68 = .data:0x80857C68; // type:object size:0x418 -lbl_80858080 = .data:0x80858080; // type:object size:0x3F0 +@stringBase0 = .data:0x808572C8; // type:object size:0x4FA scope:local data:string_table +@stringBase0 = .data:0x808577C8; // type:object size:0x4A0 scope:local data:string_table +@stringBase0 = .data:0x80857C68; // type:object size:0x418 scope:local data:string_table +@stringBase0 = .data:0x80858080; // type:object size:0x3F0 scope:local data:string_table __vt__18MultiTempoTempoMap = .data:0x80858470; // type:object size:0x40 lbl_808584B0 = .data:0x808584B0; // type:object size:0x14 lbl_808584C4 = .data:0x808584C4; // type:object size:0xC @@ -68463,10 +68463,10 @@ __vt__6String = .data:0x80858C90; // type:object size:0x10 lbl_80858CA0 = .data:0x80858CA0; // type:object size:0x8 lbl_80858CA8 = .data:0x80858CA8; // type:object size:0x48 lbl_80858CF0 = .data:0x80858CF0; // type:object size:0x38 -lbl_80858D28 = .data:0x80858D28; // type:object size:0x854E -lbl_80861278 = .data:0x80861278; // type:object size:0x6303 -lbl_80867580 = .data:0x80867580; // type:object size:0x68CF -lbl_8086DE50 = .data:0x8086DE50; // type:object size:0x6615 +@stringBase0 = .data:0x80858D28; // type:object size:0x854E scope:local data:string_table +@stringBase0 = .data:0x80861278; // type:object size:0x6303 scope:local data:string_table +@stringBase0 = .data:0x80867580; // type:object size:0x68CF scope:local data:string_table +@stringBase0 = .data:0x8086DE50; // type:object size:0x6615 scope:local data:string_table TheTempoMap = .data:0x80874468; // type:object size:0x8 data:4byte __vt__14SimpleTempoMap = .data:0x80874470; // type:object size:0x40 lbl_808744B0 = .data:0x808744B0; // type:object size:0x10 @@ -70685,8 +70685,8 @@ lbl_80890278 = .data:0x80890278; // type:object size:0x8 data:string lbl_80890280 = .data:0x80890280; // type:object size:0xF0 __vt__8UIButton = .data:0x80890370; // type:object size:0x170 lbl_808904E0 = .data:0x808904E0; // type:object size:0xC -lbl_808904EC = .data:0x808904EC; // type:object size:0xC -lbl_808904F8 = .data:0x808904F8; // type:object size:0x8 data:string +@STRING@SetType__8UIButtonF6Symbol@0 = .data:0x808904EC; // type:object size:0xC +@STRING@SetType__8UIButtonF6Symbol = .data:0x808904F8; // type:object size:0x8 data:string lbl_80890500 = .data:0x80890500; // type:object size:0x10 __vt__7UIColor = .data:0x80890510; // type:object size:0x5C lbl_8089056C = .data:0x8089056C; // type:object size:0xC @@ -71407,7 +71407,7 @@ lbl_80898FB8 = .data:0x80898FB8; // type:object size:0x14 lbl_80898FCC = .data:0x80898FCC; // type:object size:0x10 lbl_80898FDC = .data:0x80898FDC; // type:object size:0x4 data:string lbl_80898FE0 = .data:0x80898FE0; // type:object size:0x8 data:string -lbl_80898FE8 = .data:0x80898FE8; // type:object size:0x1B0 +@stringBase0 = .data:0x80898FE8; // type:object size:0x1B0 scope:local data:string_table __vt__13RndScreenMask = .data:0x80899198; // type:object size:0xD0 lbl_80899268 = .data:0x80899268; // type:object size:0x10 lbl_80899278 = .data:0x80899278; // type:object size:0x28 @@ -73605,7 +73605,7 @@ lbl_808E307A = .sdata:0x808E307A; // type:object size:0x6 sKeyCheatsEnabled = .sdata:0x808E3080; // type:object size:0x8 data:byte lbl_808E3088 = .sdata:0x808E3088; // type:object size:0x8 lbl_808E3090 = .sdata:0x808E3090; // type:object size:0x8 data:byte -StringTableLocked = .sdata:0x808E3098; // type:object size:0x8 data:byte +gLiteralSymbolStaticInitialization = .sdata:0x808E3098; // type:object size:0x8 data:byte lbl_808E30A0 = .sdata:0x808E30A0; // type:object size:0x1 data:string lbl_808E30A1 = .sdata:0x808E30A1; // type:object size:0x7 lbl_808E30A8 = .sdata:0x808E30A8; // type:object size:0x1 @@ -75166,7 +75166,7 @@ lbl_808E42DC = .sbss:0x808E42DC; // type:object size:0x1 data:byte lbl_808E42E0 = .sbss:0x808E42E0; // type:object size:0x1 data:byte lbl_808E42E1 = .sbss:0x808E42E1; // type:object size:0x7 data:byte lbl_808E42E8 = .sbss:0x808E42E8; // type:object size:0x8 data:byte -lbl_808E42F0 = .sbss:0x808E42F0; // type:object size:0x1 data:byte +@GUARD@SetType__8UIButtonF6Symbol@types = .sbss:0x808E42F0; // type:object size:0x1 data:byte lbl_808E42F1 = .sbss:0x808E42F1; // type:object size:0x1 data:byte lbl_808E42F2 = .sbss:0x808E42F2; // type:object size:0x1 data:byte lbl_808E42F3 = .sbss:0x808E42F3; // type:object size:0x5 data:byte @@ -75331,10 +75331,10 @@ lbl_808E4463 = .sbss:0x808E4463; // type:object size:0x5 data:byte lbl_808E4468 = .sbss:0x808E4468; // type:object size:0x8 data:byte lbl_808E4470 = .sbss:0x808E4470; // type:object size:0x1 data:byte lbl_808E4471 = .sbss:0x808E4471; // type:object size:0x1 data:byte -gReadingFile = .sbss:0x808E4472; // type:object size:0x6 data:byte -lbl_808E4478 = .sbss:0x808E4478; // type:object size:0x1 data:byte -lbl_808E447A = .sbss:0x808E447A; // type:object size:0x1 data:byte -lbl_808E447B = .sbss:0x808E447B; // type:object size:0x5 data:byte +gReadingFile = .sbss:0x808E4472; // type:object size:0x1 data:byte +@LOCAL@DataChar__FP9DataArray@newChar = .sbss:0x808E4478; // type:object size:0x1 data:byte +@GUARD@Filter__15DataMergeFilterFPQ23Hmx6ObjectPQ23Hmx6ObjectP9ObjectDir@d = .sbss:0x808E447A; // type:object size:0x1 data:byte +lbl_808E447B = .sbss:0x808E447B; // type:object size:0x1 data:byte @GUARD@SetType__8TextFileF6Symbol@types = .sbss:0x808E4480; // type:object size:0x1 data:byte @GUARD@StaticClassName__8TextFileFv@name = .sbss:0x808E4481; // type:object size:0x1 data:byte lbl_808E4482 = .sbss:0x808E4482; // type:object size:0x6 data:byte @@ -75390,7 +75390,7 @@ lbl_808E44CD = .sbss:0x808E44CD; // type:object size:0x1 data:byte lbl_808E44D0 = .sbss:0x808E44D0; // type:object size:0x1 data:byte lbl_808E44D1 = .sbss:0x808E44D1; // type:object size:0x1 data:byte lbl_808E44D2 = .sbss:0x808E44D2; // type:object size:0x6 data:byte -@GUARD@Handle__8TextFileFP9DataArrayb@SymPrintf = .sbss:0x808E44D8; // type:object size:0x8 data:byte +@GUARD@Handle__8TextFileFP9DataArrayb@_s = .sbss:0x808E44D8; // type:object size:0x8 data:byte @GUARD@InitObject__FPQ23Hmx6Object@objects = .sbss:0x808E44E0; // type:object size:0x1 data:byte @GUARD@InitObject__FPQ23Hmx6Object@initSym@0 = .sbss:0x808E44E1; // type:object size:0x7 data:byte lbl_808E44E8 = .sbss:0x808E44E8; // type:object size:0x1 data:byte @@ -75408,14 +75408,14 @@ lbl_808E4519 = .sbss:0x808E4519; // type:object size:0x1 data:byte lbl_808E451A = .sbss:0x808E451A; // type:object size:0x1 data:byte lbl_808E451B = .sbss:0x808E451B; // type:object size:0x5 data:byte lbl_808E4520 = .sbss:0x808E4520; // type:object size:0x8 data:byte -msglock1 = .sbss:0x808E4528; // type:object size:0x4 -msgunlock1 = .sbss:0x808E452C; // type:object size:0x4 -msglock2 = .sbss:0x808E4530; // type:object size:0x4 -msgunlock2 = .sbss:0x808E4534; // type:object size:0x4 -msglock3 = .sbss:0x808E4538; // type:object size:0x4 -msgunlock3 = .sbss:0x808E453C; // type:object size:0x4 -msglock4 = .sbss:0x808E4540; // type:object size:0x4 -msgunlock4 = .sbss:0x808E4544; // type:object size:0x4 +gBeginLiteralSymbols = .sbss:0x808E4528; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E452C; // type:object size:0x4 scope:local +gBeginLiteralSymbols = .sbss:0x808E4530; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E4534; // type:object size:0x4 scope:local +gBeginLiteralSymbols = .sbss:0x808E4538; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E453C; // type:object size:0x4 scope:local +gBeginLiteralSymbols = .sbss:0x808E4540; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E4544; // type:object size:0x4 scope:local lbl_808E4548 = .sbss:0x808E4548; // type:object size:0x8 data:byte lbl_808E4550 = .sbss:0x808E4550; // type:object size:0x8 data:byte lbl_808E4558 = .sbss:0x808E4558; // type:object size:0x1 data:byte @@ -75424,14 +75424,14 @@ lbl_808E455A = .sbss:0x808E455A; // type:object size:0x1 data:byte lbl_808E455B = .sbss:0x808E455B; // type:object size:0x1 data:byte lbl_808E455C = .sbss:0x808E455C; // type:object size:0x1 data:byte gEmpty = .sbss:0x808E4560; // type:object size:0x8 -lock1 = .sbss:0x808E4568; // type:object size:0x4 -unlock1 = .sbss:0x808E456C; // type:object size:0x4 -lock2 = .sbss:0x808E4570; // type:object size:0x4 -unlock2 = .sbss:0x808E4574; // type:object size:0x4 -lock3 = .sbss:0x808E4578; // type:object size:0x4 -unlock3 = .sbss:0x808E457C; // type:object size:0x4 -lock4 = .sbss:0x808E4580; // type:object size:0x4 -unlock4 = .sbss:0x808E4584; // type:object size:0x4 +gBeginLiteralSymbols = .sbss:0x808E4568; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E456C; // type:object size:0x4 scope:local +gBeginLiteralSymbols = .sbss:0x808E4570; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E4574; // type:object size:0x4 scope:local +gBeginLiteralSymbols = .sbss:0x808E4578; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E457C; // type:object size:0x4 scope:local +gBeginLiteralSymbols = .sbss:0x808E4580; // type:object size:0x4 scope:local +gEndLiteralSymbols = .sbss:0x808E4584; // type:object size:0x4 scope:local lbl_808E4588 = .sbss:0x808E4588; // type:object size:0x8 data:byte lbl_808E4590 = .sbss:0x808E4590; // type:object size:0x1 data:byte lbl_808E4591 = .sbss:0x808E4591; // type:object size:0x1 data:byte @@ -75897,8 +75897,8 @@ lbl_808E4A54 = .sbss:0x808E4A54; // type:object size:0x2 data:2byte lbl_808E4A58 = .sbss:0x808E4A58; // type:object size:0x8 data:byte lbl_808E4A60 = .sbss:0x808E4A60; // type:object size:0x1 data:byte lbl_808E4A61 = .sbss:0x808E4A61; // type:object size:0x7 data:byte -lbl_808E4A68 = .sbss:0x808E4A68; // type:object size:0x2 data:2byte -lbl_808E4A6A = .sbss:0x808E4A6A; // type:object size:0x6 data:2byte +gRev__8UIButton = .sbss:0x808E4A68; // type:object size:0x2 data:2byte +gAltRev__8UIButton = .sbss:0x808E4A6A; // type:object size:0x2 data:2byte lbl_808E4A70 = .sbss:0x808E4A70; // type:object size:0x2 data:2byte lbl_808E4A72 = .sbss:0x808E4A72; // type:object size:0x6 data:2byte lbl_808E4A78 = .sbss:0x808E4A78; // type:object size:0x1 data:byte @@ -77619,7 +77619,7 @@ lbl_808F0940 = .bss:0x808F0940; // type:object size:0x4 data:4byte lbl_808F0944 = .bss:0x808F0944; // type:object size:0x4 data:4byte lbl_808F0948 = .bss:0x808F0948; // type:object size:0x4 data:4byte lbl_808F094C = .bss:0x808F094C; // type:object size:0x4 data:4byte -lbl_808F0950 = .bss:0x808F0950; // type:object size:0x8 data:4byte +s_pInstance__Q26Quazal9BadEvents = .bss:0x808F0950; // type:object size:0x4 data:4byte lbl_808F0958 = .bss:0x808F0958; // type:object size:0x10 lbl_808F0968 = .bss:0x808F0968; // type:object size:0x1C data:4byte lbl_808F0984 = .bss:0x808F0984; // type:object size:0x14 @@ -78630,7 +78630,7 @@ lbl_808FF990 = .bss:0x808FF990; // type:object size:0x1D0 lbl_808FFB60 = .bss:0x808FFB60; // type:object size:0x8 data:4byte lbl_808FFB68 = .bss:0x808FFB68; // type:object size:0x8 data:4byte lbl_808FFB70 = .bss:0x808FFB70; // type:object size:0x8 data:4byte -lbl_808FFB78 = .bss:0x808FFB78; // type:object size:0x4 data:4byte +@LOCAL@SetType__8UIButtonF6Symbol@types = .bss:0x808FFB78; // type:object size:0x4 data:4byte lbl_808FFB7C = .bss:0x808FFB7C; // type:object size:0x4 data:4byte lbl_808FFB80 = .bss:0x808FFB80; // type:object size:0x4 data:4byte lbl_808FFB84 = .bss:0x808FFB84; // type:object size:0x4 data:4byte @@ -78977,8 +78977,8 @@ gDataFuncs = .bss:0x8091A528; // type:object size:0x24 gDataThisPtr = .bss:0x8091A54C; // type:object size:0xC lbl_8091A558 = .bss:0x8091A558; // type:object size:0xC lbl_8091A564 = .bss:0x8091A564; // type:object size:0x4 -lbl_8091A568 = .bss:0x8091A568; // type:object size:0x1C data:4byte -lbl_8091A584 = .bss:0x8091A584; // type:object size:0x4 data:4byte +sFileMsg = .bss:0x8091A568; // type:object size:0x4 data:4byte +@LOCAL@Filter__15DataMergeFilterFPQ23Hmx6ObjectPQ23Hmx6ObjectP9ObjectDir@d = .bss:0x8091A584; // type:object size:0x4 data:4byte lbl_8091A588 = .bss:0x8091A588; // type:object size:0x10 gDataVars = .bss:0x8091A598; // type:object size:0x28 gEvalNode = .bss:0x8091A5C0; // type:object size:0x40 @@ -79031,7 +79031,7 @@ lbl_8091B948 = .bss:0x8091B948; // type:object size:0x4 data:4byte lbl_8091B94C = .bss:0x8091B94C; // type:object size:0xC lbl_8091B958 = .bss:0x8091B958; // type:object size:0x4 data:4byte lbl_8091B95C = .bss:0x8091B95C; // type:object size:0x4 -@LOCAL@Handle__8TextFileFP9DataArrayb@SymPrintf = .bss:0x8091B960; // type:object size:0x8 +@LOCAL@Handle__8TextFileFP9DataArrayb@_s = .bss:0x8091B960; // type:object size:0x8 lbl_8091B968 = .bss:0x8091B968; // type:object size:0x60010 @LOCAL@InitObject__FPQ23Hmx6Object@objects = .bss:0x8097B978; // type:object size:0x4 data:4byte @LOCAL@InitObject__FPQ23Hmx6Object@initSym@0 = .bss:0x8097B97C; // type:object size:0x14 data:4byte @@ -84418,7 +84418,7 @@ lbl_80984D04 = .bss:0x80984D04; // type:object size:0x4 lbl_80984D08 = .bss:0x80984D08; // type:object size:0x8 lbl_80984D10 = .bss:0x80984D10; // type:object size:0x4 lbl_80984D14 = .bss:0x80984D14; // type:object size:0x4 -lbl_80984D18 = .bss:0x80984D18; // type:object size:0x4 +print = .bss:0x80984D18; // type:object size:0x4 lbl_80984D1C = .bss:0x80984D1C; // type:object size:0x4 lbl_80984D20 = .bss:0x80984D20; // type:object size:0x4 lbl_80984D24 = .bss:0x80984D24; // type:object size:0x4 @@ -84535,7 +84535,7 @@ lbl_80984F74 = .bss:0x80984F74; // type:object size:0x4 lbl_80984F78 = .bss:0x80984F78; // type:object size:0x4 reference_object_1 = .bss:0x80984F7C; // type:object size:0x4 reference_object_2 = .bss:0x80984F80; // type:object size:0x4 -lbl_80984F84 = .bss:0x80984F84; // type:object size:0x4 +reflect = .bss:0x80984F84; // type:object size:0x4 lbl_80984F88 = .bss:0x80984F88; // type:object size:0x4 lbl_80984F8C = .bss:0x80984F8C; // type:object size:0x4 lbl_80984F90 = .bss:0x80984F90; // type:object size:0x4 @@ -85793,7 +85793,7 @@ lbl_809ECBC0 = .bss:0x809ECBC0; // type:object size:0x20 data:4byte __OSExpireAlarm = .bss:0x809ECBE0; // type:object size:0x30 scope:global data:4byte Control = .bss:0x809ECC20; // type:object size:0x190 scope:local data:4byte ConfBuf = .bss:0x809ECDC0; // type:object size:0x4000 scope:local -lbl_809F0DC0 = .bss:0x809F0DC0; // type:object size:0x4000 +ConfBufForFlush = .bss:0x809F0DC0; // type:object size:0x4000 scope:local lbl_809F4DC0 = .bss:0x809F4DC0; // type:object size:0x1008 data:4byte Packet = .bss:0x809F5DC8; // type:object size:0x80 scope:local data:4byte lbl_809F5E48 = .bss:0x809F5E48; // type:object size:0x20 diff --git a/config/SZBE69_B8/objects.json b/config/SZBE69_B8/objects.json index a0f1e387..37b2fa90 100644 --- a/config/SZBE69_B8/objects.json +++ b/config/SZBE69_B8/objects.json @@ -81,9 +81,12 @@ "network/Plugins/JobGetPublicURL.cpp": "Matching", "network/Plugins/MD5.cpp": "NonMatching", + "network/Plugins/RTT.cpp": "NonMatching", "network/Plugins/ZLibPlugin.cpp": "Matching", - "network/Services/UserMessage.cpp": "Matching" + "network/Services/UserMessage.cpp": "Matching", + + "network/Utility/Statistics.cpp": "Matching" } }, "network/json_c": { @@ -102,11 +105,15 @@ "mw_version": "Wii/1.3", "cflags": "network/Platform", "objects": { + "network/Platform/BadEvents.cpp": "Matching", + "network/Platform/CIDLogFilter.cpp": "Matching", "network/Platform/CriticalSection.cpp": "Matching", "network/Platform/DateTime.cpp": "NonMatching", "network/Platform/ExceptionHandler.cpp": "Matching", "network/Platform/Inet.cpp": "Matching", "network/Platform/LockChecker.cpp": "Matching", + "network/Platform/Log.cpp": "NonMatching", + "network/Platform/LogDeviceDebugOutput.cpp": "Matching", "network/Platform/MemoryManager.cpp": "NonMatching", "network/Platform/MutexPrimitive.cpp": "NonMatching", "network/Platform/OutputFormat.cpp": "NonMatching", @@ -796,7 +803,7 @@ "mw_version": "Wii/1.3", "cflags": "sdk/MSL", "objects": { - + "sdk/PowerPC_EABI_Support/MetroTRK/custconn/MWCriticalSection_gc.c": "Matching" } }, "sdk/RVL_SDK": { @@ -811,6 +818,19 @@ "sdk/RVL_SDK/revolution/gx/GXLight.c": "Matching", "sdk/RVL_SDK/revolution/gx/GXTransform.c": "Matching", + "sdk/RVL_SDK/revolution/os/OSCrc.c": "NonMatching", + "sdk/RVL_SDK/revolution/os/OSSemaphore.c": "Matching", + + "sdk/RVL_SDK/revolution/sc/scsystem.c": "NonMatching", + + "sdk/RVL_SDK/revolution/wpad/WPAD.c": "NonMatching", + "sdk/RVL_SDK/revolution/wpad/WPADHIDParser.c": "NonMatching", + "sdk/RVL_SDK/revolution/wpad/WPADEncrypt.c": "NonMatching", + "sdk/RVL_SDK/revolution/wpad/WPADMem.c": "NonMatching", + "sdk/RVL_SDK/revolution/wpad/lint.c": "NonMatching", + "sdk/RVL_SDK/revolution/wpad/WUD.c": "NonMatching", + "sdk/RVL_SDK/revolution/wpad/WUDHidHost.c": "NonMatching", + "sdk/RVL_SDK/revolution/wpadDrm/WPADDrm.c": "Matching", "sdk/RVL_SDK/revolution/wpadGtr/WPADGtr.c": "Matching" } @@ -822,7 +842,7 @@ "sdk/RevoEX/so/SOCommon.c": "NonMatching", "sdk/RevoEX/so/SOBasic.c": "NonMatching", - "sdk/RevoEX/ssl/ssl_mutex.c": "NonMatching" + "sdk/RevoEX/ssl/ssl_mutex.c": {"status": "Matching", "extra_cflags": ["-func_align 4"]} } }, "sdk/DWC": { diff --git a/src/band3/bandtrack/TrackConfig.cpp b/src/band3/bandtrack/TrackConfig.cpp index 949e46d1..ee9656f9 100644 --- a/src/band3/bandtrack/TrackConfig.cpp +++ b/src/band3/bandtrack/TrackConfig.cpp @@ -5,7 +5,7 @@ #include "decomp.h" TrackConfig::TrackConfig(BandUser* bu) : mUser(bu), unk_0x4(true), mTrackNum(0), mMaxSlots(0), unk_0x10(0), - unk_0x14(gNullStr), mLefty(false), mCymbalLanes(0), mDisableHopos(0) {} + unk_0x14(), mLefty(false), mCymbalLanes(0), mDisableHopos(0) {} const BandUser* TrackConfig::GetBandUser() const { return mUser; } @@ -44,10 +44,15 @@ bool TrackConfig::IsRealGuitarTrack() const { const char* TrackConfig::GetSlotColor(int slot) const { MILO_ASSERT(slot >= 0 && slot <= GetMaxSlots(), 156); - DataArray* syscfg = SystemConfig("track_graphics", "slot_colors", TrackTypeToSym(mUser->GetTrackType())); + Symbol s = TrackTypeToSym(mUser->GetTrackType()); + DataArray* syscfg = SystemConfig("track_graphics", "slot_colors", s); int i = slot; +#ifdef MILO_DEBUG bool b = (mUser->GetTrackType() == kTrackDrum); if (b && mLefty && i != 0) i = mMaxSlots - i; +#else + if (IsDrumTrack() && UseLeftyGems() && i != 0) i = mMaxSlots - i; +#endif return syscfg->Str(i + 1); } @@ -56,7 +61,12 @@ void TrackConfig::SetLefty(bool b) { mLefty = b; } void TrackConfig::SetGameCymbalLanes(uint ui) { mCymbalLanes = ui; } void TrackConfig::SetDisableHopos(bool b) { mDisableHopos = b; } void TrackConfig::SetTrackNum(int i) { mTrackNum = i; } - +#ifdef MILO_DEBUG DECOMP_FORCEACTIVE(TrackConfig, "slot >= 0 && slot <= mMaxSlots\0\0R\0L\0numSlots <= mMaxSlots\0left\0right" ) +#else +DECOMP_FORCEACTIVE(TrackConfig, + "\0R\0L\0left\0right" +) +#endif diff --git a/src/band3/bandtrack/TrackConfig.h b/src/band3/bandtrack/TrackConfig.h index dfd86f85..8ca96e75 100644 --- a/src/band3/bandtrack/TrackConfig.h +++ b/src/band3/bandtrack/TrackConfig.h @@ -12,7 +12,7 @@ class TrackConfig { int mTrackNum; int TrackNum() const; void SetTrackNum(int); // 0x8 int mMaxSlots; int GetMaxSlots() const; void SetMaxSlots(int); // 0xC int unk_0x10; // 0x10 - const char* unk_0x14; // 0x14 + Symbol unk_0x14; // 0x14 bool mLefty; bool IsLefty() const; bool UseLeftyGems() const; void SetLefty(bool); // 0x18 uint mCymbalLanes; uint GetGameCymbalLanes() const; void SetGameCymbalLanes(uint); // 0x1c bool mDisableHopos; bool GetDisableHopos() const; void SetDisableHopos(bool); // 0x20 diff --git a/src/network/Platform/BadEvents.cpp b/src/network/Platform/BadEvents.cpp new file mode 100644 index 00000000..b60c29f0 --- /dev/null +++ b/src/network/Platform/BadEvents.cpp @@ -0,0 +1,10 @@ +#include "BadEvents.h" + +namespace Quazal { + int* BadEvents::s_pInstance; + void BadEvents::Signal(BadEvents::_ID id) { + if (s_pInstance) { + s_pInstance[id]++; + } + } +} \ No newline at end of file diff --git a/src/network/Platform/BadEvents.h b/src/network/Platform/BadEvents.h new file mode 100644 index 00000000..ade63089 --- /dev/null +++ b/src/network/Platform/BadEvents.h @@ -0,0 +1,11 @@ +#pragma once +namespace Quazal { + class BadEvents { + enum _ID { + + }; + + static void Signal(_ID); + static int* s_pInstance; + }; +} \ No newline at end of file diff --git a/src/network/Platform/CIDLogFilter.cpp b/src/network/Platform/CIDLogFilter.cpp new file mode 100644 index 00000000..a49864be --- /dev/null +++ b/src/network/Platform/CIDLogFilter.cpp @@ -0,0 +1,5 @@ +#include "Platform/OutputFormat.h" +#include "Platform/RefCountedObject.h" +#include + +DECOMP_FORCEBLOCK(CIDLogFilter, (void), {Quazal::OutputFormat* r = dynamic_cast(new Quazal::RefCountedObject);}) \ No newline at end of file diff --git a/src/network/Platform/DateTime.cpp b/src/network/Platform/DateTime.cpp index c4a3e9c8..33bbd6b5 100644 --- a/src/network/Platform/DateTime.cpp +++ b/src/network/Platform/DateTime.cpp @@ -1,7 +1,7 @@ #include "Platform/DateTime.h" namespace Quazal { - DateTime DateTime::Never; + DateTime* DateTime::Never; DateTime::DateTime() : m_ui64Value(0) { @@ -24,7 +24,7 @@ namespace Quazal { } unsigned int DateTime::GetYear() const { - return (m_ui64Value) >> 26; // years: bits 26-63 + return (m_ui64Value & 0xFFFC000000) >> 26; // years: bits 26-39 } unsigned int DateTime::GetMonth() const { @@ -46,4 +46,8 @@ namespace Quazal { unsigned int DateTime::GetSecond() const { return m_ui64Value & 0x3F; // seconds: bits 0-5 } + + void DateTime::GetSystemTime(DateTime&) { + + } } diff --git a/src/network/Platform/DateTime.h b/src/network/Platform/DateTime.h index e379493f..aaee0c93 100644 --- a/src/network/Platform/DateTime.h +++ b/src/network/Platform/DateTime.h @@ -1,6 +1,5 @@ #ifndef PLATFORM_DATETIME_H #define PLATFORM_DATETIME_H -// #include "Platform/RootObject.h" namespace Quazal { class DateTime { @@ -18,7 +17,8 @@ namespace Quazal { unsigned int GetMinute() const; unsigned int GetSecond() const; - static DateTime Never; + static DateTime* Never; + static void GetSystemTime(Quazal::DateTime&); unsigned long long m_ui64Value; }; diff --git a/src/network/Platform/Log.cpp b/src/network/Platform/Log.cpp new file mode 100644 index 00000000..1c63bdc2 --- /dev/null +++ b/src/network/Platform/Log.cpp @@ -0,0 +1,50 @@ +#include "Log.h" +#include "Platform/LogDeviceDebugOutput.h" +#include "Platform/OutputFormat.h" +#include +#include + +namespace Quazal { + Log::Log() : m_oLogDevice(new (__FILE__, 34) LogDeviceDebugOutput), m_oOutputFormat(new (__FILE__, 38) OutputFormat), unk_0xC(NULL) {} + // i'm pretty sure those are asserts... + + Log::~Log() { + delete m_oOutputFormat; + if (m_oLogDevice) delete m_oLogDevice; + // delete 0xC + } + + void Log::Output(const char* cc, ...) { + va_list list; + va_start(list, cc); + OutputImpl(cc, list, NULL); + } + + void Log::OutputString(const char* cc, ...) { + va_list list; + va_start(list, cc); + OutputImpl(cc, list, NULL); + } + + void Log::OutputImpl(const char* cc, va_list l, void* v) { + char buf[0x1000]; + if (m_oLogDevice == NULL) return; + // 0xC validity check + if (m_oOutputFormat == NULL) return; + + memset(buf, 0, 0x1000); + m_oOutputFormat->StartString(buf, 4094); + m_oOutputFormat->StartPrefixes(buf, 4094); + AddCustomPrefix(buf, 4094, v); + m_oOutputFormat->AddPrefixes(buf, 4094); + m_oOutputFormat->EndPrefixes(buf, 4094); + m_oOutputFormat->AddIndent(buf, 4094); + m_oOutputFormat->AddMessage(buf, 4094, cc, l); + m_oOutputFormat->EndString(buf, 4094); + m_oLogDevice->Output(buf); + } + + void Log::AddCustomPrefix(char*, int, void*) { } + + OutputFormat* Log::GetOutputFormat() { return m_oOutputFormat; } +} diff --git a/src/network/Platform/Log.h b/src/network/Platform/Log.h new file mode 100644 index 00000000..e5d59f5f --- /dev/null +++ b/src/network/Platform/Log.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Platform/OutputFormat.h" +#include "Platform/RootObject.h" +#include "Platform/String.h" +#include +#include + +namespace Quazal { + class LogEntry : public Quazal::String { public: + LogEntry(const char* s) : String(s) {} + }; + + class LogDevice : public RootObject { + public: + virtual ~LogDevice() {} + virtual void Output(const LogEntry&) = 0; + }; + + class Log : public RootObject { + public: + Log(); + virtual ~Log(); + virtual void Output(const char*, ...); + virtual void OutputString(const char*, ...); + virtual void AddCustomPrefix(char*, int, void*); + void OutputImpl(const char*, va_list, void*); + OutputFormat* GetOutputFormat(); + + LogDevice* m_oLogDevice; // 0x4 + OutputFormat* m_oOutputFormat; // 0x8 + void* unk_0xC; // this guy has a virtual dtor and its 2nd virtual function is nonvoid and that's all the context i get + }; +} \ No newline at end of file diff --git a/src/network/Platform/LogDeviceDebugOutput.cpp b/src/network/Platform/LogDeviceDebugOutput.cpp new file mode 100644 index 00000000..0cfddd5e --- /dev/null +++ b/src/network/Platform/LogDeviceDebugOutput.cpp @@ -0,0 +1,8 @@ +#include "LogDeviceDebugOutput.h" +#include + +namespace Quazal { + void LogDeviceDebugOutput::Output(const LogEntry& le) { + printf("%s\n", le.m_szContent); + } +} \ No newline at end of file diff --git a/src/network/Platform/LogDeviceDebugOutput.h b/src/network/Platform/LogDeviceDebugOutput.h new file mode 100644 index 00000000..c7813004 --- /dev/null +++ b/src/network/Platform/LogDeviceDebugOutput.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Platform/Log.h" + +namespace Quazal { + class LogDeviceDebugOutput : public LogDevice { + public: + LogDeviceDebugOutput() { } + virtual ~LogDeviceDebugOutput() { } + virtual void Output(const LogEntry&); + }; +} diff --git a/src/network/Platform/OutputFormat.h b/src/network/Platform/OutputFormat.h index 7ae0e4ac..7b457a1e 100644 --- a/src/network/Platform/OutputFormat.h +++ b/src/network/Platform/OutputFormat.h @@ -1,6 +1,7 @@ #ifndef PLATFORM_OUTPUTFORMAT_H #define PLATFORM_OUTPUTFORMAT_H #include "Platform/RootObject.h" +#include namespace Quazal { class OutputFormat : public RootObject { @@ -12,7 +13,7 @@ namespace Quazal { virtual void AddPrefixes(char*, unsigned int); virtual void EndPrefixes(char*, unsigned int); virtual void AddIndent(char*, unsigned int); - virtual int AddMessage(char*, unsigned int, const char*, ...); // that last input param should be a __va_list_struct* + virtual int AddMessage(char*, unsigned int, const char*, va_list); virtual void EndString(char*, unsigned int); unsigned int m_uiIndent; diff --git a/src/network/Platform/SmoothedAverage.h b/src/network/Platform/SmoothedAverage.h new file mode 100644 index 00000000..4a97d09c --- /dev/null +++ b/src/network/Platform/SmoothedAverage.h @@ -0,0 +1,14 @@ +#pragma once + +#include "network/Platform/RootObject.h" + +namespace Quazal { + template + class SmoothedAverage : public RootObject { + public: + SmoothedAverage(T t) : m_dAverage(0), m_dWeight(0), m_dTotalWeightOfEntries(0) { m_dWeight = t; } + T m_dAverage; // 0x0 + T m_dWeight; // 0x4 + T m_dTotalWeightOfEntries; // 0x8 + }; +} \ No newline at end of file diff --git a/src/network/Plugins/RTT.cpp b/src/network/Plugins/RTT.cpp new file mode 100644 index 00000000..3c7f743b --- /dev/null +++ b/src/network/Plugins/RTT.cpp @@ -0,0 +1,13 @@ +#include "RTT.h" + +namespace Quazal { + RTT::RTT(uint i) : unk_0x0(i * 8), unk_0x4(0), unk_0x8(i) {} + + RTT::~RTT() {} + + void RTT::Adjust(uint i) { + int r8 = i - unk_0x0/8; + unk_0x8 = i; + unk_0x0 += r8; + } +} \ No newline at end of file diff --git a/src/network/Plugins/RTT.h b/src/network/Plugins/RTT.h new file mode 100644 index 00000000..f417f84a --- /dev/null +++ b/src/network/Plugins/RTT.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Platform/RootObject.h" +#include "types.h" + +namespace Quazal { + class RTT : RootObject { + RTT(uint); + ~RTT(); + void Adjust(uint); + + uint unk_0x0; + uint unk_0x4; + uint unk_0x8; + }; +} \ No newline at end of file diff --git a/src/network/Utility/Statistics.cpp b/src/network/Utility/Statistics.cpp new file mode 100644 index 00000000..89a8c008 --- /dev/null +++ b/src/network/Utility/Statistics.cpp @@ -0,0 +1,17 @@ +#include "Statistics.h" + +namespace Quazal { + Statistics::Statistics() : m_oSmoothedAverage(0.1) { + m_uiNbEntries = 0; + + m_dTotal = 0; + m_dMaximumValue = 0; + m_dMinimumValue = 0; + + // fake it 'til you make it + m_oSmoothedAverage.m_dAverage = 0; + m_oSmoothedAverage.m_dTotalWeightOfEntries = 0; + } + + Statistics::~Statistics() {} +} diff --git a/src/network/Utility/Statistics.h b/src/network/Utility/Statistics.h new file mode 100644 index 00000000..beddf41a --- /dev/null +++ b/src/network/Utility/Statistics.h @@ -0,0 +1,18 @@ +#pragma once +#include "Platform/RootObject.h" +#include "Platform/SmoothedAverage.h" +#include "types.h" + +namespace Quazal { + class Statistics : public RootObject { + public: + Statistics(); + ~Statistics(); + + u32 m_uiNbEntries; // 0x0 + float m_dTotal; // 0x4 + float m_dMaximumValue; // 0x8 + float m_dMinimumValue; // 0xC + SmoothedAverage m_oSmoothedAverage; // 0x10 + }; +} diff --git a/src/sdk/PowerPC_EABI_Support/MetroTRK/custconn/MWCriticalSection_gc.c b/src/sdk/PowerPC_EABI_Support/MetroTRK/custconn/MWCriticalSection_gc.c new file mode 100644 index 00000000..96a79155 --- /dev/null +++ b/src/sdk/PowerPC_EABI_Support/MetroTRK/custconn/MWCriticalSection_gc.c @@ -0,0 +1,8 @@ +#include "revolution/os/OSInterrupt.h" +#include "types.h" + +void MWInitializeCriticalSection(BOOL* critsect) {} + +void MWEnterCriticalSection(BOOL* critsect) { *critsect = OSDisableInterrupts(); } + +void MWExitCriticalSection(BOOL* critsect) { OSRestoreInterrupts(*critsect); } diff --git a/src/sdk/RVL_SDK/revolution/WPAD.h b/src/sdk/RVL_SDK/revolution/WPAD.h index 8471c6c9..82960ed9 100644 --- a/src/sdk/RVL_SDK/revolution/WPAD.h +++ b/src/sdk/RVL_SDK/revolution/WPAD.h @@ -1,12 +1,14 @@ -#ifndef RVL_SDK_PUBLIC_WPAD_H -#define RVL_SDK_PUBLIC_WPAD_H -#ifdef __cplusplus -extern "C" { -#endif - -#include "revolution/wpad/debug_msg.h" - -#ifdef __cplusplus -} -#endif -#endif +#ifndef RVL_SDK_LIB_WPAD_H +#define RVL_SDK_LIB_WPAD_H + +/******************************************************************************* + * headers + */ + +#include +#include + +// i don't think this was public? so commented out +// #include + +#endif // RVL_SDK_LIB_WPAD_H diff --git a/src/sdk/RVL_SDK/revolution/os/OSCrc.c b/src/sdk/RVL_SDK/revolution/os/OSCrc.c new file mode 100644 index 00000000..17a9694e --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/os/OSCrc.c @@ -0,0 +1,17 @@ +#include "OSCrc.h" + +u32 OSCalcCRC32(const void* buf, u32 length) { + static u32 crc32_table[16] = { + 0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, + 0x76DC4190, 0x6B6B51F4, 0x4DB26158, 0x5005713C, + 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C, + 0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C + }; + unsigned int crc = -1; + u8* buf2 = (void*)buf; + while (length--) { + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf2) & 255]; + buf2++; + } + return ~crc; +} diff --git a/src/sdk/RVL_SDK/revolution/os/OSCrc.h b/src/sdk/RVL_SDK/revolution/os/OSCrc.h index 24f79312..24758be9 100644 --- a/src/sdk/RVL_SDK/revolution/os/OSCrc.h +++ b/src/sdk/RVL_SDK/revolution/os/OSCrc.h @@ -6,6 +6,7 @@ extern "C" { #endif u16 OSCalcCRC16(const u8* array, s32 length); +u32 OSCalcCRC32(const void* array, u32 length); #ifdef __cplusplus } diff --git a/src/sdk/RVL_SDK/revolution/os/OSReset.h b/src/sdk/RVL_SDK/revolution/os/OSReset.h index 11e1c2d8..d3d60b27 100644 --- a/src/sdk/RVL_SDK/revolution/os/OSReset.h +++ b/src/sdk/RVL_SDK/revolution/os/OSReset.h @@ -10,7 +10,10 @@ typedef BOOL (*OSShutdownFunction)(u32 pass, u32 event); typedef enum { OS_SD_PASS_FIRST, OS_SD_PASS_SECOND } OSShutdownPass; typedef enum { + OS_SD_EVENT_FATAL = 0, + OS_SD_EVENT_1 = 1, OS_SD_EVENT_SHUTDOWN = 2, + OS_SD_EVENT_3 = 3, OS_SD_EVENT_RESTART = 4, OS_SD_EVENT_RETURN_TO_MENU = 5, OS_SD_EVENT_LAUNCH_APP = 6, @@ -28,6 +31,8 @@ typedef struct OSShutdownFunctionQueue { OSShutdownFunctionInfo* tail; // at 0x4 } OSShutdownFunctionQueue; +extern BOOL __OSIsReturnToIdle; + void OSRegisterShutdownFunction(OSShutdownFunctionInfo* info); BOOL __OSCallShutdownFunctions(u32 pass, u32 event); void __OSShutdownDevices(u32 event); diff --git a/src/sdk/RVL_SDK/revolution/os/OSSemaphore.c b/src/sdk/RVL_SDK/revolution/os/OSSemaphore.c new file mode 100644 index 00000000..a4f4024a --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/os/OSSemaphore.c @@ -0,0 +1,30 @@ +#include "OSSemaphore.h" +#include "revolution/os/OSInterrupt.h" +#include "revolution/os/OSThread.h" + +void OSInitSemaphore(OSSemaphore *sema, s32 active_signals) { + BOOL status = OSDisableInterrupts(); + OSInitThreadQueue(&sema->threadQueue); + sema->activeSignals = active_signals; + OSRestoreInterrupts(status); +} + +s32 OSWaitSemaphore(OSSemaphore* sema) { + BOOL status = OSDisableInterrupts(); + s32 ret; + while ((ret = sema->activeSignals) <= 0) { + OSSleepThread(&sema->threadQueue); + } + sema->activeSignals--; + OSRestoreInterrupts(status); + return ret; +} + +s32 OSSignalSemaphore(OSSemaphore* sema) { + BOOL status = OSDisableInterrupts(); + s32 ret; + ret = sema->activeSignals++; + OSWakeupThread(&sema->threadQueue); + OSRestoreInterrupts(status); + return ret; +} diff --git a/src/sdk/RVL_SDK/revolution/os/OSSemaphore.h b/src/sdk/RVL_SDK/revolution/os/OSSemaphore.h new file mode 100644 index 00000000..3e85e4fa --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/os/OSSemaphore.h @@ -0,0 +1,16 @@ +#ifndef RVL_SDK_OS_SEMAPHORE_H +#define RVL_SDK_OS_SEMAPHORE_H + +#include "revolution/os/OSThread.h" +#include "types.h" + +typedef struct OSSemaphore { + vs32 activeSignals; /* 0x0 */ + OSThreadQueue threadQueue; /* 0x4 */ +} OSSemaphore; + +void OSInitSemaphore(OSSemaphore* sema, s32 active_signals); +s32 OSWaitSemaphore(OSSemaphore* sema); +s32 OSSignalSemaphore(OSSemaphore* sema); + +#endif // RVL_SDK_OS_SEMAPHORE_H \ No newline at end of file diff --git a/src/sdk/RVL_SDK/revolution/os/OSTime.h b/src/sdk/RVL_SDK/revolution/os/OSTime.h index 2710fdbe..c40ff0be 100644 --- a/src/sdk/RVL_SDK/revolution/os/OSTime.h +++ b/src/sdk/RVL_SDK/revolution/os/OSTime.h @@ -6,6 +6,8 @@ extern "C" { #endif +typedef s64 OSTime; + // Time base frequency = 1/4 bus clock #define OS_TIME_SPEED (OS_BUS_CLOCK_SPEED / 4) diff --git a/src/sdk/RVL_SDK/revolution/sc/scsystem.c b/src/sdk/RVL_SDK/revolution/sc/scsystem.c new file mode 100644 index 00000000..e22e79ff --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/sc/scsystem.c @@ -0,0 +1,41 @@ +#include "scsystem.h" +#include "revolution/OS.h" +#include "revolution/NAND.h" +#include "revolution/os/OSInterrupt.h" +#include "types.h" + +static OSMutex Control; +static u8 ConfBuf[0x4000]; +static u8 ConfBufForFlush[0x4000]; + +static u8 BgJobStatus = FALSE; +static u8 IsDevKit = FALSE; +static u8 Initialized = FALSE; +const char* __SCVersion = "<< RVL_SDK - SC \trelease build: Dec 11 2009 15:59:09 (0x4302_145) >>"; + +BOOL SCReloadConfFileAsync(u8*, int, int); + +void SCInit(void) { + BOOL s = OSDisableInterrupts(); + if (Initialized) { + OSRestoreInterrupts(s); + return; + } + Initialized = TRUE; + BgJobStatus = TRUE; + OSRestoreInterrupts(s); + OSRegisterVersion(__SCVersion); + OSInitThreadQueue(&Control.queue); + if (OSGetConsoleType() & OS_CONSOLE_MASK_EMU) IsDevKit = TRUE; + if (NANDInit() || SCReloadConfFileAsync(ConfBuf, 0x4000, 0)) BgJobStatus = 2; +} + +u32 SCCheckStatus(void) { + BOOL status = OSDisableInterrupts(); + if (BgJobStatus == 3) { + BgJobStatus = 1; + OSRestoreInterrupts(status); + } else { + OSRestoreInterrupts(status); + } +} diff --git a/src/sdk/RVL_SDK/revolution/sc/scsystem.h b/src/sdk/RVL_SDK/revolution/sc/scsystem.h index 6e3c157c..da41e247 100644 --- a/src/sdk/RVL_SDK/revolution/sc/scsystem.h +++ b/src/sdk/RVL_SDK/revolution/sc/scsystem.h @@ -56,7 +56,7 @@ typedef enum { SC_ITEM_DEV_CTC, SC_ITEM_DEV_DSM, SC_ITEM_BT_DINF, - SC_ITEM_BT_CINF, //unconfirmed name + SC_ITEM_BT_CDIF, SC_ITEM_BT_SENS, SC_ITEM_BT_SPKV, SC_ITEM_BT_MOT, diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPAD.c b/src/sdk/RVL_SDK/revolution/wpad/WPAD.c new file mode 100644 index 00000000..6ac017ef --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPAD.c @@ -0,0 +1,4261 @@ +#include + +/******************************************************************************* + * headers + */ + +#include + +#include + +#include "lint.h" +#include "WPADHIDParser.h" +#include "WPADMem.h" +#include "WPADMem2.h" +#include "WUD.h" +#include "WPAD2.h" + +#include +#include +#include +#include +#include + +#include "context_bte.h" + +/******************************************************************************* + * macros + */ + +#define RVL_SDK_WPAD_VERSION_STRING \ + "<< RVL_SDK - WPAD \trelease build: Dec 11 2009 15:59:48 (0x4302_) >>" + +/******************************************************************************* + * local function declarations + */ + +static void *__wpadNoAlloc(size_t size); +static int __wpadNoFree(void *ptr); + +static BOOL OnShutdown(OSShutdownPass pass, OSShutdownEvent event); +static WPADResult __wpadSendDataSub(WPADChannel chan, struct WPADCmd cmdBlk); +static WPADResult __wpadSendData(WPADChannel chan, struct WPADCmd cmdBlk); +static void __wpadCalcRadioQuality(WPADChannel chan); +static u32 __wpadFmt2Size(WPADDataFormat fmt); +static u8 __wpadIsButtonChanged(WPADButton lhs, WPADButton rhs); +static u8 __wpadIsAnalogChanged(s32 lhs, s32 rhs, s32 minDiff); +static BOOL __wpadCalcAnalogNoise(wpad_cb_st *p_wpd, WPADNZFilter filter_type, + BOOL analogChanged); +static BOOL __wpadIsControllerDataChanged(wpad_cb_st *p_wpd, void *lhs, + void *rhs); +static void __wpadCalcRecalibration(WPADChannel chan, void *status); +static void __wpadCalcControllerData(WPADChannel chan); +static BOOL __wpadProcExtCommand(WPADChannel chan, BOOL previousSuccess); +static void __wpadRumbleMotor(WPADChannel chan, BOOL procSuccess); +static BOOL __wpadProcCommand(WPADChannel chan, BOOL previousSuccess); +static void __wpadCalcSystemSettings(void); +static void __wpadCalcAfh(void); +static BOOL __wpadCalcReconnectWait(void); +static void __wpadManageHandler(OSAlarm *alarm, OSContext *context); +static void __wpadManageHandler0(OSAlarm *alarm, OSContext *context); +static void __wpadClearControlBlock(WPADChannel chan); +static void __wpadInitSub(void); + +static void __wpadShutdown(BOOL saveSimpleDevs); +static void __wpadCleanup(void); +static void __wpadResetModule(BOOL saveSimpleDevs); +static void __wpadReconnectStart(BOOL saveSimpleDevs); + +static void __wpadSetupConnectionCallback(WPADChannel chan, WPADResult result); +static void __wpadAbortConnectionCallback(WPADChannel chan, WPADResult result); +static void __wpadInitConnectionCallback(WPADChannel chan, WPADResult result); +static WPADChannel __wpadRetrieveChannel(WUDDevInfo *devInfo); +static void __wpadConnectionCallback(WUDDevInfo *devInfo, u8 success); +static void __wpadReceiveCallback(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len); +static WPADResult __wpadGetConnectionStatus(WPADChannel chan); +static void __wpadDisconnectCallback(WPADChannel chan, WPADResult result); +static inline void __wpadDisconnect(WPADChannel chan, BOOL afkDisconnect); + +static void __wpadInfoCallback(WPADChannel chan, WPADResult result); + +static void __wpadDpdCallback(WPADChannel chan, WPADResult result); + +static void __wpadMplsCallback(WPADChannel chan, WPADResult result); + +static s8 __wpadGetQueueSize(struct WPADCmdQueue *cmdQueue); + +static BOOL __wpadPushCommand(struct WPADCmdQueue *cmdQueue, + struct WPADCmd cmdBlk); +static BOOL __wpadGetCommand(struct WPADCmdQueue *cmdQueue, + struct WPADCmd *cmdBlkOut); +static BOOL __wpadPopCommand(struct WPADCmdQueue *cmdQueue); +static BOOL __wpadSetSensorBarPower(BOOL enabled); +static void __wpadSetScreenSaverFlag(BOOL disabled); +static u8 __wpadGetDpdSensitivity(void); +static u8 __wpadGetSensorBarPosition(void); +static u32 __wpadGetMotorMode(void); +static u8 __wpadClampSpeakerVolume(u8 volume); +static u8 __wpadGetSpeakerVolume(void); +static u16 __wpadGetBTEBufferStatus(WPADChannel chan); +static u16 __wpadGetBTMBufferStatus(WPADChannel chan); + +static void __wpadCertFailed(WPADChannel chan); +static void __wpadCertCalcMulX(WPADChannel chan); +static void __wpadCertCalcModX(WPADChannel chan); +static void __wpadCertCalcMulY(WPADChannel chan); +static void __wpadCertCalcModY(WPADChannel chan); +static void __wpadCertChallengeCallback(WPADChannel chan, WPADResult result); +static void __wpadCertChallenge(WPADChannel chan); +static void __wpadCertProbeReadyCallback(WPADChannel chan, WPADResult result); +static void __wpadCertProbeReady(WPADChannel chan); +static void __wpadCertGetParamCallback(WPADChannel chan, WPADResult result); +static u8 __wpadCertGetParam(WPADChannel chan, ULONG *certParamOut); +static void __wpadCertGetParamX(WPADChannel chan); +static void __wpadCertVerifyParamX(WPADChannel chan); +static inline void __wpadCertGetParamY(WPADChannel chan); +static void __wpadCertVerifyParamY(WPADChannel chan); +static void __wpadCertWork(WPADChannel chan); + +/******************************************************************************* + * variables + */ + +// .rodata + +// clang-format off +static const ULONG certn[] = +{ + 16, + + 0xa3dc5f11, 0x1b2ec797, + 0xac9657b8, 0xcbeb788d, + 0x991ef8b8, 0x70caa54e, + 0x071ce896, 0x63252cd0, + 0xfd8b6316, 0x9e835020, + 0xbf9ed1ef, 0x0f870932, + 0xbc88b819, 0xaf2c02e5, + 0x657bbfb9, 0x81194f1c, + + 0 +}; + +static const ULONG certv[] = +{ + 16, + + 0x99d2071a, 0x8d823a01, + 0x4c50a978, 0xd8a5bfff, + 0x4caf5ce8, 0x13a71cba, + 0x6fcff21b, 0x8c5399bf, + 0x8896982d, 0xcb6ec891, + 0x6ba136da, 0x25b8f224, + 0x8f0f42c0, 0x15ea9941, + 0xfdd1903e, 0x1af308b6, + + 0 +}; +// clang-format on + +// .data, .sdata +const char *__WPADVersion = RVL_SDK_WPAD_VERSION_STRING; +static OSShutdownFunctionInfo ShutdownFunctionInfo; + +// .bss +static OSAlarm _wpadManageAlarm; +wpad_cb_st __rvl_wpadcb[WPAD_MAX_CONTROLLERS] __attribute__((aligned(0x20))); +static WUDDevHandle _wpadHandle2PortTable[WUD_MAX_DEV_ENTRY]; +static byte_t __wpadManageHandlerStack[0x1000] __attribute__((aligned(0x20))); +wpad_cb_st *__rvl_p_wpadcb[WPAD_MAX_CONTROLLERS]; + +// .sdata +static s32 _wpadOnReconnect = -1; +static u16 _wpad_diff_count_threshold[WPAD_MAX_NZFILTERS] = {6, 4, 6, 12}; +static u16 _wpad_hyst_count_threshold[WPAD_MAX_NZFILTERS] = {30, 30, 30, 30}; + +// .sbss +static OSAppType _wpadGameType; +static const char *_wpadGameCode; + +#if !defined(NDEBUG) +static u8 _wpadDummyAttach[WPAD_MAX_CONTROLLERS]; +#endif // !defined(NDEBUG) + +static u8 _wpadSleepTime; +static u8 _wpadDpdSense; +static u8 _wpadSensorBarPos; +static BOOL _wpadRumbleFlag; +static u8 _wpadSpeakerVol; +static u8 _wpadSCSetting; +static u8 _wpadShutdownFlag; +static s8 _wpadAfhChannel; +static u8 _wpadIsUsedChannel[WPAD_MAX_CONTROLLERS]; +static BOOL _wpadInitialized; +static BOOL _wpadUsedCallback; +__attribute__((weak)) BOOL _enabledBLK; +__attribute__((weak)) BOOL _enabledTBL; +__attribute__((weak)) BOOL _enabledTKO; +__attribute__((weak)) BOOL _enabledDRM; +__attribute__((weak)) BOOL _enabledGTR; +__attribute__((weak)) BOOL _enabledTRN; +__attribute__((weak)) BOOL _enabledVSM; +__attribute__((weak)) WPADInitFunc *_wpadBLKInit; +__attribute__((weak)) WPADInitFunc *_wpadTBLInit; +__attribute__((weak)) WPADInitFunc *_wpadTKOInit; +__attribute__((weak)) WPADInitFunc *_wpadDRMInit; +__attribute__((weak)) WPADInitFunc *_wpadGTRInit; +__attribute__((weak)) WPADInitFunc *_wpadTRNInit; +__attribute__((weak)) WPADInitFunc *_wpadVSMInit; +static s32 _wpadReconnectWait; +static BOOL _wpadStartup; +static u8 _wpadRumbleCnt[WPAD_MAX_CONTROLLERS]; +static u8 _wpadExtCnt[WPAD_MAX_CONTROLLERS]; +static u16 _wpadAfhCnt; +static u8 _wpadCheckCnt; +static u16 _wpadSenseCnt; +static u8 _wpadRegisterShutdownFunc; + +/******************************************************************************* + * functions + */ + +static void *__wpadNoAlloc(size_t size __attribute__((unused))) +{ + return NULL; +} + +static int __wpadNoFree(void *ptr __attribute__((unused))) +{ + return 0; +} + +BOOL WPADIsEnabledVSM(void) +{ + return _enabledVSM; +} + +BOOL WPADIsEnabledTRN(void) +{ + return _enabledTRN; +} + +BOOL WPADIsEnabledGTR(void) +{ + return _enabledGTR; +} + +BOOL WPADIsEnabledDRM(void) +{ + return _enabledDRM; +} + +BOOL WPADIsEnabledTKO(void) +{ + return _enabledTKO; +} + +BOOL WPADIsEnabledTBL(void) +{ + return _enabledTBL; +} + +BOOL WPADIsEnabledBLK(void) +{ + return _enabledBLK; +} + +__attribute__((weak)) WPADResult WBCSetupCalibration(void) +{ + return WPAD_ESUCCESS; +} + +__attribute__((weak)) signed WBCGetCalibrationStatus(void) +{ + return 0; +} + +__attribute__((weak)) signed WBCGetBatteryLevel(u8 param_1 + __attribute__((unused))) +{ + return 0; +} + +// perhaps param_3 is ARRAY_LENGTH of param_2? who knows +__attribute__((weak)) WPADResult WBCRead(WPADBLStatus *param_1 + __attribute__((unused)), + f64 *param_2 __attribute__((unused)), + int param_3 __attribute__((unused))) +{ + return WPAD_ENODEV; +} + +__attribute__((weak)) WPADResult WBCSetZEROPoint(f64 *param_1 + __attribute__((unused)), + int param_2 + __attribute__((unused))) +{ + return WPAD_ENODEV; +} + +__attribute__((weak)) WPADResult WBCGetTGCWeight( + f64 param_1 __attribute__((unused)), f64 *param_2 __attribute__((unused)), + WPADBLStatus *param_3 __attribute__((unused))) +{ + return WPAD_ENODEV; +} + +static BOOL OnShutdown(OSShutdownPass pass, OSShutdownEvent event) +{ + WUDLibStatus wudLibStatus = WUDGetStatus(); + + if (pass != OS_SD_PASS_FIRST || wudLibStatus == WUD_LIB_STATUS_0) + return TRUE; + + if (wudLibStatus == WUD_LIB_STATUS_4 || wudLibStatus == WUD_LIB_STATUS_1 + || wudLibStatus == WUD_LIB_STATUS_2) + { + return FALSE; + } + + if (WUDIsBusy()) + { + WPADCancelSyncDevice(); + return FALSE; + } + + BOOL isCleanup; + + switch (event) + { + case OS_SD_EVENT_FATAL: + WPADRegisterAllocator(&__wpadNoAlloc, &__wpadNoFree); + + // fallthrough + + case OS_SD_EVENT_SHUTDOWN: + case OS_SD_EVENT_3: + isCleanup = TRUE; + break; + + case OS_SD_EVENT_1: + case OS_SD_EVENT_RESTART: + case OS_SD_EVENT_LAUNCH_APP: + isCleanup = FALSE; + break; + + case OS_SD_EVENT_RETURN_TO_MENU: + isCleanup = __OSIsReturnToIdle ? 1 : 0; + break; + + default: + // ERRATA: isCleanup is uninitialized here on release builds + OSAssertMessage_Line(1082, FALSE, + "WPAD: OnShutDown(): Unknown event %d\n", event); + } + + if (isCleanup) + __wpadCleanup(); + else + __wpadReconnectStart(TRUE); + + return FALSE; +} + +// clang-format off +static OSShutdownFunctionInfo ShutdownFunctionInfo = +{ + &OnShutdown, + 127, + NULL, + NULL +}; +// clang-format on + +static WPADResult __wpadSendDataSub(WPADChannel chan, struct WPADCmd cmdBlk) +{ + BOOL intrStatus; + BOOL rumbleFlag; + WUDDevHandle devHandle; + wpad_cb_st *p_wpd; + UINT8 rep_id; + BT_HDR *p_buf; + byte_t *rptData; + WPADResult status; + byte_t *cmdData; + UINT16 len; + + p_buf = NULL; + p_wpd = __rvl_p_wpadcb[chan]; + + rep_id = cmdBlk.reportID; + cmdData = cmdBlk.dataBuf; + len = cmdBlk.dataLength; + + OSAssert_Line(1138, rep_id >= 0x10 && rep_id <= 0x1a); + + intrStatus = OSDisableInterrupts(); + + status = p_wpd->status; + + devHandle = p_wpd->devHandle; + if (devHandle < 0) + { + OSRestoreInterrupts(intrStatus); + return WPAD_EINVAL; + } + + p_wpd->status = WPAD_ECOMM; + rumbleFlag = p_wpd->motorRunning & _wpadRumbleFlag; // bitand is fine here + + if (rep_id == RPTID_SET_RUMBLE) + { + p_wpd->status = status; + } + else if (rep_id == RPTID_SEND_SPEAKER_DATA) + { + OSAssert_Line(1160, p_wpd->audioFrames > 0); + + p_wpd->status = status; + p_wpd->audioFrames--; + } + else + { + switch (rep_id) + { + case RPTID_WRITE_DATA: + break; + + case RPTID_READ_DATA: + p_wpd->wmReadHadError = 0; + p_wpd->wmReadAddress = cmdBlk.readAddress; + p_wpd->wmReadLength = cmdBlk.readLength; + p_wpd->wmReadDataPtr = cmdBlk.dstBuf; + break; + + case RPTID_REQUEST_STATUS: + p_wpd->status = status; + p_wpd->wpInfoOut = cmdBlk.statusReportOut; + p_wpd->statusReqBusy = TRUE; + break; + + default: + cmdData[0] |= (1 << RPT_OUT_FLAG_REQUEST_ACK_RPT); + break; + } + + p_wpd->cmdBlkCB = cmdBlk.cmdCB; + p_wpd->lastReportID = rep_id; + p_wpd->lastReportSendTime = __OSGetSystemTime() + OS_TIMER_CLOCK * 2; + p_wpd->unk_0xb08 = 0; + } + + OSRestoreInterrupts(intrStatus); + + p_buf = GKI_getbuf((u8)(len + 18)); + OSAssert_Line(1202, p_buf != NULL); + + p_buf->len = (u8)(len + 1); + p_buf->offset = 10; + + rptData = (byte_t *)(p_buf + 1) + p_buf->offset; + rptData[0] = rep_id; + memcpy(&rptData[1], cmdData, len); + + if (rumbleFlag) + rptData[RPT_OUT_FLAGS] |= (1 << RPT_OUT_FLAG_RUMBLE); + else + rptData[RPT_OUT_FLAGS] &= ~(1 << RPT_OUT_FLAG_RUMBLE); + + BTA_HhSendData((UINT8)devHandle, p_buf); + return WPAD_ESUCCESS; +} + +static WPADResult __wpadSendData(WPADChannel chan, struct WPADCmd cmdBlk) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + WPADResult connStatus = + p_wpd->statusReqBusy ? WPAD_ECOMM : __wpadGetConnectionStatus(chan); + + OSRestoreInterrupts(intrStatus); + + if (connStatus == WPAD_ESUCCESS) + { + connStatus = __wpadSendDataSub(chan, cmdBlk); + } + else if (connStatus == WPAD_ECOMM) + { + if ((__OSGetSystemTime() - p_wpd->lastReportSendTime) / OS_TIMER_CLOCK + > 1) + { + p_wpd->lastReportSendTime = __OSGetSystemTime(); + __wpadDisconnect(chan, FALSE); + } + } + + return connStatus; +} + +static void __wpadCalcRadioQuality(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + u32 two = 2; // some define? + + if (_wpadSenseCnt != 10) + return; + + u16 a = p_wpd->radioSensitivity * 9; + a += (u16)(p_wpd->copyOutCount * 100 / two); + a /= 10; + a = MIN(100, a); + + p_wpd->radioSensitivity = a; + p_wpd->copyOutCount = 0; + + if (p_wpd->radioQuality != WPAD_RADIO_QUALITY_GOOD) + { + if (a > 85) + { + p_wpd->radioQuality = WPAD_RADIO_QUALITY_GOOD; + p_wpd->radioQualityOkMs = 0; + } + else if (a > 80) + { + p_wpd->radioQualityOkMs++; + + if (p_wpd->radioQualityOkMs >= 20) + { + p_wpd->radioQuality = WPAD_RADIO_QUALITY_GOOD; + p_wpd->radioQualityOkMs = 0; + } + } + } + else + { + if (a < 75) + { + p_wpd->radioQuality = WPAD_RADIO_QUALITY_BAD; + p_wpd->radioQualityOkMs = 0; + } + else if (a < 80) + { + p_wpd->radioQualityOkMs++; + + if (p_wpd->radioQualityOkMs >= 1) + { + p_wpd->radioQuality = WPAD_RADIO_QUALITY_BAD; + p_wpd->radioQualityOkMs = 0; + } + } + } +} + +static u32 __wpadFmt2Size(WPADDataFormat fmt) +{ + u32 fmtSize; + + switch (fmt) + { + case WPAD_FMT_FS_BTN: + case WPAD_FMT_FS_BTN_ACC: + case WPAD_FMT_FS_BTN_ACC_DPD: + fmtSize = sizeof(WPADFSStatus); + break; + + case WPAD_FMT_CLASSIC_BTN: + case WPAD_FMT_CLASSIC_BTN_ACC: + case WPAD_FMT_CLASSIC_BTN_ACC_DPD: + + case WPAD_FMT_GUITAR: + case WPAD_FMT_DRUM: + case WPAD_FMT_TAIKO: + case WPAD_FMT_TURNTABLE: + fmtSize = sizeof(WPADCLStatus); + break; + + case WPAD_FMT_BULK: + fmtSize = sizeof(WPADBKStatus); + break; + + case WPAD_FMT_TRAIN: + fmtSize = sizeof(WPADTRStatus); + break; + + case WPAD_FMT_BALANCE_CHECKER: + fmtSize = sizeof(WPADBLStatus); + break; + + case WPAD_FMT_VSM: + fmtSize = sizeof(WPADVSStatus); + break; + + case WPAD_FMT_BTN_ACC_DPD_EXTENDED: + fmtSize = sizeof(WPADStatusEx); + break; + + case WPAD_FMT_MOTION_PLUS: + fmtSize = sizeof(WPADMPStatus); + break; + + default: + /* these are not explicit cases */ + // case WPAD_FMT_BTN: + // case WPAD_FMT_BTN_ACC: + // case WPAD_FMT_BTN_ACC_DPD: + fmtSize = sizeof(WPADStatus); + break; + } + + return fmtSize; +} + +static u8 __wpadIsButtonChanged(u16 lhs, u16 rhs) +{ + return lhs != rhs ? 1 : 0; +} + +static u8 __wpadIsAnalogChanged(s32 lhs, s32 rhs, s32 minDiff) +{ + s32 diff = lhs - rhs < 0 ? rhs - lhs : lhs - rhs; + + return diff > minDiff ? 1 : 0; +} + +static BOOL __wpadCalcAnalogNoise(wpad_cb_st *p_wpd, WPADNZFilter filter_type, + BOOL analogChanged) +{ + OSAssert_Line(1387, filter_type >= 0 && filter_type < WPAD_MAX_NZFILTERS); + + if (analogChanged) + { + p_wpd->filterDiff[filter_type]++; + + if (p_wpd->filterDiff[filter_type] + > _wpad_diff_count_threshold[filter_type]) + { + p_wpd->filterDiff[filter_type] = 0; + p_wpd->filterSame[filter_type] = 0; + return TRUE; + } + } + else + { + p_wpd->filterSame[filter_type] = + (p_wpd->filterSame[filter_type] + 1) + % _wpad_hyst_count_threshold[filter_type]; + + if (p_wpd->filterSame[filter_type] + == _wpad_hyst_count_threshold[filter_type] - 1 + && p_wpd->filterDiff[filter_type]) + { + p_wpd->filterDiff[filter_type]--; + } + } + + return FALSE; +} + +static BOOL __wpadIsControllerDataChanged(wpad_cb_st *p_wpd, void *lhs, + void *rhs) +{ + WPADStatus *lhsCore = lhs; + WPADStatus *rhsCore = rhs; + u8 isChanged = FALSE; + + if ((lhsCore->err == WPAD_ESUCCESS || lhsCore->err == WPAD_EBADE) + && (rhsCore->err == WPAD_ESUCCESS || rhsCore->err == WPAD_EBADE)) + { + isChanged |= __wpadIsButtonChanged(lhsCore->button, rhsCore->button); + + isChanged |= __wpadCalcAnalogNoise( + p_wpd, WPAD_NZFILTER_ACC, + __wpadIsAnalogChanged(lhsCore->accX, rhsCore->accX, 12) + | __wpadIsAnalogChanged(lhsCore->accY, rhsCore->accY, 12) + | __wpadIsAnalogChanged(lhsCore->accZ, rhsCore->accZ, 12)); + + isChanged |= __wpadCalcAnalogNoise( + p_wpd, WPAD_NZFILTER_DPD, + __wpadIsAnalogChanged(lhsCore->obj[0].x, rhsCore->obj[0].x, 2) + | __wpadIsAnalogChanged(lhsCore->obj[0].y, rhsCore->obj[0].y, 2) + | __wpadIsAnalogChanged(lhsCore->obj[1].x, rhsCore->obj[1].x, 2) + | __wpadIsAnalogChanged(lhsCore->obj[1].y, rhsCore->obj[1].y, 2) + | __wpadIsAnalogChanged(lhsCore->obj[2].x, rhsCore->obj[2].x, 2) + | __wpadIsAnalogChanged(lhsCore->obj[2].y, rhsCore->obj[2].y, 2) + | __wpadIsAnalogChanged(lhsCore->obj[3].x, rhsCore->obj[3].x, 2) + | __wpadIsAnalogChanged(lhsCore->obj[3].y, rhsCore->obj[3].y, + 2)); + } + + if (lhsCore->err == WPAD_ESUCCESS && rhsCore->err == WPAD_ESUCCESS) + { + switch (p_wpd->dataFormat) + { + case WPAD_FMT_FS_BTN: + case WPAD_FMT_FS_BTN_ACC: + case WPAD_FMT_FS_BTN_ACC_DPD: + { + WPADFSStatus *lhsFS = lhs; + WPADFSStatus *rhsFS = rhs; + + isChanged |= __wpadCalcAnalogNoise( + p_wpd, WPAD_NZFILTER_EXT, + __wpadIsAnalogChanged(lhsFS->fsAccX, rhsFS->fsAccX, 12) + | __wpadIsAnalogChanged(lhsFS->fsAccY, rhsFS->fsAccY, 12) + | __wpadIsAnalogChanged(lhsFS->fsAccZ, rhsFS->fsAccZ, 12)); + + isChanged |= + __wpadIsAnalogChanged(lhsFS->fsStickX, rhsFS->fsStickX, 1); + isChanged |= + __wpadIsAnalogChanged(lhsFS->fsStickY, rhsFS->fsStickY, 1); + } + break; + + case WPAD_FMT_CLASSIC_BTN: + case WPAD_FMT_CLASSIC_BTN_ACC: + case WPAD_FMT_CLASSIC_BTN_ACC_DPD: + + case WPAD_FMT_GUITAR: + case WPAD_FMT_DRUM: + case WPAD_FMT_TAIKO: + case WPAD_FMT_TURNTABLE: + { + WPADCLStatus *lhsCL = lhs; + WPADCLStatus *rhsCL = rhs; + + s32 leftStickDiv; + s32 rightStickDiv; + s32 triggerDiv; + switch (p_wpd->devMode) + { + case WPAD_DEV_MODE_CLASSIC_REDUCED: + leftStickDiv = 16; + rightStickDiv = 32; + triggerDiv = 8; + break; + + case WPAD_DEV_MODE_CLASSIC_STANDARD: + leftStickDiv = 4; + rightStickDiv = 4; + triggerDiv = 1; + break; + + default: + leftStickDiv = 1; + rightStickDiv = 1; + triggerDiv = 1; + break; + } + + isChanged |= + __wpadIsButtonChanged(lhsCL->clButton, rhsCL->clButton); + + isChanged |= + __wpadIsAnalogChanged(lhsCL->clLStickX / leftStickDiv, + rhsCL->clLStickX / leftStickDiv, 1); + isChanged |= + __wpadIsAnalogChanged(lhsCL->clLStickY / leftStickDiv, + rhsCL->clLStickY / leftStickDiv, 1); + isChanged |= + __wpadIsAnalogChanged(lhsCL->clRStickX / rightStickDiv, + rhsCL->clRStickX / rightStickDiv, 1); + isChanged |= + __wpadIsAnalogChanged(lhsCL->clRStickY / rightStickDiv, + rhsCL->clRStickY / rightStickDiv, 1); + isChanged |= + __wpadIsAnalogChanged(lhsCL->clTriggerL / triggerDiv, + rhsCL->clTriggerL / triggerDiv, 1); + isChanged |= + __wpadIsAnalogChanged(lhsCL->clTriggerR / triggerDiv, + rhsCL->clTriggerR / triggerDiv, 1); + } + break; + + case WPAD_FMT_TRAIN: + { + WPADTRStatus *lhsTR = lhs; + WPADTRStatus *rhsTR = rhs; + + isChanged |= + __wpadIsButtonChanged(lhsTR->trButton, rhsTR->trButton); + isChanged |= __wpadIsAnalogChanged(lhsTR->brake, rhsTR->brake, 1); + isChanged |= __wpadIsAnalogChanged(lhsTR->mascon, rhsTR->mascon, 1); + } + break; + + case WPAD_FMT_BALANCE_CHECKER: + { + WPADBLStatus *lhsBL = lhs; + WPADBLStatus *rhsBL = rhs; + + isChanged |= __wpadCalcAnalogNoise( + p_wpd, WPAD_NZFILTER_EXT, + __wpadIsAnalogChanged(lhsBL->press[0], rhsBL->press[0], 50) + | __wpadIsAnalogChanged(lhsBL->press[1], rhsBL->press[1], + 50) + | __wpadIsAnalogChanged(lhsBL->press[2], rhsBL->press[2], + 50) + | __wpadIsAnalogChanged(lhsBL->press[3], rhsBL->press[3], + 50)); + } + break; + + case WPAD_FMT_VSM: + { + WPADVSStatus *lhsVS = lhs; + + if (p_wpd->unk_0xbbc) + isChanged |= lhsVS->at_0x42 > 200 ? 1 : 0; + } + break; + + case WPAD_FMT_MOTION_PLUS: + { + WPADMPStatus *lhsMP = lhs; + WPADMPStatus *rhsMP = rhs; + + isChanged |= __wpadCalcAnalogNoise( + p_wpd, WPAD_NZFILTER_MPLS, + __wpadIsAnalogChanged(lhsMP->pitch, rhsMP->pitch, 64) + | __wpadIsAnalogChanged(lhsMP->yaw, rhsMP->yaw, 64) + | __wpadIsAnalogChanged(lhsMP->roll, rhsMP->roll, 64)); + + if (lhsMP->stat & WPAD_MPLS_STATUS_EXTENSION_CONNECTED + && rhsMP->stat & WPAD_MPLS_STATUS_EXTENSION_CONNECTED) + { + if (p_wpd->devMode == WPAD_DEV_MODE_MPLS_PT_FS) + { + isChanged |= __wpadCalcAnalogNoise( + p_wpd, WPAD_NZFILTER_EXT, + __wpadIsAnalogChanged(lhsMP->ext.fs.fsAccX, + rhsMP->ext.fs.fsAccX, 12) + | __wpadIsAnalogChanged(lhsMP->ext.fs.fsAccY, + rhsMP->ext.fs.fsAccY, 12) + | __wpadIsAnalogChanged(lhsMP->ext.fs.fsAccZ, + rhsMP->ext.fs.fsAccZ, 12)); + + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.fs.fsStickX, rhsMP->ext.fs.fsStickX, 1); + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.fs.fsStickY, rhsMP->ext.fs.fsStickY, 1); + } + else if (p_wpd->devMode == WPAD_DEV_MODE_MPLS_PT_CLASSIC) + { + s32 lStickDiv = 16; + s32 rStickDiv = 32; + s32 triggerDiv = 8; + + isChanged |= __wpadIsButtonChanged(lhsMP->ext.cl.clButton, + rhsMP->ext.cl.clButton); + + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.cl.clLStickX / lStickDiv, + rhsMP->ext.cl.clLStickX / lStickDiv, 1); + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.cl.clLStickY / lStickDiv, + rhsMP->ext.cl.clLStickY / lStickDiv, 1); + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.cl.clRStickX / rStickDiv, + rhsMP->ext.cl.clRStickX / rStickDiv, 1); + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.cl.clRStickY / rStickDiv, + rhsMP->ext.cl.clRStickY / rStickDiv, 1); + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.cl.clTriggerL / triggerDiv, + rhsMP->ext.cl.clTriggerL / triggerDiv, 1); + isChanged |= __wpadIsAnalogChanged( + lhsMP->ext.cl.clTriggerR / triggerDiv, + rhsMP->ext.cl.clTriggerR / triggerDiv, 1); + } + } + } + break; + } + } + + return isChanged; +} + +static void __wpadCalcRecalibration(WPADChannel chan, void *status) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADCLStatus *clStatus = status; + WPADMPStatus *mpStatus = status; + + s8 recalibrateComboPressed = 0; + WPADExtButton clPressed = 0; + + if (clStatus->err != WPAD_ESUCCESS && clStatus->err != WPAD_EBADE) + return; + + if (clStatus->button + == (WPAD_BUTTON_CL_A | WPAD_BUTTON_CL_PLUS | WPAD_BUTTON_CL_MINUS + | WPAD_BUTTON_CL_HOME) + && (p_wpd->dataFormat == WPAD_FMT_FS_BTN + || p_wpd->dataFormat == WPAD_FMT_FS_BTN_ACC + || p_wpd->dataFormat == WPAD_FMT_FS_BTN_ACC_DPD + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC_DPD + || p_wpd->dataFormat == WPAD_FMT_MOTION_PLUS)) + { + recalibrateComboPressed = 1; + } + + if (p_wpd->devType == WPAD_DEV_CLASSIC) + clPressed = clStatus->clButton; + + if (p_wpd->devType == WPAD_DEV_MPLS_PT_CLASSIC) + clPressed = mpStatus->ext.cl.clButton; + + if (clPressed + == (WPAD_BUTTON_CL_A | WPAD_BUTTON_CL_B | WPAD_BUTTON_CL_PLUS + | WPAD_BUTTON_CL_MINUS) + && (p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC_DPD + || p_wpd->dataFormat == WPAD_FMT_MOTION_PLUS)) + { + recalibrateComboPressed = 1; + } + + p_wpd->recalibHoldMs += recalibrateComboPressed; + + if (p_wpd->recalibHoldMs > 600) + WPADRecalibrate(chan); +} + +static void __wpadCalcControllerData(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL isChanged = FALSE; + BOOL screenSaverFlag = FALSE; + + if (_wpadCheckCnt != 5) + return; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + WPADStatus *status = (WPADStatus *)p_wpd->rxBufs[rxBufIndex]; + + OSRestoreInterrupts(intrStatus); + + isChanged = __wpadIsControllerDataChanged(p_wpd, status, p_wpd->rxBufMain); + + __wpadCalcRecalibration(chan, status); + + if (isChanged) + { + screenSaverFlag = TRUE; + p_wpd->lastControllerDataUpdate = __OSGetSystemTime(); + memcpy(p_wpd->rxBufMain, status, sizeof p_wpd->rxBufMain); + } + else if (_wpadSleepTime) + { + s32 time = (__OSGetSystemTime() - p_wpd->lastControllerDataUpdate) + / OS_TIMER_CLOCK; + + if (time > _wpadSleepTime * 60) + __wpadDisconnect(chan, 0); + } + + if (((WPADStatus *)(p_wpd->rxBufMain))->err != WPAD_ESUCCESS + && ((WPADStatus *)(p_wpd->rxBufMain))->err != WPAD_EBADE) + { + memcpy(p_wpd->rxBufMain, status, sizeof p_wpd->rxBufMain); + } + + __wpadSetScreenSaverFlag(screenSaverFlag); +} + +static BOOL __wpadProcExtCommand(WPADChannel chan, BOOL previousSuccess) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL success = FALSE; + + if (previousSuccess) + return TRUE; + + if (_wpadExtCnt[chan] != 5) + goto end; + + struct WPADCmd cmdBlk; + if (!__wpadGetCommand(&p_wpd->extCmdQueue, &cmdBlk)) + goto end; + + if (cmdBlk.reportID != RPTID_SET_DATA_REPORT_MODE && !p_wpd->wpInfo.attach) + goto end; + + if (__wpadSendData(chan, cmdBlk) != WPAD_ESUCCESS) + goto end; + + __wpadPopCommand(&p_wpd->extCmdQueue); + success = TRUE; + _wpadExtCnt[chan] = 0; + +end: + _wpadExtCnt[chan] = + _wpadExtCnt[chan] == 5 ? _wpadExtCnt[chan] : _wpadExtCnt[chan] + 1; + + return success; +} + +static void __wpadRumbleMotor(WPADChannel chan, BOOL procSuccess) +{ + struct WPADCmd cmdBlk; + + if (procSuccess == TRUE + || __wpadGetQueueSize(&__rvl_p_wpadcb[chan]->stdCmdQueue) > 0) + { + __rvl_p_wpadcb[chan]->motorBusy = FALSE; + } + else if (_wpadRumbleCnt[chan] == 5) + { + __rvl_p_wpadcb[chan]->motorBusy = FALSE; + + cmdBlk.reportID = RPTID_SET_RUMBLE; + cmdBlk.dataLength = RPT10_SIZE; + cmdBlk.dataBuf[RPT10_RUMBLE] = FALSE; + cmdBlk.cmdCB = NULL; + __wpadSendDataSub(chan, cmdBlk); + } + + _wpadRumbleCnt[chan] = + __rvl_p_wpadcb[chan]->motorBusy ? _wpadRumbleCnt[chan] + 1 : 0; +} + +static BOOL __wpadProcCommand(WPADChannel chan, BOOL previousSuccess) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (previousSuccess) + return TRUE; + + struct WPADCmd cmdBlk; + if (__wpadGetCommand(&p_wpd->stdCmdQueue, &cmdBlk) + && __wpadSendData(chan, cmdBlk) == WPAD_ESUCCESS) + { + __wpadPopCommand(&p_wpd->stdCmdQueue); + return TRUE; + } + + return FALSE; +} + +static void __wpadCalcSystemSettings(void) +{ + if (SCCheckStatus() != SC_STATUS_READY) + return; + + WUDUpdateSCSetting(); + + if (_wpadSCSetting) + { + _wpadDpdSense = __wpadGetDpdSensitivity(); + _wpadSensorBarPos = __wpadGetSensorBarPosition(); + _wpadRumbleFlag = __wpadGetMotorMode(); + _wpadSpeakerVol = __wpadGetSpeakerVolume(); + + _wpadSCSetting = FALSE; + } +} + +static void __wpadCalcAfh(void) +{ + if (_wpadAfhCnt != 60000) + return; + +#define CURRENT_AFH_CHANNEL_PHYS_ADDR (void *)0x31a2 + u8 *currAfhChannel = OSPhysicalToCached(CURRENT_AFH_CHANNEL_PHYS_ADDR); + DCInvalidateRange(currAfhChannel, sizeof *currAfhChannel); + + if (_wpadAfhChannel == *currAfhChannel) + return; + + BOOL intrStatus = OSDisableInterrupts(); + + _wpadAfhChannel = *currAfhChannel; + + OSRestoreInterrupts(intrStatus); + + WUDSetDisableChannel(_wpadAfhChannel); +} + +static BOOL __wpadCalcReconnectWait(void) +{ + if (_wpadOnReconnect >= 0) + { + if (--_wpadReconnectWait <= 0) + __wpadResetModule(_wpadOnReconnect); + + return TRUE; + } + + return FALSE; +} + +static void __wpadManageHandler(OSAlarm *alarm __attribute__((unused)), + OSContext *context __attribute__((unused))) +{ + WPADLibStatus status = WPADGetStatus(); + + if (status != WPAD_LIB_STATUS_3) + { + if (status == WPAD_LIB_STATUS_2 && !_wpadInitialized) + { + _wpadInitialized = TRUE; + _wpadReconnectWait = 50; + + WUDSetHidConnCallback(&__wpadConnectionCallback); + WUDSetHidRecvCallback(&__wpadReceiveCallback); + } + + return; + } + + if (__wpadCalcReconnectWait()) + return; + + __wpadCalcAfh(); + __wpadCalcSystemSettings(); + + WPADChannel chan; + BOOL procSuccess; + for (chan = WPAD_CHAN0; chan < WPAD_MAX_CONTROLLERS; chan++) + { + procSuccess = FALSE; + + if (__rvl_p_wpadcb[chan]->used) + { + procSuccess |= __wpadProcExtCommand(chan, procSuccess); + procSuccess |= __wpadProcCommand(chan, procSuccess); + + __wpadRumbleMotor(chan, procSuccess); + __wpadCalcControllerData(chan); + __wpadCalcRadioQuality(chan); + } + + if (__rvl_p_wpadcb[chan]->extWasDisconnected + && __rvl_p_wpadcb[chan]->reconnectExtMs-- < 0) + { + __rvl_p_wpadcb[chan]->extWasDisconnected = FALSE; + } + + __wpadCertWork(chan); + + if (__rvl_p_wpadcb[chan]->devType == WPAD_DEV_MOTION_PLUS + || __rvl_p_wpadcb[chan]->devType == WPAD_DEV_MPLS_PT_FS + || __rvl_p_wpadcb[chan]->devType == WPAD_DEV_MPLS_PT_CLASSIC + || __rvl_p_wpadcb[chan]->devType == WPAD_DEV_MPLS_PT_UNKNOWN) + { + if (__rvl_p_wpadcb[chan]->mplsUptimeMs < 200) + __rvl_p_wpadcb[chan]->mplsUptimeMs++; + } + } + + _wpadSenseCnt = _wpadSenseCnt == 10 ? 0 : _wpadSenseCnt + 1; + _wpadCheckCnt = _wpadCheckCnt == 5 ? 0 : _wpadCheckCnt + 1; + _wpadAfhCnt = _wpadAfhCnt == 60000 ? 0 : _wpadAfhCnt + 1; + + BTA_HhGetAclQueueInfo(); +} + +static void __wpadManageHandler0(OSAlarm *alarm, OSContext *context) +{ + OSSwitchFiberEx( + (register_t)alarm, (register_t)context, 0, 0, &__wpadManageHandler, + &__wpadManageHandlerStack[sizeof __wpadManageHandlerStack]); +} + +static void __wpadClearControlBlock(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + WPADStatus *status; + int filter; + + p_wpd->wpInfoOut = NULL; + + p_wpd->motorRunning = FALSE; + + p_wpd->cmdBlkCB = NULL; + p_wpd->extensionCB = NULL; + p_wpd->samplingCB = NULL; + + p_wpd->samplingBuf = NULL; + p_wpd->samplingBufIndex = 0; + p_wpd->samplingBufSize = 0; + + p_wpd->dataFormat = WPAD_FMT_CORE_BTN; + p_wpd->status = WPAD_ENODEV; + p_wpd->devType = WPAD_DEV_NONE; + p_wpd->devMode = WPAD_DEV_MODE_NORMAL; + + p_wpd->calibrated = FALSE; + p_wpd->recalibHoldMs = 0; + + p_wpd->statusReqBusy = FALSE; + + p_wpd->defaultDpdSize = 12; + p_wpd->currentDpdCommand = WPAD_DPD_DISABLE; + p_wpd->pendingDpdCommand = 0; + + for (filter = 0; filter < WPAD_MAX_NZFILTERS; filter++) + { + p_wpd->filterDiff[filter] = 0; + p_wpd->filterSame[filter] = 0; + } + + p_wpd->lastControllerDataUpdate = __OSGetSystemTime(); + p_wpd->lastReportSendTime = __OSGetSystemTime(); + p_wpd->unk_0xb08 = 0; + p_wpd->unk_0x90d = 0; + p_wpd->unk_0x908 = 0; + p_wpd->wmReadDataPtr = NULL; + p_wpd->wmReadAddress = 0; + p_wpd->wmReadLength = 0; + p_wpd->wmReadHadError = 0; + p_wpd->devHandle = WUD_DEV_HANDLE_INVALID; + p_wpd->used = FALSE; + p_wpd->handshakeFinished = FALSE; + p_wpd->configIndex = 0; + p_wpd->radioQuality = WPAD_RADIO_QUALITY_BAD; + p_wpd->radioQualityOkMs = 0; + p_wpd->audioFrames = 0; + p_wpd->unk_0xb7a = 0; + p_wpd->radioSensitivity = 0; + p_wpd->copyOutCount = 0; + p_wpd->sleeping = TRUE; + p_wpd->getInfoBusy = FALSE; + p_wpd->getInfoCB = NULL; + p_wpd->disableContReport = FALSE; + p_wpd->blcBattery = 4; + p_wpd->savedDevType = WPAD_DEV_NONE; + p_wpd->extWasDisconnected = FALSE; + p_wpd->reconnectExtMs = 0; + p_wpd->interleaveFlags = WPAD_ILBUF_NONE; + + memset(&p_wpd->wpInfo, 0, sizeof p_wpd->wpInfo); + memset(&p_wpd->wmReadDataBuf, 0, sizeof p_wpd->wmReadDataBuf); + memset(&p_wpd->devConfig, 0, sizeof p_wpd->devConfig); + memset(&p_wpd->extConfig, 0, sizeof p_wpd->extConfig); + memset(&p_wpd->encryptionKey, 0, sizeof p_wpd->encryptionKey); + memset(&p_wpd->decryptAddTable, 0, sizeof p_wpd->decryptAddTable); + memset(&p_wpd->decryptXorTable, 0, sizeof p_wpd->decryptXorTable); + memset(&p_wpd->gameInfo, 0, sizeof p_wpd->gameInfo); + + p_wpd->rxBufIndex = 0; + memset(p_wpd->rxBufs, 0, sizeof p_wpd->rxBufs); + status = (WPADStatus *)p_wpd->rxBufs[0]; + status->err = WPAD_ERR_NO_CONTROLLER; + status = (WPADStatus *)p_wpd->rxBufs[1]; + status->err = WPAD_ERR_NO_CONTROLLER; + memcpy(p_wpd->rxBufMain, p_wpd->rxBufs[0], sizeof p_wpd->rxBufMain); + + p_wpd->at_0x038[0] = -1; + p_wpd->at_0x038[1] = -1; + + p_wpd->stdCmdQueue.queue = p_wpd->stdCmdQueueList; + p_wpd->stdCmdQueue.length = ARRAY_LENGTH(p_wpd->stdCmdQueueList); + p_wpd->extCmdQueue.queue = p_wpd->extCmdQueueList; + p_wpd->extCmdQueue.length = ARRAY_LENGTH(p_wpd->extCmdQueueList); + + WPADiClearQueue(&p_wpd->stdCmdQueue); + WPADiClearQueue(&p_wpd->extCmdQueue); + + p_wpd->isInitingMpls = FALSE; + p_wpd->controlMplsBusy = FALSE; + p_wpd->mplsCBReadBuf[0] = 0; + p_wpd->mplsCBReadBuf[1] = 0; + p_wpd->pendingMplsCommand = 0; + p_wpd->mplsCBCounter = 3; + p_wpd->noParseMplsCount = 5; + p_wpd->controlMplsCB = NULL; + p_wpd->mplsUptimeMs = 0; + + p_wpd->certChallengeRandomBit = -1; + p_wpd->certWorkBusy = FALSE; + p_wpd->certState = WPAD_STATE_CERT_INVALID; + p_wpd->certValidityStatus = WPAD_CERT_UNCHECKED; + p_wpd->certStateWorkMs = 3000; + p_wpd->certWorkCounter = 2; + p_wpd->wmParamOffset = 0; + p_wpd->certParamPtr = NULL; + + memset(p_wpd->certBuf0, 0, sizeof p_wpd->certBuf0); + memset(p_wpd->certBuf1, 0, sizeof p_wpd->certBuf1); + memset(p_wpd->certBufBig, 0, sizeof p_wpd->certBufBig); + p_wpd->certBuf0[0] = p_wpd->certBuf1[0] = p_wpd->certBufBig[0] = 1; + + p_wpd->noParseExtCount = 0; + p_wpd->extErr = WPAD_ENODEV; + p_wpd->extDevType = WPAD_DEV_NONE; + p_wpd->extDataLength = 0; + memset(&p_wpd->extDataBuf, 0, sizeof p_wpd->extDataBuf); + + WPADiClearMemBlock(chan); + + p_wpd->unk_0xae4 = 0; + + _wpadExtCnt[chan] = 0; + _wpadRumbleCnt[chan] = 0; + +#if !defined(NDEBUG) + _wpadDummyAttach[chan] = FALSE; +#endif // !defined(NDEBUG) +} + +// TODO on release +static void __wpadInitSub(void) +{ + __wpadSetSensorBarPower(TRUE); + + WPADChannel chan; + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) + _wpadHandle2PortTable[i] = WUD_DEV_HANDLE_INVALID; + + for (chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++) + { + __rvl_p_wpadcb[chan] = &__rvl_wpadcb[chan]; + + _wpadIsUsedChannel[chan] = FALSE; + + __rvl_p_wpadcb[chan]->connectCB = NULL; + __wpadClearControlBlock(chan); + OSInitThreadQueue(&__rvl_wpadcb[chan].threadQueue); + __rvl_p_wpadcb[chan]->certMayVerifyByCalibBlock = FALSE; + + _wpadExtCnt[chan] = 0; + _wpadRumbleCnt[chan] = 0; + } + + _wpadSleepTime = 5; + _wpadGameCode = OSGetAppGamename(); + _wpadGameType = OSGetAppType(); + _wpadDpdSense = __wpadGetDpdSensitivity(); + _wpadSensorBarPos = __wpadGetSensorBarPosition(); + _wpadRumbleFlag = __wpadGetMotorMode(); + _wpadSpeakerVol = __wpadGetSpeakerVolume(); + _wpadSenseCnt = 0; + _wpadCheckCnt = 0; + _wpadAfhCnt = 0; + _wpadShutdownFlag = FALSE; + _wpadSCSetting = TRUE; + _wpadAfhChannel = -1; + _wpadUsedCallback = FALSE; + + OSRegisterVersion(__WPADVersion); + + // dont care + // clang-format off + if (_wpadVSMInit) (*_wpadVSMInit)(); + if (_wpadTRNInit) (*_wpadTRNInit)(); + if (_wpadGTRInit) (*_wpadGTRInit)(); + if (_wpadDRMInit) (*_wpadDRMInit)(); + if (_wpadTKOInit) (*_wpadTKOInit)(); + if (_wpadTBLInit) (*_wpadTBLInit)(); + if (_wpadBLKInit) (*_wpadBLKInit)(); + // clang-format on + + OSCreateAlarm(&_wpadManageAlarm); + OSSetPeriodicAlarm(&_wpadManageAlarm, OSGetTime(), OSMillisecondsToTicks(1), + &__wpadManageHandler0); +} + +void WPADInit(void) +{ + _wpadStartup = TRUE; + + if (!_wpadRegisterShutdownFunc) + { + OSRegisterShutdownFunction(&ShutdownFunctionInfo); + _wpadRegisterShutdownFunc = TRUE; + } + + BOOL wudInitSuccess = WUDInit(); + if (wudInitSuccess) + { + _wpadInitialized = FALSE; + _wpadOnReconnect = -1; + _wpadReconnectWait = 50; + __wpadInitSub(); + } +} + +void WPADShutdown(void) +{ + return; +} + +static void __wpadShutdown(BOOL saveSimpleDevs) +{ + OSCancelAlarm(&_wpadManageAlarm); + WUDSetHidRecvCallback(NULL); + WUDShutdown(saveSimpleDevs); +} + +static void __wpadCleanup(void) +{ + BOOL intrStatus = OSDisableInterrupts(); + + if (_wpadShutdownFlag) + { + OSRestoreInterrupts(intrStatus); + return; + } + + _wpadShutdownFlag = TRUE; + WUDSetVisibility(FALSE, FALSE); + + WPADChannel chan; + for (chan = WPAD_CHAN0; chan < WPAD_MAX_CONTROLLERS; chan++) + WUDSetDeviceHistory(chan, NULL); + + __wpadShutdown(FALSE); + + OSRestoreInterrupts(intrStatus); +} + +static void __wpadResetModule(BOOL saveSimpleDevs) +{ + BTA_DmSendHciReset(); + __wpadShutdown(saveSimpleDevs); +} + +static void __wpadReconnectStart(BOOL saveSimpleDevs) +{ + BOOL intrStatus = OSDisableInterrupts(); + + if (!_wpadStartup) + { + OSRestoreInterrupts(intrStatus); + return; + } + + if (_wpadShutdownFlag) + { + OSRestoreInterrupts(intrStatus); + return; + } + + _wpadShutdownFlag = TRUE; + _wpadOnReconnect = saveSimpleDevs ? 1 : 0; + + OSRestoreInterrupts(intrStatus); +} + +BOOL WPADStartFastSimpleSync(void) +{ + return WUDStartFastSyncSimple(); +} + +BOOL WPADStopSimpleSync(void) +{ + return WUDStopSyncSimple(); +} + +BOOL WPADCancelSyncDevice(void) +{ + return WUDCancelSyncDevice(); +} + +WPADSimpleSyncCallback *WPADSetSimpleSyncCallback(WPADSimpleSyncCallback *cb) +{ + return WUDSetSyncSimpleCallback(cb); +} + +void WPADRegisterAllocator(WPADAllocFunc *alloc, WPADFreeFunc *free) +{ + WUDRegisterAllocator(alloc, free); +} + +WPADLibStatus WPADGetStatus(void) +{ + return WUDGetStatus(); +} + +u8 WPADGetRadioSensitivity(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 radioSensitivity = p_wpd->radioSensitivity; + + OSRestoreInterrupts(intrStatus); + + return radioSensitivity; +} + +void WPADGetAddress(WPADChannel chan, BD_ADDR_PTR addr) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(2666, addr != NULL); + + BOOL intrStatus = OSDisableInterrupts(); + + s8 dev_handle = p_wpd->devHandle; + + OSRestoreInterrupts(intrStatus); + + BD_ADDR_PTR devAddr = _WUDGetDevAddr(dev_handle); + + if (devAddr) + memcpy(addr, devAddr, BD_ADDR_LEN); + else + memset(addr, 0, BD_ADDR_LEN); +} + +// WPADGetCalibratedDPDObject ([SGLEA4]/MAP/GormitiDebug.MAP:25309) +extern void __deadstrip1(void) +{ + (void)"Failed assertion src != NULL && dst != NULL"; +} + +u8 WPADGetSensorBarPosition(void) +{ + BOOL intrStatus = OSDisableInterrupts(); + + u8 sensorBarPos = _wpadSensorBarPos; + + OSRestoreInterrupts(intrStatus); + + return sensorBarPos; +} + +static void __wpadSetupConnectionCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (result == WPAD_ESUCCESS) + { + p_wpd->handshakeFinished = TRUE; + + if (p_wpd->connectCB) + (*p_wpd->connectCB)(chan, result); + } + else + { + __wpadDisconnect(chan, 0); + } +} + +static void __wpadAbortConnectionCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (result != WPAD_ESUCCESS) + { + WPADiClearQueue(&p_wpd->stdCmdQueue); + __wpadDisconnect(chan, 0); + } +} + +static void __wpadInitConnectionCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (result == WPAD_ENODEV) + return; + + u32 address; + + BOOL intrStatus = OSDisableInterrupts(); + + p_wpd->configIndex = result == WPAD_ESUCCESS ? 1 : 0; + p_wpd->status = WPAD_ESUCCESS; + + OSRestoreInterrupts(intrStatus); + + u16 size = result == WPAD_ESUCCESS ? 20 : 42; + address = + result == WPAD_ESUCCESS ? WM_ADDR_MEM_176C : WM_ADDR_MEM_DEV_CONFIG_0; + u8 port = p_wpd->devType == WPAD_DEV_BALANCE_CHECKER ? 1 : 1 << chan; + + WPADiSendSetReportType(&p_wpd->stdCmdQueue, 0, p_wpd->disableContReport, + &__wpadAbortConnectionCallback); + WPADiSendDPDCSB(&p_wpd->stdCmdQueue, FALSE, &__wpadAbortConnectionCallback); + WPADiSendSetPort(&p_wpd->stdCmdQueue, port, &__wpadAbortConnectionCallback); + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, + sizeof(WPADGameInfo), WM_ADDR_MEM_GAME_INFO_0, + &__wpadAbortConnectionCallback); + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, + sizeof(WPADGameInfo), WM_ADDR_MEM_GAME_INFO_1, + &__wpadAbortConnectionCallback); + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, size, address, + &__wpadSetupConnectionCallback); + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, NULL); +} + +static WPADChannel __wpadRetrieveChannel(WUDDevInfo *devInfo) +{ + BD_ADDR_PTR devAddr; + int i; + WPADChannel chan = WPAD_CHAN_INVALID; + + u8 devHandle = devInfo->devHandle; + devAddr = _WUDGetDevAddr(devHandle); + + if (WUD_DEV_NAME_IS_WBC(devInfo->small.devName)) + { + chan = WPAD_CHAN3; + + if (__rvl_p_wpadcb[chan]->used) + { + btm_remove_acl(devAddr); + return WPAD_CHAN_INVALID; + } + } + else + { + for (i = 0; i < WPAD_MAX_CONTROLLERS; i++) + { + if (WUDIsLatestDevice(i, devAddr) && !_wpadIsUsedChannel[i]) + { + chan = i; + break; + } + + if (!_wpadIsUsedChannel[i] && chan < WPAD_CHAN0) + chan = i; + } + } + + OSAssert_Line(2922, (chan >= 0) && (chan < WPAD_MAX_CONTROLLERS)); + OSAssert_Line(2923, __rvl_p_wpadcb[chan]->used == FALSE); + + if (!WUDIsLatestDevice(chan, devAddr)) + WUDSetDeviceHistory(chan, devAddr); + + _wpadIsUsedChannel[chan] = TRUE; + return chan; +} + +static void __wpadConnectionCallback(WUDDevInfo *devInfo, u8 success) +{ + UINT8 dev_handle = devInfo->devHandle; + + OSAssertMessage_Line(2951, dev_handle <= WUD_MAX_DEV_ENTRY, + "__wpadConnectionCallback(): Illegal dev_handle\n"); + + WPADChannel chan; + wpad_cb_st *p_wpd; + struct WPADCmd cmdBlk; + + if (success) + { + chan = __wpadRetrieveChannel(devInfo); + if (chan < 0) + return; + + _wpadHandle2PortTable[dev_handle] = (UINT8)chan; + + __wpadClearControlBlock(chan); + p_wpd = __rvl_p_wpadcb[chan]; + + if (WUD_DEV_NAME_IS_CNT(&devInfo->small.devName)) + { + p_wpd->devType = WPAD_DEV_CORE; + p_wpd->dataFormat = WPAD_FMT_CORE_BTN; + } + else if (WUD_DEV_NAME_IS_WBC(&devInfo->small.devName) + && WUDIsLinkedWBC()) + { + p_wpd->devType = WPAD_DEV_BALANCE_CHECKER; + p_wpd->dataFormat = WPAD_FMT_BALANCE_CHECKER; + } + else + { + p_wpd->devType = WPAD_DEV_251; + p_wpd->dataFormat = WPAD_FMT_CORE_BTN; + } + + p_wpd->devHandle = dev_handle; + p_wpd->used = TRUE; + p_wpd->status = WPAD_ESUCCESS; + p_wpd->radioSensitivity = 100; + p_wpd->sleeping = FALSE; + p_wpd->extState = WPAD_STATE_EXT_UNINITIALIZED; + p_wpd->savedDevType = p_wpd->devType; + + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, 1, + WM_ADDR_MEM_1770, &__wpadInitConnectionCallback); + __wpadSetScreenSaverFlag(TRUE); + } + else + { + chan = _wpadHandle2PortTable[dev_handle]; + _wpadHandle2PortTable[dev_handle] = WUD_DEV_HANDLE_INVALID; + if (chan == WUD_DEV_HANDLE_INVALID) + return; + + /* ERRATA: sanctioned OOB access of __rvl_p_wpadcb if + * chan == WPAD_MAX_CONTROLLERS + */ + OSAssert_Line(2991, chan <= WPAD_MAX_CONTROLLERS); + + p_wpd = __rvl_p_wpadcb[chan]; + p_wpd->status = WPAD_ENODEV; + + if (p_wpd->cmdBlkCB) + (*p_wpd->cmdBlkCB)(chan, WPAD_ENODEV); + else if (p_wpd->memBlock.at_0x10) + (*p_wpd->memBlock.at_0x10)(chan, WPAD_ENODEV); + + while (__wpadGetCommand(&p_wpd->stdCmdQueue, &cmdBlk)) + { + if (cmdBlk.cmdCB) + (*cmdBlk.cmdCB)(chan, WPAD_ENODEV); + + __wpadPopCommand(&p_wpd->stdCmdQueue); + } + + if (p_wpd->samplingBuf) + { + WPADSetAutoSamplingBuf(chan, p_wpd->samplingBuf, + p_wpd->samplingBufSize); + } + + __wpadClearControlBlock(chan); + _wpadIsUsedChannel[chan] = FALSE; + + if (p_wpd->connectCB) + (*p_wpd->connectCB)(chan, WPAD_ENODEV); + } +} + +static void __wpadReceiveCallback(UINT8 dev_handle, UINT8 *p_rpt, + UINT16 len __attribute__((unused))) +{ + signed result __attribute__((unused)); + + OSAssertMessage_Line(3052, dev_handle <= WUD_MAX_DEV_ENTRY, + "__wpadReceiveCallback(): Illegal dev_handle!\n"); + + if (dev_handle > WUD_MAX_DEV_ENTRY) + return; + + UINT8 port = _wpadHandle2PortTable[dev_handle]; + + if (port < (u32)WPAD_MAX_CONTROLLERS) + result = WPADiHIDParser(port, p_rpt); + + (void)result; // cool +} + +static WPADResult __wpadGetConnectionStatus(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3088, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + + BOOL intrStatus = OSDisableInterrupts(); + + WPADResult connStatus = p_wpd->status; + + OSRestoreInterrupts(intrStatus); + + return connStatus; +} + +void WPADGetAccGravityUnit(WPADChannel chan, WPADAccGravityUnitType type, + WPADAccGravityUnit *acc) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3112, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + OSAssert_Line(3113, p_wpd->status != WPAD_ERR_NO_CONTROLLER); + OSAssert_Line(3114, acc != NULL); + + BOOL intrStatus = OSDisableInterrupts(); + + if (acc != NULL) + { + switch (type) + { + case WPAD_ACC_GRAVITY_UNIT_CORE: + acc->x = p_wpd->devConfig.accX1g - p_wpd->devConfig.accX0g; + acc->y = p_wpd->devConfig.accY1g - p_wpd->devConfig.accY0g; + acc->z = p_wpd->devConfig.accZ1g - p_wpd->devConfig.accZ0g; + break; + + case WPAD_ACC_GRAVITY_UNIT_FS: + acc->x = p_wpd->extConfig.fs.accX1g - p_wpd->extConfig.fs.accX0g; + acc->y = p_wpd->extConfig.fs.accY1g - p_wpd->extConfig.fs.accY0g; + acc->z = p_wpd->extConfig.fs.accZ1g - p_wpd->extConfig.fs.accZ0g; + break; + } + } + + OSRestoreInterrupts(intrStatus); +} + +// WPADGetCLTriggerThreshold ([SGLEA4]/MAP/GormitiDebug.MAP:25321) +extern void __deadstrip2(void) +{ + (void)"Failed assertion p_wpd->devType == WPAD_DEV_CLASSIC"; + (void)"Failed assertion left != NULL && right != NULL"; +} + +static void __wpadDisconnectCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (result == WPAD_ENODEV) + return; + + BTA_HhClose(p_wpd->devHandle); +} + +static inline void __wpadDisconnect(WPADChannel chan, BOOL afkDisconnect) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADResult connStatus = __wpadGetConnectionStatus(chan); + if (connStatus == WPAD_ENODEV) + return; + + if (afkDisconnect) + { + BOOL intrStatus = OSDisableInterrupts(); + + if (p_wpd->sleeping) + { + OSRestoreInterrupts(intrStatus); + return; + } + + p_wpd->sleeping = TRUE; + + OSRestoreInterrupts(intrStatus); + + WPADControlLed(chan, 0, &__wpadDisconnectCallback); + } + else + { + BD_ADDR devAddr; + WPADGetAddress(chan, devAddr); + + btm_remove_acl(devAddr); + } +} + +void WPADDisconnect(WPADChannel chan) +{ + wpad_cb_st *p_wpd __attribute__((unused)) = __rvl_p_wpadcb[chan]; + + WPADResult connStatus = __wpadGetConnectionStatus(chan); + if (connStatus == WPAD_ENODEV) + return; + + WUDSetDeviceHistory(chan, NULL); + __wpadDisconnect(chan, TRUE); +} + +WPADResult WPADProbe(WPADChannel chan, WPADDeviceType *devTypeOut) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3332, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + + BOOL intrStatus = OSDisableInterrupts(); + + if (devTypeOut) + *devTypeOut = p_wpd->devType; + + WPADResult status = p_wpd->status; + if (status != WPAD_ENODEV) + { + if (p_wpd->devType == WPAD_DEV_NONE) + status = WPAD_ENODEV; + else if (!p_wpd->handshakeFinished) + status = WPAD_ECOMM; + } + + OSRestoreInterrupts(intrStatus); + + return status; +} + +WPADSamplingCallback *WPADSetSamplingCallback(WPADChannel chan, + WPADSamplingCallback *cb) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3371, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + + if (WPADIsUsedCallbackByKPAD()) + { + // clang-format off + OSReport("WARNING: Overwritten the callback needed by KPAD.\n"); + OSReport(" Please call KPADSetSamplingCallback instead of " + "WPADSetSamplingCallback.\n"); + // clang-format on + } + + WPADSamplingCallback *old; + BOOL intrStatus = OSDisableInterrupts(); + + old = p_wpd->samplingCB; + p_wpd->samplingCB = cb; + + OSRestoreInterrupts(intrStatus); + + return old; +} + +WPADConnectCallback *WPADSetConnectCallback(WPADChannel chan, + WPADConnectCallback *cb) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3402, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + + if (WPADIsUsedCallbackByKPAD()) + { + // clang-format off + OSReport("WARNING: Overwritten the callback needed by KPAD.\n"); + OSReport(" Please call KPADSetConnectCallback instead of " + "WPADSetConnectCallback.\n"); + // clang-format on + } + + WPADConnectCallback *old; + BOOL intrStatus = OSDisableInterrupts(); + + old = p_wpd->connectCB; + p_wpd->connectCB = cb; + + OSRestoreInterrupts(intrStatus); + + return old; +} + +WPADExtensionCallback *WPADSetExtensionCallback(WPADChannel chan, + WPADExtensionCallback *cb) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3434, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + + WPADExtensionCallback *old; + BOOL intrStatus = OSDisableInterrupts(); + + old = p_wpd->extensionCB; + p_wpd->extensionCB = cb; + + OSRestoreInterrupts(intrStatus); + + return old; +} + +WPADDataFormat WPADGetDataFormat(WPADChannel chan) +{ + WPADDataFormat format; + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3477, 0 <= chan && chan < WPAD_MAX_CONTROLLERS); + + BOOL intrStatus = OSDisableInterrupts(); + + format = p_wpd->dataFormat; + + OSRestoreInterrupts(intrStatus); + + return format; +} + +WPADResult WPADSetDataFormat(WPADChannel chan, WPADDataFormat fmt) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3524, 0 <= chan && chan < WPAD_MAX_CONTROLLERS); + OSAssert_Line(3525, WUDIsLinkedWBC() || fmt != WPAD_FMT_BALANCE_CHECKER); + OSAssert_Line(3526, WPADIsEnabledTRN() || fmt != WPAD_FMT_TRAIN); + OSAssert_Line(3527, WPADIsEnabledGTR() || fmt != WPAD_FMT_GUITAR); + OSAssert_Line(3528, WPADIsEnabledDRM() || fmt != WPAD_FMT_DRUM); + OSAssert_Line(3529, WPADIsEnabledVSM() || fmt != WPAD_FMT_VSM); + OSAssert_Line(3530, WPADIsEnabledTKO() || fmt != WPAD_FMT_TAIKO); + OSAssert_Line(3531, WPADIsEnabledTBL() || fmt != WPAD_FMT_TURNTABLE); + OSAssert_Line(3532, WPADIsEnabledBLK() || fmt != WPAD_FMT_BULK); + + WPADResult status; + BOOL intrStatus = OSDisableInterrupts(); + + BOOL handshakeFinished = p_wpd->handshakeFinished; + status = p_wpd->status; + WPADDataFormat currFormat = p_wpd->dataFormat; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + return WPAD_ENODEV; + + if (!handshakeFinished) + return WPAD_ECOMM; + + if (currFormat == fmt) + return WPAD_ESUCCESS; + + if (WPADiSendSetReportType(&p_wpd->stdCmdQueue, fmt, + p_wpd->disableContReport, NULL)) + { + intrStatus = OSDisableInterrupts(); + + p_wpd->dataFormat = fmt; + p_wpd->interleaveFlags = WPAD_ILBUF_NONE; + + OSRestoreInterrupts(intrStatus); + + status = WPAD_ESUCCESS; + } + else + { + status = WPAD_ECOMM; + } + + return status; +} + +static void __wpadInfoCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (p_wpd->getInfoCB) + (*p_wpd->getInfoCB)(chan, result); + + p_wpd->getInfoCB = NULL; + p_wpd->getInfoBusy = FALSE; +} + +WPADResult WPADGetInfoAsync(WPADChannel chan, WPADInfo *info, WPADCallback *cb) +{ + BOOL handshakeFinished; + WPADResult status; + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3619, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + + BOOL intrStatus = OSDisableInterrupts(); + + handshakeFinished = p_wpd->handshakeFinished; + status = p_wpd->status; + u8 getInfoBusy = p_wpd->getInfoBusy; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + goto end; + + if (!handshakeFinished || getInfoBusy) + { + status = WPAD_ECOMM; + goto end; + } + + intrStatus = OSDisableInterrupts(); + + p_wpd->getInfoBusy = TRUE; + p_wpd->getInfoCB = cb; + + OSRestoreInterrupts(intrStatus); + + if (WPADiSendGetContStat(&p_wpd->stdCmdQueue, info, &__wpadInfoCallback)) + { + status = WPAD_ESUCCESS; + goto end; + } + + status = WPAD_ECOMM; + + intrStatus = OSDisableInterrupts(); + + p_wpd->getInfoBusy = FALSE; + p_wpd->getInfoCB = NULL; + + OSRestoreInterrupts(intrStatus); + +end: + if (status != WPAD_ESUCCESS && cb) + (*cb)(chan, status); + + return status; +} + +// WPADGetSyncType ([SGLEA4]/MAP/GormitiDebug.MAP:25337) +extern void __deadstrip3(void) +{ + (void)"Failed assertion type != NULL"; +} + +void WPADControlMotor(WPADChannel chan, WPADMotorCommand command) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + int a __attribute__((unused)) = 0; // What + + OSAssert_Line(3723, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + OSAssert_Line(3724, ( WPAD_MOTOR_STOP == command ) || ( WPAD_MOTOR_RUMBLE == command )); + + BOOL intrStatus = OSDisableInterrupts(); + + WPADResult status = p_wpd->status; + + if (status == WPAD_ENODEV) + { + OSRestoreInterrupts(intrStatus); + return; + } + + if (!_wpadRumbleFlag + && (command != WPAD_MOTOR_STOP || p_wpd->motorRunning != TRUE)) + { + OSRestoreInterrupts(intrStatus); + return; + } + + if ((command == WPAD_MOTOR_STOP && p_wpd->motorRunning == FALSE) + || (command == WPAD_MOTOR_RUMBLE && p_wpd->motorRunning == TRUE)) + { + OSRestoreInterrupts(intrStatus); + return; + } + + p_wpd->motorRunning = command == WPAD_MOTOR_STOP ? 0 : 1; + p_wpd->motorBusy = TRUE; + + OSRestoreInterrupts(intrStatus); +} + +void WPADEnableMotor(BOOL enabled) +{ + BOOL intrStatus = OSDisableInterrupts(); + + _wpadRumbleFlag = enabled; + + OSRestoreInterrupts(intrStatus); +} + +BOOL WPADIsMotorEnabled(void) +{ + BOOL enabled; + + BOOL intrStatus = OSDisableInterrupts(); + + enabled = _wpadRumbleFlag; + + OSRestoreInterrupts(intrStatus); + + return enabled; +} + +WPADResult WPADControlLed(WPADChannel chan, u8 ledFlags, WPADCallback *cb) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL success; + BOOL intrStatus; + BOOL handshakeFinished; + WPADResult status; + + status = WPAD_ESUCCESS; + + OSAssert_Line(3818, ( 0 <= chan ) && ( chan < WPAD_MAX_CONTROLLERS )); + + intrStatus = OSDisableInterrupts(); + + status = p_wpd->status; + handshakeFinished = p_wpd->handshakeFinished; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + goto end; + + if (!handshakeFinished) + { + status = WPAD_ECOMM; + goto end; + } + + success = WPADiSendSetPort(&p_wpd->stdCmdQueue, ledFlags, cb); + + status = success ? WPAD_CESUCCESS : WPAD_CECOMM; + +end: + if (status != WPAD_ESUCCESS && cb) + (*cb)(chan, status); + + return status; +} + +BOOL WPADSaveConfig(SCFlushCallback *cb) +{ + BOOL success = TRUE; + + if (SCCheckStatus() != SC_STATUS_READY) + return FALSE; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 speakerVol = _wpadSpeakerVol; + u8 rumble = _wpadRumbleFlag ? 1 : 0; + + OSRestoreInterrupts(intrStatus); + + success &= SCSetWpadSpeakerVolume(speakerVol); + success &= SCSetWpadMotorMode(rumble); + + if (success) + SCFlushAsync(cb); + else if (cb) + (*cb)(SC_STATUS_FATAL); + + return success; +} + +void WPADRead(WPADChannel chan, WPADStatus *status) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3905, (0 <= chan) && (chan < WPAD_MAX_CONTROLLERS)); + OSAssert_Line(3906, status != NULL); + + BOOL intrStatus = OSDisableInterrupts(); + + u8 rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + WPADStatus *rxStatus = (WPADStatus *)p_wpd->rxBufs[rxBufIndex]; + u32 fmtSize = __wpadFmt2Size(p_wpd->dataFormat); + + if (rxStatus->err != WPAD_ESUCCESS) + fmtSize = sizeof(WPADStatus); + + memcpy(status, rxStatus, fmtSize); + + OSRestoreInterrupts(intrStatus); +} + +void WPADSetAutoSamplingBuf(WPADChannel chan, void *buf, u32 length) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(3944, (0 <= chan) && (chan < WPAD_MAX_CONTROLLERS)); + OSAssert_Line(3945, (buf && length > 0) || (buf == NULL)); + + BOOL intrStatus = OSDisableInterrupts(); + + s8 defaultErr = p_wpd->status == WPAD_ENODEV ? WPAD_CENODEV : WPAD_CEINVAL; + u32 fmtSize = __wpadFmt2Size(p_wpd->dataFormat); + + int i; + if (buf) + { + memset(buf, 0, fmtSize * length); + + for (i = 0; (u32)i < length; i++) + ((WPADStatus *)((u32)buf + i * fmtSize))->err = defaultErr; + + p_wpd->samplingBufIndex = -1; + p_wpd->samplingBufSize = length; + } + + p_wpd->samplingBuf = buf; + + OSRestoreInterrupts(intrStatus); +} + +void WPADiExcludeButton(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + void *rxBuf = p_wpd->rxBufs[rxBufIndex]; + + WPADStatus *status = rxBuf; + + if ((status->button & (WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT)) + == (WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT)) + { + status->button &= ~WPAD_BUTTON_RIGHT; + } + + if ((status->button & (WPAD_BUTTON_UP | WPAD_BUTTON_DOWN)) + == (WPAD_BUTTON_UP | WPAD_BUTTON_DOWN)) + { + status->button &= ~WPAD_BUTTON_DOWN; + } + + WPADCLStatus *clStatus; + if (p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC_DPD + || p_wpd->dataFormat == WPAD_FMT_GUITAR + || p_wpd->dataFormat == WPAD_FMT_DRUM + || p_wpd->dataFormat == WPAD_FMT_TAIKO) + { + clStatus = rxBuf; + + if ((clStatus->clButton + & (WPAD_BUTTON_CL_LEFT | WPAD_BUTTON_CL_RIGHT)) + == (WPAD_BUTTON_CL_LEFT | WPAD_BUTTON_CL_RIGHT)) + { + clStatus->clButton &= ~(WPAD_BUTTON_CL_RIGHT); + } + + if ((clStatus->clButton & (WPAD_BUTTON_CL_UP | WPAD_BUTTON_CL_DOWN)) + == (WPAD_BUTTON_CL_UP | WPAD_BUTTON_CL_DOWN)) + { + clStatus->clButton &= ~WPAD_BUTTON_CL_DOWN; + } + } + + WPADTRStatus *trStatus; + if (p_wpd->dataFormat == WPAD_FMT_TRAIN) + { + trStatus = rxBuf; + + if ((trStatus->trButton + & (WPAD_BUTTON_TR_LEFT | WPAD_BUTTON_TR_RIGHT)) + == (WPAD_BUTTON_TR_LEFT | WPAD_BUTTON_TR_RIGHT)) + { + trStatus->trButton &= ~WPAD_BUTTON_TR_RIGHT; + } + + if ((trStatus->trButton & (WPAD_BUTTON_TR_UP | WPAD_BUTTON_TR_DOWN)) + == (WPAD_BUTTON_TR_UP | WPAD_BUTTON_TR_DOWN)) + { + trStatus->trButton &= ~WPAD_BUTTON_TR_DOWN; + } + } + + OSRestoreInterrupts(intrStatus); +} + +void WPADiCopyOut(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + u32 fmtSize; + u8 rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + WPADStatus *status = (WPADStatus *)p_wpd->rxBufs[rxBufIndex]; + fmtSize = __wpadFmt2Size(p_wpd->dataFormat); + + WPADStatus *statusOut; + if (p_wpd->samplingBuf) + { + p_wpd->samplingBufIndex++; + if (p_wpd->samplingBufIndex >= p_wpd->samplingBufSize) + p_wpd->samplingBufIndex = 0; + + statusOut = (WPADStatus *)((u32)p_wpd->samplingBuf + + p_wpd->samplingBufIndex * fmtSize); + + if (status->err != WPAD_ESUCCESS) + fmtSize = sizeof(WPADStatus); + + memcpy(statusOut, status, fmtSize); + } + + if (p_wpd->samplingCB) + (*p_wpd->samplingCB)(chan); + + p_wpd->copyOutCount++; + + OSRestoreInterrupts(intrStatus); +} + +BOOL WPADIsSpeakerEnabled(WPADChannel chan) +{ + BOOL enabled; + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + enabled = p_wpd->wpInfo.speaker; + + OSRestoreInterrupts(intrStatus); + + return enabled; +} + +WPADResult WPADControlSpeaker(WPADChannel chan, WPADSpeakerCommand command, + WPADCallback *cb) +{ + // the last two bytes are different than wiibrew? so they must mean something + byte_t data[7] = {0x00, 0x00, 0xd0, 0x07, 0x40, 0x0c, 0x0e}; + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + BOOL speakerEnabled = p_wpd->wpInfo.speaker; + BOOL handshakeFinished; + WPADResult status = p_wpd->status; + handshakeFinished = p_wpd->handshakeFinished; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + goto end; + + if (!handshakeFinished) + { + status = WPAD_ECOMM; + goto end; + } + + if (command == WPAD_SPEAKER_DISABLE) + { + if (!speakerEnabled) + { + status = WPAD_ESUCCESS; + goto end; + } + + intrStatus = OSDisableInterrupts(); + + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 5)) + { + WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, WM_REG_SPEAKER_01, + NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x00, WM_REG_SPEAKER_09, + NULL); + WPADiSendEnableSpeaker(&p_wpd->stdCmdQueue, FALSE, NULL); + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, cb); + + OSRestoreInterrupts(intrStatus); + + return WPAD_ESUCCESS; + } + + status = WPAD_ECOMM; + OSRestoreInterrupts(intrStatus); + } + else + { + switch (command) + { + case WPAD_SPEAKER_ENABLE: + case WPAD_SPEAKER_CMD_05: + intrStatus = OSDisableInterrupts(); + + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 7)) + { + WPADiSendEnableSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, + WM_REG_SPEAKER_09, NULL); + + // sends 0x80 instead of 0x08? + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x80, + WM_REG_SPEAKER_01, NULL); + + data[4] = _wpadSpeakerVol; + WPADiSendWriteData(&p_wpd->stdCmdQueue, &data, sizeof data, + WM_REG_SPEAKER_01, NULL); + WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, FALSE, NULL); + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, cb); + + OSRestoreInterrupts(intrStatus); + + return WPAD_ESUCCESS; + } + + status = WPAD_ECOMM; + + OSRestoreInterrupts(intrStatus); + + break; + + case WPAD_SPEAKER_MUTE: + if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, cb)) + { + status = WPAD_ECOMM; + goto end; + } + + return WPAD_ESUCCESS; + + case WPAD_SPEAKER_UNMUTE: + if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, FALSE, cb)) + { + status = WPAD_ECOMM; + goto end; + } + + return WPAD_ESUCCESS; + + case WPAD_SPEAKER_PLAY: + if (!WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, + WM_REG_SPEAKER_08, cb)) + { + status = WPAD_ECOMM; + goto end; + } + + return WPAD_ESUCCESS; + } + } + +end: + if (cb) + (*cb)(chan, status); + + return status; +} + +u8 WPADGetSpeakerVolume(void) +{ + BOOL intrStatus = OSDisableInterrupts(); + + u8 speakerVolume = _wpadSpeakerVol; + + OSRestoreInterrupts(intrStatus); + + return speakerVolume; +} + +void WPADSetSpeakerVolume(u8 volume) +{ + BOOL intrStatus = OSDisableInterrupts(); + + _wpadSpeakerVol = __wpadClampSpeakerVolume(volume); + + OSRestoreInterrupts(intrStatus); +} + +static BOOL __wpadIsBusyStream(WPADChannel chan) +{ + BOOL intrStatus; + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + intrStatus = OSDisableInterrupts(); + + WPADRadioQuality radioQuality = p_wpd->radioQuality; + u32 devType = p_wpd->devType; + u8 bufferStatus = WUDGetBufferStatus(); + + // I Love Declaration Order!!! + u16 bteBufferStatus __attribute__((unused)); + u16 btmBufferStatus; + u8 audioFrames; + + s8 queueSize = __wpadGetQueueSize(&p_wpd->stdCmdQueue); + + bteBufferStatus = __wpadGetBTEBufferStatus(chan); // hm? + btmBufferStatus = __wpadGetBTMBufferStatus(chan); + audioFrames = p_wpd->audioFrames; + + u8 linkNumber = _WUDGetLinkNumber(); + + OSRestoreInterrupts(intrStatus); + + if (radioQuality != WPAD_RADIO_QUALITY_GOOD || btmBufferStatus > 3 + || bufferStatus == 10 || bufferStatus >= linkNumber * 2 + 2 + || devType == WPAD_DEV_INITIALIZING || queueSize >= 21 + || audioFrames >= 1) + { + return TRUE; + } + else + { + return FALSE; + } +} + +BOOL WPADCanSendStreamData(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + BOOL handshakeFinished; + WPADResult status = p_wpd->status; + handshakeFinished = p_wpd->handshakeFinished; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV || !handshakeFinished || __wpadIsBusyStream(chan)) + return FALSE; + else + return TRUE; +} + +WPADResult WPADSendStreamData(WPADChannel chan, void *p_buf, u16 len) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(4420, p_buf != NULL); + OSAssert_Line(4421, len >= 0 && len <= 20); + + BOOL intrStatus = OSDisableInterrupts(); + + BOOL handshakeFinished; + WPADResult status = p_wpd->status; + handshakeFinished = p_wpd->handshakeFinished; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + return WPAD_ENODEV; + + if (!handshakeFinished) + return WPAD_ECOMM; + + if (__wpadIsBusyStream(chan)) + return WPAD_ECOMM; + + if (!WPADiSendStreamData(&p_wpd->stdCmdQueue, p_buf, len)) + return WPAD_ECOMM; + + intrStatus = OSDisableInterrupts(); + + p_wpd->audioFrames++; + + OSRestoreInterrupts(intrStatus); + + return WPAD_ESUCCESS; +} + +// WPADSetDpdSensitivity ([SGLEA4]/MAP/GormitiDebug.MAP:25355) +extern void __deadstrip4(void) +{ + (void)"Sensitivity must be from 1 to 5.\n"; +} + +u8 WPADGetDpdSensitivity(void) +{ + BOOL intrStatus = OSDisableInterrupts(); + + u8 dpdSensitivity = _wpadDpdSense; + + OSRestoreInterrupts(intrStatus); + + return dpdSensitivity; +} + +BOOL WPADIsDpdEnabled(WPADChannel chan) +{ + BOOL enabled; + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + enabled = p_wpd->wpInfo.dpd; + + OSRestoreInterrupts(intrStatus); + + return enabled; +} + +static void __wpadDpdCallback(WPADChannel chan, + WPADResult result __attribute__((unused))) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->currentDpdCommand = p_wpd->pendingDpdCommand; + p_wpd->dpdBusy = FALSE; + p_wpd->wpInfo.dpd = p_wpd->pendingDpdCommand == WPAD_DPD_DISABLE ? 0 : 1; + + (void)result; // OfCourse +} + +WPADResult WPADControlDpd(WPADChannel chan, WPADDpdCommand command, + WPADCallback *cb) +{ + // clang-format off + static const byte_t cfg1[WPAD_MAX_DPD_SENS][9] = + { + {0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0x64, 0x00, 0xfe}, + {0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0x96, 0x00, 0xb4}, + {0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0xaa, 0x00, 0x64}, + {0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0xc8, 0x00, 0x36}, + {0x07, 0x00, 0x00, 0x71, 0x01, 0x00, 0x72, 0x00, 0x20} + }; + + static const byte_t cfg2[WPAD_MAX_DPD_SENS][2] = + { + {0xfd, 0x05}, + {0xb3, 0x04}, + {0x63, 0x03}, + {0x35, 0x03}, + {0x1f, 0x03} + }; + // clang-format on + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + BOOL dpdEnabled = p_wpd->wpInfo.dpd; + BOOL handshakeFinished; + + u8 currCmd __attribute__((unused)) = p_wpd->currentDpdCommand; + u8 pendingCmd = p_wpd->pendingDpdCommand; + WPADResult status = p_wpd->status; + handshakeFinished = p_wpd->handshakeFinished; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + goto end; + + if (!handshakeFinished) + { + status = WPAD_ECOMM; + goto end; + } + + if (command == WPAD_DPD_DISABLE) + { + if (!dpdEnabled) + { + status = WPAD_ESUCCESS; + goto end; + } + + intrStatus = OSDisableInterrupts(); + + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 3)) + { + p_wpd->pendingDpdCommand = command; + + WPADiSendEnableDPD(&p_wpd->stdCmdQueue, FALSE, NULL); + WPADiSendDPDCSB(&p_wpd->stdCmdQueue, FALSE, &__wpadDpdCallback); + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, cb); + + OSRestoreInterrupts(intrStatus); + + return WPAD_ESUCCESS; + } + + status = WPAD_ECOMM; + + OSRestoreInterrupts(intrStatus); + } + else + { + if (command == pendingCmd) + goto end; + + intrStatus = OSDisableInterrupts(); + + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 8)) + { + p_wpd->pendingDpdCommand = command; + p_wpd->dpdBusy = TRUE; + + WPADiSendEnableDPD(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendDPDCSB(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, WM_REG_DPD_30, + NULL); + WPADiSendWriteData(&p_wpd->stdCmdQueue, cfg1[_wpadDpdSense - 1], + sizeof cfg1[_wpadDpdSense - 1], + WM_REG_DPD_CONFIG_BLOCK_1, NULL); + WPADiSendWriteData(&p_wpd->stdCmdQueue, cfg2[_wpadDpdSense - 1], + sizeof cfg2[_wpadDpdSense - 1], + WM_REG_DPD_CONFIG_BLOCK_2, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, command, + WM_REG_DPD_DATA_FORMAT, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x08, WM_REG_DPD_30, + &__wpadDpdCallback); + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, cb); + + OSRestoreInterrupts(intrStatus); + + return WPAD_ESUCCESS; + } + + status = WPAD_ECOMM; + + OSRestoreInterrupts(intrStatus); + } + +end: + if (cb) + (*cb)(chan, status); + + return status; +} + +WPADResult WPADControlBLC(WPADChannel chan, WPADBLCCommand command, + WPADCallback *cb) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(4763, WUDIsLinkedWBC()); + + BOOL intrStatus = OSDisableInterrupts(); + + WPADResult status = p_wpd->status; + BOOL handshakeFinished = p_wpd->handshakeFinished; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + goto end; + + if (!handshakeFinished || !WUDIsLinkedWBC()) + { + status = WPAD_ECOMM; + goto end; + } + else + { + byte_t data[7]; + data[0] = data[1] = data[2] = 0xaa; + data[3] = 0x55; + data[4] = data[5] = data[6] = command; + + intrStatus = OSDisableInterrupts(); + + switch (command) + { + case WPAD_BLC_ENABLE: + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 4)) + { + WPADWriteExtReg(chan, data, sizeof data, WPAD_EXT_REG_EXTENSION, + 0xf1, NULL); + WPADWriteExtReg(chan, data, 1, WPAD_EXT_REG_EXTENSION, 0xf1, + NULL); + WPADWriteExtReg(chan, data, 1, WPAD_EXT_REG_EXTENSION, 0xf1, + NULL); + WPADWriteExtReg(chan, data, 1, WPAD_EXT_REG_EXTENSION, 0xf1, + cb); + + OSRestoreInterrupts(intrStatus); + + return WPAD_ESUCCESS; + } + + status = WPAD_ECOMM; + break; + + case WPAD_BLC_CMD_55: + status = WPADWriteExtReg(chan, data, sizeof data, + WPAD_EXT_REG_EXTENSION, 0xf1, cb); + + if (status == WPAD_ESUCCESS) + { + OSRestoreInterrupts(intrStatus); + return WPAD_ESUCCESS; + } + + break; + + case WPAD_BLC_DISABLE: + status = WPADWriteExtReg(chan, data, 1, WPAD_EXT_REG_EXTENSION, + 0xf1, cb); + + if (status == WPAD_ESUCCESS) + { + OSRestoreInterrupts(intrStatus); + return WPAD_ESUCCESS; + } + + break; + + default: + status = WPAD_ECOMM; + break; + } + } + + OSRestoreInterrupts(intrStatus); + +end: + if (cb) + (*cb)(chan, status); + + return status; +} + +// clang-format off +// Various functions in between ([SGLEA4]/MAP/GormitiDebug.MAP:25366-25379) +extern void __deadstrip5(void) +{ + (void)"Failed assertion ( addr >= 0x20 && addr < 0x24 ) || ( addr >= 0xf1 && addr < 0xf6 )"; + (void)"Failed assertion ( addr >= WPAD_BLCLB_BLK1_ADDR && addr + (len - 1) < WPAD_BLCLB_BLK3_ADDR + WPAD_BLCLB_BLK3_LEN ) || ( addr >= WPAD_BLCLB_BLK4_ADDR && addr + (len - 1) < WPAD_BLCLB_BLK5_ADDR + WPAD_BLCLB_BLK5_LEN )"; + (void)"Failed assertion addr >= WPAD_VSMCLB_ADDR1 && addr + (len - 1) < WPAD_VSMCLB_ADDR1 + WPAD_VSMCLB_LEN"; +} +// clang-format on + +u8 WPADiGetMplsStatus(WPADChannel chan) +{ + u8 status = 0; + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + if (p_wpd->devType == WPAD_DEV_MOTION_PLUS + || p_wpd->devType == WPAD_DEV_MPLS_PT_FS + || p_wpd->devType == WPAD_DEV_MPLS_PT_CLASSIC + || p_wpd->devType == WPAD_DEV_MPLS_PT_UNKNOWN) + { + status = p_wpd->devMode; + } + + OSRestoreInterrupts(intrStatus); + + return status; +} + +// WPADGetMplsStatus ([SGLEA4]/MAP/GormitiDebug.MAP:25381) +extern void __deadstrip6(void) +{ + (void)"WPADGetMplsStatus is obsolete.\n"; +} + +static void __wpadMplsCallback(WPADChannel chan, WPADResult result) +{ +#define CALC_STATUS(x) (!(x) ? WPAD_CECOMM : WPAD_CESUCCESS) + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADResult status = result; + WPADCallback *controlMplsCB; + u32 addr; + + switch (p_wpd->mplsCBState) + { + case WPAD_STATE_MPLS_CB_1: + if (result == WPAD_ESUCCESS) + { + if (p_wpd->mplsCBReadBuf[1] != WPAD_DEV_MOTION_PLUS + && p_wpd->mplsCBReadBuf[1] != WPAD_DEV_MPLS_PT_FS + && p_wpd->mplsCBReadBuf[1] != WPAD_DEV_MPLS_PT_CLASSIC + && p_wpd->mplsCBReadBuf[1] != WPAD_DEV_MPLS_PT_UNKNOWN) + { + p_wpd->mplsCBCounter--; + if (!p_wpd->mplsCBCounter) + { + status = WPAD_ERR_3; + } + else + { + if (p_wpd->mplsCBCounter > 1) + p_wpd->mplsCBReadAddress = WM_REG_MPLS_DEV_MODE; + else + p_wpd->mplsCBReadAddress = WM_REG_EXTENSION_DEV_MODE; + + status = CALC_STATUS(WPADiSendReadData( + &p_wpd->stdCmdQueue, &p_wpd->mplsCBReadBuf, 2, + p_wpd->mplsCBReadAddress, &__wpadMplsCallback)); + } + } + else + { + addr = (p_wpd->mplsCBReadAddress & ~0xff) | 0xf0; + if (addr == WM_REG_MPLS_F0) + { + p_wpd->mplsCBState = + WPAD_STATE_MPLS_CB_WRITE_PENDING_MPLS_DEV_MODE; + status = CALC_STATUS(WPADiSendWriteDataCmd( + &p_wpd->stdCmdQueue, 0x55, addr, &__wpadMplsCallback)); + } + else if (p_wpd->mplsCBReadBuf[0] == p_wpd->pendingMplsCommand) + { + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_START; + } + else if (--p_wpd->mplsCBCounter) + { + p_wpd->mplsCBReadAddress = WM_REG_EXTENSION_DEV_MODE; + status = CALC_STATUS(WPADiSendReadData( + &p_wpd->stdCmdQueue, &p_wpd->mplsCBReadBuf, 2, + p_wpd->mplsCBReadAddress, &__wpadMplsCallback)); + } + else + { + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_GET_EXTENSION_ID; + status = CALC_STATUS(WPADiSendWriteDataCmd( + &p_wpd->stdCmdQueue, 0x00, WM_REG_EXTENSION_DEV_MODE, + &__wpadMplsCallback)); + } + } + } + else if (result == WPAD_ERR_3) + { + if (p_wpd->mplsCBCounter) + { + if (--p_wpd->mplsCBCounter > 1) + p_wpd->mplsCBReadAddress = WM_REG_MPLS_DEV_MODE; + else + p_wpd->mplsCBReadAddress = WM_REG_EXTENSION_DEV_MODE; + + status = CALC_STATUS(WPADiSendReadData( + &p_wpd->stdCmdQueue, &p_wpd->mplsCBReadBuf, 2, + p_wpd->mplsCBReadAddress, &__wpadMplsCallback)); + } + } + break; + + case WPAD_STATE_MPLS_CB_CLEAR_DEV_MODE: + if (result == WPAD_ESUCCESS) + { + if (p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MOTION_PLUS + || p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MPLS_PT_FS + || p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MPLS_PT_CLASSIC + || p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MPLS_PT_UNKNOWN) + { + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_DONE; + + status = CALC_STATUS(WPADiSendWriteDataCmd( + &p_wpd->stdCmdQueue, 0x00, WM_REG_EXTENSION_DEV_MODE, + &__wpadMplsCallback)); + } + else + { + status = WPAD_ERR_3; + } + } + + break; + + case WPAD_STATE_MPLS_CB_WRITE_PENDING_MPLS_DEV_MODE: + if (result == WPAD_ESUCCESS) + { + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_INIT_MPLS_EXT; + + status = CALC_STATUS(WPADiSendWriteDataCmd( + &p_wpd->stdCmdQueue, p_wpd->pendingMplsCommand, + WM_REG_MPLS_DEV_MODE, &__wpadMplsCallback)); + } + + break; + + case WPAD_STATE_MPLS_CB_INIT_MPLS_EXT: + if (result == WPAD_ESUCCESS) + { + p_wpd->isInitingMpls = TRUE; + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_START; + } + + break; + + case WPAD_STATE_MPLS_CB_5: + if (result == WPAD_ESUCCESS) + { + if (p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MOTION_PLUS + || p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MPLS_PT_FS + || p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MPLS_PT_CLASSIC + || p_wpd->mplsCBReadBuf[1] == WPAD_DEV_MPLS_PT_UNKNOWN) + { + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_RESET; + + status = CALC_STATUS(WPADiSendWriteDataCmd( + &p_wpd->stdCmdQueue, 0x00, WM_REG_EXTENSION_F2, + &__wpadMplsCallback)); + } + else + { + status = WPAD_ERR_3; + } + } + + break; + + case WPAD_STATE_MPLS_CB_GET_EXTENSION_ID: + if (result == WPAD_ESUCCESS) + { + p_wpd->mplsCBCounter = 4; + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_1; + + status = CALC_STATUS( + WPADiSendReadData(&p_wpd->stdCmdQueue, &p_wpd->mplsCBReadBuf, 1, + WM_REG_MPLS_ID_BYTE, &__wpadMplsCallback)); + } + + break; + + case WPAD_STATE_MPLS_CB_DONE: + status = WPAD_ESUCCESS; + + // fallthrough + + case WPAD_STATE_MPLS_CB_RESET: + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_START; + break; + } + + if (p_wpd->mplsCBState == WPAD_STATE_MPLS_CB_START + || status != WPAD_ESUCCESS) + { + controlMplsCB = p_wpd->controlMplsCB; + p_wpd->controlMplsBusy = FALSE; + p_wpd->controlMplsCB = NULL; + + if (controlMplsCB) + (*controlMplsCB)(chan, status); + } + +#undef CALC_STATUS +} + +WPADResult WPADiControlMpls(WPADChannel chan, WPADMplsCommand command, + WPADCallback *cb) +{ + BOOL intrStatus; + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + intrStatus = OSDisableInterrupts(); + + BOOL handshakeFinished; + u32 devType = p_wpd->devType; + u8 devMode = p_wpd->devMode; + WPADResult status = p_wpd->status; + handshakeFinished = p_wpd->handshakeFinished; + u8 controlMplsCBRegistered = + p_wpd->controlMplsCB ? TRUE : p_wpd->controlMplsBusy; + + if (status == WPAD_ENODEV) + goto end; + + if (!handshakeFinished || controlMplsCBRegistered) + { + status = WPAD_ECOMM; + goto end; + } + + if (p_wpd->certValidityStatus < 0) // == WPAD_CERT_INVALID + { + status = WPAD_EINVAL; + goto end; + } + + if (command == devMode) + { + status = WPAD_ESUCCESS; + goto end; + } + + // clang-format off + if (((devType == WPAD_DEV_MOTION_PLUS + || devType == WPAD_DEV_MPLS_PT_FS + || devType == WPAD_DEV_MPLS_PT_CLASSIC + || devType == WPAD_DEV_MPLS_PT_UNKNOWN) + && (command == WPAD_MPLS_DISABLE + || command == WPAD_MPLS_CMD_80)) + || ((devType != WPAD_DEV_MOTION_PLUS + && devType != WPAD_DEV_MPLS_PT_FS + && devType != WPAD_DEV_MPLS_PT_CLASSIC + && devType != WPAD_DEV_MPLS_PT_UNKNOWN) + && (command == WPAD_MPLS_MAIN + || command == WPAD_MPLS_FS + || command == WPAD_MPLS_CLASSIC))) + // clang-format on + { + if (command == WPAD_MPLS_CMD_80 && p_wpd->mplsUptimeMs < 200) + { + status = WPAD_ECOMM; + goto end; + } + + p_wpd->pendingMplsCommand = command; + p_wpd->mplsCBCounter = 4; + status = WPAD_ESUCCESS; + + switch (command) + { + case WPAD_MPLS_DISABLE: + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_CLEAR_DEV_MODE; + p_wpd->mplsCBReadAddress = WM_REG_EXTENSION_DEV_MODE; + break; + + case WPAD_MPLS_CMD_80: + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_5; + p_wpd->mplsCBReadAddress = WM_REG_EXTENSION_DEV_MODE; + break; + + default: + p_wpd->mplsCBState = WPAD_STATE_MPLS_CB_1; + p_wpd->mplsCBReadAddress = WM_REG_MPLS_DEV_MODE; + break; + } + + if (!WPADiSendReadData(&p_wpd->stdCmdQueue, &p_wpd->mplsCBReadBuf, 2, + p_wpd->mplsCBReadAddress, &__wpadMplsCallback)) + { + status = WPAD_ECOMM; + goto end; + } + + p_wpd->controlMplsBusy = TRUE; + p_wpd->controlMplsCB = cb; + + OSRestoreInterrupts(intrStatus); + + return WPAD_ESUCCESS; + } + else + { + status = WPAD_EINVAL; + } + +end: // earlier this time. hm + OSRestoreInterrupts(intrStatus); + + if (cb) + (*cb)(chan, status); + + return status; +} + +// WPADControlMpls ([SGLEA4]/MAP/GormitiDebug.MAP:25384) +extern void __deadstrip7(void) +{ + (void)"WPADControlMpls is obsolete.\n"; +} + +void WPADiGetMplsCalibration(WPADChannel chan, struct WPADMplsCalibration *high, + struct WPADMplsCalibration *low) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSAssert_Line(5516, high != NULL && low != NULL); + + BOOL intrStatus = OSDisableInterrupts(); + + if (high != NULL && low != NULL) + { + *high = p_wpd->extConfig.mpls.high; + *low = p_wpd->extConfig.mpls.low; + } + + OSRestoreInterrupts(intrStatus); +} + +// WPADGetMplsCalibration ([SGLEA4]/MAP/GormitiDebug.MAP:25386) +extern void __deadstrip8(void) +{ + (void)"WPADGetMplsCalibration is obsolete.\n"; +} + +// WPADSetMplsCalibration ([SGLEA4]/MAP/GormitiDebug.MAP:25387) +extern void __deadstrip9(void) +{ + (void)"WPADSetMplsCalibration is obsolete.\n"; +} + +BOOL WPADiSendSetPort(struct WPADCmdQueue *cmdQueue, u8 port, WPADCallback *cb) +{ + BOOL success; + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_SET_PORT; + cmdBlk.dataLength = RPT11_SIZE; + cmdBlk.dataBuf[RPT11_LED] = port << 4; + cmdBlk.cmdCB = cb; + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendSetReportType(struct WPADCmdQueue *cmdQueue, s32 format, + BOOL notContinuous, WPADCallback *cb) +{ + BOOL success; + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_SET_DATA_REPORT_MODE; + cmdBlk.dataLength = RPT12_SIZE; + cmdBlk.dataBuf[RPT12_CONT_REPORT] = notContinuous ? 0 : 4; + cmdBlk.cmdCB = cb; + + switch (format) + { + case WPAD_FMT_CORE_BTN: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN; + break; + + case WPAD_FMT_CORE_BTN_ACC: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC; + break; + + case WPAD_FMT_CORE_BTN_ACC_DPD: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD12; + break; + + case WPAD_FMT_FS_BTN: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_EXT8; + break; + + case WPAD_FMT_FS_BTN_ACC: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_EXT16; + break; + + case WPAD_FMT_FS_BTN_ACC_DPD: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + + case WPAD_FMT_CLASSIC_BTN: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_EXT8; + break; + + case WPAD_FMT_CLASSIC_BTN_ACC: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_EXT16; + break; + + case WPAD_FMT_CLASSIC_BTN_ACC_DPD: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + + case WPAD_FMT_BTN_ACC_DPD_EXTENDED: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD18_1; + break; + + case WPAD_FMT_TRAIN: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_EXT8; + break; + + case WPAD_FMT_GUITAR: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + + case WPAD_FMT_DRUM: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + + case WPAD_FMT_TURNTABLE: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + + case WPAD_FMT_BULK: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_EXT16; + break; + + case WPAD_FMT_BALANCE_CHECKER: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_EXT19; + break; + + case WPAD_FMT_VSM: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_EXT16; + break; + + case WPAD_FMT_TAIKO: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + + case WPAD_FMT_MOTION_PLUS: + cmdBlk.dataBuf[RPT12_DATA_REPORT_MODE] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + } + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendEnableDPD(struct WPADCmdQueue *cmdQueue, BOOL enabled, + WPADCallback *cb) +{ + BOOL success; + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_ENABLE_DPD; + cmdBlk.dataLength = RPT13_SIZE; + cmdBlk.dataBuf[RPT13_DPD_ENABLE] = enabled ? 4 : 0; + cmdBlk.cmdCB = cb; + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendEnableSpeaker(struct WPADCmdQueue *cmdQueue, BOOL enabled, + WPADCallback *cb) +{ + BOOL success; + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_ENABLE_SPEAKER; + cmdBlk.dataLength = RPT14_SIZE; + cmdBlk.dataBuf[RPT14_SPEAKER_ENABLE] = enabled ? 4 : 0; + cmdBlk.cmdCB = cb; + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +// SendGetContinuousStatus? +// this is just the request status report report; what is Cont +BOOL WPADiSendGetContStat(struct WPADCmdQueue *cmdQueue, WPADInfo *wpInfoOut, + WPADCallback *cb) +{ + BOOL success; + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_REQUEST_STATUS; + cmdBlk.dataLength = RPT15_SIZE; + cmdBlk.dataBuf[0] = 0; // nothing special + cmdBlk.cmdCB = cb; + cmdBlk.statusReportOut = wpInfoOut; + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendWriteDataCmd(struct WPADCmdQueue *cmdQueue, u8 cmd, u32 address, + WPADCallback *cb) +{ + return WPADiSendWriteData(cmdQueue, &cmd, sizeof cmd, address, cb); +} + +BOOL WPADiSendWriteData(struct WPADCmdQueue *cmdQueue, const void *p_buf, + u16 len, u32 address, WPADCallback *cb) +{ + BOOL success; + u8 packedLen = len & 0x1f; + + OSAssert_Line(5721, len > 0 && len <= 16); + OSAssert_Line(5722, p_buf != NULL); + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_WRITE_DATA; + cmdBlk.dataLength = RPT16_SIZE; + cmdBlk.cmdCB = cb; + memcpy(&cmdBlk.dataBuf[RPT16_DATA_DST_ADDRESS], &address, sizeof address); + memcpy(&cmdBlk.dataBuf[RPT16_DATA_LENGTH], &packedLen, sizeof packedLen); + memcpy(&cmdBlk.dataBuf[RPT16_DATA], p_buf, len); + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendReadData(struct WPADCmdQueue *cmdQueue, void *p_buf, u16 len, + u32 address, WPADCallback *cb) +{ + BOOL success; + + OSAssert_Line(5740, p_buf != NULL); + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_READ_DATA; + cmdBlk.dataLength = RPT17_SIZE; + cmdBlk.cmdCB = cb; + memcpy(&cmdBlk.dataBuf[RPT17_DATA_SRC_ADDRESS], &address, sizeof address); + memcpy(&cmdBlk.dataBuf[RPT17_DATA_LENGTH], &len, sizeof len); + cmdBlk.dstBuf = p_buf; + cmdBlk.readLength = len; + cmdBlk.readAddress = address; + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendStreamData(struct WPADCmdQueue *cmdQueue, const void *p_buf, + u16 len) +{ + BOOL success; + u8 packedLen = len << 3; + + OSAssert_Line(5764, len > 0 && len <= 20); + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_SEND_SPEAKER_DATA; + cmdBlk.dataLength = sizeof cmdBlk.dataBuf; + cmdBlk.dataBuf[RPT18_DATA_LENGTH] = packedLen; + cmdBlk.cmdCB = NULL; + memcpy(&cmdBlk.dataBuf[RPT18_DATA], p_buf, len); + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendMuteSpeaker(struct WPADCmdQueue *cmdQueue, BOOL muted, + WPADCallback *cb) +{ + BOOL success; + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_MUTE_SPEAKER; + cmdBlk.dataLength = RPT19_SIZE; + cmdBlk.dataBuf[RPT19_SPEAKER_MUTE] = muted ? 4 : 0; + cmdBlk.cmdCB = cb; + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiSendDPDCSB(struct WPADCmdQueue *cmdQueue, BOOL enabled, + WPADCallback *cb) +{ + BOOL success; + + struct WPADCmd cmdBlk; + cmdBlk.reportID = RPTID_SEND_DPD_CSB; + cmdBlk.dataLength = RPT1A_SIZE; + cmdBlk.dataBuf[RPT1A_DPD_CSB] = enabled ? 4 : 0; + cmdBlk.cmdCB = cb; + + success = __wpadPushCommand(cmdQueue, cmdBlk); + return success; +} + +BOOL WPADiIsAvailableCmdQueue(struct WPADCmdQueue *cmdQueue, s8 num) +{ + s8 queueSize = __wpadGetQueueSize(cmdQueue); + + if ((u32)(queueSize + num) <= cmdQueue->length - 1) + return TRUE; + else + return FALSE; +} + +static s8 __wpadGetQueueSize(struct WPADCmdQueue *cmdQueue) +{ + BOOL intrStatus = OSDisableInterrupts(); + + s8 queueRemaining = cmdQueue->indexIn - cmdQueue->indexOut; + + if (queueRemaining < 0) + queueRemaining += cmdQueue->length; + + OSRestoreInterrupts(intrStatus); + + return queueRemaining; +} + +void WPADiClearQueue(struct WPADCmdQueue *cmdQueue) +{ + BOOL intrStatus = OSDisableInterrupts(); + + cmdQueue->indexOut = 0; + cmdQueue->indexIn = 0; + memset(cmdQueue->queue, 0, sizeof *cmdQueue->queue * cmdQueue->length); + + OSRestoreInterrupts(intrStatus); +} + +static BOOL __wpadPushCommand(struct WPADCmdQueue *cmdQueue, + struct WPADCmd cmdBlk) +{ + BOOL intrStatus = OSDisableInterrupts(); + + if (cmdQueue->length - 1 == (u32)__wpadGetQueueSize(cmdQueue)) + { + OSRestoreInterrupts(intrStatus); + + return FALSE; + } + + // unnecessary call + memset(&cmdQueue->queue[cmdQueue->indexIn], 0, + sizeof cmdQueue->queue[cmdQueue->indexIn]); + + memcpy(&cmdQueue->queue[cmdQueue->indexIn], &cmdBlk, + sizeof cmdQueue->queue[cmdQueue->indexIn]); + + cmdQueue->indexIn = (u32)cmdQueue->indexIn == ((cmdQueue->length) - 1) + ? 0 + : cmdQueue->indexIn + 1; + + OSRestoreInterrupts(intrStatus); + + return TRUE; +} + +static BOOL __wpadGetCommand(struct WPADCmdQueue *cmdQueue, + struct WPADCmd *cmdBlkOut) +{ + if (__wpadGetQueueSize(cmdQueue) == 0) + return FALSE; + + BOOL intrStatus = OSDisableInterrupts(); + + memcpy(cmdBlkOut, &cmdQueue->queue[cmdQueue->indexOut], sizeof *cmdBlkOut); + + OSRestoreInterrupts(intrStatus); + + return TRUE; +} + +static BOOL __wpadPopCommand(struct WPADCmdQueue *cmdQueue) +{ + BOOL intrStatus = OSDisableInterrupts(); + + if (__wpadGetQueueSize(cmdQueue) == 0) + { + OSRestoreInterrupts(intrStatus); + return FALSE; + } + + memset(&cmdQueue->queue[cmdQueue->indexOut], 0, + sizeof cmdQueue->queue[cmdQueue->indexOut]); + + cmdQueue->indexOut = (u32)cmdQueue->indexOut == cmdQueue->length - 1 + ? 0 + : cmdQueue->indexOut + 1; + + OSRestoreInterrupts(intrStatus); + + return TRUE; +} + +static BOOL __wpadSetSensorBarPower(BOOL enabled) +{ + u32 reg; + BOOL intrStatus = OSDisableInterrupts(); + + reg = ACRReadReg(0xc0); + + register_t newStatus; + if (enabled) + newStatus = reg | (1 << 8); + else + newStatus = reg & ~(1 << 8); + + ACRWriteReg(0xc0, newStatus); + BOOL oldStatus = reg & (1 << 8) ? 1 : 0; + + OSRestoreInterrupts(intrStatus); + + return oldStatus; +} + +static void __wpadSetScreenSaverFlag(BOOL disabled) +{ + if (disabled) + __VIResetRFIdle(); +} + +static u8 __wpadGetDpdSensitivity(void) +{ + u8 dpdSens = SCGetBtDpdSensibility(); + + if (dpdSens < WPAD_MIN_DPD_SENS) + dpdSens = WPAD_MIN_DPD_SENS; + + if (dpdSens > WPAD_MAX_DPD_SENS) + dpdSens = WPAD_MAX_DPD_SENS; + + return dpdSens; +} + +static u8 __wpadGetSensorBarPosition(void) +{ + return SCGetWpadSensorBarPosition() == SC_SENSOR_BAR_TOP + ? SC_SENSOR_BAR_TOP + : SC_SENSOR_BAR_BOTTOM; +} + +static u32 __wpadGetMotorMode(void) +{ + // ? + return !!(SCGetWpadMotorMode() == 1); +} + +static u8 __wpadClampSpeakerVolume(u8 volume) +{ + u8 clampedVol = volume; + + if (volume <= 0) + clampedVol = 0; + + if (volume >= 127) + clampedVol = 127; + + return clampedVol; +} + +static u8 __wpadGetSpeakerVolume(void) +{ + u8 volume = SCGetWpadSpeakerVolume(); + volume = __wpadClampSpeakerVolume(volume); + return volume; +} + +static u16 __wpadGetBTEBufferStatus(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + WPADResult status = p_wpd->status; + WUDDevHandle dev_handle = p_wpd->devHandle; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + return 0; + + return _WUDGetQueuedSize(dev_handle); +} + +static u16 __wpadGetBTMBufferStatus(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + WPADResult status = p_wpd->status; + WUDDevHandle dev_handle = p_wpd->devHandle; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + return 0; + + return _WUDGetNotAckedSize(dev_handle); +} + +void WPADRecalibrate(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL intrStatus = OSDisableInterrupts(); + + p_wpd->calibrated = FALSE; + p_wpd->recalibHoldMs = 0; + + OSRestoreInterrupts(intrStatus); +} + +#if !defined(NDEBUG) +BOOL WPADiIsDummyExtension(WPADChannel chan) +{ + return _wpadDummyAttach[chan]; +} +#endif + +BOOL WPADIsUsedCallbackByKPAD(void) +{ + return _wpadUsedCallback; +} + +void WPADSetCallbackByKPAD(BOOL isKPAD) +{ + _wpadUsedCallback = isKPAD; +} + +static void __wpadCertFailed(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + switch (p_wpd->certState) + { + case WPAD_STATE_CERT_PROBE_X: + case WPAD_STATE_CERT_GET_X: + case WPAD_STATE_CERT_VERIFY_X: + case WPAD_STATE_CERT_CHALLENGE: + case WPAD_STATE_CERT_PROBE_Y: + case WPAD_STATE_CERT_GET_Y: + case WPAD_STATE_CERT_VERIFY_Y: + case WPAD_STATE_CERT_CHECK: + case WPAD_STATE_CERT_ETIME: + default: // ??? + p_wpd->certValidityStatus = WPAD_CERT_INVALID; + p_wpd->certWorkBusy = FALSE; + p_wpd->certChallengeRandomBit = -1; + p_wpd->certState = WPAD_STATE_CERT_INVALID; + p_wpd->certStateWorkMs = 0; + p_wpd->certWorkCounter = 0; + p_wpd->certWorkMs = 0; + + memset(p_wpd->certBuf0, 0, sizeof p_wpd->certBuf0); + memset(p_wpd->certBuf1, 0, sizeof p_wpd->certBuf1); + memset(p_wpd->certBufBig, 0, sizeof p_wpd->certBufBig); + + p_wpd->certBuf0[0] = p_wpd->certBuf1[0] = p_wpd->certBufBig[0] = 1; + + p_wpd->wmParamOffset = 0; + p_wpd->certMayVerifyByCalibBlock = -1; + p_wpd->devType = WPAD_DEV_252; + + break; + } + + if (p_wpd->extensionCB) + (*p_wpd->extensionCB)(chan, WPAD_DEV_252); +} + +static void __wpadCertCalcMulX(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (p_wpd->certChallengeRandomBit != 0) + LINTMul(p_wpd->certBufBig, p_wpd->certBuf0, certv); + else + memcpy(p_wpd->certBufBig, p_wpd->certBuf0, sizeof p_wpd->certBuf0); + + p_wpd->certWorkBusy = FALSE; + p_wpd->certStateWorkMs = 0; + p_wpd->certState = WPAD_STATE_CERT_CALC_MOD_X; +} + +static void __wpadCertCalcModX(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSTime start = OSGetTime(); + + int msbCertn = LINTMsb(certn); + int msbBuf; + + ULONG buf[64 + 2]; + do + { + msbBuf = LINTMsb(p_wpd->certBufBig); + + if (msbBuf > msbCertn) + { + LINTLshift(buf, (ULONG *)certn, msbBuf - msbCertn - 1); + + if (LINTCmp(p_wpd->certBufBig, buf) >= 0) + LINTSub(p_wpd->certBufBig, p_wpd->certBufBig, buf); + } + else + { + if (LINTCmp(p_wpd->certBufBig, certn) >= 0) + LINTSub(p_wpd->certBufBig, p_wpd->certBufBig, certn); + + memcpy(p_wpd->certBuf0, p_wpd->certBufBig, sizeof p_wpd->certBuf0); + + p_wpd->certState = WPAD_STATE_CERT_CALC_MUL_Y; + } + } while (OSTicksToMicroseconds(OSDiffTick(OSGetTime(), start)) < 80); + + p_wpd->certWorkBusy = FALSE; + p_wpd->certStateWorkMs = 0; +} + +static void __wpadCertCalcMulY(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + LINTMul(p_wpd->certBufBig, p_wpd->certBuf1, p_wpd->certBuf1); + + p_wpd->certWorkBusy = FALSE; + p_wpd->certStateWorkMs = 0; + p_wpd->certState = WPAD_STATE_CERT_CALC_MOD_Y; +} + +static void __wpadCertCalcModY(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + OSTime start = OSGetTime(); + + int msbCertn = LINTMsb(certn); + int msbBuf; + + ULONG buf[64 + 2]; + do + { + msbBuf = LINTMsb(p_wpd->certBufBig); + + if (msbBuf > msbCertn) + { + LINTLshift(buf, (ULONG *)certn, msbBuf - msbCertn - 1); + + if (LINTCmp(p_wpd->certBufBig, buf) >= 0) + LINTSub(p_wpd->certBufBig, p_wpd->certBufBig, buf); + } + else + { + if (LINTCmp(p_wpd->certBufBig, certn) >= 0) + LINTSub(p_wpd->certBufBig, p_wpd->certBufBig, certn); + + memcpy(p_wpd->certBuf1, p_wpd->certBufBig, sizeof p_wpd->certBuf1); + + p_wpd->certState = WPAD_STATE_CERT_CHECK; + } + } while (OSTicksToMicroseconds(OSDiffTick(OSGetTime(), start)) < 80); + + p_wpd->certWorkBusy = FALSE; + p_wpd->certStateWorkMs = 0; +} + +static void __wpadCertCheckResult(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + int result = LINTCmp(p_wpd->certBuf0, p_wpd->certBuf1); + + p_wpd->certWorkBusy = FALSE; + p_wpd->certStateWorkMs = 0; + p_wpd->certState = WPAD_STATE_CERT_SUCCESS; + + if (result == 0) + { + p_wpd->certValidityStatus = WPAD_CERT_VALID; + p_wpd->certMayVerifyByCalibBlock = TRUE; + } + else + { + __wpadCertFailed(chan); + } +} + +static void __wpadCertChallengeCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->certWorkBusy = FALSE; + + if (result == WPAD_ESUCCESS) + { + p_wpd->certStateWorkMs = + p_wpd->certChallengeRandomBit == 0 ? 1000 : 9000; + p_wpd->certState = WPAD_STATE_CERT_PROBE_Y; + } + else if (p_wpd->certWorkCounter++) + { + p_wpd->certStateWorkMs = 0; + __wpadCertFailed(chan); + } +} + +static void __wpadCertChallenge(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADiSendWriteDataCmd(&p_wpd->extCmdQueue, p_wpd->certChallengeRandomBit, + WM_REG_EXTENSION_CERT_CHALLENGE, + &__wpadCertChallengeCallback); +} + +static void __wpadCertProbeReadyCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->certWorkBusy = FALSE; + + if (result == WPAD_ESUCCESS) + { + p_wpd->certStateWorkMs = 0; + p_wpd->certWorkCounter++; + + if (p_wpd->certState == WPAD_STATE_CERT_PROBE_X) + { + /* NOTE: unnecessary check, because if x <= 4, then x also <= 12 and + * certWorkCounter is set to 0 anyways + */ + if (p_wpd->certProbeByte <= 4) + p_wpd->certWorkCounter = 0; + + if (p_wpd->certProbeByte <= 12) + { + p_wpd->certStateWorkMs = 5500; + p_wpd->certWorkCounter = 0; + } + + if (p_wpd->certProbeByte == 14) + { + p_wpd->certState = WPAD_STATE_CERT_GET_X; + p_wpd->certWorkCounter = 0; + } + } + + if (p_wpd->certState == WPAD_STATE_CERT_PROBE_Y) + { + if (p_wpd->certProbeByte == 26) + { + p_wpd->certState = WPAD_STATE_CERT_GET_Y; + p_wpd->certWorkCounter = 0; + } + } + } + else + { + p_wpd->certStateWorkMs = 1000; + p_wpd->certWorkCounter += 4; + } + + if (p_wpd->certWorkCounter > 100) + __wpadCertFailed(chan); +} + +static void __wpadCertProbeReady(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADiSendReadData(&p_wpd->extCmdQueue, &p_wpd->certProbeByte, + sizeof p_wpd->certProbeByte, WM_REG_EXTENSION_CERT_PROBE, + &__wpadCertProbeReadyCallback); +} + +static void __wpadCertGetParamCallback(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->certWorkBusy = FALSE; + + u32 i; + if (result == WPAD_ESUCCESS) + { + for (i = 0; i < p_wpd->wmReadLength / (int)sizeof(ULONG); i++) + { + // lwbrx op + u32 wbr = p_wpd->wmReadDataBuf[i * 4 + 0] << 0 + | p_wpd->wmReadDataBuf[i * 4 + 1] << 8 + | p_wpd->wmReadDataBuf[i * 4 + 2] << 16 + | p_wpd->wmReadDataBuf[i * 4 + 3] << 24; + + LINTNextElement(p_wpd->certParamPtr, + i + p_wpd->wmParamOffset / (int)sizeof(ULONG)) = + wbr; + } + + p_wpd->certWorkCounter = 0; + + p_wpd->wmParamOffset += p_wpd->wmReadLength; + if (p_wpd->wmParamOffset < WM_EXTENSION_CERT_PARAM_SIZE) + { + p_wpd->certStateWorkMs = 0; + } + else + { + for (i = 0; i < WM_EXTENSION_CERT_PARAM_SIZE / (int)sizeof(ULONG); + i++) + { + if (LINTNextElement(p_wpd->certParamPtr, i)) + *p_wpd->certParamPtr = i + 1; + } + } + } + else + { + if (p_wpd->certWorkCounter++ < 1) + p_wpd->certStateWorkMs = 0; + else + __wpadCertFailed(chan); + } +} + +static u8 __wpadCertGetParam(WPADChannel chan, ULONG *certParamOut) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (p_wpd->wmParamOffset < WM_EXTENSION_CERT_PARAM_SIZE) + { + p_wpd->certParamPtr = certParamOut; + WPADiSendReadData(&p_wpd->extCmdQueue, p_wpd->wmReadDataBuf, + sizeof p_wpd->wmReadDataBuf, + WM_REG_EXTENSION_CERT_PARAM + p_wpd->wmParamOffset, + &__wpadCertGetParamCallback); + + return FALSE; + } + else + { + p_wpd->certWorkBusy = FALSE; + p_wpd->wmParamOffset = 0; + + return TRUE; + } +} + +static void __wpadCertGetParamX(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (!__wpadCertGetParam(chan, p_wpd->certBuf0)) + return; + + if (p_wpd->certBuf0[0] <= 1 && p_wpd->certBuf0[1] <= 1) + goto fail; + + if (LINTCmp(p_wpd->certBuf0, certn) != -1) + goto fail; + + p_wpd->certState = WPAD_STATE_CERT_VERIFY_X; + p_wpd->certStateWorkMs = 500; + + return; + +fail: + __wpadCertFailed(chan); +} + +static void __wpadCertVerifyParamX(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (!__wpadCertGetParam(chan, p_wpd->certBufBig)) + return; + + if (p_wpd->certBufBig[0] <= 1 && p_wpd->certBufBig[1] <= 1) + goto fail; + + if (LINTCmp(p_wpd->certBufBig, certn) != -1) + goto fail; + + if (LINTCmp(p_wpd->certBufBig, p_wpd->certBuf0) != 0) + goto fail; + + memset(p_wpd->certBufBig, 0, sizeof p_wpd->certBufBig); + p_wpd->certBufBig[0] = 1; + p_wpd->certChallengeRandomBit = OSGetTick() % 2; + p_wpd->certState = WPAD_STATE_CERT_CHALLENGE; + p_wpd->certStateWorkMs = 0; + + return; + +fail: + __wpadCertFailed(chan); +} + +static inline void __wpadCertGetParamY(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (!__wpadCertGetParam(chan, p_wpd->certBuf1)) + return; + + { // block + ULONG localCert[16 + 2]; + __memcpy(localCert, certn, sizeof localCert); + + localCert[1]--; + + if (p_wpd->certBuf1[0] <= 1 && p_wpd->certBuf1[1] <= 1) + goto fail; + + // could be a ternary to be more concise + if ((!p_wpd->certChallengeRandomBit + || LINTCmp(p_wpd->certBuf1, certn) != -1) + && (p_wpd->certChallengeRandomBit + || LINTCmp(p_wpd->certBuf1, localCert) != -1)) + { + goto fail; + } + + p_wpd->certStateWorkMs = 500; + p_wpd->certState = WPAD_STATE_CERT_VERIFY_Y; + } + + return; + +fail: + __wpadCertFailed(chan); +} + +static void __wpadCertVerifyParamY(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (!__wpadCertGetParam(chan, p_wpd->certBufBig)) + return; + + { // block + ULONG localCert[16 + 2]; + __memcpy(localCert, certn, sizeof localCert); + + localCert[1]--; + + if (p_wpd->certBufBig[0] <= 1 && p_wpd->certBufBig[1] <= 1) + goto fail; + + // same here + if ((!p_wpd->certChallengeRandomBit + || LINTCmp(p_wpd->certBufBig, certn) != -1) + && (p_wpd->certChallengeRandomBit + || LINTCmp(p_wpd->certBufBig, localCert) != -1)) + { + goto fail; + } + + if (LINTCmp(p_wpd->certBufBig, p_wpd->certBuf1) != 0) + goto fail; + + memset(p_wpd->certBufBig, 0, sizeof p_wpd->certBufBig); + p_wpd->certBufBig[0] = 1; + p_wpd->certState = WPAD_STATE_CERT_CALC_MUL_X; + p_wpd->certStateWorkMs = 0; + } + + return; + +fail: + __wpadCertFailed(chan); +} + +static void __wpadCertWork(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (p_wpd->certValidityStatus != WPAD_CERT_UNCHECKED) + return; + + if (p_wpd->certState < 0) + return; + + if (!p_wpd->wpInfo.attach) + return; + + if (!p_wpd->certWorkBusy && p_wpd->certStateWorkMs-- < 0) + { + p_wpd->certWorkBusy = TRUE; + + switch (p_wpd->certState) + { + case WPAD_STATE_CERT_PROBE_X: + __wpadCertProbeReady(chan); + break; + + case WPAD_STATE_CERT_GET_X: + __wpadCertGetParamX(chan); + break; + + case WPAD_STATE_CERT_VERIFY_X: + __wpadCertVerifyParamX(chan); + break; + + case WPAD_STATE_CERT_CHALLENGE: + __wpadCertChallenge(chan); + break; + + case WPAD_STATE_CERT_PROBE_Y: + __wpadCertProbeReady(chan); + break; + + case WPAD_STATE_CERT_GET_Y: + __wpadCertGetParamY(chan); + break; + + case WPAD_STATE_CERT_VERIFY_Y: + __wpadCertVerifyParamY(chan); + break; + + case WPAD_STATE_CERT_CALC_MUL_X: + __wpadCertCalcMulX(chan); + break; + + case WPAD_STATE_CERT_CALC_MOD_X: + __wpadCertCalcModX(chan); + break; + + case WPAD_STATE_CERT_CALC_MUL_Y: + __wpadCertCalcMulY(chan); + break; + + case WPAD_STATE_CERT_CALC_MOD_Y: + __wpadCertCalcModY(chan); + break; + + case WPAD_STATE_CERT_CHECK: + __wpadCertCheckResult(chan); + break; + } + } + + if (p_wpd->certWorkMs++ > 60000) + { + p_wpd->certState = WPAD_STATE_CERT_ETIME; + __wpadCertFailed(chan); + } +} diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPAD.h b/src/sdk/RVL_SDK/revolution/wpad/WPAD.h new file mode 100644 index 00000000..c50dfe95 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPAD.h @@ -0,0 +1,665 @@ +#ifndef RVL_SDK_WPAD_H +#define RVL_SDK_WPAD_H + +/******************************************************************************* + * headers + */ + +#include + +#include "WUD.h" + +#include + +//#include "context_rvl.h" + +/******************************************************************************* + * macros + */ + +#define WPAD_MAX_DPD_OBJECTS 4 + +#define WPAD_MIN_DPD_SENS 1 +#define WPAD_MAX_DPD_SENS 5 + +/******************************************************************************* + * types + */ + +#ifdef __cplusplus + extern "C" { +#endif + +// for ease of use in ternaries +typedef s32 WPADResult; +enum WPADResult_et +{ + WPAD_ERR_OK = 0, + + WPAD_ERR_NO_CONTROLLER = -1, /* name known from asserts */ + WPAD_ERR_COMMUNICATION_ERROR = -2, + WPAD_ERR_3 = -3, + WPAD_ERR_INVALID_ARG = -4, +// WPAD_ERR_5 = -5, /* unknown */ +// WPAD_ERR_6 = -6, /* unknown */ + WPAD_ERR_INVALID_DATA = -7, + +#define WPAD_ESUCCESS WPAD_ERR_OK +#define WPAD_ENODEV WPAD_ERR_NO_CONTROLLER +#define WPAD_ECOMM WPAD_ERR_COMMUNICATION_ERROR + +#define WPAD_EINVAL WPAD_ERR_INVALID_ARG + +/* maybe? i was scouring the internet for explanation and usage of this error + * macro, and it seems close enough + * + * it's not ENODATA, that's more like if you got no data, but here it's that we + * did get the data but it wasn't good + */ +#define WPAD_EBADE WPAD_ERR_INVALID_DATA + +// apparently enum vs literal is a thing. cool +#define WPAD_CESUCCESS (WPAD_ESUCCESS + 0) +#define WPAD_CENODEV (WPAD_ENODEV + 0) +#define WPAD_CECOMM (WPAD_ECOMM + 0) +#define WPAD_CERR_3 (WPAD_ERR_3 + 0) +#define WPAD_CEINVAL (WPAD_EINVAL + 0) +#define WPAD_CEBADE (WPAD_EBADE + 0) +}; + +typedef WUDLibStatus WPADLibStatus; +enum WPADLibStatus_et +{ + WPAD_LIB_STATUS_0 = WUD_LIB_STATUS_0, + WPAD_LIB_STATUS_1 = WUD_LIB_STATUS_1, + WPAD_LIB_STATUS_2 = WUD_LIB_STATUS_2, + WPAD_LIB_STATUS_3 = WUD_LIB_STATUS_3, + WPAD_LIB_STATUS_4 = WUD_LIB_STATUS_4, +}; + +// for ease of use in for loops +typedef s32 WPADChannel; +enum WPADChannel_et +{ + WPAD_CHAN0, + WPAD_CHAN1, + WPAD_CHAN2, + WPAD_CHAN3, /* name known from asserts */ + + WPAD_MAX_CONTROLLERS, /* name known from asserts */ + WPAD_CHAN_INVALID = -1, +}; + +typedef s32 WPADDeviceType; +enum WPADDeviceType_et +{ + WPAD_DEV_CORE = 0, + WPAD_DEV_FS = 1, + WPAD_DEV_CLASSIC = 2, /* name known from asserts, but not value */ + WPAD_DEV_BALANCE_CHECKER = 3, + WPAD_DEV_VSM = 4, + + WPAD_DEV_MOTION_PLUS = 5, + WPAD_DEV_MPLS_PT_FS = 6, + WPAD_DEV_MPLS_PT_CLASSIC = 7, + + WPAD_DEV_TRAIN = 16, + WPAD_DEV_GUITAR = 17, + WPAD_DEV_DRUM = 18, + WPAD_DEV_TAIKO = 19, + WPAD_DEV_TURNTABLE = 20, + + // seems to be like maybe general purpose non-specific device types + // maybe this was for testing or something? idk + WPAD_DEV_BULK_1 = 21, + WPAD_DEV_BULK_2 = 22, + WPAD_DEV_BULK_3 = 23, + WPAD_DEV_BULK_4 = 24, + WPAD_DEV_BULK_5 = 25, + WPAD_DEV_BULK_6 = 26, + WPAD_DEV_BULK_7 = 27, + WPAD_DEV_BULK_8 = 28, + + WPAD_DEV_MPLS_PT_UNKNOWN = 250, + + WPAD_DEV_251 = 251, + WPAD_DEV_252 = 252, // invalid device mode? + WPAD_DEV_NONE = 253, // sort of like WPAD_ENODEV (see __wpadAbortInitExtension in WPADHIDParser.c) +// WPAD_DEV_254 = 254, /* unknown, doesn't seem to be used anywhere */ + WPAD_DEV_INITIALIZING = 255, // see __a1_20_status_report +}; + +typedef u32 WPADDataFormat; +enum WPADDataFormat_et +{ + // see WPADiSendSetReportType and __wpadFmt2Size + WPAD_FMT_CORE_BTN = 0, + WPAD_FMT_CORE_BTN_ACC = 1, + WPAD_FMT_CORE_BTN_ACC_DPD = 2, + + WPAD_FMT_FS_BTN = 3, + WPAD_FMT_FS_BTN_ACC = 4, + WPAD_FMT_FS_BTN_ACC_DPD = 5, + + WPAD_FMT_CLASSIC_BTN = 6, + WPAD_FMT_CLASSIC_BTN_ACC = 7, + WPAD_FMT_CLASSIC_BTN_ACC_DPD = 8, + + WPAD_FMT_BTN_ACC_DPD_EXTENDED = 9, + + // extensions + WPAD_FMT_TRAIN = 10, /* name known from asserts */ + WPAD_FMT_GUITAR = 11, /* name known from asserts */ + WPAD_FMT_BALANCE_CHECKER = 12, /* name known from asserts */ + WPAD_FMT_VSM = 13, /* name known from asserts */ +// WPAD_FMT_14 = 14, /* unknown */ + WPAD_FMT_DRUM = 15, /* name known from asserts */ + WPAD_FMT_MOTION_PLUS = 16, // see __wpadFmt2Size + WPAD_FMT_TAIKO = 17, /* name known from asserts */ + WPAD_FMT_TURNTABLE = 18, /* name known from asserts */ + WPAD_FMT_BULK = 19, /* name known from asserts */ +}; + +typedef s32 WPADDeviceMode; +enum WPADDeviceMode_et +{ + WPAD_DEV_MODE_NORMAL = 0, + + WPAD_DEV_MODE_CLASSIC_REDUCED = 1, + WPAD_DEV_MODE_CLASSIC_EXTENDED = 2, + WPAD_DEV_MODE_CLASSIC_STANDARD = 3, + + WPAD_DEV_MODE_MPLS_PT_MAIN = 4, + WPAD_DEV_MODE_MPLS_PT_FS = 5, +// WPAD_DEV_MODE_6 = 6, /* unknown */ + WPAD_DEV_MODE_MPLS_PT_CLASSIC = 7, +}; + +// names from wiiuse/wpad.h +typedef u16 WPADButton; +enum WPADButton_et +{ +// H..-AB12 ...+^v>< + /* NOTE: the bytes from the report are swapped when being placed into this + * format (see MAKE_BUTTON in WPADHIDParser.c) + */ + WPAD_BUTTON_LEFT = (1 << 0), + WPAD_BUTTON_RIGHT = (1 << 1), + WPAD_BUTTON_DOWN = (1 << 2), + WPAD_BUTTON_UP = (1 << 3), + WPAD_BUTTON_PLUS = (1 << 4), + // (1 << 5), + // (1 << 6), + // (1 << 7), + WPAD_BUTTON_2 = (1 << 8), + WPAD_BUTTON_1 = (1 << 9), + WPAD_BUTTON_B = (1 << 10), + WPAD_BUTTON_A = (1 << 11), + WPAD_BUTTON_MINUS = (1 << 12), + // (1 << 13), // WPAD_BUTTON_FS_Z + // (1 << 14), // WPAD_BUTTON_FS_C + WPAD_BUTTON_HOME = (1 << 15), + + WPAD_BUTTON_ALL = 0x9f1f +}; + +// names from wiiuse/wpad.h +typedef u16 WPADExtButton; +enum WPADExtButton_et +{ + // Nunchuk (fight stick?) +// .CZ..... ........ + /* NOTE: these bits are actually in the normal button variable, but are + * enumerated here because they are buttons for an extension + */ + WPAD_BUTTON_FS_Z = (1 << 13), + WPAD_BUTTON_FS_C = (1 << 14), + + WPAD_BUTTON_FS_ALL = 0x6000, + + // Classic Controller +// >vL-H+R. lBYAXr<^ + WPAD_BUTTON_CL_UP = (1 << 0), + WPAD_BUTTON_CL_LEFT = (1 << 1), + WPAD_BUTTON_CL_ZR = (1 << 2), + WPAD_BUTTON_CL_X = (1 << 3), + WPAD_BUTTON_CL_A = (1 << 4), + WPAD_BUTTON_CL_Y = (1 << 5), + WPAD_BUTTON_CL_B = (1 << 6), + WPAD_BUTTON_CL_ZL = (1 << 7), + // (1 << 8), + WPAD_BUTTON_CL_FULL_R = (1 << 9), + WPAD_BUTTON_CL_PLUS = (1 << 10), + WPAD_BUTTON_CL_HOME = (1 << 11), + WPAD_BUTTON_CL_MINUS = (1 << 12), + WPAD_BUTTON_CL_FULL_L = (1 << 13), + WPAD_BUTTON_CL_DOWN = (1 << 14), + WPAD_BUTTON_CL_RIGHT = (1 << 15), + + WPAD_BUTTON_CL_ALL = 0xfeff, + + // Shinkansen train controller + // shares the same format as the Classic Controller + // (see WPADiExcludeButton) + WPAD_BUTTON_TR_UP = WPAD_BUTTON_CL_UP, + WPAD_BUTTON_TR_LEFT = WPAD_BUTTON_CL_LEFT, + WPAD_BUTTON_TR_ZR = WPAD_BUTTON_CL_ZR, + WPAD_BUTTON_TR_X = WPAD_BUTTON_CL_X, + WPAD_BUTTON_TR_A = WPAD_BUTTON_CL_A, + WPAD_BUTTON_TR_Y = WPAD_BUTTON_CL_Y, + WPAD_BUTTON_TR_B = WPAD_BUTTON_CL_B, + WPAD_BUTTON_TR_ZL = WPAD_BUTTON_CL_ZL, + // = WPAD_BUTTON_CL_8, + WPAD_BUTTON_TR_FULL_R = WPAD_BUTTON_CL_FULL_R, + WPAD_BUTTON_TR_PLUS = WPAD_BUTTON_CL_PLUS, + WPAD_BUTTON_TR_HOME = WPAD_BUTTON_CL_HOME, + WPAD_BUTTON_TR_MINUS = WPAD_BUTTON_CL_MINUS, + WPAD_BUTTON_TR_FULL_L = WPAD_BUTTON_CL_FULL_L, + WPAD_BUTTON_TR_DOWN = WPAD_BUTTON_CL_DOWN, + WPAD_BUTTON_TR_RIGHT = WPAD_BUTTON_CL_RIGHT, + + WPAD_BUTTON_TR_ALL = WPAD_BUTTON_CL_ALL, +}; + +// WPADControlMotor +typedef u32 WPADMotorCommand; +enum WPADMotorCommand_et +{ + WPAD_MOTOR_STOP = 0, /* name known from asserts */ + WPAD_MOTOR_RUMBLE = 1, /* name known from asserts */ +}; + +// WPADControlSpeaker +typedef u32 WPADSpeakerCommand; +enum WPADSpeakerCommand_et +{ + WPAD_SPEAKER_DISABLE = 0, + WPAD_SPEAKER_ENABLE = 1, // might be ON? see HBMRemoteSpk.cpp + WPAD_SPEAKER_MUTE = 2, + WPAD_SPEAKER_UNMUTE = 3, + WPAD_SPEAKER_PLAY = 4, // figured out from HBM usage + + // does the same thing as ENABLE? unless i'm missing something + // not used so i don't know the context + WPAD_SPEAKER_CMD_05 = 5, +}; + +// WPADControlDpd +typedef u32 WPADDpdCommand; +enum WPADDpdCommand_et +{ + WPAD_DPD_DISABLE = 0x00, + + // the command here is actually the data format + WPAD_DPD_BASIC = 0x01, + WPAD_DPD_STANDARD = 0x03, + WPAD_DPD_EXTENDED = 0x05, +}; + +// WPADControlBLC +typedef u8 WPADBLCCommand; +enum WPADBLCCommand_et +{ + WPAD_BLC_DISABLE = 0x00, + WPAD_BLC_CMD_55 = 0x55, + + /* NOTE: maybe? the code on this case in WPADControlBLC seems to follow what + * WiiBrew describes as the initialization sequence after the generic one + * (https://wiibrew.org/wiki/Wii_Balance_Board#Wii_Initialisation_Sequence). + */ + WPAD_BLC_ENABLE = 0xaa, +}; + +// WPADMPStatus::stat +typedef u8 WPADMPStatusFlags; +enum WPADMPStatusFlags_et +{ + WPAD_MPLS_STATUS_DATA_VALID = (1 << 7), + WPAD_MPLS_STATUS_EXTENSION_DATA_VALID = (1 << 6), + + WPAD_MPLS_STATUS_YAW_SLOW_MODE = (1 << 3), + WPAD_MPLS_STATUS_PITCH_SLOW_MODE = (1 << 2), + WPAD_MPLS_STATUS_ROLL_SLOW_MODE = (1 << 1), + WPAD_MPLS_STATUS_EXTENSION_CONNECTED = (1 << 0), // just that it's present; not that it's actually being used +}; + +// WPADGetAccGravityUnit +typedef u32 WPADAccGravityUnitType; +enum WPADAccGravityUnitType_et +{ + WPAD_ACC_GRAVITY_UNIT_CORE, + WPAD_ACC_GRAVITY_UNIT_FS, +}; + +typedef WUDAllocFunc WPADAllocFunc; +typedef WUDFreeFunc WPADFreeFunc; + +typedef void WPADInitFunc(void); // see __wpadInitSub in WPAD.c + +typedef void WPADCallback(WPADChannel chan, WPADResult result); + +typedef void WPADSamplingCallback(WPADChannel chan); +typedef void WPADConnectCallback(WPADChannel chan, s32 result); +typedef void WPADExtensionCallback(WPADChannel chan, WPADDeviceType devType); + +typedef WUDSyncDeviceCallback WPADSimpleSyncCallback; + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x79f49 +typedef struct DPDObject +{ + s16 x; // size 0x02, offset 0x00 + s16 y; // size 0x02, offset 0x02 + u16 size; // size 0x02, offset 0x04 + u8 traceId; // size 0x01, offset 0x06 + // 1 byte padding +} DPDObject; // size 0x08 + +// TODO: get a specific source (name, game id) +// TODO: check library version of game that has this +// dwarfv1_megadump.txt:21551-21559 +typedef struct DPDObjEx +{ + s16 range_x1; // size 0x02, offset 0x00 + s16 range_y1; // size 0x02, offset 0x02 + s16 range_x2; // size 0x02, offset 0x04 + s16 range_y2; // size 0x02, offset 0x06 + u16 pixel; // size 0x02, offset 0x08 + s8 radius; // size 0x01, offset 0x0a + // 1 byte padding +} DPDObjEx; // size 0x0c + +// [SPQE7T]/ISpyD.elf:.debug_info::0xd675b +typedef struct WPADInfo +{ + BOOL dpd; // size 0x04, offset 0x00 + BOOL speaker; // size 0x04, offset 0x04 + BOOL attach; // size 0x04, offset 0x08 + BOOL lowBat; // size 0x04, offset 0x0c + BOOL nearempty; // size 0x04, offset 0x10 + u8 battery; // size 0x01, offset 0x14 + u8 led; // size 0x01, offset 0x15 + u8 protocol; // size 0x01, offset 0x16 + u8 firmware; // size 0x01, offset 0x17 +} WPADInfo; // size 0x18 + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x7ab19 +typedef struct WPADStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 +} WPADStatus; // size 0x2a + +/* The following take their initial members from WPADStatus instead of including + * an instance of it. For ease of use? + */ + +// TODO: get a specific source (name, game id) +// TODO: check library version of game that has this +// dwarfv1_megadump.txt:21560-21570 +typedef struct WPADStatusEx +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + DPDObjEx exp[WPAD_MAX_DPD_OBJECTS]; // size 0x30, offset 0x2a +} WPADStatusEx; // size 0x5a + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x79e65 +typedef struct WPADFSStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + s16 fsAccX; // size 0x02, offset 0x2a + s16 fsAccY; // size 0x02, offset 0x2c + s16 fsAccZ; // size 0x02, offset 0x2e + s8 fsStickX; // size 0x01, offset 0x30 + s8 fsStickY; // size 0x01, offset 0x31 +} WPADFSStatus; // size 0x32 + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x7aba2 +typedef struct WPADCLStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + WPADExtButton clButton; // size 0x02, offset 0x2a + s16 clLStickX; // size 0x02, offset 0x2c + s16 clLStickY; // size 0x02, offset 0x2e + s16 clRStickX; // size 0x02, offset 0x30 + s16 clRStickY; // size 0x02, offset 0x32 + u8 clTriggerL; // size 0x01, offset 0x34 + u8 clTriggerR; // size 0x01, offset 0x35 +} WPADCLStatus; // size 0x36 + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x7acba +typedef struct WPADTRStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + WPADExtButton trButton; // size 0x02, offset 0x2a + u8 brake; // size 0x01, offset 0x2c + u8 mascon; // size 0x01, offset 0x2d +} WPADTRStatus; // size 0x2e + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x7ad79 +typedef struct WPADBLStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + u16 press[4]; // size 0x08, offset 0x2a + s8 temp; // size 0x01, offset 0x32 + u8 battery; // size 0x01, offset 0x33 +} WPADBLStatus; // size 0x34 + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x7ae44 +typedef struct WPADMPStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + // [SGLEA4]/GormitiDebug.elf:.debug_info::0x7af2c + union /* explicitly untagged */ + { + // Takes its members from WPADFSStatus + // [SGLEA4]/GormitiDebug.elf:.debug_info::0x7af54 + struct /* explicitly untagged */ + { + s16 fsAccX; // size 0x02, offset 0x00 + s16 fsAccY; // size 0x02, offset 0x02 + s16 fsAccZ; // size 0x02, offset 0x04 + s8 fsStickX; // size 0x01, offset 0x06 + s8 fsStickY; // size 0x01, offset 0x07 + } fs; // size 0x08 + + // Takes its members from WPADCLStatus + // [SGLEA4]/GormitiDebug.elf:.debug_info::0x7afbb + struct /* explicitly untagged */ + { + WPADExtButton clButton; // size 0x02, offset 0x00 + s16 clLStickX; // size 0x02, offset 0x02 + s16 clLStickY; // size 0x02, offset 0x04 + s16 clRStickX; // size 0x02, offset 0x06 + s16 clRStickY; // size 0x02, offset 0x08 + u8 clTriggerL; // size 0x01, offset 0x0a + u8 clTriggerR; // size 0x01, offset 0x0b + } cl; // size 0x0c + } ext; // size 0x0c, offset 0x2a + + WPADMPStatusFlags stat; // size 0x01, offset 0x36 + u8 reserved; // size 0x01, offset 0x37 + + s16 pitch; // size 0x02, offset 0x38 + s16 yaw; // size 0x02, offset 0x3a + s16 roll; // size 0x02, offset 0x3c +} WPADMPStatus; // size 0x3e + +// [SGLEA4]/GormitiDebug.elf:.debug_info::0x7b056 +typedef struct WPADBKStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + byte_t bulk[21]; // size 0x15, offset 0x2a + byte_t padding[1]; // size 0x01, offset 0x3f +} WPADBKStatus; // size 0x40 + +typedef struct WPADVSStatus +{ + WPADButton button; // size 0x02, offset 0x00 + s16 accX; // size 0x02, offset 0x02 + s16 accY; // size 0x02, offset 0x04 + s16 accZ; // size 0x02, offset 0x06 + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x08 + u8 dev; // size 0x01, offset 0x28 + s8 err; // size 0x01, offset 0x29 + + u16 at_0x2a[5]; // size 0x0a, offset 0x2a + u8 at_0x34; // size 0x02, offset 0x34 + // 1 byte padding (alignment? probably) + u16 at_0x36[5]; // size 0x0a, offset 0x36 + u8 at_0x40; // size 0x02, offset 0x40 + // 1 byte padding (alignment? probably) + u16 at_0x42; // size 0x02, offset 0x42 + u8 at_0x44; // size 0x01, offset 0x44 + // 1 byte padding (alignment? probably) +} WPADVSStatus; // size 0x46 (see __wpadFmt2Size) + +typedef struct WPADAccGravityUnit +{ + // probably maybe + s16 x; // size 0x02, offset 0x00 + s16 y; // size 0x02, offset 0x02 + s16 z; // size 0x02, offset 0x04 +} WPADAccGravityUnit; // size 0x06 + +/******************************************************************************* + * functions + */ + +BOOL WPADIsEnabledVSM(void); +BOOL WPADIsEnabledTRN(void); +BOOL WPADIsEnabledGTR(void); +BOOL WPADIsEnabledDRM(void); +BOOL WPADIsEnabledTKO(void); +BOOL WPADIsEnabledTBL(void); +BOOL WPADIsEnabledBLK(void); + +// Likely overridden by a WBC-specific library +__attribute__((weak)) WPADResult WBCSetupCalibration(void); +__attribute__((weak)) signed WBCGetCalibrationStatus(void); +__attribute__((weak)) signed WBCGetBatteryLevel(u8); +__attribute__((weak)) WPADResult WBCRead(WPADBLStatus *, f64 *, int); +__attribute__((weak)) WPADResult WBCSetZEROPoint(f64 *, int); +__attribute__((weak)) WPADResult WBCGetTGCWeight(f64, f64 *, WPADBLStatus *); + +void WPADInit(void); +void WPADShutdown(void); + +BOOL WPADStartFastSimpleSync(void); +BOOL WPADStopSimpleSync(void); +BOOL WPADCancelSyncDevice(void); +WPADSimpleSyncCallback *WPADSetSimpleSyncCallback(WPADSimpleSyncCallback *cb); +void WPADRegisterAllocator(WPADAllocFunc *alloc, WPADFreeFunc *free); +WPADLibStatus WPADGetStatus(void); +u8 WPADGetRadioSensitivity(WPADChannel chan); +void WPADGetAddress(WPADChannel chan, BD_ADDR_PTR addr); +u8 WPADGetSensorBarPosition(void); + +void WPADGetAccGravityUnit(WPADChannel chan, WPADAccGravityUnitType type, + WPADAccGravityUnit *acc); + +void WPADDisconnect(WPADChannel chan); +WPADResult WPADProbe(WPADChannel chan, WPADDeviceType *devTypeOut); +WPADSamplingCallback *WPADSetSamplingCallback(WPADChannel chan, + WPADSamplingCallback *cb); +WPADConnectCallback *WPADSetConnectCallback(WPADChannel chan, + WPADConnectCallback *cb); +WPADExtensionCallback *WPADSetExtensionCallback(WPADChannel chan, + WPADExtensionCallback *cb); +WPADDataFormat WPADGetDataFormat(WPADChannel chan); +WPADResult WPADSetDataFormat(WPADChannel chan, WPADDataFormat fmt); + +WPADResult WPADGetInfoAsync(WPADChannel chan, WPADInfo *info, WPADCallback *cb); +void WPADControlMotor(WPADChannel chan, WPADMotorCommand command); +void WPADEnableMotor(BOOL enabled); +BOOL WPADIsMotorEnabled(void); +WPADResult WPADControlLed(WPADChannel chan, u8 ledFlags, WPADCallback cb); +BOOL WPADSaveConfig(SCFlushCallback *cb); + +/* NOTE: status should match the WPADStatus type for the channel; a check + * against the currently assigned device type is made to know how much to copy + * + * for example, if devType[chan] == WPAD_DEV_CLASSIC, status should be a + * pointer to WPADCLStatus cast to a pointer to WPADStatus + */ +void WPADRead(WPADChannel chan, WPADStatus *status); +void WPADSetAutoSamplingBuf(WPADChannel chan, void *buf, u32 length); + +BOOL WPADIsSpeakerEnabled(WPADChannel chan); +WPADResult WPADControlSpeaker(WPADChannel chan, WPADSpeakerCommand command, + WPADCallback *cb); +u8 WPADGetSpeakerVolume(void); +void WPADSetSpeakerVolume(u8 vol); + +BOOL WPADCanSendStreamData(WPADChannel chan); +WPADResult WPADSendStreamData(WPADChannel chan, void *p_buf, u16 len); +u8 WPADGetDpdSensitivity(void); +BOOL WPADIsDpdEnabled(WPADChannel chan); + +WPADResult WPADControlDpd(WPADChannel chan, WPADDpdCommand command, + WPADCallback *cb); +WPADResult WPADControlBLC(WPADChannel chan, WPADBLCCommand command, + WPADCallback *cb); + +void WPADRecalibrate(WPADChannel chan); +BOOL WPADIsUsedCallbackByKPAD(void); +void WPADSetCallbackByKPAD(BOOL isKPAD); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPAD2.h b/src/sdk/RVL_SDK/revolution/wpad/WPAD2.h new file mode 100644 index 00000000..24dfa9fe --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPAD2.h @@ -0,0 +1,484 @@ +#ifndef RVL_SDK_WPAD_INTERNAL_WPAD_H +#define RVL_SDK_WPAD_INTERNAL_WPAD_H + +#include + +/******************************************************************************* + * headers + */ + +#include + +#include "lint.h" // ULONG +#include "WPADHIDParser.h" // RPT_MAX_SIZE +#include "WPADMem.h" + + +#include +#include + +//#include "context_rvl.h" + +/******************************************************************************* + * macros + */ + +// WPADStatusEx is the largest WPADStatus variant (size 0x5a) +// 0x20 is an arbitrary power of 2 that rounds up to 0x60 +#define RX_BUFFER_SIZE ROUND_UP(sizeof(WPADStatusEx), 0x20) + +#define WPAD_CONFIG_BLOCK_CHECKSUM_BIAS 0x55 +#define WPAD_MAX_CONFIG_BLOCKS 2 + +#define WPAD_DPD_CONFIG_BLOCK_CHECKSUM 10 +#define WPAD_DPD_CONFIG_BLOCK_SIZE 11 + +#define WPAD_DEV_CONFIG_BLOCK_CHECKSUM 9 +#define WPAD_DEV_CONFIG_BLOCK_SIZE 10 + +// for WPADDevConfig::dpd::obj +#define DPD_CFG_OBJ_BL 0 +#define DPD_CFG_OBJ_BR 1 +#define DPD_CFG_OBJ_TR 2 +#define DPD_CFG_OBJ_TL 3 + +/* + * Wiimote memory addresses + */ + +// https://wiibrew.org/wiki/Wiimote#EEPROM_Memory +#define WM_ADDR_MEM_DEV_CONFIG_0 WM_MEM_ADDR(0x0000) +#define WM_ADDR_MEM_GAME_INFO_0 WM_MEM_ADDR(0x002a) +#define WM_ADDR_MEM_GAME_INFO_1 WM_MEM_ADDR(0x0062) + +// out of range??? wiibrew says the wiimote only has 0x1600 bytes of memory +#define WM_ADDR_MEM_176C WM_MEM_ADDR(0x176c) +#define WM_ADDR_MEM_1770 WM_MEM_ADDR(0x1770) + +/* + * Wiimote extension register addresses + */ + +// Speaker register addresses +#define WM_REG_SPEAKER_01 WM_EXT_REG_ADDR(SPEAKER, 0x01) +#define WM_REG_SPEAKER_08 WM_EXT_REG_ADDR(SPEAKER, 0x08) +#define WM_REG_SPEAKER_09 WM_EXT_REG_ADDR(SPEAKER, 0x09) + +// Extension register addresses +#define WM_REG_EXTENSION_CONFIG WM_EXT_REG_ADDR(EXTENSION, 0x20) +#define WM_REG_EXTENSION_40 WM_EXT_REG_ADDR(EXTENSION, 0x40) +#define WM_REG_EXTENSION_CERT_PARAM WM_EXT_REG_ADDR(EXTENSION, 0x50) +#define WM_REG_EXTENSION_F0 WM_EXT_REG_ADDR(EXTENSION, 0xf0) +#define WM_REG_EXTENSION_CERT_CHALLENGE WM_EXT_REG_ADDR(EXTENSION, 0xf1) +#define WM_REG_EXTENSION_F2 WM_EXT_REG_ADDR(EXTENSION, 0xf2) +#define WM_REG_EXTENSION_F3 WM_EXT_REG_ADDR(EXTENSION, 0xf3) +#define WM_REG_EXTENSION_EXT_TYPE_2 WM_EXT_REG_ADDR(EXTENSION, 0xf6) +#define WM_REG_EXTENSION_CERT_PROBE WM_EXT_REG_ADDR(EXTENSION, 0xf7) +#define WM_REG_EXTENSION_FA WM_EXT_REG_ADDR(EXTENSION, 0xfa) +#define WM_REG_EXTENSION_FB WM_EXT_REG_ADDR(EXTENSION, 0xfb) +#define WM_REG_EXTENSION_DEV_MODE WM_EXT_REG_ADDR(EXTENSION, 0xfe) +#define WM_REG_EXTENSION_ID_BYTE WM_EXT_REG_ADDR(EXTENSION, 0xff) + +#define WM_EXTENSION_CONFIG_SIZE 0x20 // 0xa40020 - 0xa4003f +#define WM_EXTENSION_CERT_PARAM_SIZE 0x40 // 0xa40050 - 0xa4008f + +// Wiimote Motion Plus register addresses +#define WM_REG_MPLS_F0 WM_EXT_REG_ADDR(MOTION_PLUS, 0xf0) +#define WM_REG_MPLS_DEV_MODE WM_EXT_REG_ADDR(MOTION_PLUS, 0xfe) +#define WM_REG_MPLS_ID_BYTE WM_EXT_REG_ADDR(MOTION_PLUS, 0xff) + +// IR camera register addresses +#define WM_REG_DPD_CONFIG_BLOCK_1 WM_EXT_REG_ADDR(DPD, 0x00) +#define WM_REG_DPD_CONFIG_BLOCK_2 WM_EXT_REG_ADDR(DPD, 0x1a) +#define WM_REG_DPD_30 WM_EXT_REG_ADDR(DPD, 0x30) +#define WM_REG_DPD_DATA_FORMAT WM_EXT_REG_ADDR(DPD, 0x33) + +/******************************************************************************* + * types + */ + +#ifdef __cplusplus + extern "C" { +#endif + +// NoiZe filter? only thing i can think of idk +// probably confirmed since its only uses are in __wpadCalcAnalogNoise +typedef u8 WPADNZFilter; +enum WPADNZFilter_et +{ + WPAD_NZFILTER_ACC, + WPAD_NZFILTER_DPD, + WPAD_NZFILTER_EXT, + WPAD_NZFILTER_MPLS, + + WPAD_MAX_NZFILTERS /* name known from asserts */ +}; + +// WPADiControlMpls +typedef u8 WPADMplsCommand; +enum WPADMplsCommand_et +{ + WPAD_MPLS_DISABLE = 0x00, + + // the command here is actually the device mode + WPAD_MPLS_MAIN = WPAD_DEV_MODE_MPLS_PT_MAIN, + WPAD_MPLS_FS = WPAD_DEV_MODE_MPLS_PT_FS, + WPAD_MPLS_CLASSIC = WPAD_DEV_MODE_MPLS_PT_CLASSIC, + + // except for this + WPAD_MPLS_CMD_80 = 0x80, +}; + +typedef u8 WPADMplsCBState; +enum WPADMplsCBState_et +{ + WPAD_STATE_MPLS_CB_START, + WPAD_STATE_MPLS_CB_1, + WPAD_STATE_MPLS_CB_CLEAR_DEV_MODE, + WPAD_STATE_MPLS_CB_WRITE_PENDING_MPLS_DEV_MODE, + WPAD_STATE_MPLS_CB_INIT_MPLS_EXT, + WPAD_STATE_MPLS_CB_5, + WPAD_STATE_MPLS_CB_GET_EXTENSION_ID, + WPAD_STATE_MPLS_CB_DONE, + WPAD_STATE_MPLS_CB_RESET, +}; + +typedef s8 WPADCertValidityStatus; +enum WPADCertValidityStatus_et +{ + WPAD_CERT_INVALID = -1, + WPAD_CERT_UNCHECKED = 0, + WPAD_CERT_VALID = 1, +}; + +typedef s8 WPADCertState; +enum WPADCertState_et +{ + WPAD_STATE_CERT_PROBE_X, + WPAD_STATE_CERT_GET_X, + WPAD_STATE_CERT_VERIFY_X, + WPAD_STATE_CERT_CHALLENGE, + WPAD_STATE_CERT_PROBE_Y, + WPAD_STATE_CERT_GET_Y, + WPAD_STATE_CERT_VERIFY_Y, + WPAD_STATE_CERT_CALC_MUL_X, + WPAD_STATE_CERT_CALC_MOD_X, + WPAD_STATE_CERT_CALC_MUL_Y, + WPAD_STATE_CERT_CALC_MOD_Y, + WPAD_STATE_CERT_CHECK, + WPAD_STATE_CERT_SUCCESS, + + WPAD_STATE_CERT_ERROR_TIMEOUT = 120, + WPAD_STATE_CERT_INVALID = -1, + +#define WPAD_STATE_CERT_ETIME WPAD_STATE_CERT_ERROR_TIMEOUT +}; + +typedef u8 WPADExtensionState; +enum WPADExtensionState_et +{ + WPAD_STATE_EXT_UNINITIALIZED, + WPAD_STATE_EXT_INITIALIZED, + WPAD_STATE_EXT_ENCRYPTED, + WPAD_STATE_EXT_ENCRYPTED_3RD, +}; + +// __rvl_wpadcb::radioQuality +typedef u8 WPADRadioQuality; +enum WPADRadioQuality_et +{ + WPAD_RADIO_QUALITY_GOOD, // 80+ + WPAD_RADIO_QUALITY_BAD // 80- + // if radioQuality calculation == 80, state stays the same +}; + +enum WPADInterleaveBufferFlags +{ + WPAD_ILBUF_NONE = 0, + + WPAD_ILBUF_BUF3E = (1 << 0), + WPAD_ILBUF_BUF3F = (1 << 1), + + WPAD_ILBUF_ALL = WPAD_ILBUF_BUF3E | WPAD_ILBUF_BUF3F, +}; + +struct WPADCmd +{ + u32 reportID; // size 0x04, offset 0x00 + byte_t dataBuf[RPT_MAX_SIZE]; // size 0x15, offset 0x04 + // 1 byte padding (alignment) + u16 dataLength; // size 0x02, offset 0x1a + void *dstBuf; // size 0x04, offset 0x1c + u16 readLength; // size 0x02, offset 0x20 + // 2 bytes padding (alignment? probably) + u32 readAddress; // size 0x04, offset 0x24 + WPADInfo *statusReportOut; // size 0x04, offset 0x28 + WPADCallback *cmdCB; // size 0x04, offset 0x2c +}; // size 0x30 + +struct WPADCmdQueue +{ + s8 indexOut; // size 0x01, offset 0x00 + s8 indexIn; // size 0x01, offset 0x01 + // 2 bytes padding (alignment? probably) + struct WPADCmd *queue; // size 0x04, offset 0x04 + u32 length; // size 0x04, offset 0x08 +}; // size 0x0c + +struct WPADMplsCalibration +{ + f32 pitchZero; // size 0x04, offset 0x00 + f32 pitchScale; // size 0x04, offset 0x04 + + f32 yawZero; // size 0x04, offset 0x08 + f32 yawScale; // size 0x04, offset 0x0c + + f32 rollZero; // size 0x04, offset 0x10 + f32 rollScale; // size 0x04, offset 0x14 + + s32 degrees; // size 0x04, offset 0x18 +}; // size 0x1c + +struct WPADDevConfig +{ + DPDObject dpd[WPAD_MAX_DPD_OBJECTS]; // size 0x20, offset 0x00 + + s16 accX0g; // size 0x02, offset 0x20 + s16 accY0g; // size 0x02, offset 0x22 + s16 accZ0g; // size 0x02, offset 0x24 + + s16 accX1g; // size 0x02, offset 0x26 + s16 accY1g; // size 0x02, offset 0x28 + s16 accZ1g; // size 0x02, offset 0x2a + + u8 motor; // size 0x01, offset 0x2c + u8 volume; // size 0x01, offset 0x2d + byte_t __pad0[2]; // padding to 0x30? +}; // size 0x30 + +struct WPADExtConfig +{ + union + { + struct WPADFSConfig + { + s16 stickXCenter; // size 0x02, offset 0x00 + s16 at_0x02; // size 0x02, offset 0x02 + s16 at_0x04; // size 0x02, offset 0x04 + s16 stickYCenter; // size 0x02, offset 0x06 + s16 at_0x08; // size 0x02, offset 0x08 + s16 at_0x0a; // size 0x02, offset 0x0a + + s16 accX0g; // size 0x02, offset 0x0c + s16 accY0g; // size 0x02, offset 0x0e + s16 accZ0g; // size 0x02, offset 0x10 + + s16 accX1g; // size 0x02, offset 0x12 + s16 accY1g; // size 0x02, offset 0x14 + s16 accZ1g; // size 0x02, offset 0x16 + } fs; // size 0x1a + + struct WPADCLConfig + { + s16 lStickXCenter; // size 0x02, offset 0x00 + s16 at_0x02; // size 0x02, offset 0x02 + s16 at_0x04; // size 0x02, offset 0x04 + s16 lStickYCenter; // size 0x02, offset 0x06 + s16 at_0x08; // size 0x02, offset 0x08 + s16 at_0x0a; // size 0x02, offset 0x0a + + s16 rStickXCenter; // size 0x02, offset 0x0c + s16 at_0x0e; // size 0x02, offset 0x0e + s16 at_0x10; // size 0x02, offset 0x10 + s16 rStickYCenter; // size 0x02, offset 0x12 + s16 at_0x14; // size 0x02, offset 0x14 + s16 at_0x16; // size 0x02, offset 0x16 + + u8 triggerLZero; // size 0x01, offset 0x18 + u8 triggerRZero; // size 0x01, offset 0x19 + } cl; // size 0x1a + + byte_t FORCE_UNION_SIZE[0x1c]; // alignment? + }; // size 0x1c + + struct WPADMplsConfig + { + struct WPADMplsCalibration high; // size 0x1c, offset 0x00 + struct WPADMplsCalibration low; // size 0x1c, offset 0x1c + u32 calibCRC; // size 0x04, offset 0x38 + u16 calibID; // size 0x02, offset 0x3c + // 2 bytes padding (alignment? probably) + } mpls; // size 0x40, offset 0x01a +}; // size 0x5c + + +typedef struct /* possibly untagged, like kpad */ +{ + WPADGameInfo gameInfo; // size 0x038, offset 0x000 + long signed at_0x038[2]; // size 0x008, offset 0x038 /* unknown */ // WPADResult[2]? see __wpadGetGameInfo + byte_t rxBufMain[RX_BUFFER_SIZE]; // size 0x060, offset 0x040 + byte_t rxBufs[2][RX_BUFFER_SIZE]; // size 0x060, offset 0x0a0 + struct WPADCmdQueue stdCmdQueue; // size 0x00c, offset 0x160 + struct WPADCmd stdCmdQueueList[24]; // size 0x480, offset 0x16c + struct WPADCmdQueue extCmdQueue; // size 0x00c, offset 0x5ec + struct WPADCmd extCmdQueueList[12]; // size 0x240, offset 0x16c + WPADInfo wpInfo; // size 0x018, offset 0x838 + WPADInfo *wpInfoOut; // size 0x004, offset 0x850 + struct WPADDevConfig devConfig; // size 0x030, offset 0x854 + struct WPADExtConfig extConfig; // size 0x05c, offset 0x884 + WPADCallback *cmdBlkCB; // size 0x004, offset 0x8e0 + WPADExtensionCallback *extensionCB; // size 0x004, offset 0x8e4 + WPADConnectCallback *connectCB; // size 0x004, offset 0x8e8 + WPADSamplingCallback *samplingCB; // size 0x004, offset 0x8ec + void *samplingBuf; // size 0x004, offset 0x8f0 + u32 samplingBufIndex; // size 0x004, offset 0x8f4 + u32 samplingBufSize; // size 0x004, offset 0x8f8 + WPADDataFormat dataFormat; // size 0x004, offset 0x8fc + WPADResult status; // size 0x004, offset 0x900 /* name known from asserts */ + u8 statusReqBusy; // size 0x001, offset 0x904 + u8 devType; // size 0x001, offset 0x905 /* possible name from assert */ + u8 devMode; // size 0x001, offset 0x906 + WUDDevHandle devHandle; // size 0x001, offset 0x907 + int signed unk_0x908; // size 0x001, offset 0x908 /* unknown */ + u8 rxBufIndex; // size 0x001, offset 0x90c + char signed unk_0x90d; // size 0x001, offset 0x90d /* unknown */ + u8 defaultDpdSize; // size 0x001, offset 0x90e // maybe? + u8 currentDpdCommand; // size 0x001, offset 0x90f + u8 pendingDpdCommand; // size 0x001, offset 0x910 + WPADRadioQuality radioQuality; // size 0x001, offset 0x911 + u8 radioQualityOkMs; // size 0x001, offset 0x912 // see __wpadCalcRadioQuality + u8 audioFrames; // size 0x001, offset 0x913 /* name known from asserts */ + u32 motorBusy; // size 0x004, offset 0x914 + BOOL motorRunning; // size 0x004, offset 0x918 // signedness known (yes) + BOOL used; // size 0x004, offset 0x91c /* name known from asserts */ + BOOL handshakeFinished; // size 0x004, offset 0x920 + int configIndex; // size 0x004, offset 0x924 + OSThreadQueue threadQueue; // size 0x008, offset 0x928 /* purpose unknown */ + byte_t __pad0[4]; /* unknown (can't be alignment) */ + u8 controlMplsBusy; // size 0x001, offset 0x934 + byte_t mplsCBReadBuf[2]; // size 0x002, offset 0x935 + u8 mplsCBCounter; // size 0x001, offset 0x937 // idk??? + u8 pendingMplsCommand; // size 0x001, offset 0x938 + u8 noParseMplsCount; // size 0x001, offset 0x939 + u8 isInitingMpls; // size 0x001, offset 0x93a // maybe? + u8 hasReadExtType2; // size 0x001, offset 0x93b // maybe? + char unsigned unk_0x93c; // size 0x001, offset 0x93c /* unknown */ + u8 parseMPState; // size 0x001, offset 0x93d + u8 wmParamOffset; // size 0x001, offset 0x93e + u8 certWorkCounter; // size 0x001, offset 0x93f // idk??? + u16 certWorkMs; // size 0x002, offset 0x940 + s16 certStateWorkMs; // size 0x002, offset 0x942 + s8 certChallengeRandomBit; // size 0x001, offset 0x944 + u8 certWorkBusy; // size 0x001, offset 0x945 + WPADCertValidityStatus certValidityStatus; // size 0x001, offset 0x946 + WPADCertState certState; // size 0x001, offset 0x947 + ULONG *certParamPtr; // size 0x001, offset 0x948 + ULONG certBuf0[16 + 2]; // size 0x048, offset 0x94c + ULONG certBuf1[16 + 2]; // size 0x048, offset 0x994 + ULONG certBufBig[64 + 2]; // size 0x048, offset 0x994 + int signed unk_0xae4; // size 0x004, offset 0xae4 /* unknown */ + OSTime lastControllerDataUpdate; // size 0x008, offset 0xae8 + u16 filterDiff[WPAD_MAX_NZFILTERS]; // size 0x008, offset 0xaf0 + u16 filterSame[WPAD_MAX_NZFILTERS]; // size 0x008, offset 0xaf8 + OSTime lastReportSendTime; // size 0x008, offset 0xb00 + char unsigned unk_0xb08; // size 0x001, offset 0xb08 /* unknown */ + u8 calibrated; // size 0x001, offset 0xb09 + u16 recalibHoldMs; // size 0x002, offset 0xb0a + byte_t encryptionKey[16]; // size 0x010, offset 0xb0c + byte_t decryptAddTable[8]; // size 0x008, offset 0xb1c + byte_t decryptXorTable[8]; // size 0x008, offset 0xb24 + byte_t wmReadDataBuf[64]; // size 0x020, offset 0xb2c + byte_t *wmReadDataPtr; // size 0x004, offset 0xb6c + u32 wmReadAddress; // size 0x004, offset 0xb70 + int wmReadHadError; // size 0x004, offset 0xb74 + u16 wmReadLength; // size 0x002, offset 0xb78 + char signed unk_0xb7a; // size 0x001, offset 0xb7a /* unknown */ + u8 radioSensitivity; // size 0x001, offset 0xb7b + u16 copyOutCount; // size 0x002, offset 0xb7c + u8 sleeping; // size 0x001, offset 0xb7e + u8 lastReportID; // size 0x001, offset 0xb7f + WPADCallback *getInfoCB; // size 0x004, offset 0xb80 + u8 getInfoBusy; // size 0x001, offset 0xb84 + u8 extState; // size 0x001, offset 0xb85 + u8 disableContReport; // size 0x001, offset 0xb86 + u8 blcBattery; // size 0x001, offset 0xb87 + u8 savedDevType; // size 0x001, offset 0xb88 // maybe? + u8 extWasDisconnected; // size 0x001, offset 0xb89 + s16 reconnectExtMs; // size 0x002, offset 0xb8a + struct WPADMemBlock memBlock; // size 0x014, offset 0xb8c + WPADCallback *controlMplsCB; // size 0x004, offset 0xba0 + u8 parseMPBuf; // size 0x001, offset 0xba4 + u8 certProbeByte; // size 0x001, offset 0xba5 + u8 dpdBusy; // size 0x001, offset 0xba6 + u8 interleaveFlags; // size 0x001, offset 0xba7 + u32 mplsCBReadAddress; // size 0x004, offset 0xba8 + WPADMplsCBState mplsCBState; // size 0x001, offset 0xbac + u8 mplsUptimeMs; // size 0x001, offset 0xbad + s8 certMayVerifyByCalibBlock; // size 0x001, offset 0xbae + byte_t __pad1[2]; /* unknown (can't be alignment) */ + u8 certProbeStartingValue; // size 0x001, offset 0xbb1 + u16 lastMplsCalibID; // size 0x002, offset 0xbb2 + u32 lastMplsCalibCRC; // size 0x004, offset 0xbb4 + u8 noParseExtCount; // size 0x001, offset 0xbb8 + s8 extErr; // size 0x001, offset 0xbb9 + u8 extDataLength; // size 0x001, offset 0xbba + u8 extDevType; // size 0x001, offset 0xbbb + char unsigned unk_0xbbc; // size 0x001, offset 0xbbc /* unknown */ // related to VSM + byte_t __pad2[3]; /* unknown (can't be alignment) */ + byte_t extDataBuf[32]; // size 0x020, offset 0xbc0 +} wpad_cb_st; // size 0xbe0 + +/******************************************************************************* + * external variables + */ + +extern wpad_cb_st *__rvl_p_wpadcb[WPAD_MAX_CONTROLLERS]; + +/******************************************************************************* + * functions + */ + +void WPADiExcludeButton(WPADChannel chan); +void WPADiCopyOut(WPADChannel chan); + +u8 WPADiGetMplsStatus(WPADChannel chan); + +WPADResult WPADiControlMpls(WPADChannel chan, WPADMplsCommand command, + WPADCallback *cb); + +void WPADiGetMplsCalibration(WPADChannel chan, struct WPADMplsCalibration *high, + struct WPADMplsCalibration *low); +BOOL WPADiSendSetPort(struct WPADCmdQueue *cmdQueue, u8 port, WPADCallback *cb); +BOOL WPADiSendSetReportType(struct WPADCmdQueue *cmdQueue, s32 format, + BOOL notContinuous, WPADCallback *cb); +BOOL WPADiSendEnableDPD(struct WPADCmdQueue *cmdQueue, BOOL enabled, + WPADCallback *cb); +BOOL WPADiSendEnableSpeaker(struct WPADCmdQueue *cmdQueue, BOOL enabled, + WPADCallback *cb); +BOOL WPADiSendGetContStat(struct WPADCmdQueue *cmdQueue, WPADInfo *wpInfoOut, + WPADCallback *cb); +BOOL WPADiSendWriteDataCmd(struct WPADCmdQueue *cmdQueue, u8 cmd, u32 address, + WPADCallback *cb); +BOOL WPADiSendWriteData(struct WPADCmdQueue *cmdQueue, const void *p_buf, + u16 len, u32 address, WPADCallback *cb); +BOOL WPADiSendReadData(struct WPADCmdQueue *cmdQueue, void *p_buf, u16 len, + u32 address, WPADCallback *cb); +BOOL WPADiSendStreamData(struct WPADCmdQueue *cmdQueue, const void *p_buf, + u16 len); +BOOL WPADiSendMuteSpeaker(struct WPADCmdQueue *cmdQueue, BOOL muted, + WPADCallback *cb); +BOOL WPADiSendDPDCSB(struct WPADCmdQueue *cmdQueue, BOOL enabled, + WPADCallback *cb); +BOOL WPADiIsAvailableCmdQueue(struct WPADCmdQueue *cmdQueue, s8 count); + +void WPADiClearQueue(struct WPADCmdQueue *cmdQueue); + +#if !defined(NDEBUG) +BOOL WPADiIsDummyExtension(WPADChannel chan); +#endif // !defined(NDEBUG) + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_INTERNAL_WPAD_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPADEncrypt.c b/src/sdk/RVL_SDK/revolution/wpad/WPADEncrypt.c new file mode 100644 index 00000000..6a1778e1 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPADEncrypt.c @@ -0,0 +1,1017 @@ +#include "WPADEncrypt.h" + +/******************************************************************************* + * headers + */ + +#include // memcpy + +#include // ARRAY_LENGTH +#include + +#include "WPAD.h" + +#if 0 +#include +#include +#endif + +#include "context_rvl.h" + +/******************************************************************************* + * local function declarations + */ + +static u8 random(void); +static u8 ror(u8 x, u8 shift); +static u8 rol(u8 x, u8 shift); + +/******************************************************************************* + * variables + */ + +// .data + +// WPADiCreateKey +static byte_t base[] = +{ + 0xa8, 0x77, 0xa6, 0xe0, 0xf7, 0x43, + 0x5a, 0x35, 0x85, 0xe2, 0x72, 0x97, + 0x8f, 0xb7, 0x1a, 0x62, 0x87, 0x38, + 0x0d, 0x67, 0xc7, 0xbe, 0x4f, 0x3e, + 0x20, 0x76, 0x37, 0x8f, 0x68, 0xb7, + 0xa9, 0x26, 0x3f, 0x2b, 0x10, 0xe3, + 0x30, 0x7e, 0x90, 0x0e, 0x85, 0x0a +}; + +static byte_t tb[] = +{ + 0x70, 0x51, 0x03, 0x86, 0x40, 0x0d, + 0x4f, 0xeb, 0x3e, 0xcc, 0xd1, 0x87, + 0x35, 0xbd, 0xf5, 0x0b, 0x5e, 0xd0, + 0xf8, 0xf2, 0xd5, 0xe2, 0x6c, 0x31, + 0x0c, 0xad, 0xfc, 0x21, 0xc3, 0x78, + 0xc1, 0x06, 0xc2, 0x4c, 0x55, 0xe6, + 0x4a, 0x34, 0x48, 0x11, 0x1e, 0xda, + 0xe7, 0x1a, 0x84, 0xa0, 0x96, 0xa7, + 0xe3, 0x7f, 0xaf, 0x63, 0x9c, 0xfa, + 0x23, 0x5b, 0x79, 0xc8, 0x9e, 0xba, + 0xb2, 0xc9, 0x22, 0x12, 0x4b, 0xb3, + 0xa1, 0xb6, 0x32, 0x49, 0xa2, 0xe1, + 0x89, 0x39, 0x10, 0x66, 0xc5, 0x07, + 0x8f, 0x54, 0xea, 0x91, 0xca, 0x3f, + 0xf9, 0x19, 0xf0, 0xd7, 0x46, 0xbc, + 0x28, 0x1b, 0x61, 0xe8, 0x2f, 0x6a, + 0xae, 0x9d, 0xf6, 0x4e, 0x09, 0x14, + 0x77, 0x4d, 0xdb, 0x1f, 0x2e, 0x7b, + 0x7c, 0xf1, 0x43, 0xa3, 0x00, 0xb8, + 0x13, 0x8c, 0x85, 0xb9, 0x29, 0x75, + 0x88, 0xfd, 0xd2, 0x56, 0x1c, 0x50, + 0x97, 0x41, 0xe5, 0x3b, 0x60, 0xb5, + 0xc0, 0x64, 0xee, 0x98, 0xd6, 0x2d, + 0x25, 0xa4, 0xaa, 0xcd, 0x7d, 0xa8, + 0x83, 0xc6, 0xab, 0xbe, 0x44, 0x99, + 0x26, 0x3c, 0xce, 0x9f, 0xbf, 0xd3, + 0xcb, 0x76, 0x7a, 0x7e, 0x82, 0x01, + 0x8a, 0x9a, 0x80, 0x1d, 0x0e, 0xb0, + 0x5c, 0xd4, 0x38, 0x62, 0xf4, 0x30, + 0xe0, 0x8e, 0x53, 0xb7, 0x02, 0x57, + 0xac, 0xa6, 0x52, 0x0a, 0x6d, 0x92, + 0x65, 0x17, 0x24, 0x33, 0x45, 0x72, + 0x74, 0xb1, 0xb4, 0xf7, 0x5d, 0xed, + 0x2c, 0xff, 0x47, 0x37, 0x5a, 0x90, + 0xbb, 0xdf, 0x2a, 0x16, 0x59, 0x95, + 0xd9, 0xc4, 0x27, 0x67, 0x73, 0xc7, + 0x68, 0xfe, 0xa5, 0xdd, 0x6b, 0x5f, + 0x93, 0xd8, 0xec, 0x05, 0x3a, 0x8d, + 0x6e, 0xfb, 0x3d, 0xa9, 0x69, 0x36, + 0xf3, 0x94, 0xde, 0xef, 0x15, 0x6f, + 0x8b, 0x9b, 0x08, 0x0f, 0xdc, 0x81, + 0x18, 0x20, 0x04, 0xe4, 0x71, 0xcf, + 0xe9, 0x2b, 0x42, 0x58, 0x01, 0xa0, + 0xa9, 0x62, 0xd6, 0x3f, 0x85, 0xa7, + 0xb6, 0xd4, 0xfa, 0x15, 0x66, 0x17, + 0x09, 0xbd, 0x5d, 0x14, 0x34, 0x26, + 0x59, 0x72, 0x91, 0x54, 0x06, 0x4f, + 0xf8, 0xb0, 0x5b, 0x74, 0x93, 0x99, + 0x8c, 0xf2, 0x45, 0xcd, 0xea, 0x4e, + 0xad, 0x10, 0x4a, 0xe5, 0xca, 0xee, + 0xdf, 0xc6, 0x6f, 0x9f, 0x88, 0x8e, + 0x02, 0xcc, 0x08, 0xa8, 0x77, 0x94, + 0x6d, 0x21, 0xb1, 0x28, 0xe4, 0x39, + 0x79, 0x96, 0x60, 0x71, 0x81, 0x16, + 0x2e, 0xe6, 0x78, 0xb9, 0xc4, 0x46, + 0x9a, 0x42, 0xae, 0xb7, 0x7c, 0x43, + 0xb3, 0x22, 0x1a, 0x86, 0xc2, 0x32, + 0x3d, 0x2d, 0x9c, 0xd2, 0x29, 0xe9, + 0x63, 0x9b, 0xd1, 0x31, 0x38, 0x5e, + 0x1e, 0x36, 0x41, 0xbb, 0x03, 0x18, + 0x2b, 0x3e, 0xbf, 0x68, 0x61, 0xfc, + 0x52, 0xc0, 0xde, 0xe0, 0x0a, 0x58, + 0x13, 0x5a, 0x00, 0xbe, 0x1c, 0x90, + 0x0e, 0x53, 0x12, 0xfd, 0xe2, 0x6e, + 0xba, 0xce, 0x24, 0x27, 0x44, 0x7f, + 0x87, 0xa3, 0xa1, 0xd5, 0x50, 0x40, + 0xe3, 0xf9, 0x83, 0xf7, 0xc7, 0xa2, + 0x35, 0xc8, 0xdb, 0x19, 0xab, 0x2f, + 0x11, 0x25, 0xed, 0x33, 0x9e, 0x55, + 0xe1, 0x48, 0xaf, 0x73, 0x84, 0xda, + 0x2a, 0xaa, 0x51, 0xeb, 0x9d, 0x95, + 0xb2, 0xcb, 0xe7, 0x70, 0x80, 0xfe, + 0x4c, 0x65, 0x04, 0xef, 0xc5, 0xf1, + 0xc3, 0x3a, 0xb4, 0xf5, 0x5f, 0x23, + 0x89, 0xdd, 0x30, 0xa5, 0x8b, 0xd3, + 0xf6, 0xdc, 0x4d, 0x64, 0xd7, 0xf0, + 0x8f, 0xec, 0x56, 0x37, 0x5c, 0xa4, + 0x0d, 0x07, 0x76, 0x8a, 0x2c, 0x0b, + 0xb5, 0xd8, 0xc1, 0x1f, 0xe8, 0x3b, + 0xf4, 0x4b, 0x1b, 0x47, 0x6c, 0x49, + 0x67, 0x7b, 0x92, 0xcf, 0x75, 0x7e, + 0x20, 0xd9, 0x7d, 0x3c, 0x97, 0x7a, + 0xd0, 0x05, 0x6b, 0x0f, 0x1d, 0xfb, + 0x82, 0x98, 0x57, 0x8d, 0xf3, 0x6a, + 0xbc, 0xac, 0xc9, 0xa6, 0xff, 0xb8, + 0x69, 0x0c, 0x4c, 0x4d, 0x72, 0x07, + 0x5a, 0x49, 0x33, 0x8d, 0xa2, 0xab, + 0x46, 0x3d, 0x63, 0x0d, 0xa0, 0x97, + 0xff, 0xf0, 0xf5, 0xfa, 0xc0, 0xe9, + 0xdb, 0x62, 0xe4, 0xe1, 0x74, 0x43, + 0xdc, 0x86, 0x18, 0x29, 0x37, 0xf4, + 0x06, 0xe2, 0xed, 0x6f, 0x90, 0x48, + 0x1e, 0x2d, 0x1d, 0xea, 0x73, 0x94, + 0x54, 0xdf, 0x25, 0xf6, 0x47, 0x27, + 0xd9, 0x11, 0x77, 0xc9, 0x84, 0x1c, + 0x5b, 0x5c, 0x51, 0x81, 0xa6, 0x22, + 0x3e, 0x24, 0x96, 0xc8, 0x8a, 0xec, + 0x82, 0x7c, 0x09, 0xb8, 0x45, 0x4a, + 0x57, 0xbb, 0x2f, 0x50, 0x75, 0x8e, + 0x61, 0x70, 0x8c, 0x6c, 0xaf, 0xd0, + 0xfd, 0xb4, 0x1b, 0xae, 0xde, 0xfe, + 0x3b, 0xb5, 0x36, 0xbd, 0x55, 0x01, + 0x0e, 0x9c, 0x41, 0x56, 0x5f, 0xb3, + 0x26, 0x03, 0x83, 0xba, 0x13, 0x4b, + 0xca, 0xc5, 0x0a, 0xf8, 0x60, 0xa5, + 0xb9, 0xc7, 0xc3, 0x98, 0x32, 0xfb, + 0x12, 0xf9, 0xa7, 0x92, 0xaa, 0x68, + 0xf3, 0x78, 0x7e, 0x05, 0x20, 0x21, + 0x02, 0xe8, 0xbf, 0xf2, 0xb0, 0x59, + 0x8f, 0xd2, 0xcb, 0x87, 0x65, 0x15, + 0xf1, 0x1a, 0xb2, 0x30, 0xad, 0xee, + 0x58, 0xa3, 0x8b, 0x66, 0x1f, 0x2c, + 0xd7, 0x5d, 0x19, 0x85, 0xa8, 0xe6, + 0xd3, 0x6b, 0xa1, 0x0c, 0x91, 0x93, + 0x6a, 0x5e, 0x0b, 0x79, 0xe3, 0xdd, + 0x00, 0x4f, 0x3c, 0x89, 0x6e, 0x71, + 0x69, 0xa9, 0xac, 0x40, 0xe5, 0x99, + 0x28, 0xc6, 0x31, 0x4e, 0x7a, 0xcd, + 0x08, 0x9e, 0x7d, 0xef, 0x17, 0xfc, + 0x88, 0xd8, 0xa4, 0x6d, 0x44, 0x95, + 0xd1, 0xb7, 0xd4, 0x9b, 0xbe, 0x2a, + 0x34, 0x64, 0x2b, 0xcf, 0x2e, 0xeb, + 0x38, 0xce, 0x23, 0xe0, 0x3a, 0x3f, + 0xf7, 0x7b, 0x9f, 0x10, 0x53, 0xbc, + 0x52, 0x67, 0x16, 0xe7, 0x80, 0x76, + 0x04, 0xc4, 0xb6, 0xc1, 0xc2, 0x7f, + 0x9a, 0xda, 0xd5, 0x39, 0x42, 0x14, + 0x9d, 0xb1, 0x0f, 0x35, 0xd6, 0xcc, + 0xb9, 0xda, 0x38, 0x0c, 0xa2, 0x9c, + 0x09, 0x1f, 0x06, 0xb1, 0xb6, 0xfd, + 0x1a, 0x69, 0x23, 0x30, 0xc4, 0xde, + 0x01, 0xd1, 0xf4, 0x58, 0x29, 0x37, + 0x1c, 0x7d, 0xd5, 0xbf, 0xff, 0xbd, + 0xc8, 0xc9, 0xcf, 0x65, 0xbe, 0x7b, + 0x78, 0x97, 0x98, 0x67, 0x08, 0xb3, + 0x26, 0x57, 0xf7, 0xfa, 0x40, 0xad, + 0x8e, 0x75, 0xa6, 0x7c, 0xdb, 0x91, + 0x8b, 0x51, 0x99, 0xd4, 0x17, 0x7a, + 0x90, 0x8d, 0xce, 0x63, 0xcb, 0x4e, + 0xa0, 0xab, 0x18, 0x3a, 0x5b, 0x50, + 0x7f, 0x21, 0x74, 0xc1, 0xbb, 0xb8, + 0xb7, 0xba, 0x0b, 0x35, 0x95, 0x31, + 0x59, 0x9a, 0x4d, 0x04, 0x07, 0x1e, + 0x5a, 0x76, 0x13, 0xf3, 0x71, 0x83, + 0xf0, 0x86, 0x03, 0xa8, 0x39, 0x42, + 0xaa, 0x28, 0xe6, 0xe4, 0xd8, 0x5d, + 0xd3, 0xd0, 0x6e, 0x6f, 0x96, 0xfb, + 0x5e, 0xbc, 0x56, 0xc2, 0x5f, 0x85, + 0x9b, 0xe7, 0xaf, 0xd2, 0x3b, 0x84, + 0x6a, 0xa7, 0x53, 0xc5, 0x44, 0x49, + 0xa5, 0xf9, 0x36, 0x72, 0x3d, 0x2c, + 0xd9, 0x1b, 0xa1, 0xf5, 0x4f, 0x93, + 0x9d, 0x68, 0x47, 0x41, 0x16, 0xca, + 0x2a, 0x4c, 0xa3, 0x87, 0xd6, 0xe5, + 0x19, 0x2e, 0x77, 0x15, 0x6d, 0x70, + 0xc0, 0xdf, 0xb2, 0x00, 0x46, 0xed, + 0xc6, 0x6c, 0x43, 0x60, 0x92, 0x2d, + 0xa9, 0x22, 0x45, 0x8f, 0x34, 0x55, + 0xae, 0xa4, 0x0a, 0x66, 0x32, 0xe0, + 0xdc, 0x02, 0xac, 0xe8, 0x20, 0x8c, + 0x89, 0x62, 0x4a, 0xfe, 0xee, 0xc3, + 0xe3, 0x3c, 0xf1, 0x79, 0x05, 0xe9, + 0xf6, 0x27, 0x33, 0xcc, 0xf2, 0x9e, + 0x11, 0x81, 0x7e, 0x80, 0x10, 0x8a, + 0x82, 0x9f, 0x48, 0x0d, 0xd7, 0xb4, + 0xfc, 0x2f, 0xb5, 0xc7, 0xdd, 0x88, + 0x14, 0x6b, 0x2b, 0x54, 0xea, 0x1d, + 0x94, 0x5c, 0xb0, 0xef, 0x12, 0x24, + 0xcd, 0xeb, 0xe1, 0xe2, 0x64, 0x73, + 0x3f, 0x0e, 0x52, 0x61, 0x25, 0x3e, + 0xf8, 0x0f, 0x4b, 0xec, 0xc0, 0x00, + 0x30, 0xf6, 0x02, 0x49, 0x3d, 0x10, + 0x6e, 0x20, 0xc9, 0xa6, 0x2f, 0xfe, + 0x2c, 0x2b, 0x75, 0x2e, 0x45, 0x26, + 0xab, 0x48, 0xa9, 0x80, 0xfc, 0x04, + 0xcc, 0xd3, 0xb5, 0xba, 0xa3, 0x38, + 0x31, 0x7d, 0x01, 0xd9, 0xa7, 0x7b, + 0x96, 0xb6, 0x63, 0x69, 0x4e, 0xf7, + 0xde, 0xe0, 0x78, 0xca, 0x50, 0xaa, + 0x41, 0x91, 0x65, 0x88, 0xe4, 0x21, + 0x85, 0xda, 0x3a, 0x27, 0xbe, 0x1c, + 0x3e, 0x42, 0x5e, 0x17, 0x52, 0x7f, + 0x1f, 0x89, 0x24, 0x6f, 0x8f, 0x5c, + 0x67, 0x74, 0x0e, 0x12, 0x87, 0x8d, + 0xe9, 0x34, 0xed, 0x73, 0xc4, 0xf8, + 0x61, 0x5b, 0x05, 0xdf, 0x59, 0x4c, + 0x97, 0x79, 0x83, 0x18, 0xa4, 0x55, + 0x95, 0xeb, 0xbd, 0x53, 0xf5, 0xf1, + 0x57, 0x66, 0x46, 0x9f, 0xb2, 0x81, + 0x09, 0x51, 0x86, 0x22, 0x16, 0xdd, + 0x23, 0x93, 0x76, 0x29, 0xc2, 0xd7, + 0x1d, 0xd4, 0xbf, 0x36, 0x3f, 0xea, + 0x4b, 0x11, 0x32, 0xb9, 0x62, 0x54, + 0x60, 0xd6, 0x6d, 0x43, 0x9a, 0x0d, + 0x92, 0x9c, 0xb0, 0xef, 0x58, 0x6c, + 0x9d, 0x77, 0x2d, 0x70, 0xfa, 0xf3, + 0xb3, 0x0b, 0xe2, 0x40, 0x7e, 0xf4, + 0x8a, 0xe5, 0x8c, 0x3c, 0x56, 0x71, + 0xd1, 0x64, 0xe1, 0x82, 0x0a, 0xcb, + 0x13, 0x15, 0x90, 0xec, 0x03, 0x99, + 0xaf, 0x14, 0x5d, 0x0f, 0x33, 0x4a, + 0x94, 0xa5, 0xa8, 0x35, 0x1b, 0xe3, + 0x6a, 0xc6, 0x28, 0xff, 0x4d, 0xe7, + 0x25, 0x84, 0xac, 0x08, 0xae, 0xc5, + 0xa2, 0x2a, 0xb8, 0x37, 0x0c, 0x7a, + 0xa0, 0xc3, 0xce, 0xad, 0x06, 0x1a, + 0x9e, 0x8b, 0xfb, 0xd5, 0xf0, 0xc1, + 0x1e, 0xd0, 0xb4, 0x9b, 0xb1, 0x44, + 0xf2, 0x47, 0xc7, 0x68, 0xcf, 0x72, + 0xbb, 0x4f, 0x5a, 0xf9, 0xdc, 0x6b, + 0xdb, 0xd2, 0xe8, 0x7c, 0xc8, 0xee, + 0x98, 0xa1, 0xe6, 0xd8, 0x39, 0x07, + 0x5f, 0xfd, 0x8e, 0x19, 0xb7, 0x3b, + 0xbc, 0xcd, 0x7c, 0xe3, 0x81, 0x73, + 0xb2, 0x11, 0xbf, 0x6f, 0x20, 0x98, + 0xfe, 0x75, 0x96, 0xef, 0x6c, 0xda, + 0x50, 0xe1, 0x09, 0x72, 0x54, 0x45, + 0xba, 0x34, 0x80, 0x5b, 0xed, 0x3e, + 0x53, 0x2c, 0x87, 0xa4, 0x57, 0xf3, + 0x33, 0x3f, 0x3c, 0xb7, 0x67, 0xb4, + 0xa3, 0x25, 0x60, 0x4f, 0x07, 0x6b, + 0x1b, 0x47, 0x15, 0x0f, 0xe4, 0x0a, + 0xea, 0xd1, 0x32, 0x78, 0x36, 0x49, + 0x8d, 0x4b, 0xd2, 0xbc, 0xa5, 0xdc, + 0x1d, 0x0d, 0x4d, 0xcd, 0x9a, 0x82, + 0x5f, 0xfc, 0x94, 0x65, 0xbe, 0xe2, + 0xf4, 0xc9, 0x1e, 0x44, 0xcb, 0x9e, + 0x0c, 0x64, 0x71, 0x26, 0x63, 0xb3, + 0x14, 0xe8, 0x40, 0x70, 0x8a, 0x0e, + 0x19, 0x42, 0x6d, 0xac, 0x88, 0x10, + 0x5c, 0xdf, 0x41, 0xa9, 0xad, 0xe5, + 0xfb, 0x74, 0xcc, 0xd5, 0x06, 0x8e, + 0x59, 0x86, 0xce, 0x1f, 0x3d, 0x76, + 0xe0, 0x8f, 0xb9, 0x77, 0x27, 0x7b, + 0xa6, 0xd8, 0x29, 0xd3, 0xec, 0xb8, + 0x13, 0xf7, 0xfa, 0xc3, 0x51, 0x6a, + 0xde, 0x4a, 0x5a, 0xeb, 0xc2, 0x8b, + 0x23, 0x48, 0x92, 0xcf, 0x62, 0xa8, + 0x99, 0xf8, 0xd0, 0x2e, 0x85, 0x61, + 0x43, 0xc8, 0xbd, 0xf0, 0x05, 0x93, + 0xca, 0x4e, 0xf1, 0x7d, 0x30, 0xfd, + 0xc4, 0x69, 0x66, 0x2f, 0x08, 0xb1, + 0x52, 0xf9, 0x21, 0xe6, 0x7a, 0x2b, + 0xdd, 0x39, 0x84, 0xff, 0xc0, 0x91, + 0xd6, 0x37, 0xd4, 0x7f, 0x2d, 0x9b, + 0x5d, 0xa1, 0x3b, 0x6e, 0xb5, 0xc5, + 0x46, 0x04, 0xf5, 0x90, 0xee, 0x7e, + 0x83, 0x1c, 0x03, 0x56, 0xb6, 0xaa, + 0x00, 0x17, 0x01, 0x35, 0x55, 0x79, + 0x0b, 0x12, 0xbb, 0x1a, 0x31, 0xe7, + 0x02, 0x28, 0x16, 0xc1, 0xf6, 0xa2, + 0xdb, 0x18, 0x9c, 0x89, 0x68, 0x38, + 0x97, 0xab, 0xc7, 0x2a, 0xd7, 0x3a, + 0xf2, 0xc6, 0x24, 0x4c, 0xb0, 0x58, + 0xa0, 0x22, 0x5e, 0x9d, 0xd9, 0xa7, + 0xe9, 0xae, 0xaf, 0x8c, 0x95, 0x9f, + 0x28, 0xb7, 0x20, 0xd7, 0xb0, 0x30, + 0xc3, 0x09, 0x19, 0xc0, 0x67, 0xd6, + 0x00, 0x3c, 0x7e, 0xe7, 0xe9, 0xf4, + 0x08, 0x5a, 0xf8, 0xb8, 0x2e, 0x05, + 0xa6, 0x25, 0x9e, 0x5c, 0xd8, 0x15, + 0x0d, 0xe1, 0xf6, 0x11, 0x54, 0x6b, + 0xcd, 0x21, 0x46, 0x66, 0x5e, 0x84, + 0xad, 0x06, 0x38, 0x29, 0x44, 0xc5, + 0xa2, 0xce, 0xf1, 0xaa, 0xc1, 0x40, + 0x71, 0x86, 0xb5, 0xef, 0xfc, 0x36, + 0xa8, 0xcb, 0x0a, 0x48, 0x27, 0x45, + 0x64, 0xa3, 0xaf, 0x8c, 0xb2, 0xc6, + 0x9f, 0x07, 0x89, 0xdc, 0x17, 0xd3, + 0x49, 0x79, 0xfb, 0xfe, 0x1d, 0xd0, + 0xb9, 0x88, 0x43, 0x52, 0xbc, 0x01, + 0x78, 0x2b, 0x7d, 0x94, 0xc7, 0x0e, + 0xde, 0xa5, 0xd5, 0x9b, 0xcc, 0xf7, + 0x61, 0x7a, 0xc2, 0x74, 0x81, 0x39, + 0x03, 0xab, 0x96, 0xa0, 0x37, 0xbd, + 0x2d, 0x72, 0x75, 0x3f, 0xc9, 0xd4, + 0x8e, 0x6f, 0xf9, 0x8d, 0xed, 0x62, + 0xdb, 0x1c, 0xdf, 0x04, 0xac, 0x1b, + 0x6c, 0x14, 0x4b, 0x63, 0xf0, 0xbf, + 0xb4, 0x82, 0xec, 0x7b, 0x1a, 0x59, + 0x92, 0xd2, 0x10, 0x60, 0xb6, 0x3d, + 0x5f, 0xe6, 0x80, 0x6e, 0x70, 0xc4, + 0xf2, 0x35, 0xd9, 0x7c, 0xee, 0xe5, + 0x41, 0xa4, 0x5b, 0x50, 0xdd, 0xbb, + 0x4c, 0xf3, 0x1f, 0x9d, 0x5d, 0x57, + 0x55, 0x51, 0x97, 0xe3, 0x58, 0x42, + 0x4d, 0x9c, 0x73, 0xba, 0xc8, 0x77, + 0x31, 0x69, 0x26, 0xae, 0xea, 0x8a, + 0xda, 0x22, 0xb3, 0x87, 0x56, 0xfa, + 0x93, 0x0b, 0x34, 0x16, 0x33, 0xe8, + 0xe4, 0x53, 0xbe, 0xa9, 0xb1, 0x3a, + 0x3e, 0xf5, 0x90, 0x6a, 0xcf, 0x3b, + 0x12, 0xfd, 0x8f, 0x9a, 0xa7, 0x47, + 0x91, 0x99, 0xeb, 0x0f, 0x24, 0xff, + 0x23, 0x18, 0x85, 0x4e, 0x7f, 0x0c, + 0xe0, 0xa1, 0xe2, 0xd1, 0x2c, 0x2a, + 0x4a, 0x02, 0x4f, 0x1e, 0x95, 0x68, + 0x8b, 0x98, 0x83, 0x6d, 0x76, 0xca, + 0x65, 0x32, 0x13, 0x2f, 0xc3, 0x82, + 0x9a, 0xa4, 0xba, 0x81, 0x60, 0x37, + 0x34, 0x35, 0xfc, 0x80, 0xa8, 0x51, + 0x65, 0x67, 0xed, 0x30, 0x5f, 0x10, + 0xd3, 0x4a, 0x27, 0x2f, 0x13, 0xb9, + 0x2a, 0xd2, 0xcc, 0xe1, 0xef, 0xae, + 0xeb, 0xbe, 0xf4, 0xbd, 0xcf, 0x43, + 0xb3, 0xc5, 0x88, 0x84, 0xb7, 0xdd, + 0x39, 0x40, 0xce, 0x48, 0x6d, 0x9b, + 0x72, 0x61, 0x7e, 0xe7, 0xa1, 0x4e, + 0x53, 0x2e, 0x77, 0x3b, 0xe2, 0xc9, + 0x36, 0x22, 0x1b, 0x6e, 0x73, 0xb1, + 0x03, 0xb2, 0x4c, 0x87, 0xa9, 0xd4, + 0x4d, 0x0f, 0xd8, 0x15, 0x6c, 0xaa, + 0x18, 0xf6, 0x49, 0x57, 0x5d, 0xfb, + 0x7a, 0x14, 0x94, 0x63, 0xa0, 0x11, + 0xb0, 0x9e, 0xde, 0x05, 0x46, 0xc8, + 0xee, 0x47, 0xdb, 0xdc, 0x24, 0x89, + 0x9c, 0x91, 0x97, 0x29, 0xe9, 0x7b, + 0xc1, 0x07, 0x1e, 0xb8, 0xfd, 0xfe, + 0xac, 0xc6, 0x62, 0x98, 0x4f, 0xf1, + 0x79, 0xe0, 0xe8, 0x6b, 0x78, 0x56, + 0xb6, 0x8d, 0x04, 0x50, 0x86, 0xca, + 0x6f, 0x20, 0xe6, 0xea, 0xe5, 0x76, + 0x17, 0x1c, 0x74, 0x7f, 0xbc, 0x0d, + 0x2c, 0x85, 0xf7, 0x66, 0x96, 0xe4, + 0x8b, 0x75, 0x3f, 0x4b, 0xd9, 0x38, + 0xaf, 0x7c, 0xda, 0x0b, 0x83, 0x2d, + 0x31, 0x32, 0xa2, 0xf5, 0x1d, 0x59, + 0x41, 0x45, 0xbf, 0x3c, 0x1f, 0xf8, + 0xf9, 0x8a, 0xd0, 0x16, 0x25, 0x69, + 0x12, 0x99, 0x9d, 0x21, 0x95, 0xab, + 0x01, 0xa6, 0xd7, 0xb5, 0xc0, 0x7d, + 0xff, 0x58, 0x0e, 0x3a, 0x92, 0xd1, + 0x55, 0xe3, 0x08, 0x9f, 0xd6, 0x3e, + 0x52, 0x8e, 0xfa, 0xa3, 0xc7, 0x02, + 0xcd, 0xdf, 0x8f, 0x64, 0x19, 0x8c, + 0xf3, 0xa7, 0x0c, 0x5e, 0x0a, 0x6a, + 0x09, 0xf0, 0x93, 0x5b, 0x42, 0xc2, + 0x06, 0x23, 0xec, 0x71, 0xad, 0xb4, + 0xcb, 0xbb, 0x70, 0x28, 0xd5, 0x1a, + 0x5c, 0x33, 0x68, 0x5a, 0x00, 0x44, + 0x90, 0xa5, 0xc4, 0x26, 0x3d, 0x2b, + 0xf2, 0x54, 0x96, 0xad, 0xda, 0x1f, + 0xed, 0x33, 0xe1, 0x81, 0x69, 0x08, + 0x0d, 0x0a, 0xdb, 0x35, 0x77, 0x9a, + 0x64, 0xd1, 0xfc, 0x78, 0xaa, 0x1b, + 0xd0, 0x67, 0xa0, 0xdd, 0xfa, 0x6c, + 0x63, 0x71, 0x05, 0x84, 0x17, 0x6a, + 0x89, 0x4f, 0x66, 0x7f, 0xc6, 0x50, + 0x55, 0x92, 0x6f, 0xbd, 0xe7, 0xd2, + 0x40, 0x72, 0x8d, 0xbb, 0xec, 0x06, + 0x42, 0x8a, 0xe4, 0x88, 0x9d, 0x7e, + 0x7a, 0x82, 0x27, 0x13, 0x41, 0x1a, + 0xaf, 0xc8, 0xa4, 0x76, 0xb4, 0xc2, + 0xfe, 0x6d, 0x1c, 0xd9, 0x61, 0x30, + 0xb3, 0x7c, 0xea, 0xf7, 0x29, 0x0f, + 0xf2, 0x3b, 0x51, 0xc1, 0xde, 0x5f, + 0xe5, 0x2a, 0x2f, 0x99, 0x0b, 0x5d, + 0xa3, 0x2b, 0x4a, 0xab, 0x95, 0xa5, + 0xd3, 0x58, 0x56, 0xee, 0x28, 0x31, + 0x00, 0xcc, 0x15, 0x46, 0xca, 0xe6, + 0x86, 0x38, 0x3c, 0x65, 0xf5, 0xe3, + 0x9f, 0xd6, 0x5b, 0x09, 0x49, 0x83, + 0x70, 0x2d, 0x53, 0xa9, 0x7d, 0xe2, + 0xc4, 0xac, 0x8e, 0x5e, 0xb8, 0x25, + 0xf4, 0xb9, 0x57, 0xf3, 0xf1, 0x68, + 0x47, 0xb2, 0xa2, 0x59, 0x20, 0xce, + 0x34, 0x79, 0x5c, 0x90, 0x0e, 0x1e, + 0xbe, 0xd5, 0x22, 0x23, 0xb1, 0xc9, + 0x18, 0x62, 0x16, 0x2e, 0x91, 0x3e, + 0x07, 0x8f, 0xd8, 0x3f, 0x93, 0x3d, + 0xd4, 0x9b, 0xdf, 0x85, 0x21, 0xfb, + 0x11, 0x74, 0x97, 0xc7, 0xd7, 0xdc, + 0x4c, 0x19, 0x45, 0x98, 0xe9, 0x43, + 0x02, 0x4b, 0xbc, 0xc3, 0x04, 0x9c, + 0x6b, 0xf0, 0x75, 0x52, 0xa7, 0x26, + 0xf6, 0xc5, 0xba, 0xcf, 0xb0, 0xb7, + 0xae, 0x5a, 0xa1, 0xbf, 0x03, 0x8b, + 0x80, 0x12, 0x6e, 0x0c, 0xeb, 0xf9, + 0xc0, 0x44, 0x24, 0xef, 0x10, 0xf8, + 0xa8, 0x8c, 0xe8, 0x7b, 0xff, 0x9e, + 0x2c, 0xcd, 0x60, 0x36, 0x87, 0xb5, + 0x94, 0xa6, 0x54, 0x73, 0x3a, 0x14, + 0x4e, 0x01, 0x1d, 0xb6, 0xfd, 0x37, + 0x48, 0x4d, 0x39, 0xcb, 0xe0, 0x32 +}; + +// WPADiCreateKeyFor3rd +static byte_t base3[] = +{ + 0x54, 0x29, 0x28, 0x4e, 0x0f, 0xfc, + 0xa4, 0x6c, 0x87, 0x50, 0x49, 0x3c, + 0xf2, 0xb4, 0xb1, 0xf9, 0xc3, 0x58, + 0x2e, 0x83, 0x5f, 0x71, 0x8a, 0x9b, + 0x82, 0xca, 0xc2, 0xbe, 0xba, 0x75, + 0x91, 0x60, 0x78, 0xa8, 0x2a, 0x4c, + 0x25, 0x5b, 0x8b, 0xb0, 0xda, 0xaf +}; + +static byte_t tb3[] = +{ + 0xa4, 0x38, 0x33, 0x69, 0xd4, 0xf5, + 0x6a, 0xa8, 0xd7, 0xec, 0x74, 0xa6, + 0x7b, 0xc7, 0x3c, 0x41, 0xb7, 0x21, + 0x98, 0x4a, 0x8d, 0xc8, 0x28, 0xf3, + 0xf8, 0x32, 0x91, 0xab, 0xad, 0x34, + 0x86, 0x30, 0x4c, 0xbc, 0xff, 0xce, + 0x14, 0x1e, 0x2e, 0xf9, 0x31, 0x59, + 0x85, 0x87, 0xfc, 0xc2, 0xfd, 0x3e, + 0xbb, 0x56, 0x88, 0x8b, 0xbf, 0x47, + 0x61, 0x92, 0xb1, 0x94, 0x7a, 0x51, + 0x9c, 0x8f, 0xb0, 0x49, 0x9b, 0xb9, + 0x05, 0x36, 0x10, 0x3b, 0xd5, 0xd3, + 0x0c, 0x96, 0xcb, 0x79, 0x60, 0x4e, + 0xa2, 0xb5, 0xd1, 0xee, 0x17, 0xba, + 0x1f, 0x09, 0x78, 0x93, 0xb4, 0x35, + 0x3a, 0x9d, 0x1d, 0x39, 0xc9, 0x3f, + 0x7c, 0x2f, 0xca, 0x0b, 0x37, 0xe6, + 0x1b, 0xd0, 0x67, 0xd9, 0x18, 0x84, + 0xe1, 0x42, 0x5a, 0x7e, 0xb8, 0x97, + 0xdf, 0x54, 0x70, 0x03, 0x6e, 0xdb, + 0x63, 0xae, 0x55, 0x5d, 0xc4, 0x4b, + 0x89, 0xcc, 0x13, 0xb3, 0x90, 0xf6, + 0xe9, 0xb2, 0xa3, 0xbe, 0x2d, 0x19, + 0x73, 0x23, 0x20, 0x7f, 0x40, 0x02, + 0x9e, 0xc3, 0x6b, 0x1a, 0x52, 0xda, + 0x29, 0x80, 0x0d, 0x5f, 0xd6, 0x8e, + 0x0e, 0x22, 0xe3, 0x6d, 0xdc, 0x58, + 0x75, 0xe0, 0x01, 0x0a, 0x26, 0x50, + 0x08, 0xa9, 0xfe, 0x4d, 0x15, 0xf7, + 0x6c, 0xcf, 0x4f, 0xf0, 0x64, 0x5e, + 0xc6, 0x68, 0x8a, 0xac, 0xde, 0xb6, + 0x48, 0x66, 0xed, 0x6f, 0x71, 0x45, + 0x3d, 0xeb, 0x9f, 0x04, 0x25, 0x5c, + 0xbd, 0x65, 0xdd, 0x53, 0xcd, 0x24, + 0xef, 0x72, 0xe8, 0x9a, 0xe7, 0x16, + 0xc1, 0x00, 0x77, 0x2c, 0x7d, 0xa5, + 0x2a, 0x44, 0x62, 0x27, 0xf4, 0xc0, + 0x07, 0x1c, 0x5b, 0x99, 0x82, 0x57, + 0x06, 0xfa, 0xfb, 0x12, 0xaf, 0xa7, + 0xd2, 0xaa, 0x2b, 0x8c, 0xf2, 0xd8, + 0x83, 0xa0, 0x76, 0x11, 0xc5, 0x43, + 0x81, 0x46, 0xe5, 0xf1, 0xea, 0x95, + 0xe2, 0xe4, 0x0f, 0xa1, 0x2b, 0xd2, + 0xa5, 0x8e, 0x26, 0x09, 0x0f, 0xf7, + 0x45, 0x5b, 0x3c, 0xfd, 0x8c, 0x72, + 0x22, 0xbf, 0xca, 0xda, 0xe7, 0xaf, + 0x16, 0xb2, 0x5e, 0x8a, 0x6f, 0x94, + 0xb7, 0xd6, 0x1c, 0xb1, 0x29, 0x4c, + 0xb5, 0x43, 0x18, 0x9c, 0x31, 0xce, + 0xb6, 0x84, 0x71, 0x60, 0x7f, 0x2a, + 0x6e, 0x35, 0xf8, 0xa6, 0x54, 0xea, + 0x74, 0x88, 0xac, 0x03, 0x19, 0x1b, + 0x3d, 0x79, 0xfc, 0xee, 0x42, 0x9f, + 0x93, 0xdb, 0x80, 0xad, 0x8b, 0x15, + 0x41, 0x5d, 0x48, 0xcd, 0x7c, 0xa3, + 0x2c, 0x32, 0x1f, 0x63, 0xd1, 0xed, + 0x4f, 0x04, 0x66, 0x1e, 0x46, 0x9b, + 0xbb, 0x38, 0x06, 0x7e, 0x95, 0xc8, + 0x5f, 0x4a, 0x51, 0x6b, 0x97, 0xbe, + 0x2e, 0x98, 0xbd, 0xec, 0x0e, 0x05, + 0x0a, 0xa0, 0x01, 0x52, 0x85, 0xc0, + 0xd8, 0x3b, 0xfe, 0x12, 0x64, 0xe1, + 0xf3, 0x24, 0x4b, 0xf5, 0x49, 0x7a, + 0xe4, 0x4e, 0x34, 0x25, 0x08, 0x53, + 0x1a, 0xe3, 0xef, 0x86, 0xdf, 0xf1, + 0x91, 0xeb, 0xc6, 0xd9, 0xd3, 0x83, + 0x14, 0x1d, 0xb0, 0xa7, 0x0b, 0x10, + 0x40, 0x89, 0xb4, 0xd4, 0x3a, 0x02, + 0x0c, 0xdd, 0x2f, 0x5a, 0x56, 0x28, + 0xae, 0x2d, 0x55, 0xf6, 0xc1, 0xd5, + 0xa8, 0x44, 0xcf, 0x58, 0x9d, 0xb3, + 0x23, 0xc5, 0xa4, 0x3e, 0x7d, 0x30, + 0x13, 0x6a, 0x61, 0xd0, 0xf0, 0x3f, + 0x67, 0xcb, 0x0d, 0xff, 0x92, 0x68, + 0xe0, 0x81, 0x69, 0x62, 0xab, 0x75, + 0x59, 0x11, 0xf2, 0xc9, 0x07, 0xe9, + 0xc7, 0xa1, 0xc2, 0x78, 0x33, 0x17, + 0x6c, 0xf9, 0xc4, 0xb8, 0xb9, 0xdc, + 0x27, 0x90, 0xbc, 0xfb, 0x70, 0xaa, + 0xe8, 0x96, 0x73, 0x39, 0xf4, 0xc3, + 0x77, 0x87, 0xde, 0x00, 0xa2, 0x9a, + 0xe2, 0x7b, 0xfa, 0x36, 0x65, 0x6d, + 0x20, 0xd7, 0x57, 0x5c, 0x37, 0x8f, + 0x4d, 0x9e, 0x47, 0xa9, 0xe5, 0xcc, + 0x99, 0x8d, 0x76, 0x50, 0xba, 0xe6, + 0x82, 0x21, 0xb0, 0x0d, 0xeb, 0x75, + 0x6d, 0x22, 0xce, 0xe7, 0x63, 0x2c, + 0xde, 0xe2, 0xf5, 0x45, 0xba, 0x44, + 0x95, 0x1f, 0xe5, 0x39, 0xd7, 0xa5, + 0xb5, 0x8d, 0x07, 0x93, 0xfd, 0xbc, + 0x62, 0x7e, 0x89, 0xb3, 0x48, 0x59, + 0x7f, 0xd3, 0xbe, 0xd0, 0xf2, 0x36, + 0x53, 0x9f, 0xe6, 0xb1, 0x82, 0xc0, + 0x94, 0xb8, 0x2f, 0x03, 0x24, 0x3c, + 0x00, 0x0a, 0x42, 0x65, 0xe8, 0x5c, + 0x96, 0xd5, 0xa9, 0x90, 0xb9, 0x85, + 0xe9, 0xea, 0x0e, 0x16, 0x7b, 0x84, + 0x29, 0x4e, 0x5e, 0x87, 0x9d, 0x35, + 0x06, 0x86, 0xe1, 0xe0, 0xe3, 0xec, + 0xef, 0xc8, 0x52, 0x5f, 0x64, 0xe4, + 0x46, 0x30, 0x5a, 0xcd, 0xed, 0xd1, + 0x51, 0x81, 0x0c, 0x3a, 0x66, 0xfe, + 0x04, 0x67, 0x1e, 0xd6, 0xf7, 0x8c, + 0xbd, 0x33, 0xb2, 0x91, 0xd4, 0xa8, + 0x4a, 0x14, 0x0b, 0x79, 0x58, 0x88, + 0xb6, 0xc1, 0x19, 0x56, 0xf8, 0x27, + 0xac, 0x23, 0x99, 0xb4, 0xc3, 0x12, + 0xf3, 0x20, 0x78, 0x34, 0x49, 0xdc, + 0xd8, 0x05, 0xbb, 0x55, 0x8a, 0x71, + 0x11, 0x21, 0xc7, 0xdb, 0xf1, 0x9b, + 0xf6, 0x9e, 0x17, 0xf9, 0xfa, 0xfb, + 0xa7, 0x60, 0x8e, 0x6e, 0x8b, 0xca, + 0x15, 0xab, 0xdd, 0x3d, 0xa6, 0xc6, + 0x80, 0xc2, 0xda, 0x4c, 0x1d, 0x4f, + 0x5d, 0x92, 0x69, 0x98, 0xa2, 0x32, + 0x9c, 0x2b, 0x6a, 0x41, 0x1a, 0x6c, + 0xa3, 0xc5, 0x72, 0xaa, 0xcc, 0x6b, + 0x10, 0x5b, 0x4d, 0x57, 0x28, 0x68, + 0xee, 0x09, 0x40, 0xf0, 0xad, 0x26, + 0x2e, 0x2d, 0x9a, 0xa0, 0x7a, 0xcb, + 0x74, 0x3e, 0x1b, 0x70, 0xfc, 0x43, + 0xc4, 0x77, 0x08, 0xb7, 0xcf, 0x1c, + 0x7d, 0x18, 0x0f, 0x13, 0x25, 0xbf, + 0x61, 0x01, 0x37, 0xae, 0xd2, 0x2a, + 0x7c, 0x97, 0xaf, 0x3f, 0x50, 0xdf, + 0x6f, 0xa1, 0xa4, 0xff, 0x38, 0xc9, + 0x83, 0x8f, 0x54, 0x73, 0x02, 0x47, + 0xd9, 0x31, 0x76, 0x3b, 0x4b, 0xf4, + 0x9c, 0x49, 0xc7, 0xb6, 0x14, 0x21, + 0x5f, 0x52, 0xf3, 0xb7, 0xd5, 0xf2, + 0x95, 0xa0, 0x25, 0x54, 0xd9, 0xe7, + 0xb0, 0xbf, 0x69, 0x13, 0x78, 0xf0, + 0x33, 0xe0, 0x8c, 0x94, 0xdb, 0xe6, + 0xa7, 0xb5, 0xec, 0xc2, 0x63, 0xe3, + 0x18, 0xb9, 0x4b, 0x74, 0xe5, 0x01, + 0x8e, 0xb1, 0x27, 0x35, 0xb4, 0x3d, + 0x26, 0x48, 0x1f, 0xfa, 0xbb, 0x90, + 0xd3, 0x98, 0xdf, 0xa4, 0x37, 0x67, + 0x5d, 0x80, 0xd2, 0x62, 0xe1, 0x6f, + 0x96, 0x2d, 0xa8, 0x6a, 0x97, 0x30, + 0x89, 0xea, 0x3a, 0xbe, 0x22, 0x19, + 0x41, 0xac, 0x79, 0xf1, 0x85, 0xee, + 0x70, 0xc0, 0x0a, 0x1b, 0x7f, 0xc1, + 0xd0, 0xa6, 0xf4, 0x16, 0xfc, 0xba, + 0x4e, 0x4a, 0xc9, 0x12, 0x8a, 0x1a, + 0x9d, 0xc5, 0x38, 0xd4, 0xde, 0xad, + 0xc4, 0x43, 0x03, 0xb3, 0xf7, 0xa9, + 0x59, 0x6d, 0xa3, 0x20, 0x36, 0x4d, + 0x86, 0x5b, 0xae, 0x61, 0x17, 0xa5, + 0x93, 0xdc, 0x50, 0x2c, 0xef, 0x2a, + 0x68, 0x75, 0x7a, 0x8b, 0xd6, 0xfb, + 0x00, 0x9e, 0x2e, 0x02, 0xcd, 0xed, + 0x47, 0xab, 0x82, 0xbd, 0x71, 0x11, + 0xb2, 0x66, 0x5e, 0x3c, 0x7c, 0x08, + 0x6e, 0xf6, 0x09, 0x45, 0x3f, 0x5a, + 0x0f, 0x84, 0xcc, 0xdd, 0x73, 0x0d, + 0xf8, 0x92, 0xe8, 0x0b, 0xe9, 0xcf, + 0x4f, 0x1c, 0xda, 0x10, 0x0e, 0x9f, + 0xa2, 0x58, 0xff, 0x40, 0x87, 0x77, + 0x2f, 0x60, 0x4c, 0xc3, 0x28, 0x88, + 0x15, 0x81, 0x06, 0x56, 0xd1, 0x55, + 0x8d, 0x9b, 0x57, 0x83, 0x65, 0x91, + 0x34, 0xce, 0x53, 0x42, 0x04, 0x0c, + 0x46, 0x7d, 0x07, 0x29, 0xfe, 0x24, + 0x2b, 0x6c, 0x05, 0x32, 0xcb, 0x72, + 0x1e, 0x7e, 0xaa, 0xe4, 0x99, 0x6b, + 0xe2, 0xa1, 0xd8, 0x1d, 0x3e, 0xc6, + 0xc8, 0x5c, 0x8f, 0xd7, 0x64, 0x39, + 0xb8, 0x44, 0x23, 0x31, 0x7b, 0x51, + 0xca, 0x3b, 0xf5, 0xf9, 0xfd, 0x76, + 0xeb, 0x9a, 0xaf, 0xbc, 0x94, 0xc5, + 0x26, 0x3f, 0xf6, 0xf8, 0x93, 0x6e, + 0x73, 0x84, 0x82, 0xe7, 0x54, 0x2c, + 0x57, 0xaa, 0x46, 0x6d, 0x7a, 0x7e, + 0xf7, 0xe6, 0x9a, 0x9f, 0xd6, 0xed, + 0xe1, 0xf0, 0xf5, 0x67, 0xde, 0xf4, + 0xd1, 0x41, 0xfc, 0x4a, 0x53, 0xc8, + 0x4d, 0x30, 0x4e, 0x36, 0x40, 0x31, + 0x8d, 0x98, 0x0c, 0xa2, 0xc0, 0xea, + 0x6c, 0x0a, 0x18, 0x58, 0x8f, 0xee, + 0x00, 0x62, 0x83, 0xe2, 0x0d, 0x5b, + 0x8b, 0xc7, 0xd7, 0x04, 0x90, 0xa1, + 0xe9, 0xcd, 0x16, 0x15, 0x56, 0x78, + 0x92, 0x77, 0xd5, 0x12, 0xe3, 0xce, + 0x19, 0xbe, 0x34, 0x50, 0x51, 0x4b, + 0x32, 0xc1, 0x06, 0x07, 0x37, 0x35, + 0x60, 0xac, 0xad, 0x2b, 0x27, 0xeb, + 0x08, 0x9b, 0xdb, 0x7b, 0x4f, 0x03, + 0x79, 0x11, 0x17, 0xd3, 0xf1, 0xd9, + 0xa6, 0x66, 0xf3, 0xcf, 0x72, 0x99, + 0x3a, 0xca, 0x3d, 0x0b, 0x89, 0x47, + 0x24, 0xdf, 0x65, 0x14, 0x38, 0x61, + 0xc2, 0x6f, 0x13, 0xaf, 0x91, 0x3e, + 0x2a, 0x33, 0xda, 0xe0, 0xa5, 0x3b, + 0x1b, 0x1d, 0xa0, 0x22, 0x6a, 0xc4, + 0x95, 0xfa, 0xb6, 0xb2, 0x69, 0x9c, + 0xf2, 0x80, 0x44, 0x21, 0xef, 0x9d, + 0xa7, 0xcb, 0xa9, 0x96, 0x1e, 0x43, + 0x76, 0x8a, 0x7f, 0x3c, 0xd0, 0xa8, + 0x59, 0x20, 0xdc, 0x81, 0xc9, 0xcc, + 0x97, 0xa4, 0xbc, 0xbd, 0x7d, 0xab, + 0xa3, 0xb4, 0x52, 0xe4, 0xb0, 0x8c, + 0xb9, 0x2f, 0x9e, 0xb7, 0x4c, 0xe8, + 0x45, 0x63, 0x09, 0x64, 0x5d, 0x88, + 0xd2, 0x1c, 0x74, 0x87, 0x48, 0x5e, + 0x55, 0x6b, 0xb3, 0xec, 0x39, 0x05, + 0x2d, 0x28, 0x10, 0xb1, 0xc6, 0xfe, + 0x70, 0x29, 0x5a, 0xfb, 0x49, 0x23, + 0xdd, 0x86, 0x01, 0xe5, 0xd4, 0x25, + 0x42, 0xae, 0x85, 0x75, 0xff, 0x68, + 0x2e, 0x5c, 0x1f, 0x02, 0xba, 0xb5, + 0xbf, 0x7c, 0xfd, 0x71, 0xf9, 0x8e, + 0x5f, 0xb8, 0x0e, 0x0f, 0xc3, 0x1a, + 0xbb, 0xd8, 0xaa, 0xf3, 0xc7, 0xa9, + 0x43, 0x20, 0xc6, 0xd0, 0xf4, 0x07, + 0x00, 0x9f, 0x89, 0x8e, 0xba, 0xe0, + 0x5a, 0x24, 0x1f, 0x2a, 0xdd, 0xd4, + 0xe3, 0x0d, 0xb0, 0xed, 0xbe, 0xb2, + 0x2b, 0x75, 0x2e, 0x66, 0x17, 0x6e, + 0x7c, 0x52, 0x76, 0x91, 0x01, 0x59, + 0x61, 0x3c, 0x86, 0x2c, 0xfd, 0x2d, + 0xf6, 0x0b, 0xab, 0xe5, 0x22, 0x41, + 0x67, 0x72, 0xc2, 0xad, 0xbd, 0xfe, + 0x96, 0xfa, 0x7b, 0x9e, 0x40, 0x5f, + 0x71, 0x98, 0x4c, 0x88, 0xfb, 0xeb, + 0x6b, 0xc9, 0xce, 0xbb, 0xc0, 0x03, + 0x5b, 0x3a, 0xae, 0x15, 0x3e, 0x56, + 0x4d, 0xd8, 0x3b, 0x50, 0x35, 0x84, + 0x97, 0x34, 0xc4, 0x54, 0xcc, 0x4e, + 0x5e, 0xcd, 0xe6, 0x68, 0x4f, 0xb3, + 0xb4, 0x9d, 0x5d, 0xa5, 0xa3, 0x78, + 0xe9, 0x38, 0x7e, 0x08, 0x60, 0x6c, + 0xdb, 0x7f, 0xbf, 0x82, 0x30, 0xe2, + 0x48, 0x19, 0x6d, 0x1a, 0xa2, 0xdf, + 0x58, 0x95, 0x69, 0x51, 0x31, 0xda, + 0x0c, 0x4b, 0xa4, 0x0a, 0x45, 0x27, + 0xd7, 0x1e, 0x65, 0x87, 0x1b, 0xb7, + 0xb5, 0x42, 0x8c, 0x26, 0x6f, 0x25, + 0xea, 0xfc, 0xef, 0x8a, 0xa7, 0x10, + 0xbc, 0xf5, 0xa0, 0x21, 0x44, 0x57, + 0x02, 0xd2, 0x2f, 0x63, 0x3d, 0xd5, + 0x79, 0x9c, 0x05, 0xf2, 0xe4, 0xcf, + 0x29, 0xf1, 0x53, 0x0e, 0x7a, 0xb1, + 0x14, 0x12, 0xf9, 0xf7, 0x11, 0x8b, + 0x36, 0xa6, 0xb6, 0xd6, 0xa1, 0x18, + 0x39, 0xec, 0x04, 0xc1, 0xe8, 0x8d, + 0x28, 0x99, 0x73, 0x90, 0x70, 0xd3, + 0x1d, 0x8f, 0xcb, 0xf8, 0xf0, 0xb9, + 0xde, 0x77, 0x92, 0x32, 0xe7, 0xee, + 0x85, 0x33, 0x13, 0xa8, 0x9a, 0x3f, + 0xc8, 0xe1, 0x80, 0x9b, 0x06, 0x23, + 0x37, 0x09, 0xd1, 0xff, 0xac, 0x81, + 0x94, 0x64, 0xaf, 0x4a, 0x46, 0x7d, + 0x16, 0xc3, 0x55, 0x47, 0xca, 0xd9, + 0x0f, 0x1c, 0x6a, 0x74, 0xdc, 0x49, + 0x83, 0xc5, 0xb8, 0x5c, 0x93, 0x62, + 0xdc, 0x2f, 0xd4, 0xf0, 0x86, 0x18, + 0xb1, 0x8c, 0x4f, 0xb9, 0xd5, 0x97, + 0x1b, 0x43, 0x4c, 0x1d, 0xea, 0x5b, + 0xc3, 0x11, 0x82, 0xfc, 0xa2, 0x4a, + 0xa0, 0x7f, 0x47, 0xaf, 0xa3, 0x0a, + 0x59, 0xad, 0xe5, 0x06, 0x2a, 0x4e, + 0x6e, 0xe3, 0x40, 0xdb, 0x53, 0x83, + 0x49, 0xb4, 0xba, 0x71, 0x95, 0x9b, + 0x51, 0xb3, 0xac, 0xd1, 0xae, 0xc4, + 0xcf, 0x4b, 0x4d, 0x69, 0x16, 0xec, + 0x0b, 0xa5, 0x91, 0x73, 0x07, 0x3b, + 0x19, 0x84, 0xc2, 0x6d, 0x8d, 0xb2, + 0xbd, 0x25, 0x48, 0x96, 0xc5, 0x20, + 0x1a, 0xa1, 0x8b, 0xc6, 0xe1, 0x3f, + 0x28, 0xa7, 0xe7, 0x12, 0x76, 0xb0, + 0x1c, 0x8e, 0xd0, 0x45, 0x90, 0xca, + 0x98, 0xd6, 0xa6, 0x36, 0x32, 0x72, + 0x8a, 0xa8, 0x0d, 0x3a, 0x9f, 0x37, + 0x3c, 0x89, 0xdd, 0x67, 0x22, 0x81, + 0xe9, 0x15, 0x41, 0x42, 0xf5, 0x2e, + 0x66, 0xd2, 0x61, 0x80, 0x0f, 0x54, + 0x93, 0xaa, 0xed, 0x5d, 0xe4, 0x7d, + 0x30, 0xc9, 0x3d, 0xe0, 0xe2, 0x26, + 0xf2, 0x08, 0xa9, 0x63, 0x24, 0x2d, + 0x8f, 0x79, 0x9c, 0xda, 0xbf, 0x55, + 0x62, 0x5c, 0x00, 0xb6, 0x27, 0x6a, + 0x0e, 0x92, 0x01, 0xd7, 0xff, 0xeb, + 0x1f, 0x74, 0x14, 0x99, 0xf7, 0x44, + 0x87, 0x33, 0x6c, 0x94, 0x13, 0x50, + 0x75, 0x68, 0x10, 0x17, 0xbb, 0x2c, + 0x6b, 0x04, 0xdf, 0xbc, 0x35, 0x6f, + 0xb7, 0xf1, 0x57, 0xc1, 0xe6, 0x7c, + 0xb8, 0x77, 0x65, 0x3e, 0x5f, 0xd3, + 0x64, 0xcb, 0x02, 0x1e, 0x38, 0xab, + 0x88, 0x60, 0x5e, 0x9d, 0xbe, 0xc8, + 0xa4, 0xd8, 0x52, 0x7b, 0x29, 0xf4, + 0x05, 0x70, 0xce, 0x78, 0x85, 0x39, + 0x23, 0xf3, 0x34, 0x58, 0x9e, 0xfb, + 0x31, 0xcc, 0x46, 0xef, 0x9a, 0x5a, + 0xfe, 0x7a, 0x56, 0xfd, 0xee, 0xde, + 0x0c, 0xf9, 0xcd, 0xc0, 0x2b, 0xd9, + 0xb5, 0x09, 0xf6, 0xc7, 0x21, 0xfa, + 0xf8, 0x03, 0xe8, 0x7e, 0x9f, 0xbd, + 0x79, 0x91, 0xcc, 0x78, 0x7f, 0xd5, + 0x1b, 0xee, 0xbb, 0xb7, 0xdc, 0xed, + 0x6d, 0x9b, 0xef, 0x58, 0xfb, 0x5d, + 0x67, 0x69, 0x1f, 0x4e, 0xaf, 0x62, + 0x4b, 0xb8, 0xa8, 0xae, 0x08, 0x60, + 0x8c, 0xad, 0x24, 0xa1, 0x48, 0x2f, + 0x8a, 0x00, 0x90, 0xb1, 0x53, 0x07, + 0x26, 0x12, 0x72, 0x9d, 0x56, 0x1c, + 0x51, 0x34, 0x46, 0x2e, 0x81, 0xcf, + 0xb3, 0xf3, 0x37, 0xf1, 0xfa, 0x3c, + 0xba, 0x06, 0x54, 0x85, 0x14, 0x59, + 0x36, 0x5e, 0xa5, 0x55, 0x0c, 0x52, + 0x89, 0xcb, 0x97, 0xe2, 0x3b, 0x11, + 0xbe, 0xd9, 0x1d, 0xfc, 0x13, 0x7d, + 0xa0, 0x05, 0x41, 0xc3, 0xc5, 0xfd, + 0x76, 0x33, 0x82, 0xcd, 0x88, 0x16, + 0x1a, 0x29, 0x87, 0x1e, 0x40, 0x6f, + 0xe8, 0x03, 0x3a, 0x50, 0xa6, 0xe4, + 0xf4, 0x4f, 0xd6, 0x98, 0x39, 0x71, + 0xd0, 0xf2, 0xf0, 0x3e, 0xea, 0x8d, + 0x2c, 0xa2, 0xa9, 0x57, 0x0b, 0x8b, + 0x0d, 0xaa, 0xe9, 0x31, 0xc2, 0x35, + 0x5c, 0xd1, 0x38, 0xff, 0x01, 0xa7, + 0xec, 0x80, 0xf9, 0x23, 0xdf, 0x30, + 0xeb, 0x2a, 0xb0, 0x17, 0xd2, 0x19, + 0x6e, 0xda, 0x25, 0x9e, 0xb6, 0x4c, + 0xc6, 0x93, 0xdb, 0x75, 0x6b, 0x3f, + 0x15, 0x73, 0xfe, 0x3d, 0x65, 0x66, + 0xb5, 0x7a, 0x9a, 0x32, 0xca, 0x68, + 0x8e, 0x22, 0xc0, 0x44, 0x43, 0xa3, + 0x0e, 0x21, 0xb9, 0x02, 0x4d, 0xc8, + 0xb4, 0x0a, 0xf6, 0xd3, 0x45, 0x96, + 0x5a, 0x84, 0x70, 0x18, 0xd4, 0xbf, + 0xc4, 0xa4, 0x9c, 0xc1, 0xe0, 0x47, + 0xc7, 0xe5, 0xe6, 0x7e, 0x63, 0xdd, + 0x6a, 0xce, 0x28, 0x94, 0xe7, 0x10, + 0xbc, 0x5f, 0x04, 0x64, 0x2d, 0x8f, + 0x6c, 0xf7, 0x2b, 0x92, 0x83, 0xd8, + 0x99, 0xe3, 0xde, 0xd7, 0x5b, 0xab, + 0x4a, 0x74, 0x77, 0xc9, 0xf5, 0x7b, + 0x0f, 0x20, 0xf8, 0x61, 0x42, 0x86, + 0x7c, 0x49, 0x95, 0xac, 0x27, 0xe1, + 0x09, 0xb2, 0x0b, 0xd3, 0x6f, 0x0a, + 0x39, 0x77, 0x21, 0x17, 0x8f, 0xc7, + 0xd5, 0xe5, 0xb5, 0xb9, 0x11, 0xa4, + 0xdc, 0xa3, 0xcd, 0xbb, 0x1a, 0x81, + 0x8a, 0xb7, 0xd9, 0x5b, 0x47, 0x61, + 0x8e, 0x88, 0xb8, 0x0c, 0x3b, 0x3a, + 0x9a, 0x54, 0xfd, 0x2d, 0x53, 0xb4, + 0xc3, 0x5f, 0x69, 0x60, 0xb1, 0xab, + 0x26, 0x56, 0x83, 0x7e, 0xb3, 0x3d, + 0x4a, 0x0d, 0x5a, 0x1d, 0x1e, 0x59, + 0xd6, 0x35, 0x8c, 0xf3, 0x9b, 0x18, + 0x66, 0xbf, 0xe2, 0x62, 0x92, 0x7b, + 0xff, 0x2e, 0x5c, 0xcf, 0x25, 0xc4, + 0xaf, 0xd2, 0x29, 0x63, 0xa5, 0xb2, + 0xf9, 0x6a, 0xc1, 0xfb, 0x14, 0x87, + 0x55, 0x73, 0x2c, 0x44, 0x31, 0x79, + 0xf4, 0x2a, 0x41, 0x01, 0x24, 0x80, + 0x19, 0x65, 0x4d, 0x9d, 0x9c, 0xe8, + 0x13, 0xa2, 0xc0, 0xc5, 0xfe, 0x6b, + 0xce, 0x50, 0xf8, 0x04, 0x48, 0xa8, + 0x06, 0x16, 0xbe, 0x67, 0xba, 0xea, + 0xc6, 0x0f, 0xd7, 0x74, 0x85, 0xb6, + 0xd8, 0x0e, 0x4c, 0x93, 0x15, 0xbd, + 0xe6, 0x78, 0x03, 0x05, 0x32, 0xf7, + 0x34, 0xe4, 0xad, 0x30, 0x98, 0xa1, + 0x27, 0x9e, 0xf6, 0x43, 0x64, 0x3c, + 0x49, 0xbc, 0xf0, 0x99, 0xdd, 0x12, + 0xd1, 0xc9, 0x5d, 0x7c, 0x22, 0x75, + 0x1f, 0x28, 0x2f, 0x09, 0xc2, 0x84, + 0x6d, 0xfa, 0x23, 0x3f, 0x7d, 0x91, + 0x89, 0x82, 0x86, 0x58, 0xdf, 0x76, + 0xe9, 0xaa, 0xdb, 0xac, 0x2b, 0xf5, + 0x90, 0x42, 0x20, 0xe1, 0xa0, 0xed, + 0xd4, 0x52, 0x10, 0xef, 0x3e, 0xe3, + 0x1c, 0xda, 0x96, 0xb0, 0x72, 0x38, + 0x9f, 0x7a, 0x1b, 0xde, 0x02, 0xa6, + 0x4e, 0x97, 0x33, 0x36, 0x6e, 0xe0, + 0xc8, 0x4f, 0xfc, 0x37, 0x71, 0xec, + 0x94, 0x00, 0x95, 0xd0, 0xa7, 0xcb, + 0xf1, 0x70, 0xa9, 0x8b, 0x40, 0xf2, + 0x4b, 0x46, 0x45, 0xee, 0x51, 0x8d, + 0xcc, 0x6c, 0xca, 0xeb, 0x7f, 0x68, + 0x07, 0xae, 0x5e, 0x57, 0x08, 0xe7 +}; + +// .sbss2 +static u8 SEED; +static u8 NUM_A; +static u8 NUM_B; +static u8 NUM_C; + +/******************************************************************************* + * functions + */ + +static u8 random(void) +{ + SEED = (u32)(SEED * NUM_A + NUM_B) % NUM_C; + + return SEED; +} + +static u8 ror(u8 x, u8 shift) +{ + u8 shiftMod = shift % 8; + u8 result = x >> shiftMod | x << (8 - shiftMod); + + return result; +} + +static u8 rol(u8 x, u8 shift) +{ + u8 shiftMod = shift % 8; + u8 result = x << shiftMod | x >> (8 - shiftMod); + + return result; +} + +/* help with naming comes from + * https://wiibrew.org/wiki/Wiimote/Extension_Controllers#Registers_.2F_Initialization + */ +void WPADiCreateKey(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + SEED = OSGetTick() >> 8 & 0xff; + NUM_A = OSGetTick() >> 16 & 0x3f; + NUM_B = OSGetTick() >> 24 & 0x4c; + NUM_C = 0xff; + + u8 numRand = random() % 7; + u8 num = numRand * 6; + + byte_t addTable[8], xorTable[8]; + byte_t key1[10], key2[6]; + + u8 i; + for (i = 0; i < (int)ARRAY_LENGTH(key1); i++) + key1[i] = tb[random()]; + + BOOL intrStatus = OSDisableInterrupts(); + + // clang-format off + key2[0] = tb[key1[4]] ^ ror(base[num + 0] ^ tb[key1[5]], tb[key1[2]]) - tb[key1[9]]; + key2[1] = tb[key1[7]] ^ ror(base[num + 1] ^ tb[key1[1]], tb[key1[0]]) - tb[key1[5]]; + key2[2] = tb[key1[0]] ^ ror(base[num + 2] ^ tb[key1[6]], tb[key1[8]]) - tb[key1[2]]; + key2[3] = tb[key1[2]] ^ ror(base[num + 3] ^ tb[key1[4]], tb[key1[7]]) - tb[key1[3]]; + key2[4] = tb[key1[4]] ^ ror(base[num + 4] ^ tb[key1[1]], tb[key1[6]]) - tb[key1[3]]; + key2[5] = tb[key1[9]] ^ ror(base[num + 5] ^ tb[key1[7]], tb[key1[8]]) - tb[key1[5]]; + + addTable[0] = tb[key2[4] + ((numRand + 1) << 8)] ^ tb[key1[3] + ((numRand + 2) << 8)]; + addTable[1] = tb[key2[2] + ((numRand + 1) << 8)] ^ tb[key1[5] + ((numRand + 2) << 8)]; + addTable[2] = tb[key2[5] + ((numRand + 1) << 8)] ^ tb[key1[7] + ((numRand + 2) << 8)]; + addTable[3] = tb[key2[0] + ((numRand + 1) << 8)] ^ tb[key1[2] + ((numRand + 2) << 8)]; + addTable[4] = tb[key2[1] + ((numRand + 1) << 8)] ^ tb[key1[4] + ((numRand + 2) << 8)]; + addTable[5] = tb[key2[3] + ((numRand + 1) << 8)] ^ tb[key1[9] + ((numRand + 2) << 8)]; + // NOTE: switch from key2 to key1 for these last two + addTable[6] = tb[key1[0] + ((numRand + 1) << 8)] ^ tb[key1[6] + ((numRand + 2) << 8)]; + addTable[7] = tb[key1[1] + ((numRand + 1) << 8)] ^ tb[key1[8] + ((numRand + 2) << 8)]; + + xorTable[0] = tb[key2[0] + ((numRand + 1) << 8)] ^ tb[key1[1] + ((numRand + 2) << 8)]; + xorTable[1] = tb[key2[5] + ((numRand + 1) << 8)] ^ tb[key1[4] + ((numRand + 2) << 8)]; + xorTable[2] = tb[key2[3] + ((numRand + 1) << 8)] ^ tb[key1[0] + ((numRand + 2) << 8)]; + xorTable[3] = tb[key2[2] + ((numRand + 1) << 8)] ^ tb[key1[9] + ((numRand + 2) << 8)]; + xorTable[4] = tb[key2[4] + ((numRand + 1) << 8)] ^ tb[key1[7] + ((numRand + 2) << 8)]; + xorTable[5] = tb[key2[1] + ((numRand + 1) << 8)] ^ tb[key1[8] + ((numRand + 2) << 8)]; + // NOTE: switch from key2 to key1 for these last two + xorTable[6] = tb[key1[3] + ((numRand + 1) << 8)] ^ tb[key1[5] + ((numRand + 2) << 8)]; + xorTable[7] = tb[key1[2] + ((numRand + 1) << 8)] ^ tb[key1[6] + ((numRand + 2) << 8)]; + // clang-format on + + for (i = 0; i < (int)ARRAY_LENGTH(key1); i++) + p_wpd->encryptionKey[i] = key1[9 - i]; + + for (i = 0; i < (int)ARRAY_LENGTH(key2); i++) + p_wpd->encryptionKey[(int)ARRAY_LENGTH(key1) + i] = key2[5 - i]; + + memcpy(p_wpd->decryptAddTable, addTable, sizeof p_wpd->decryptAddTable); + memcpy(p_wpd->decryptXorTable, xorTable, sizeof p_wpd->decryptXorTable); + + OSRestoreInterrupts(intrStatus); +} + +void WPADiCreateKeyFor3rd(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + SEED = OSGetTick() >> 8 & 0xff; + NUM_A = OSGetTick() >> 16 & 0x3f; + NUM_B = OSGetTick() >> 24 & 0x4c; + NUM_C = 0xff; + + u8 numRand = random() % 7; + u8 num = numRand * 6; + + byte_t addTable[8], xorTable[8]; + byte_t key1[10], key2[6]; + + u8 i; + for (i = 0; i < (int)ARRAY_LENGTH(key1); i++) + key1[i] = tb3[random()]; + + BOOL intrStatus = OSDisableInterrupts(); + + // clang-format off + // NOTE: initialization of key2 here is different from WPADiCreateKey + key2[0] = tb3[key1[7]] ^ rol(base3[num + 0] ^ tb3[key1[0]], tb3[key1[1]]) + tb3[key1[6]]; + key2[1] = tb3[key1[1]] ^ rol(base3[num + 1] ^ tb3[key1[4]], tb3[key1[2]]) + tb3[key1[3]]; + key2[2] = tb3[key1[5]] ^ rol(base3[num + 2] ^ tb3[key1[2]], tb3[key1[8]]) + tb3[key1[4]]; + key2[3] = tb3[key1[0]] ^ rol(base3[num + 3] ^ tb3[key1[6]], tb3[key1[9]]) + tb3[key1[7]]; + key2[4] = tb3[key1[1]] ^ rol(base3[num + 4] ^ tb3[key1[5]], tb3[key1[4]]) + tb3[key1[8]]; + key2[5] = tb3[key1[5]] ^ rol(base3[num + 5] ^ tb3[key1[9]], tb3[key1[3]]) + tb3[key1[8]]; + + // this is the same though + addTable[0] = tb3[key2[4] + ((numRand + 1) << 8)] ^ tb3[key1[3] + ((numRand + 2) << 8)]; + addTable[1] = tb3[key2[2] + ((numRand + 1) << 8)] ^ tb3[key1[5] + ((numRand + 2) << 8)]; + addTable[2] = tb3[key2[5] + ((numRand + 1) << 8)] ^ tb3[key1[7] + ((numRand + 2) << 8)]; + addTable[3] = tb3[key2[0] + ((numRand + 1) << 8)] ^ tb3[key1[2] + ((numRand + 2) << 8)]; + addTable[4] = tb3[key2[1] + ((numRand + 1) << 8)] ^ tb3[key1[4] + ((numRand + 2) << 8)]; + addTable[5] = tb3[key2[3] + ((numRand + 1) << 8)] ^ tb3[key1[9] + ((numRand + 2) << 8)]; + // NOTE: switch from key2 to key1 for these last two + addTable[6] = tb3[key1[0] + ((numRand + 1) << 8)] ^ tb3[key1[6] + ((numRand + 2) << 8)]; + addTable[7] = tb3[key1[1] + ((numRand + 1) << 8)] ^ tb3[key1[8] + ((numRand + 2) << 8)]; + + xorTable[0] = tb3[key2[0] + ((numRand + 1) << 8)] ^ tb3[key1[1] + ((numRand + 2) << 8)]; + xorTable[1] = tb3[key2[5] + ((numRand + 1) << 8)] ^ tb3[key1[4] + ((numRand + 2) << 8)]; + xorTable[2] = tb3[key2[3] + ((numRand + 1) << 8)] ^ tb3[key1[0] + ((numRand + 2) << 8)]; + xorTable[3] = tb3[key2[2] + ((numRand + 1) << 8)] ^ tb3[key1[9] + ((numRand + 2) << 8)]; + xorTable[4] = tb3[key2[4] + ((numRand + 1) << 8)] ^ tb3[key1[7] + ((numRand + 2) << 8)]; + xorTable[5] = tb3[key2[1] + ((numRand + 1) << 8)] ^ tb3[key1[8] + ((numRand + 2) << 8)]; + // NOTE: switch from key2 to key1 for these last two + xorTable[6] = tb3[key1[3] + ((numRand + 1) << 8)] ^ tb3[key1[5] + ((numRand + 2) << 8)]; + xorTable[7] = tb3[key1[2] + ((numRand + 1) << 8)] ^ tb3[key1[6] + ((numRand + 2) << 8)]; + // clang-format on + + for (i = 0; i < (int)ARRAY_LENGTH(key1); i++) + p_wpd->encryptionKey[i] = key1[9 - i]; + + for (i = 0; i < (int)ARRAY_LENGTH(key2); i++) + p_wpd->encryptionKey[(int)ARRAY_LENGTH(key1) + i] = key2[5 - i]; + + memcpy(p_wpd->decryptAddTable, addTable, sizeof p_wpd->decryptAddTable); + memcpy(p_wpd->decryptXorTable, xorTable, sizeof p_wpd->decryptXorTable); + + OSRestoreInterrupts(intrStatus); +} + +void WPADiDecode(WPADChannel chan, byte_t *data, u16 length, u16 startIndex) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + byte_t *buffer; + u8 tableIndex; + + u16 i; + if (p_wpd->extState == WPAD_STATE_EXT_ENCRYPTED + || p_wpd->extState == WPAD_STATE_EXT_ENCRYPTED_3RD) + { + buffer = data; + + for (i = 0; i < length; i++) + { + tableIndex = (startIndex + i) % 8; + buffer[i] = p_wpd->decryptAddTable[tableIndex] + + (buffer[i] ^ p_wpd->decryptXorTable[tableIndex]); + } + } +} diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPADEncrypt.h b/src/sdk/RVL_SDK/revolution/wpad/WPADEncrypt.h new file mode 100644 index 00000000..2c0d0d14 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPADEncrypt.h @@ -0,0 +1,30 @@ +#ifndef RVL_SDK_WPAD_INTERNAL_ENCRYPT_H +#define RVL_SDK_WPAD_INTERNAL_ENCRYPT_H + +/* no public header */ + +/******************************************************************************* + * headers + */ + +#include + +#include // WPADChannel + +/******************************************************************************* + * functions + */ + +#ifdef __cplusplus + extern "C" { +#endif + +void WPADiCreateKey(WPADChannel chan); +void WPADiCreateKeyFor3rd(WPADChannel chan); +void WPADiDecode(WPADChannel chan, byte_t *data, u16 length, u16 startIndex); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_INTERNAL_ENCRYPT_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPADHIDParser.c b/src/sdk/RVL_SDK/revolution/wpad/WPADHIDParser.c new file mode 100644 index 00000000..e1048eac --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPADHIDParser.c @@ -0,0 +1,2793 @@ +#include "WPADHIDParser.h" + +/******************************************************************************* + * headers + */ + +#include +#include +#include + +#include + +#include "WPAD.h" +#include "WPADEncrypt.h" +#include // WUDIsLinkedWBC + +#if 0 +#include // __OSInIPL +#include // OSCalcCRC32 +#include +#endif + +#include "context_bte.h" // UINT8 +#include "context_rvl.h" + +/******************************************************************************* + * constants + */ + +#define CONST_FLOAT_PI 3.141592f + +// TODO: may want to move these to ? + +#define DPD_MAX_X 0x3ff +#define DPD_MAX_Y 0x2ff + +/******************************************************************************* + * macros + */ + +// clang-format off + +/* WARNING: This macro cannot be wrapped in a do-while block because the + * declaration of unusedBits_ would cause the stack to be referenced through r31 + * instead of r1 on debug, so take care when using. + */ +#define RETRIEVE_BUTTON_STATE(chan_, status_, dataPtr_, rptPtr_) \ + memcpy(dataPtr_, __wpadGetLastRxBuffer(chan_), RX_BUFFER_SIZE); \ + \ + (status_) = (dataPtr_); \ + u16 unusedBits_ = (status_)->button & 0x6000; \ + \ + (status_)->button = MAKE_BUTTON((rptPtr_)[RPT_BTN1], (rptPtr_)[RPT_BTN0]); \ + (status_)->button |= unusedBits_; \ + \ + if ((status_)->dev != p_wpd->devType) \ + { \ + (status_)->dev = p_wpd->devType; \ + (status_)->err = WPAD_EINVAL; \ + } \ + \ + do {} while (0) // swallow semicolon + +/* + * Calibration (referred to as configuration) + */ + +// IR camera (DPD) + +// Accelerometer +#define MAKE_DEV_CONFIG_ACC_X(high_, low_) ((u16)(((u16)(high_) << 2) & 0xfffc) | (u16)(((u16)(low_) >> 4) & 0x0003)) +#define MAKE_DEV_CONFIG_ACC_Y(high_, low_) ((u16)(((u16)(high_) << 2) & 0xfffc) | (u16)(((u16)(low_) >> 2) & 0x0003)) +#define MAKE_DEV_CONFIG_ACC_Z(high_, low_) ((u16)(((u16)(high_) << 2) & 0xfffc) | (u16)( (u16)(low_) & 0x0003)) + +// Assorted +#define MAKE_DEV_CONFIG_VOLUME(val_) ((val_) & (u8) 0x7f) +#define MAKE_DEV_CONFIG_MOTOR(val_) ((val_) & (u8)~0x7f) + +// Nunchuk extension +#define MAKE_FS_CONFIG_ACC_X MAKE_DEV_CONFIG_ACC_X +#define MAKE_FS_CONFIG_ACC_Y MAKE_DEV_CONFIG_ACC_Y +#define MAKE_FS_CONFIG_ACC_Z MAKE_DEV_CONFIG_ACC_Z + +// Motion Plus extension +#define MAKE_MP_CONFIG_ZERO_VALUE(high_, low_) (((u16)(((u16)(high_) << 8) & 0xff00) | (u16)((u16)(low_) & 0x00ff)) / 10.0f + 5000.0f) +#define MAKE_MP_CONFIG_SCALE_VALUE(high_, low_) (((s16)(((u16)(high_) << 8) & 0xff00) | (s16)((u16)(low_) & 0x00ff)) / 10.0f) + +#define RECALC_MP_CONFIG_SCALE_VALUE(val_) (val_) = (val_) < 0.0f ? (val_) - 4000.0f : (val_) + 4000.0f + +#define MAKE_MPLS_CONFIG_ID(high_, low_) ((u16)((u16)((u16)(high_) << 8) & 0xff00) | (u16)((u16)(low_) & 0x00ff)) + +/* + * Data reports + */ + +// Buttons +#define MAKE_BUTTON(high_, low_) ((u16)((u16)((u16)((u16)(low_) & 0x00ff)) | (u16)((u16)((high_) << 8) & 0xff00)) & WPAD_BUTTON_ALL) + +// Standard accelerometer report +#define MAKE_ACC_STANDARD_X(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)(u16)((low_) >> 5) & 0x03)) - (s16)((wpadcb_)->devConfig.accX0g)) +#define MAKE_ACC_STANDARD_Y(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)(u16)((low_) >> 4) & 0x02)) - (s16)((wpadcb_)->devConfig.accY0g)) +#define MAKE_ACC_STANDARD_Z(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)(u16)((low_) >> 5) & 0x02)) - (s16)((wpadcb_)->devConfig.accZ0g)) + +// Interleaved accelerometer reports +#define MAKE_ACC_INTERLEAVED0_X(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)(u16)((low_) >> 6) & 0x02)) - (s16)((wpadcb_)->devConfig.accX0g)) +#define CALC_ACC_INTERLEAVED0_Z(val_, high_, low_) (val_) |= (s16)((s16)((s16)((s16)(high_) << 3) & ~0xff) | (s16)((s16)(u16)((low_) << 1) & 0xc0)) + +#define MAKE_ACC_INTERLEAVED1_Y(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)(u16)((low_) >> 6) & 0x02)) - (s16)((wpadcb_)->devConfig.accY0g)) +#define CALC_ACC_INTERLEAVED1_Z(val_, high_, low_) (val_) |= (s16)((s16)((s16)((s16)(high_) >> 1) & 0x30) | (s16)((s16)(u16)((low_) >> 3) & 0x0c)) + +// Basic IR camera report +#define GET_DPD_BASIC_REPORT_X_LOW_BYTE(data_, i_) ((u8 *)((u32)data_ + ((i_) * 3) - ((i_) / 2)))[0] +#define GET_DPD_BASIC_REPORT_Y_LOW_BYTE(data_, i_) ((u8 *)((u32)data_ + ((i_) * 3) - ((i_) / 2)))[1] +#define GET_DPD_BASIC_REPORT_XY_HIGH_BITS(data_, i_) ((u8 *)((u32)data_ + 5 * ((i_) / 2)))[2] + +#define MAKE_DPD_BASIC_X1(high_, low_) ((s16)((low_) & 0xff) | (u16)((u16)((u16)(high_) & 0x30) << 4)) +#define MAKE_DPD_BASIC_Y1(high_, low_) (DPD_MAX_Y - (s16)((s16)((low_) & 0xff) | (u16)((u16)((u16)(high_) & 0xc0) << 2))) +#define MAKE_DPD_BASIC_X2(high_, low_) ((s16)((low_) & 0xff) | (u16)((u16)((u16)(high_) & 0x03) << 8)) +#define MAKE_DPD_BASIC_Y2(high_, low_) (DPD_MAX_Y - (s16)((s16)((low_) & 0xff) | (u16)((u16)((u16)(high_) & 0x0c) << 6))) + +// Standard IR camera report +#define MAKE_DPD_STANDARD_X(high_, low_) ((s16)((low_) & 0xff) | (u16)(((u16)(high_) & 0x30) << 4)) +#define MAKE_DPD_STANDARD_Y(high_, low_) (DPD_MAX_Y - (s16)((s16)((low_) & 0xff) | (u16)(((u16)(high_) & 0xc0) << 2))) +#define MAKE_DPD_STANDARD_SIZE(byte_) ((u8)((byte_) & 0x0f) & 0xffff) + +#define RECALC_DPD_STANDARD_SIZE(size_) (size_) = (u8)((f32)(size_) * (f32)(size_) * CONST_FLOAT_PI) + +// Extended IR camera report +#define MAKE_DPD_EXTENDED_X(high_, low_) ((s16)((low_) & 0xff) | (u16)((u16)((high_) & 0x30) << 4)) +#define MAKE_DPD_EXTENDED_Y(high_, low_) (DPD_MAX_Y - (s16)((s16)((low_) & 0xff) | (u16)((u16)((high_) & 0xc0) << 2))) +#define MAKE_DPD_EXTENDED_PIXEL(high_, low_) (u16)((s16)((s16)(((u16)(high_) << 8 ) & 0xff00) | (u16)((low_) & 0xff)) << 6) +#define MAKE_DPD_EXTENDED_RADIUS(data_) ((data_) & 0x0f) + +#define CALC_DPD_EXTENDED_X(x_) (x_) = (x_) << 3 +#define CALC_DPD_EXTENDED_Y(y_) (y_) = (DPD_MAX_Y - (s16)((y_) << 3)) +#define MAKE_DPD_EXTENDED_SIZE(radius_) ((f32)(radius_) * (f32)(radius_) * CONST_FLOAT_PI) + +// Nunchuk extension report +#define MAKE_FS_ACC_X(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)((low_) >> 2) & 0x03)) - (s16)((wpadcb_)->extConfig.fs.accX0g)) +#define MAKE_FS_ACC_Y(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)((low_) >> 4) & 0x03)) - (s16)((wpadcb_)->extConfig.fs.accY0g)) +#define MAKE_FS_ACC_Z(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)((low_) >> 6) & 0x03)) - (s16)((wpadcb_)->extConfig.fs.accZ0g)) + +#define CALC_FS_BUTTON(button_, data_) (button_) |= (u16)((((u16)~(data_)) << 13) & 0x6000) + +#define CLAMP_FS_STICK_X(wpadcb_, x_) (x_) = __clamp((u8)(x_) - (u8)(wpadcb_)->extConfig.fs.stickXCenter, -128, 127) +#define CLAMP_FS_STICK_Y(wpadcb_, y_) (y_) = __clamp((u8)(y_) - (u8)(wpadcb_)->extConfig.fs.stickYCenter, -128, 127) + +// Classic Controller extension reports +#define CLAMP_CL_STICK_LX(wpadcb_, lx_, low_, high_) (lx_) = __clamp((lx_) - (wpadcb_)->extConfig.cl.lStickXCenter, (low_), (high_)) +#define CLAMP_CL_STICK_LY(wpadcb_, ly_, low_, high_) (ly_) = __clamp((ly_) - (wpadcb_)->extConfig.cl.lStickYCenter, (low_), (high_)) +#define CLAMP_CL_STICK_RX(wpadcb_, rx_, low_, high_) (rx_) = __clamp((rx_) - (wpadcb_)->extConfig.cl.rStickXCenter, (low_), (high_)) +#define CLAMP_CL_STICK_RY(wpadcb_, ry_, low_, high_) (ry_) = __clamp((ry_) - (wpadcb_)->extConfig.cl.rStickYCenter, (low_), (high_)) + +#define MAKE_CL_BUTTON(high_, low_) ((u16)((u16)(((u16)((u16)(high_) << 8) & 0xff00) | (u8)(low_)) ^ 0xffff)) + +// Reduced Classic Controller extension report +#define MAKE_CL_REDUCED_STICK_LX(byte_) ((s16)((byte_) & 0x3f) << 4) +#define MAKE_CL_REDUCED_STICK_LY(byte_) ((s16)((byte_) & 0x3f) << 4) +// Hey Fellas Make Sure This Is A Signed Short +#define MAKE_CL_REDUCED_STICK_RX(high_, mid_, low_) ((s16)((s16)((s16)((s16)((s16)(high_) >> 3) & 0x18) | (s16)((s16)((s16)(mid_) >> 5) & 0x06) | (s16)((s16)((s16)(low_) >> 7) & 0x01)) << 5)) +#define MAKE_CL_REDUCED_STICK_RY(byte_) ((s16)((byte_) & 0x1f) << 5) + +#define MAKE_CL_REDUCED_TRIGGER_L(high_, low_) ((u8)((u8)((u8)((u8)((high_) >> 2) & 0x18) | (u8)((u8)((low_) >> 5) & 0x07)) << 3)) +#define MAKE_CL_REDUCED_TRIGGER_R(byte_) ((u8)((u8)(byte_) & 0x1f) << 3) + +// Standard Classic Controller extension report +#define MAKE_CL_STANDARD_STICK_AXIS(byte_) ((s16)((byte_) & 0xff) << 2) + +#define MAKE_CL_STANDARD_STICK_LX MAKE_CL_STANDARD_STICK_AXIS +#define MAKE_CL_STANDARD_STICK_LY MAKE_CL_STANDARD_STICK_AXIS +#define MAKE_CL_STANDARD_STICK_RX MAKE_CL_STANDARD_STICK_AXIS +#define MAKE_CL_STANDARD_STICK_RY MAKE_CL_STANDARD_STICK_AXIS + +// Extended Classic Controller extension report +#define MAKE_CL_EXTENDED_STICK_LX(high_, low_) ((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)( (s16)(low_) & 0x03)) +#define MAKE_CL_EXTENDED_STICK_LY(high_, low_) ((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)((s16)(low_) >> 4) & 0x03)) +#define MAKE_CL_EXTENDED_STICK_RX(high_, low_) ((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)((s16)(low_) >> 2) & 0x03)) +#define MAKE_CL_EXTENDED_STICK_RY(high_, low_) ((s16)((s16)((s16)(high_) << 2) & ~0x03) | (s16)((s16)((s16)(low_) >> 6) & 0x03)) + +// Shinkansen train controller extension report +#define MAKE_TR_BUTTON MAKE_CL_BUTTON + +// Balance Board extension report +#define MAKE_BL_WEIGHT(high_, low_) ((u16)((u16)((high_) << 8) & 0xff00) | (u16)((low_) & 0x00ff)) + +#define MAKE_BL_WEIGHT_UL MAKE_BL_WEIGHT +#define MAKE_BL_WEIGHT_UR MAKE_BL_WEIGHT +#define MAKE_BL_WEIGHT_DL MAKE_BL_WEIGHT +#define MAKE_BL_WEIGHT_DR MAKE_BL_WEIGHT + +// VSM extension report +/* The extension this report is for is unknown, but was suggested to possibly be + * the cancelled Vitality Sensor by NWPlayer123. + */ +#define MAKE_VS_SET_0(high_, low_) ((u16)((u16)((u16)(high_) << 2) & 0xfffc) | (u16)((u16)((low_) >> 6) & 0x0003)) +#define MAKE_VS_SET_1(high_, low_) ((u16)((u16)((u16)(high_) << 2) & 0xfffc) | (u16)((u16)((low_) >> 4) & 0x0003)) +#define MAKE_VS_SET_2(high_, low_) ((u16)((u16)((u16)(high_) << 2) & 0xfffc) | (u16)((u16)((low_) >> 2) & 0x0003)) +#define MAKE_VS_SET_3(high_, low_) ((u16)((u16)((u16)(high_) << 2) & 0xfffc) | (u16)((u16)((low_) >> 0) & 0x0003)) +#define MAKE_VS_SET_4(high_, low_) ((u16)((u16)((u16)(high_) << 2) & 0xfffc) | (u16)((u16)((low_) >> 6) & 0x0003)) // same as MAKE_VS_SET_1 + +#define MAKE_VS_42(high_, low_) ((u16)((u16)((u16)((u16)(high_) << 4) & 0xf3f0)) | (u16)((u16)((low_) >> 2) & 0x000f)) + +#define MAKE_VS_44(byte_) ((u8)((u8)(byte_) & 0x03)) + +// Motion Plus extension reports + +// Motion Plus non-passthrough acc/gyro report +#define MAKE_MP_MAIN_STAT(high_, low_) ((u8)((u8)((u8)((high_) << 2) & 0x0c) | (u8)((u8)(low_) & 0x03)) | WPAD_MPLS_STATUS_DATA_VALID) +#define MAKE_MP_MAIN_PITCH(high_, low_) (s16)((low_) & 0x00ff) | (s16)((s16)((high_) << 6) & 0x3f00) +#define MAKE_MP_MAIN_YAW(high_, low_) (s16)((low_) & 0x00ff) | (s16)((s16)((high_) << 6) & 0x3f00) +#define MAKE_MP_MAIN_ROLL(high_, low_) (s16)((low_) & 0x00ff) | (s16)((s16)((high_) << 6) & 0x3f00) + +// Motion Plus passthrough main acc/gyro report +#define CALC_MP_PT_MAIN_BUTTON(button_, cbBox_) (button_) |= (u16)((cbBox_)->button & 0x6000) +#define MAKE_MP_PT_MAIN_STAT(high_, low_) ((u8)((u8)((u8)((high_) << 2) & 0x0c) | (u8)((u8)(low_) & 3)) | WPAD_MPLS_STATUS_DATA_VALID) +#define MAKE_MP_PT_MAIN_PITCH MAKE_MP_MAIN_PITCH +#define MAKE_MP_PT_MAIN_YAW MAKE_MP_MAIN_YAW +#define MAKE_MP_PT_MAIN_ROLL MAKE_MP_MAIN_ROLL + +#define RECALC_MP_PT_MAIN_STAT(stat_, cbBox_) (stat_) |= (u8)((cbBox_)->stat & WPAD_MPLS_STATUS_EXTENSION_DATA_VALID) + +// Motion Plus passthrough extension report +#define CALC_MP_PT_EXT_STAT(stat_, val_) (stat_) |= (u8)((u8)((val_) & 0x01) | WPAD_MPLS_STATUS_EXTENSION_DATA_VALID) + +// Motion Plus Nunchuk passthrough report +#define MAKE_MP_FS_ACC_X(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | ((s16)((s16)((low_) >> 3) & 0x02))) - (s16)(wpadcb_)->extConfig.fs.accX0g) +#define MAKE_MP_FS_ACC_Y(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x03) | ((s16)((s16)((low_) >> 4) & 0x02))) - (s16)(wpadcb_)->extConfig.fs.accY0g) +#define MAKE_MP_FS_ACC_Z(wpadcb_, high_, low_) ((s16)((s16)((s16)((s16)(high_) << 2) & ~0x07) | ((s16)((s16)((low_) >> 5) & 0x06))) - (s16)(wpadcb_)->extConfig.fs.accZ0g) + +#define CALC_MP_FS_BUTTON(button_, data_) (button_) |= (u16)((((u16)~(data_)) << 11) & WPAD_BUTTON_FS_ALL) + +// Motion Plus Classic Controller passthrough report +#define MAKE_MP_CL_STICK_LX(val_) ((s16)((val_) & 0x3e) << 4) +#define MAKE_MP_CL_STICK_LY(val_) ((s16)((val_) & 0x3e) << 4) +#define MAKE_MP_CL_STICK_RX(high_, mid_, low_) ((s16)((s16)((s16)((s16)(high_) >> 3) & 0x18) | (s16)((s16)((s16)(mid_) >> 5) & 0x06) | (s16)((s16)((s16)(low_) >> 7) & 0x01)) << 5) +#define MAKE_MP_CL_STICK_RY(val_) ((s16)((val_) & 0x1f) << 5) +#define MAKE_MP_CL_TRIGGER_L(high_, low_) ((u8)((u8)((u8)((high_) >> 2) & 0x18) | (u8)((u8)((low_) >> 5) & 0x07)) << 3) +#define MAKE_MP_CL_TRIGGER_R(val_) ((u8)((u8)(val_) & 0x1f) << 3) +#define MAKE_MP_CL_BUTTON(high_, low_, up_, left_) ((u16)(((u16)((u16)(high_) << 8) & 0xfe00) | ((low_) & 0xfc) | (((u16)(left_) << 1) & 0x02) | ((up_) & 0x01)) ^ WPAD_BUTTON_CL_ALL) + +// Button report +#define __parse_btn_data(wpadcb_, status_, btnFormat_, data_, length_) \ + do \ + { \ + (status_)->button = MAKE_BUTTON((data_)[RPT_BTN1], (data_)[RPT_BTN0]); \ + \ + if ((btnFormat_) == BTN_FORMAT_STANDARD) \ + (wpadcb_)->wpInfo.nearempty = (u8)(((data_)[RPT_BTN0] & 0x80) >> 7); \ + else if ((btnFormat_) == BTN_FORMAT_INTERLEAVED) \ + (wpadcb_)->wpInfo.nearempty = FALSE; \ + } while (0) + +// clang-format on + +/******************************************************************************* + * types + */ + +typedef u8 ChecksumType; +enum ChecksumType_et +{ + CHECKSUM_SIMPLE_SUM, + CHECKSUM_CRC32, +}; + +typedef u8 MplsConfigDataType; +enum MplsConfigDataType_et +{ + MPLS_CALIB_TYPE_HIGH, + MPLS_CALIB_TYPE_LOW, +}; + +enum +{ + // Dummy button formats (for use in the __parse_btn_data macro) + BTN_FORMAT_STANDARD = 0, + BTN_FORMAT_INTERLEAVED = 1, + + // Accelerometer data format + ACC_FORMAT_STANDARD = 0, + ACC_FORMAT_INTERLEAVED0 = 1, + ACC_FORMAT_INTERLEAVED1 = 2, +}; + +typedef void InputReportParser(u8 chan, byte_t *hidReport, void *rxBuffer); + +/******************************************************************************* + * local function declarations + */ + +static void __wpadAbortInitExtension(WPADChannel chan, WPADResult result); +static void __wpadGetDevConfig(WPADChannel chan, WPADResult result); +static BOOL __wpadCheckCalibration(byte_t *data, u8 checksumOffset, + ChecksumType checksumType); +static void __wpadGetFsConfig(WPADChannel chan, byte_t *config); +static void __wpadGetClConfig(WPADChannel chan, byte_t *config); +static void __wpadGetMpConfig(WPADChannel chan, byte_t *config, + MplsConfigDataType type); +static void __wpadGetExtConfig(WPADChannel chan, WPADResult result); +static void __wpadGetExtConfig2(WPADChannel chan, WPADResult result); +static BOOL __wpadIsExtEncryptMain(u8 type); +static void __wpadGetExtType(WPADChannel chan, WPADResult result); +static void __wpadGetExtType2(WPADChannel chan, WPADResult result); +static void __wpadGetGameInfo(WPADChannel chan, WPADResult result, u8); +static void __wpadInitExtension(WPADChannel chan); +static void __wpadInvertRxBuffer(u8 chan); +static void *__wpadGetWorkRxBuffer(u8 chan); +static void *__wpadGetLastRxBuffer(u8 chan); +static void __wpadCheckDataFormat(u8 chan, u8 rep_id, void *data); + +static void __a1_20_status_report(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_21_user_data(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_22_ack(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __parse_dpd_data(WPADChannel chan, WPADStatus **status, + u8 dpdCommand, byte_t *data, u8 length); +static void __parse_dpdex_data(WPADChannel chan, WPADStatusEx **statusEx, + u8 objIndex, byte_t *data, u8 length); +static void __parse_acc_data(WPADChannel chan, WPADStatus **status, + u8 accFormat, byte_t *data, u8 length); +static s16 __clamp(s16 x, s16 low, s16 high); +static void __parse_fs_data(WPADChannel chan, WPADFSStatus **fsStatus, + u8 fsFormat, byte_t *data, u8 length); +static void __parse_cl_data(WPADChannel chan, WPADCLStatus **clStatus, + u8 clFormat, byte_t *data, u8 length); +static void __parse_bk_data(WPADChannel chan, WPADBKStatus **bkStatus, + u8 bkFormat, byte_t *data, u8 length); +static void __parse_tr_data(WPADChannel chan, WPADTRStatus **trStatus, + u8 trFormat, byte_t *data, u8 length); +static void __parse_bl_data(WPADChannel chan, WPADBLStatus **blStatus, + u8 blFormat, byte_t *data, u8 length); +static void __parse_vs_data(WPADChannel chan, WPADVSStatus **vsStatus, + u8 vsFormat, byte_t *data, u8 length); +static void __parse_mp_data(WPADChannel chan, WPADMPStatus **mpStatus, + u8 mpFormat, byte_t *data, u8 length); +static void __parse_ext_data(WPADChannel chan, void *parseBuf, u8 dataFormat, + byte_t *data, u8 length); +static void __a1_30_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_31_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_32_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_33_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_34_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_35_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_36_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_37_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_3d_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_3e_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_3f_data_type(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __a1_unused_report(u8 chan, byte_t *hidReport, void *rxBuffer); +static void __wpadCertReset(WPADChannel chan); + +/******************************************************************************* + * variables + */ + +// .rodata + +// clang-format off +static const byte_t _cExtInvalidData[RPT_MAX_SIZE] = +{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const byte_t _cExtInvalidData2[RPT_MAX_SIZE] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +// clang-format on + +// .data + +// clang-format off +static InputReportParser *__a1_input_reports_array[] = +{ + // double-indented entries are the used ones + + &__a1_20_status_report, + &__a1_21_user_data, + &__a1_22_ack, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_30_data_type, + &__a1_31_data_type, + &__a1_32_data_type, + &__a1_33_data_type, + &__a1_34_data_type, + &__a1_35_data_type, + &__a1_36_data_type, + &__a1_37_data_type, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_unused_report, + &__a1_3d_data_type, + &__a1_3e_data_type, + &__a1_3f_data_type, +}; +// clang-format on + +// .bss +static f32 _wpadCalibrationX[WPAD_MAX_CONTROLLERS]; +static f32 _wpadCalibrationY[WPAD_MAX_CONTROLLERS]; +static f32 _wpadCenterX[WPAD_MAX_CONTROLLERS]; +static f32 _wpadCenterY[WPAD_MAX_CONTROLLERS]; +static f32 _wpadRolag[WPAD_MAX_CONTROLLERS]; + +// .sbss +static u8 _wpadDevType[WPAD_MAX_CONTROLLERS]; +static u8 _wpadDevMode[WPAD_MAX_CONTROLLERS]; +static u8 _wpadDevType2[WPAD_MAX_CONTROLLERS]; +static u8 _wpadDevType2Sub[WPAD_MAX_CONTROLLERS]; +static u8 _wpadCLCompt[WPAD_MAX_CONTROLLERS]; +static u8 _wpadExtInitRetryCnt[WPAD_MAX_CONTROLLERS]; + +/******************************************************************************* + * functions + */ + +static void __wpadAbortInitExtension(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (result == WPAD_ESUCCESS) + return; + + WPADiClearQueue(&p_wpd->extCmdQueue); + p_wpd->extState = WPAD_STATE_EXT_UNINITIALIZED; + + s32 devType; + if (result == WPAD_ENODEV) + { + devType = WPAD_DEV_NONE; + } + else if (p_wpd->wpInfo.attach) + { + if (_wpadExtInitRetryCnt[chan]++ < 32) + { + __wpadInitExtension(chan); + return; + } + else + { + devType = WPAD_DEV_252; + } + } + else + { + WPADiSendSetReportType(&p_wpd->extCmdQueue, p_wpd->dataFormat, + p_wpd->disableContReport, NULL); + return; + } + + p_wpd->devType = devType; + p_wpd->savedDevType = p_wpd->devType; + p_wpd->extWasDisconnected = FALSE; + + if (p_wpd->extensionCB) + (*p_wpd->extensionCB)(chan, devType); +} + +static void __wpadGetDevConfig(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + byte_t *data = p_wpd->wmReadDataPtr; + + u8 checksum; + u8 i; + int j; + int index; + + f32 x, y; + f32 x_atan, y_atan; + + DPDObject obj[WPAD_MAX_DPD_OBJECTS]; + f32 a[WPAD_MAX_DPD_OBJECTS]; + f32 b[WPAD_MAX_DPD_OBJECTS]; + f32 c[WPAD_MAX_DPD_OBJECTS]; + f32 d[WPAD_MAX_DPD_OBJECTS]; + s16 defaultDpdX[WPAD_MAX_DPD_OBJECTS] = {127, 896, 896, 127}; + s16 defaultDpdY[WPAD_MAX_DPD_OBJECTS] = {93, 93, 674, 674}; + + for (i = 0; i < WPAD_MAX_DPD_OBJECTS; i++) + { + p_wpd->devConfig.dpd[i].x = (s16)defaultDpdX[i]; + p_wpd->devConfig.dpd[i].y = (s16)defaultDpdY[i]; + p_wpd->devConfig.dpd[i].size = p_wpd->defaultDpdSize; + p_wpd->devConfig.dpd[i].traceId = i; + } + + p_wpd->devConfig.accX0g = 530; + p_wpd->devConfig.accY0g = 530; + p_wpd->devConfig.accZ0g = 530; + + p_wpd->devConfig.accX1g = 636; + p_wpd->devConfig.accY1g = 636; + p_wpd->devConfig.accZ1g = 636; + + p_wpd->devConfig.volume = 0; + p_wpd->devConfig.motor = 0; + + if (result != WPAD_ESUCCESS) + return; + + if (p_wpd->configIndex == 0) + { + for (i = 0; i < WPAD_MAX_CONFIG_BLOCKS; i++) + { + checksum = 0; + index = i * WPAD_DPD_CONFIG_BLOCK_SIZE; + + for (j = index; j < index + WPAD_DPD_CONFIG_BLOCK_CHECKSUM; j++) + checksum += data[j]; + + checksum += WPAD_CONFIG_BLOCK_CHECKSUM_BIAS; + if (checksum != data[index + WPAD_DPD_CONFIG_BLOCK_CHECKSUM]) + continue; + + obj[0].x = MAKE_DPD_BASIC_X1(data[index + 2], data[index + 0]); + obj[0].y = MAKE_DPD_BASIC_Y1(data[index + 2], data[index + 1]); + obj[0].size = p_wpd->defaultDpdSize; + obj[0].traceId = 0; + + obj[1].x = MAKE_DPD_BASIC_X2(data[index + 2], data[index + 3]); + obj[1].y = MAKE_DPD_BASIC_Y2(data[index + 2], data[index + 4]); + obj[1].size = p_wpd->defaultDpdSize; + obj[1].traceId = 1; + + obj[2].x = MAKE_DPD_BASIC_X1(data[index + 7], data[index + 5]); + obj[2].y = MAKE_DPD_BASIC_Y1(data[index + 7], data[index + 6]); + obj[2].size = p_wpd->defaultDpdSize; + obj[2].traceId = 2; + + obj[3].x = MAKE_DPD_BASIC_X2(data[index + 7], data[index + 8]); + obj[3].y = MAKE_DPD_BASIC_Y2(data[index + 7], data[index + 9]); + obj[3].size = p_wpd->defaultDpdSize; + obj[3].traceId = 3; + + for (j = 0; j < WPAD_MAX_DPD_OBJECTS; j++) + { + if (obj[j].x < 0x200 && obj[j].y < 0x180) + { + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BL].x = obj[j].x; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BL].y = obj[j].y; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BL].size = obj[j].size; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BL].traceId = + obj[j].traceId; + } + + if (obj[j].x > 0x200 && obj[j].y < 0x180) + { + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BR].x = obj[j].x; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BR].y = obj[j].y; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BR].size = obj[j].size; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_BR].traceId = + obj[j].traceId; + } + + if (obj[j].x > 0x200 && obj[j].y > 0x180) + { + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TR].x = obj[j].x; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TR].y = obj[j].y; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TR].size = obj[j].size; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TR].traceId = + obj[j].traceId; + } + + if (obj[j].x < 0x200 && obj[j].y > 0x180) + { + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TL].x = obj[j].x; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TL].y = obj[j].y; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TL].size = obj[j].size; + p_wpd->devConfig.dpd[DPD_CFG_OBJ_TL].traceId = + obj[j].traceId; + } + } + + break; + } + } + + x = y = 0.0f; + for (i = 0; i < WPAD_MAX_DPD_OBJECTS; i++) + { + a[i] = p_wpd->devConfig.dpd[i].x; + b[i] = p_wpd->devConfig.dpd[i].y; + x += p_wpd->devConfig.dpd[i].x - defaultDpdX[i]; + y += p_wpd->devConfig.dpd[i].y - defaultDpdY[i]; + } + + // NOTE: specifically not a compound assignment + x = x / 4.0f; + y = y / 4.0f; + + x_atan = (f32)atan((x + 126.5f) / 1332.5f) - (f32)atan(0.09493433684110641); + y_atan = (f32)atan((y + 93.0f) / 1337.4f) - (f32)atan(0.06953790783882141); + + _wpadCalibrationX[chan] = (f32)tan(x_atan) * -1.0f * 1332.5f; + _wpadCalibrationY[chan] = (f32)tan(y_atan) * -1.0f * 1337.4f; + _wpadCenterX[chan] = _wpadCenterY[chan] = 0.0f; + + for (i = 0; i < WPAD_MAX_CONTROLLERS; i++) + { + a[i] += _wpadCalibrationX[chan]; + b[i] += _wpadCalibrationY[chan]; + + _wpadCenterX[chan] += a[i]; + _wpadCenterY[chan] += b[i]; + } + + // NOTE: specifically not a compound assignment + _wpadCenterX[chan] = _wpadCenterX[chan] / 4.0f; + _wpadCenterY[chan] = _wpadCenterY[chan] / 4.0f; + + _wpadRolag[chan] = 0; + + for (i = 0; i < WPAD_MAX_DPD_OBJECTS; i++) + { + c[i] = atan((b[i] - _wpadCenterY[chan]) / (a[i] - _wpadCenterX[chan])); + d[i] = atan((defaultDpdY[i] - 383.5f) / (defaultDpdX[i] - 511.5f)); + + _wpadRolag[chan] += c[i] - d[i]; + } + + _wpadRolag[chan] = _wpadRolag[chan] / 4.0f; + + for (i = 0; i < WPAD_MAX_CONFIG_BLOCKS; i++) + { + checksum = 0; + index = i * WPAD_DEV_CONFIG_BLOCK_SIZE; + if (p_wpd->configIndex == 0) + index += WPAD_DPD_CONFIG_BLOCK_SIZE * WPAD_MAX_CONFIG_BLOCKS; + + for (j = index; j < index + WPAD_DEV_CONFIG_BLOCK_CHECKSUM; j++) + checksum += data[j]; + + checksum += WPAD_CONFIG_BLOCK_CHECKSUM_BIAS; + + if (checksum != data[index + WPAD_DEV_CONFIG_BLOCK_CHECKSUM]) + continue; + + p_wpd->devConfig.accX0g = + MAKE_DEV_CONFIG_ACC_X(data[index + 0], data[index + 3]); + p_wpd->devConfig.accY0g = + MAKE_DEV_CONFIG_ACC_Y(data[index + 1], data[index + 3]); + p_wpd->devConfig.accZ0g = + MAKE_DEV_CONFIG_ACC_Z(data[index + 2], data[index + 3]); + + p_wpd->devConfig.accX1g = + MAKE_DEV_CONFIG_ACC_X(data[index + 4], data[index + 7]); + p_wpd->devConfig.accY1g = + MAKE_DEV_CONFIG_ACC_Y(data[index + 5], data[index + 7]); + p_wpd->devConfig.accZ1g = + MAKE_DEV_CONFIG_ACC_Z(data[index + 6], data[index + 7]); + + p_wpd->devConfig.volume = MAKE_DEV_CONFIG_VOLUME(data[index + 8]); + p_wpd->devConfig.motor = MAKE_DEV_CONFIG_MOTOR(data[index + 8]); + + break; + } +} + +static BOOL __wpadCheckCalibration(byte_t *data, u8 checksumOffset, + ChecksumType checksumType) +{ + BOOL success = FALSE; + u32 crc = 0; + + u8 i; + if (checksumType == CHECKSUM_SIMPLE_SUM) + { + for (i = 0; i < checksumOffset; i++) + crc += data[i]; + + if ((u8)(crc + 0x55) == data[checksumOffset] + && (u8)(crc + 0xaa) == data[checksumOffset + 1]) + { + success = TRUE; + } + } + else + { + crc = OSCalcCRC32(data, checksumOffset); + + if (crc == *(u32 *)&data[checksumOffset]) + success = TRUE; + } + + return success; +} + +static void __wpadGetFsConfig(WPADChannel chan, byte_t *config) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->extConfig.fs.accX0g = MAKE_DEV_CONFIG_ACC_X(config[0], config[3]); + p_wpd->extConfig.fs.accY0g = MAKE_DEV_CONFIG_ACC_Y(config[1], config[3]); + p_wpd->extConfig.fs.accZ0g = MAKE_DEV_CONFIG_ACC_Z(config[2], config[3]); + + p_wpd->extConfig.fs.accX1g = MAKE_DEV_CONFIG_ACC_X(config[4], config[7]); + p_wpd->extConfig.fs.accY1g = MAKE_DEV_CONFIG_ACC_Y(config[5], config[7]); + p_wpd->extConfig.fs.accZ1g = MAKE_DEV_CONFIG_ACC_Z(config[6], config[7]); + + p_wpd->extConfig.fs.at_0x04 = (s8)config[8]; + p_wpd->extConfig.fs.at_0x02 = (s8)config[9]; + p_wpd->extConfig.fs.at_0x0a = (s8)config[11]; + p_wpd->extConfig.fs.at_0x08 = (s8)config[12]; + + if (!p_wpd->calibrated) + { + p_wpd->extConfig.fs.stickXCenter = (s8)config[10]; + p_wpd->extConfig.fs.stickYCenter = (s8)config[13]; + } +} + +static void __wpadGetClConfig(WPADChannel chan, byte_t *config) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->extConfig.cl.at_0x04 = (s8)config[0]; + p_wpd->extConfig.cl.at_0x02 = (s8)config[1]; + p_wpd->extConfig.cl.at_0x0a = (s8)config[3]; + p_wpd->extConfig.cl.at_0x08 = (s8)config[4]; + p_wpd->extConfig.cl.at_0x10 = (s8)config[6]; + p_wpd->extConfig.cl.at_0x0e = (s8)config[7]; + p_wpd->extConfig.cl.at_0x16 = (s8)config[9]; + p_wpd->extConfig.cl.at_0x14 = (s8)config[10]; + + if (!p_wpd->calibrated) + { + p_wpd->extConfig.cl.lStickXCenter = (s8)config[2]; + p_wpd->extConfig.cl.lStickYCenter = (s8)config[5]; + p_wpd->extConfig.cl.rStickXCenter = (s8)config[8]; + p_wpd->extConfig.cl.rStickYCenter = (s8)config[11]; + + p_wpd->extConfig.cl.triggerLZero = config[12]; + p_wpd->extConfig.cl.triggerRZero = config[13]; + } + + return; +} + +static void __wpadGetMpConfig(WPADChannel chan, byte_t *config, + MplsConfigDataType type) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + struct WPADMplsCalibration *calib = type == MPLS_CALIB_TYPE_HIGH + ? &p_wpd->extConfig.mpls.high + : &p_wpd->extConfig.mpls.low; + + calib->pitchZero = MAKE_MP_CONFIG_ZERO_VALUE(config[4], config[5]); + calib->yawZero = MAKE_MP_CONFIG_ZERO_VALUE(config[0], config[1]); + calib->rollZero = MAKE_MP_CONFIG_ZERO_VALUE(config[2], config[3]); + + calib->degrees = config[12] * 6; + if (calib->degrees == 0) + calib->degrees = 91; + + calib->pitchScale = MAKE_MP_CONFIG_SCALE_VALUE(config[10], config[11]); + calib->yawScale = MAKE_MP_CONFIG_SCALE_VALUE(config[6], config[7]); + calib->rollScale = MAKE_MP_CONFIG_SCALE_VALUE(config[8], config[9]); + + RECALC_MP_CONFIG_SCALE_VALUE(calib->pitchScale); + RECALC_MP_CONFIG_SCALE_VALUE(calib->yawScale); + RECALC_MP_CONFIG_SCALE_VALUE(calib->rollScale); +} + +static void __wpadGetExtConfig(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + byte_t *data = p_wpd->wmReadDataPtr; + + if (!p_wpd->wpInfo.attach) + { + p_wpd->devType = _wpadDevType[chan] = WPAD_DEV_CORE; + p_wpd->devMode = _wpadDevMode[chan] = WPAD_DEV_MODE_NORMAL; + + return; + } + + switch (result) + { + case WPAD_ENODEV: + p_wpd->devType = WPAD_DEV_NONE; + p_wpd->savedDevType = p_wpd->devType; + p_wpd->extWasDisconnected = FALSE; + break; + + case WPAD_ESUCCESS: + p_wpd->devType = _wpadDevType[chan]; + break; + + default: + p_wpd->devType = WPAD_DEV_252; // can't get device? + p_wpd->savedDevType = p_wpd->devType; + p_wpd->extWasDisconnected = FALSE; + break; + } + + p_wpd->devMode = _wpadDevMode[chan]; + + if (p_wpd->devType == WPAD_DEV_FS) + { + p_wpd->extConfig.fs.accX0g = p_wpd->extConfig.fs.accY0g = + p_wpd->extConfig.fs.accZ0g = 512; + + p_wpd->extConfig.fs.accX1g = p_wpd->extConfig.fs.accY1g = + p_wpd->extConfig.fs.accZ1g = 716; + + if (__wpadCheckCalibration(&data[0], 14, CHECKSUM_SIMPLE_SUM)) + __wpadGetFsConfig(chan, &data[0]); + else if (__wpadCheckCalibration(&data[16], 14, CHECKSUM_SIMPLE_SUM)) + __wpadGetFsConfig(chan, &data[16]); + } + else if (p_wpd->devType == WPAD_DEV_CLASSIC) + { + if (__wpadCheckCalibration(&data[0], 14, CHECKSUM_SIMPLE_SUM)) + __wpadGetClConfig(chan, &data[0]); + else + __wpadGetClConfig(chan, &data[16]); + } + else if (p_wpd->devType == WPAD_DEV_MOTION_PLUS + || p_wpd->devType == WPAD_DEV_MPLS_PT_FS + || p_wpd->devType == WPAD_DEV_MPLS_PT_CLASSIC + || p_wpd->devType == WPAD_DEV_MPLS_PT_UNKNOWN) + { + p_wpd->noParseMplsCount = 5; + + p_wpd->extConfig.mpls.high.pitchZero = + p_wpd->extConfig.mpls.high.yawZero = + p_wpd->extConfig.mpls.high.rollZero = 8192.0f; + p_wpd->extConfig.mpls.high.pitchScale = + p_wpd->extConfig.mpls.high.yawScale = + p_wpd->extConfig.mpls.high.rollScale = 5333.0f; + p_wpd->extConfig.mpls.high.degrees = 1200; + + p_wpd->extConfig.mpls.low.pitchZero = + p_wpd->extConfig.mpls.low.yawZero = + p_wpd->extConfig.mpls.low.rollZero = 8192.0f; + p_wpd->extConfig.mpls.low.pitchScale = + p_wpd->extConfig.mpls.low.yawScale = + p_wpd->extConfig.mpls.low.rollScale = 5400.0f; + p_wpd->extConfig.mpls.low.degrees = 270; + + p_wpd->extConfig.mpls.calibID = -1; + p_wpd->extConfig.mpls.calibCRC = -1; + + byte_t saveCRC[sizeof(u16)]; + saveCRC[0] = data[14]; + saveCRC[1] = data[15]; + + memcpy(&data[14], &data[16], 14); + + data[28] = saveCRC[0]; + data[29] = saveCRC[1]; + + if (__wpadCheckCalibration(data, 28, CHECKSUM_CRC32)) + { + __wpadGetMpConfig(chan, &data[0], MPLS_CALIB_TYPE_HIGH); + __wpadGetMpConfig(chan, &data[14], MPLS_CALIB_TYPE_LOW); + + p_wpd->extConfig.mpls.calibID = + MAKE_MPLS_CONFIG_ID(data[13], data[27]); + + p_wpd->extConfig.mpls.calibCRC = OSCalcCRC32(data, 28); + } + + p_wpd->certState = WPAD_STATE_CERT_PROBE_X; + + if (p_wpd->lastMplsCalibID == p_wpd->extConfig.mpls.calibID + && p_wpd->lastMplsCalibCRC == p_wpd->extConfig.mpls.calibCRC) + { + if (p_wpd->certMayVerifyByCalibBlock == TRUE) + { + p_wpd->certValidityStatus = WPAD_CERT_VALID; + p_wpd->certState = WPAD_STATE_CERT_SUCCESS; + } + } + else + { + p_wpd->certMayVerifyByCalibBlock = FALSE; + } + + if (p_wpd->certMayVerifyByCalibBlock != TRUE + && p_wpd->certProbeStartingValue >= 14) + { + p_wpd->devType = _wpadDevType[chan] = WPAD_DEV_252; + } + + p_wpd->lastMplsCalibID = p_wpd->extConfig.mpls.calibID; + p_wpd->lastMplsCalibCRC = p_wpd->extConfig.mpls.calibCRC; + } + else if (p_wpd->devType == WPAD_DEV_BALANCE_CHECKER) + { + if (p_wpd->wmReadLength == 1) + return; + } + + if (p_wpd->extensionCB) + (*p_wpd->extensionCB)(chan, p_wpd->devType); + + p_wpd->cmdBlkCB = NULL; +} + +static void __wpadGetExtConfig2(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + byte_t *data = p_wpd->wmReadDataPtr; + + if (!p_wpd->hasReadExtType2) + return; + + if (result == WPAD_ESUCCESS) + { + if (_wpadDevType2[chan] == 0) + { + p_wpd->extConfig.fs.accX0g = p_wpd->extConfig.fs.accY0g = + p_wpd->extConfig.fs.accZ0g = 512; + + p_wpd->extConfig.fs.accX1g = p_wpd->extConfig.fs.accY1g = + p_wpd->extConfig.fs.accZ1g = 716; + + if (__wpadCheckCalibration(data, 14, CHECKSUM_SIMPLE_SUM)) + { + __wpadGetFsConfig(chan, data); + p_wpd->parseMPState = 4; + } + else + { + if (p_wpd->parseMPState == 3) + p_wpd->parseMPState += 3; + else + p_wpd->parseMPState = 4; + } + } + else + { + p_wpd->parseMPState = 4; + } + } + else if (result == WPAD_ERR_3) + { + p_wpd->parseMPState = 2; + } +} + +static BOOL __wpadIsExtEncryptMain(u8 devType) +{ + // poor WPAD_DEV_TAIKO, wasn't included :( + if (devType == WPAD_DEV_FS || devType == WPAD_DEV_CLASSIC + || devType == WPAD_DEV_BALANCE_CHECKER || devType == WPAD_DEV_GUITAR + || devType == WPAD_DEV_DRUM || devType == WPAD_DEV_TURNTABLE + || devType == WPAD_DEV_VSM || devType == WPAD_DEV_BULK_1 + || devType == WPAD_DEV_BULK_2 || devType == WPAD_DEV_BULK_3 + || devType == WPAD_DEV_BULK_4 || devType == WPAD_DEV_BULK_5 + || devType == WPAD_DEV_BULK_6 || devType == WPAD_DEV_BULK_7 + || devType == WPAD_DEV_BULK_8) + { + return TRUE; + } + else + { + return FALSE; + } +} + +static void __wpadGetExtType(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + struct WPADCmdQueue *queue = &p_wpd->extCmdQueue; + byte_t *data = p_wpd->wmReadDataBuf; + + if (result == WPAD_ESUCCESS) + { + if (!p_wpd->wpInfo.attach) + { + p_wpd->devType = _wpadDevType[chan] = WPAD_DEV_CORE; + p_wpd->devMode = _wpadDevMode[chan] = WPAD_DEV_MODE_NORMAL; + + return; + } + + if (memcmp(data, _cExtInvalidData, 16) == 0 + || (data[12] == 0 && data[13] == 0)) + { + _wpadDevType[chan] = WPAD_DEV_252; + _wpadDevMode[chan] = WPAD_DEV_MODE_NORMAL; + } + else + { + _wpadCLCompt[chan] = FALSE; + _wpadDevMode[chan] = data[14]; + + switch (data[15]) + { + case 0: + _wpadDevType[chan] = WPAD_DEV_FS; + break; + + case 1: + _wpadDevType[chan] = WPAD_DEV_CLASSIC; + break; + + case 2: + _wpadDevType[chan] = + WUDIsLinkedWBC() ? WPAD_DEV_BALANCE_CHECKER : WPAD_DEV_251; + break; + + case 16: + _wpadDevType[chan] = + WPADIsEnabledTRN() ? WPAD_DEV_TRAIN : WPAD_DEV_251; + break; + + case 17: + _wpadDevType[chan] = + WPADIsEnabledTKO() ? WPAD_DEV_TAIKO : WPAD_DEV_251; + break; + + case 3: + if (__OSInIPL) + { + _wpadDevType[chan] = WPAD_DEV_CLASSIC; + _wpadDevMode[chan] = WPAD_DEV_MODE_CLASSIC_REDUCED; + _wpadCLCompt[chan] = TRUE; + } + else + { + switch (data[10]) + { + case 0: + _wpadDevType[chan] = + WPADIsEnabledGTR() ? WPAD_DEV_GUITAR : WPAD_DEV_251; + break; + + case 1: + _wpadDevType[chan] = + WPADIsEnabledDRM() ? WPAD_DEV_DRUM : WPAD_DEV_251; + break; + + case 3: + _wpadDevType[chan] = WPADIsEnabledTBL() + ? WPAD_DEV_TURNTABLE + : WPAD_DEV_251; + break; + + case 4: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_1 : WPAD_DEV_251; + break; + + case 5: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_2 : WPAD_DEV_251; + break; + + case 6: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_3 : WPAD_DEV_251; + break; + + case 7: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_4 : WPAD_DEV_251; + break; + + case 8: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_5 : WPAD_DEV_251; + break; + + case 9: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_6 : WPAD_DEV_251; + break; + + case 10: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_7 : WPAD_DEV_251; + break; + + case 11: + _wpadDevType[chan] = + WPADIsEnabledBLK() ? WPAD_DEV_BULK_8 : WPAD_DEV_251; + break; + + default: + _wpadDevType[chan] = WPAD_DEV_251; + break; + } + } + + break; + + case 4: + if (WPADIsEnabledVSM()) + { + _wpadDevType[chan] = WPAD_DEV_VSM; + p_wpd->unk_0xbbc = 0; + } + else + { + _wpadDevType[chan] = WPAD_DEV_251; + } + + break; + + case 5: + switch (data[14]) + { + case 4: + case 5: + case 7: + _wpadDevType[chan] = WPAD_DEV_MOTION_PLUS; + break; + + default: + _wpadDevType[chan] = WPAD_DEV_251; + break; + } + + p_wpd->hasReadExtType2 = FALSE; + p_wpd->parseMPState = 0; + p_wpd->unk_0x93c = WPAD_DEV_NONE; + + _wpadDevType2[chan] = data[9]; + _wpadDevType2Sub[chan] = data[8]; + + p_wpd->mplsUptimeMs = 0; + + break; + + default: + _wpadDevType[chan] = WPAD_DEV_251; + break; + } + } + + if (_wpadDevType[chan] == WPAD_DEV_CLASSIC + && (_wpadDevMode[chan] < WPAD_DEV_MODE_CLASSIC_REDUCED + || _wpadDevMode[chan] > WPAD_DEV_MODE_CLASSIC_STANDARD)) + { + _wpadDevType[chan] = WPAD_DEV_252; + } + + if (p_wpd->extWasDisconnected + && p_wpd->savedDevType == _wpadDevType[chan]) + { + if (p_wpd->calibrated) + p_wpd->calibrated = TRUE; // ? + } + else + { + p_wpd->calibrated = FALSE; + } + + p_wpd->savedDevType = _wpadDevType[chan]; + p_wpd->extWasDisconnected = FALSE; + + if (_wpadDevType[chan] == WPAD_DEV_251 + || _wpadDevType[chan] == WPAD_DEV_252) + { + p_wpd->devType = _wpadDevType[chan]; + p_wpd->devMode = _wpadDevMode[chan]; + + if (p_wpd->extensionCB) + (*p_wpd->extensionCB)(chan, p_wpd->devType); + } + else + { + if (_wpadDevType[chan] == WPAD_DEV_MOTION_PLUS + || _wpadDevType[chan] == WPAD_DEV_MPLS_PT_FS + || _wpadDevType[chan] == WPAD_DEV_MPLS_PT_CLASSIC + || _wpadDevType[chan] == WPAD_DEV_MPLS_PT_UNKNOWN) + { + __wpadCertReset(chan); + p_wpd->certProbeStartingValue = data[7]; + } + else + { + // favoritism + if (__wpadIsExtEncryptMain(_wpadDevType[chan])) + { + p_wpd->extState = WPAD_STATE_EXT_ENCRYPTED; + WPADiCreateKey(chan); + } + else + { + p_wpd->extState = WPAD_STATE_EXT_ENCRYPTED_3RD; + WPADiCreateKeyFor3rd(chan); + } + + // see https://wiibrew.org/wiki/Wiimote/Extension_Controllers#Encryption_setup + WPADiSendWriteDataCmd(queue, 0xaa, WM_REG_EXTENSION_F0, + &__wpadAbortInitExtension); + WPADiSendWriteData(queue, &p_wpd->encryptionKey[0], 6, + WM_REG_EXTENSION_40 + 0, + &__wpadAbortInitExtension); + WPADiSendWriteData(queue, &p_wpd->encryptionKey[6], 6, + WM_REG_EXTENSION_40 + 6, + &__wpadAbortInitExtension); + WPADiSendWriteData(queue, &p_wpd->encryptionKey[12], 4, + WM_REG_EXTENSION_40 + 12, + &__wpadAbortInitExtension); + + if (_wpadDevType[chan] == WPAD_DEV_BALANCE_CHECKER) + { + WPADiSendWriteDataCmd(queue, 0xaa, + WM_REG_EXTENSION_CERT_CHALLENGE, + &__wpadAbortInitExtension); + WPADiSendWriteDataCmd(queue, 0xaa, + WM_REG_EXTENSION_CERT_CHALLENGE, + &__wpadAbortInitExtension); + WPADiSendWriteDataCmd(queue, 0xaa, + WM_REG_EXTENSION_CERT_CHALLENGE, + &__wpadAbortInitExtension); + } + } + + WPADiSendReadData(queue, p_wpd->wmReadDataBuf, + WM_EXTENSION_CONFIG_SIZE, WM_REG_EXTENSION_CONFIG, + (WPADCallback *)p_wpd->extensionCB); + } + } + else + { + p_wpd->devType = WPAD_DEV_252; + p_wpd->devMode = WPAD_DEV_MODE_NORMAL; + p_wpd->savedDevType = p_wpd->devType; + p_wpd->extWasDisconnected = FALSE; + } +} + +static void __wpadGetExtType2(WPADChannel chan, WPADResult result) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + byte_t *bufPtr = p_wpd->wmReadDataPtr; + + if (!p_wpd->hasReadExtType2) + return; + + if (p_wpd->parseMPState != 1) + return; + + if (result != WPAD_ESUCCESS) + { + p_wpd->parseMPState = 0; + return; + } + + p_wpd->parseMPState = 2; + p_wpd->calibrated = FALSE; + _wpadDevType2[chan] = bufPtr[3]; + _wpadDevType2Sub[chan] = bufPtr[2]; +} + +static void __wpadGetGameInfo(WPADChannel chan, WPADResult result, u8 param_3) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + int i; + + byte_t *bufPtrRead = p_wpd->wmReadDataPtr; + byte_t *bufPtrCalc = p_wpd->wmReadDataPtr; + u8 crc = 0; + + if (result == WPAD_ESUCCESS) + { + for (i = 0; i < 47; i++) + crc += bufPtrCalc[i]; + + crc += 0x55; + if (bufPtrRead[47] == crc) + { + memcpy(&p_wpd->gameInfo, bufPtrCalc, sizeof p_wpd->gameInfo); + p_wpd->at_0x038[param_3] = 0; // WPAD_ESUCCESS? + } + else + { + p_wpd->at_0x038[param_3] = -4; // WPAD_EINVAL? + } + } + else + { + p_wpd->at_0x038[param_3] = -4; + } +} + +static void __wpadInitExtension(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + u8 cmd = 0x00; // TODO: some define? + + WPADiClearQueue(&p_wpd->extCmdQueue); + + WPADiSendSetReportType(&p_wpd->extCmdQueue, p_wpd->dataFormat, + p_wpd->disableContReport, &__wpadAbortInitExtension); + + p_wpd->extState = WPAD_STATE_EXT_INITIALIZED; + + if (p_wpd->isInitingMpls) + { + WPADiSendWriteDataCmd(&p_wpd->extCmdQueue, cmd, WM_REG_EXTENSION_FB, + &__wpadAbortInitExtension); + WPADiSendReadData(&p_wpd->extCmdQueue, p_wpd->wmReadDataBuf, 16, + WM_REG_EXTENSION_F0, &__wpadAbortInitExtension); + } + else + { + WPADiSendWriteDataCmd(&p_wpd->extCmdQueue, 0x55, WM_REG_EXTENSION_F0, + &__wpadAbortInitExtension); + WPADiSendWriteDataCmd(&p_wpd->extCmdQueue, cmd, WM_REG_EXTENSION_FB, + &__wpadAbortInitExtension); + WPADiSendReadData(&p_wpd->extCmdQueue, &p_wpd->wmReadDataBuf[10], + 16 - 10, WM_REG_EXTENSION_F0 + 10, + &__wpadAbortInitExtension); + } + + p_wpd->isInitingMpls = FALSE; +} + +static void __wpadInvertRxBuffer(u8 chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; +} + +static void *__wpadGetWorkRxBuffer(u8 chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + void *rxBuf = &p_wpd->rxBufs[p_wpd->rxBufIndex]; + + return rxBuf; +} + +static void *__wpadGetLastRxBuffer(u8 chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + u32 lastIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + void *rxBuf = &p_wpd->rxBufs[lastIndex]; + + return rxBuf; +} + +static void __wpadCheckDataFormat(u8 chan, u8 rep_id, void *data) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = data; + +/* + WPAD_FMT_BTN = RPTID_DATA_BTN + WPAD_FMT_BTN_ACC = RPTID_DATA_BTN_ACC + WPAD_FMT_BTN_ACC_DPD = RPTID_DATA_BTN_ACC_DPD12 + WPAD_FMT_FS_BTN = RPTID_DATA_BTN_EXT8 + WPAD_FMT_FS_BTN_ACC = RPTID_DATA_BTN_ACC_EXT16 + WPAD_FMT_FS_BTN_ACC_DPD = RPTID_DATA_BTN_ACC_DPD10_EXT9 + WPAD_FMT_CLASSIC_BTN = RPTID_DATA_BTN_EXT8 + WPAD_FMT_CLASSIC_BTN_ACC = RPTID_DATA_BTN_ACC_EXT16 + WPAD_FMT_CLASSIC_BTN_ACC_DPD = RPTID_DATA_BTN_ACC_DPD10_EXT9 + WPAD_FMT_DPD_EXTENDED = RPTID_DATA_BTN_ACC_DPD18_1 or 2 + + WPAD_FMT_TRAIN = RPTID_DATA_BTN_EXT8 + WPAD_FMT_GUITAR = RPTID_DATA_BTN_ACC_DPD10_EXT9 + WPAD_FMT_BALANCE_CHECKER = RPTID_DATA_BTN_EXT19 + WPAD_FMT_VSM = RPTID_DATA_BTN_ACC_EXT16 +// WPAD_FMT_14 + WPAD_FMT_DRUM = RPTID_DATA_BTN_ACC_DPD10_EXT9 + WPAD_FMT_MOTION_PLUS = RPTID_DATA_BTN_ACC_DPD10_EXT9 + WPAD_FMT_TAIKO = RPTID_DATA_BTN_ACC_DPD10_EXT9 + WPAD_FMT_TURNTABLE = RPTID_DATA_BTN_ACC_DPD10_EXT9 + WPAD_FMT_BULK = RPTID_DATA_BTN_ACC_EXT16 +*/ + + // clang-format off + if ((rep_id == RPTID_DATA_BTN + && p_wpd->dataFormat == WPAD_FMT_CORE_BTN) + || (rep_id == RPTID_DATA_BTN_ACC + && p_wpd->dataFormat == WPAD_FMT_CORE_BTN_ACC) + || (rep_id == RPTID_DATA_BTN_EXT8 + && (p_wpd->dataFormat == WPAD_FMT_FS_BTN + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN + || p_wpd->dataFormat == WPAD_FMT_TRAIN)) + || (rep_id == RPTID_DATA_BTN_ACC_DPD12 + && p_wpd->dataFormat == WPAD_FMT_CORE_BTN_ACC_DPD) + || (rep_id == RPTID_DATA_BTN_EXT19 + && p_wpd->dataFormat == WPAD_FMT_BALANCE_CHECKER) + || (rep_id == RPTID_DATA_BTN_ACC_EXT16 + && (p_wpd->dataFormat == WPAD_FMT_FS_BTN_ACC + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC + || p_wpd->dataFormat == WPAD_FMT_VSM + || p_wpd->dataFormat == WPAD_FMT_BULK)) + || (rep_id == RPTID_DATA_BTN_ACC_DPD10_EXT9 + && (p_wpd->dataFormat == WPAD_FMT_FS_BTN_ACC_DPD + || p_wpd->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC_DPD + || p_wpd->dataFormat == WPAD_FMT_GUITAR + || p_wpd->dataFormat == WPAD_FMT_DRUM + || p_wpd->dataFormat == WPAD_FMT_TURNTABLE + || p_wpd->dataFormat == WPAD_FMT_TAIKO + || p_wpd->dataFormat == WPAD_FMT_MOTION_PLUS)) + || (rep_id == RPTID_DATA_BTN_ACC_DPD18_1 + && p_wpd->dataFormat == WPAD_FMT_BTN_ACC_DPD_EXTENDED) + || (rep_id == RPTID_DATA_BTN_ACC_DPD18_2 + && p_wpd->dataFormat == WPAD_FMT_BTN_ACC_DPD_EXTENDED)) + // clang-format on + { + status->err = WPAD_ESUCCESS; + } + else + { + status->err = WPAD_EINVAL; + } +} + +signed WPADiHIDParser(UINT8 port, UINT8 *p_rpt) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[port]; + + BOOL intrStatus; + + signed ret = 0; // is this a WPADResult? + byte_t *rxBuf; + if (p_rpt[RPT_REPORT_ID] >= RPTID_IN_LO + && p_rpt[RPT_REPORT_ID] <= RPTID_IN_HI) + { + intrStatus = OSDisableInterrupts(); + + rxBuf = __wpadGetWorkRxBuffer(port); + + if (p_rpt[RPT_REPORT_ID] != RPTID_DATA_BTN_ACC_DPD18_1 + && p_rpt[RPT_REPORT_ID] != RPTID_DATA_BTN_ACC_DPD18_2) + { + memset(rxBuf, 0, RX_BUFFER_SIZE); + } + + __wpadCheckDataFormat(port, p_rpt[RPT_REPORT_ID], rxBuf); + + (*__a1_input_reports_array[p_rpt[RPT_REPORT_ID] - RPTID_IN_LO])( + port, p_rpt, rxBuf); + + if (!p_wpd->handshakeFinished) + ((WPADStatus *)(rxBuf))->err = WPAD_EINVAL; + + ((WPADStatus *)(rxBuf))->dev = p_wpd->devType; + + if (p_rpt[RPT_REPORT_ID] != RPTID_DATA_BTN_ACC_DPD18_1 + && p_rpt[RPT_REPORT_ID] != RPTID_DATA_BTN_ACC_DPD18_2) + { + __wpadInvertRxBuffer(port); + } + + OSRestoreInterrupts(intrStatus); + + WPADiExcludeButton(port); + WPADiCopyOut(port); + } + else + { + // maybe not, WPAD_ENODEV doesn't make sense here + ret = -1; + } + + return ret; // is it a tBTA_STATUS or similar? +} + +static void __a1_20_status_report(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + BOOL intrStatus; + BOOL currentlyHasExtension = p_wpd->wpInfo.attach; + + intrStatus = OSDisableInterrupts(); + + if (!p_wpd->handshakeFinished) + { + OSRestoreInterrupts(intrStatus); + return; + } + +#if !defined(NDEBUG) + if (!WPADiIsDummyExtension(chan)) +#endif + p_wpd->wpInfo.attach = (hidReport[RPT20_FLAGS] & 0x02) >> 1; + + p_wpd->wpInfo.lowBat = hidReport[RPT20_FLAGS] & 0x01; + p_wpd->wpInfo.led = (hidReport[RPT20_FLAGS] & 0xf0) >> 4; + + /* ERRATA: the masks (or shifts?) on the following statements are switched + * + * protocol is always 0 after the shift (probably wrong) + * firmware holds protocol(?) in its upper nibble (probably not intended) + */ + p_wpd->wpInfo.protocol = (hidReport[RPT20_PROTO_FW] & 0x0f) >> 4; + p_wpd->wpInfo.firmware = (hidReport[RPT20_PROTO_FW] & 0xf0) >> 0; + + p_wpd->wpInfo.nearempty = (u8)((hidReport[RPT_BTN0] & 0x80) >> 7); + p_wpd->wpInfo.dpd = (hidReport[RPT20_FLAGS] & 0x08) >> 3; + p_wpd->wpInfo.speaker = (hidReport[RPT20_FLAGS] & 0x04) >> 2; + + if (p_wpd->devType == WPAD_DEV_BALANCE_CHECKER) + p_wpd->wpInfo.battery = p_wpd->blcBattery; + else if ((u8)hidReport[RPT20_BATTERY] >= 0x55) + p_wpd->wpInfo.battery = 4; + else if ((u8)hidReport[RPT20_BATTERY] >= 0x44) + p_wpd->wpInfo.battery = 3; + else if ((u8)hidReport[RPT20_BATTERY] >= 0x33) + p_wpd->wpInfo.battery = 2; + else if ((u8)hidReport[RPT20_BATTERY] >= 0x03) + p_wpd->wpInfo.battery = 1; + else + p_wpd->wpInfo.battery = 0; + + WPADExtensionCallback *extCB; + if (p_wpd->wpInfo.attach) + { + if (!currentlyHasExtension) + { + _wpadExtInitRetryCnt[chan] = 0; + + extCB = p_wpd->extensionCB; + __wpadInitExtension(chan); + + p_wpd->devType = WPAD_DEV_INITIALIZING; + p_wpd->devMode = WPAD_DEV_MODE_NORMAL; + __wpadCertReset(chan); + + if (extCB) + (*extCB)(chan, WPAD_DEV_INITIALIZING); + } + } + else + { + p_wpd->devType = WPAD_DEV_CORE; + p_wpd->devMode = WPAD_DEV_MODE_NORMAL; + + WPADiClearQueue(&p_wpd->extCmdQueue); + WPADiSendSetReportType(&p_wpd->extCmdQueue, p_wpd->dataFormat, + p_wpd->disableContReport, NULL); + + if (currentlyHasExtension) + { + p_wpd->extWasDisconnected = TRUE; + p_wpd->reconnectExtMs = 300; + __wpadCertReset(chan); + + if (p_wpd->extensionCB) + (*p_wpd->extensionCB)(chan, WPAD_DEV_CORE); + } + } + + if (p_wpd->wpInfoOut) + { + memcpy(p_wpd->wpInfoOut, &p_wpd->wpInfo, sizeof *p_wpd->wpInfoOut); + p_wpd->wpInfoOut = NULL; + } + + RETRIEVE_BUTTON_STATE(chan, status, rxBuffer, hidReport); + + if (p_wpd->cmdBlkCB && p_wpd->statusReqBusy) + { + (*p_wpd->cmdBlkCB)(chan, WPAD_ESUCCESS); + p_wpd->cmdBlkCB = NULL; + } + + p_wpd->statusReqBusy = FALSE; + + OSRestoreInterrupts(intrStatus); +} + +static void __a1_21_user_data(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + BOOL intrStatus = OSDisableInterrupts(); + + u16 addrLow; + u16 readAddrLow; + u16 readAddrHigh; + s16 addrDiff; + + u8 errCode = (u8)hidReport[RPT21_SIZE_ERR] & 0x0f; + if (errCode != 0) + { + p_wpd->wmReadHadError = -1; + + if (p_wpd->cmdBlkCB) + { + if (!p_wpd->extensionCB || p_wpd->extensionCB != p_wpd->cmdBlkCB) + (*p_wpd->cmdBlkCB)(chan, WPAD_ERR_3); + + p_wpd->cmdBlkCB = NULL; + } + + p_wpd->status = WPAD_ESUCCESS; + } + + u8 size = ((u8)((u8)hidReport[RPT21_SIZE_ERR] >> 4) & 0x0f) + 1; + addrLow = (u16)((u16)((u16)hidReport[RPT21_ADDR0] << 8) & 0xff00) + | (u16)((u16)((u16)hidReport[RPT21_ADDR1]) & 0x00ff); + + readAddrLow = p_wpd->wmReadAddress & 0x0000ffff; + readAddrHigh = (p_wpd->wmReadAddress & 0xffff0000) >> 16; + addrDiff = addrLow - readAddrLow; + + WPADResult cbRet; + if ((u16)addrLow >= readAddrLow + && addrLow <= readAddrLow + p_wpd->wmReadLength) + { + if (errCode == 0) + { + memcpy(p_wpd->wmReadDataPtr + addrDiff, &hidReport[RPT21_DATA], + size); + } + + if (readAddrLow + p_wpd->wmReadLength == addrLow + size) + { + cbRet = p_wpd->wmReadHadError < 0 ? WPAD_CERR_3 : WPAD_CESUCCESS; + + if (readAddrHigh == 0x04a4 + && (p_wpd->extState == WPAD_STATE_EXT_ENCRYPTED + || p_wpd->extState == WPAD_STATE_EXT_ENCRYPTED_3RD)) + { + WPADiDecode(chan, p_wpd->wmReadDataPtr, p_wpd->wmReadLength, + readAddrLow); + } + + if ((p_wpd->wmReadAddress == WM_ADDR_MEM_DEV_CONFIG_0 + && p_wpd->configIndex == 0) + || (p_wpd->wmReadAddress == WM_ADDR_MEM_176C + && p_wpd->configIndex == 1)) + { + __wpadGetDevConfig(chan, cbRet); + } + + if (p_wpd->wmReadAddress == WM_REG_EXTENSION_CONFIG) + __wpadGetExtConfig(chan, cbRet); + + if (p_wpd->wmReadAddress == WM_REG_EXTENSION_F0 + || p_wpd->wmReadAddress == WM_REG_EXTENSION_FA) + { + __wpadGetExtType(chan, cbRet); + } + + if (p_wpd->wmReadAddress == WM_REG_EXTENSION_EXT_TYPE_2) + __wpadGetExtType2(chan, cbRet); + + if (p_wpd->wmReadAddress == WM_REG_EXTENSION_40) + __wpadGetExtConfig2(chan, cbRet); + + if (p_wpd->wmReadAddress == WM_REG_EXTENSION_F3) + { + if (p_wpd->parseMPBuf == 3) + p_wpd->parseMPState = 9; + else if (p_wpd->parseMPBuf == 4) + p_wpd->parseMPState = 6; + } + + if (p_wpd->wmReadAddress == WM_ADDR_MEM_GAME_INFO_0) + __wpadGetGameInfo(chan, cbRet, 0); + + if (p_wpd->wmReadAddress == WM_ADDR_MEM_GAME_INFO_1) + __wpadGetGameInfo(chan, cbRet, 1); + + if (p_wpd->cmdBlkCB) + { + (*p_wpd->cmdBlkCB)(chan, cbRet); + p_wpd->cmdBlkCB = NULL; + } + + p_wpd->status = WPAD_ESUCCESS; + } + } + + RETRIEVE_BUTTON_STATE(chan, status, rxBuffer, hidReport); + + OSRestoreInterrupts(intrStatus); +} + +static void __a1_22_ack(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + BOOL intrStatus = OSDisableInterrupts(); + + RETRIEVE_BUTTON_STATE(chan, status, rxBuffer, hidReport); + + u8 ackedID = (u8)hidReport[RPT22_ACKED_RPT_ID]; + u8 err = (u8)hidReport[RPT22_ERR_CODE]; + + WPADResult cbRet = err == 0 ? WPAD_CESUCCESS : WPAD_CERR_3; + + if (p_wpd->lastReportID == ackedID) + { + if (p_wpd->cmdBlkCB) + { + (*p_wpd->cmdBlkCB)(chan, cbRet); + p_wpd->cmdBlkCB = NULL; + } + + p_wpd->status = WPAD_ESUCCESS; + } + + OSRestoreInterrupts(intrStatus); +} + +static void __parse_dpd_data(WPADChannel chan, WPADStatus **status, + u8 dpdFormat, byte_t *data, u8 length) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (p_wpd->dpdBusy) + { + status[0]->err = WPAD_EINVAL; + return; + } + + u8 i; + u8 a, b, c; + if (dpdFormat == WPAD_DPD_STANDARD) + { + for (i = 0; i < WPAD_MAX_DPD_OBJECTS; i++) + { + if (i * 3 + 2 < length) + { + a = ((u8 *)(data + i * 3))[0]; + b = ((u8 *)(data + i * 3))[1]; + c = ((u8 *)(data + i * 3))[2]; + + status[0]->obj[i].x = MAKE_DPD_STANDARD_X(c, a); + status[0]->obj[i].y = MAKE_DPD_STANDARD_Y(c, b); + status[0]->obj[i].size = MAKE_DPD_STANDARD_SIZE(c); + RECALC_DPD_STANDARD_SIZE(status[0]->obj[i].size); + + if (status[0]->obj[i].size == 0 + || status[0]->obj[i].x == DPD_MAX_X + || status[0]->obj[i].y == DPD_MAX_Y) + { + status[0]->obj[i].x = 0; + status[0]->obj[i].y = DPD_MAX_Y; + status[0]->obj[i].size = 0; + } + + status[0]->obj[i].traceId = i; + } + else + { + status[0]->obj[i].x = 0; + status[0]->obj[i].y = DPD_MAX_Y; + status[0]->obj[i].size = 0; + status[0]->obj[i].traceId = i; + } + } + } + else if (dpdFormat == WPAD_DPD_BASIC) + { + for (i = 0; i < WPAD_MAX_DPD_OBJECTS; i++) + { + a = GET_DPD_BASIC_REPORT_X_LOW_BYTE(data, i); + b = GET_DPD_BASIC_REPORT_Y_LOW_BYTE(data, i); + c = GET_DPD_BASIC_REPORT_XY_HIGH_BITS(data, i); + + if (i % 2 == 0) + { + // First object of the pair + status[0]->obj[i].x = MAKE_DPD_BASIC_X1(c, a); + status[0]->obj[i].y = MAKE_DPD_BASIC_Y1(c, b); + } + else + { + // Second object of the pair + status[0]->obj[i].x = MAKE_DPD_BASIC_X2(c, a); + status[0]->obj[i].y = MAKE_DPD_BASIC_Y2(c, b); + } + + if (status[0]->obj[i].x == DPD_MAX_X + || status[0]->obj[i].y == DPD_MAX_Y) + { + status[0]->obj[i].x = 0; + status[0]->obj[i].y = DPD_MAX_Y; + status[0]->obj[i].size = 0; + } + else + { + status[0]->obj[i].size = 12; + } + + status[0]->obj[i].traceId = i; + } + } + + f32 fx, fy; + for (i = 0; i < WPAD_MAX_DPD_OBJECTS; i++) + { + if (status[0]->obj[i].x != 0 || status[0]->obj[i].y != DPD_MAX_Y) + { + fx = (f32)status[0]->obj[i].x + _wpadCalibrationX[chan] + - _wpadCenterX[chan]; + fy = (f32)status[0]->obj[i].y + _wpadCalibrationY[chan] + - _wpadCenterY[chan]; + + status[0]->obj[i].x = _wpadCenterX[chan] + + ((fx * (f32)cos(_wpadRolag[chan] * -1.0f)) + - (fy * (f32)sin(_wpadRolag[chan] * -1.0f))); + + status[0]->obj[i].y = _wpadCenterY[chan] + + ((fx * (f32)sin(_wpadRolag[chan] * -1.0f)) + + (fy * (f32)cos(_wpadRolag[chan] * -1.0f))); + } + } +} + +static void __parse_dpdex_data(WPADChannel chan, WPADStatusEx **statusEx, + u8 objIndex, byte_t *data, + u8 length __attribute__((unused))) +{ + wpad_cb_st *p_wpd __attribute__((unused)) = __rvl_p_wpadcb[chan]; + + statusEx[0]->obj[objIndex].x = MAKE_DPD_EXTENDED_X(data[2], data[0]); + statusEx[0]->obj[objIndex].y = MAKE_DPD_EXTENDED_Y(data[2], data[1]); + statusEx[0]->exp[objIndex].pixel = + MAKE_DPD_EXTENDED_PIXEL(data[7], data[8]); + statusEx[0]->exp[objIndex].radius = MAKE_DPD_EXTENDED_RADIUS(data[2]); + + statusEx[0]->exp[objIndex].range_x1 = (s8)data[3] == -1 ? 0 : data[3]; + statusEx[0]->exp[objIndex].range_y1 = (s8)data[4] == -1 ? 0 : data[4]; + statusEx[0]->exp[objIndex].range_x2 = (s8)data[5] == -1 ? 0 : data[5]; + statusEx[0]->exp[objIndex].range_y2 = (s8)data[6] == -1 ? 0 : data[6]; + + CALC_DPD_EXTENDED_X(statusEx[0]->exp[objIndex].range_x1); + CALC_DPD_EXTENDED_Y(statusEx[0]->exp[objIndex].range_y1); + CALC_DPD_EXTENDED_X(statusEx[0]->exp[objIndex].range_x2); + CALC_DPD_EXTENDED_Y(statusEx[0]->exp[objIndex].range_y2); + statusEx[0]->obj[objIndex].size = + MAKE_DPD_EXTENDED_SIZE(statusEx[0]->exp[objIndex].radius); + + if (statusEx[0]->obj[objIndex].size == 0 + || statusEx[0]->obj[objIndex].x == DPD_MAX_X + || statusEx[0]->obj[objIndex].y == DPD_MAX_Y + || statusEx[0]->exp[objIndex].radius == 15) + { + statusEx[0]->obj[objIndex].x = 0; + statusEx[0]->obj[objIndex].y = DPD_MAX_Y; + statusEx[0]->obj[objIndex].size = 0; + statusEx[0]->exp[objIndex].pixel = 0; + statusEx[0]->exp[objIndex].radius = 0; + } + + statusEx[0]->obj[objIndex].traceId = objIndex; +} + +static void __parse_acc_data(WPADChannel chan, WPADStatus **status, + u8 accFormat, byte_t *data, + u8 length __attribute__((unused))) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + switch (accFormat) + { + case ACC_FORMAT_STANDARD: + status[0]->accX = MAKE_ACC_STANDARD_X(p_wpd, data[2], data[0]); + status[0]->accY = MAKE_ACC_STANDARD_Y(p_wpd, data[3], data[1]); + status[0]->accZ = MAKE_ACC_STANDARD_Z(p_wpd, data[4], data[1]); + break; + + case ACC_FORMAT_INTERLEAVED0: + status[0]->accX = MAKE_ACC_INTERLEAVED0_X(p_wpd, data[2], data[0]); + CALC_ACC_INTERLEAVED0_Z(status[0]->accZ, data[1], data[0]); + break; + + case ACC_FORMAT_INTERLEAVED1: + status[0]->accY = MAKE_ACC_INTERLEAVED1_Y(p_wpd, data[2], data[0]); + CALC_ACC_INTERLEAVED1_Z(status[0]->accZ, data[1], data[0]); + break; + } +} + +static s16 __clamp(s16 x, s16 low, s16 high) +{ + s16 result = x; + + if (x < low) + result = low; + + if (x > high) + result = high; + + return result; +} + +static void __parse_fs_data(WPADChannel chan, WPADFSStatus **fsStatus, + u8 fsFormat __attribute__((unused)), byte_t *data, + u8 length __attribute__((unused))) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + fsStatus[0]->fsStickX = data[0]; + fsStatus[0]->fsStickY = data[1]; + + fsStatus[0]->fsAccX = MAKE_FS_ACC_X(p_wpd, data[2], data[5]); + fsStatus[0]->fsAccY = MAKE_FS_ACC_Y(p_wpd, data[3], data[5]); + fsStatus[0]->fsAccZ = MAKE_FS_ACC_Z(p_wpd, data[4], data[5]); + + CALC_FS_BUTTON(fsStatus[0]->button, data[5]); + + if (!p_wpd->calibrated) + { + p_wpd->calibrated = TRUE; + p_wpd->extConfig.fs.stickXCenter = fsStatus[0]->fsStickX; + p_wpd->extConfig.fs.stickYCenter = fsStatus[0]->fsStickY; + } + + CLAMP_FS_STICK_X(p_wpd, fsStatus[0]->fsStickX); + CLAMP_FS_STICK_Y(p_wpd, fsStatus[0]->fsStickY); +} + +static void __parse_cl_data(WPADChannel chan, WPADCLStatus **clStatus, + u8 clFormat, byte_t *data, u8 length) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + switch (clFormat) + { + case WPAD_DEV_MODE_CLASSIC_EXTENDED: + clStatus[0]->clLStickX = MAKE_CL_EXTENDED_STICK_LX(data[0], data[4]); + clStatus[0]->clRStickX = MAKE_CL_EXTENDED_STICK_RX(data[1], data[4]); + clStatus[0]->clLStickY = MAKE_CL_EXTENDED_STICK_LY(data[2], data[4]); + clStatus[0]->clRStickY = MAKE_CL_EXTENDED_STICK_RY(data[3], data[4]); + + clStatus[0]->clTriggerL = (u8)data[5]; + clStatus[0]->clTriggerR = length < 9 ? 0 : (u8)data[6]; + clStatus[0]->clButton = + length < 9 ? 0 : MAKE_CL_BUTTON(data[7], data[8]); + break; + + case WPAD_DEV_MODE_CLASSIC_STANDARD: + clStatus[0]->clLStickX = MAKE_CL_STANDARD_STICK_LX(data[0]); + clStatus[0]->clRStickX = MAKE_CL_STANDARD_STICK_RX(data[1]); + clStatus[0]->clLStickY = MAKE_CL_STANDARD_STICK_LY(data[2]); + clStatus[0]->clRStickY = MAKE_CL_STANDARD_STICK_RY(data[3]); + + clStatus[0]->clTriggerL = (u8)data[4]; + clStatus[0]->clTriggerR = (u8)data[5]; + clStatus[0]->clButton = + length < 8 ? 0 : MAKE_CL_BUTTON(data[6], data[7]); + break; + + default: + case WPAD_DEV_MODE_CLASSIC_REDUCED: + clStatus[0]->clLStickX = MAKE_CL_REDUCED_STICK_LX(data[0]); + clStatus[0]->clLStickY = MAKE_CL_REDUCED_STICK_LY(data[1]); + clStatus[0]->clRStickX = + MAKE_CL_REDUCED_STICK_RX(data[0], data[1], data[2]); + clStatus[0]->clRStickY = MAKE_CL_REDUCED_STICK_RY(data[2]); + + clStatus[0]->clTriggerL = MAKE_CL_REDUCED_TRIGGER_L(data[2], data[3]); + clStatus[0]->clTriggerR = MAKE_CL_REDUCED_TRIGGER_R(data[3]); + clStatus[0]->clButton = MAKE_CL_BUTTON(data[4], data[5]); + break; + } + + if (p_wpd->devType == WPAD_DEV_CLASSIC) + { + clStatus[0]->clLStickX -= (s16)512; + clStatus[0]->clLStickY -= (s16)512; + clStatus[0]->clRStickX -= (s16)512; + clStatus[0]->clRStickY -= (s16)512; + } + else if (p_wpd->devType != WPAD_DEV_TAIKO) + { + clStatus[0]->clLStickX -= (s16)512; + clStatus[0]->clLStickY -= (s16)512; + } + + if (!p_wpd->calibrated) + { + p_wpd->calibrated = TRUE; + + if (p_wpd->devType != WPAD_DEV_TAIKO) + { + p_wpd->extConfig.cl.lStickXCenter = clStatus[0]->clLStickX; + p_wpd->extConfig.cl.lStickYCenter = clStatus[0]->clLStickY; + } + else + { + p_wpd->extConfig.cl.lStickXCenter = 0; + p_wpd->extConfig.cl.lStickYCenter = 0; + } + + if (p_wpd->devType == WPAD_DEV_CLASSIC) + { + p_wpd->extConfig.cl.rStickXCenter = clStatus[0]->clRStickX; + p_wpd->extConfig.cl.rStickYCenter = clStatus[0]->clRStickY; + p_wpd->extConfig.cl.triggerLZero = clStatus[0]->clTriggerL; + p_wpd->extConfig.cl.triggerRZero = clStatus[0]->clTriggerR; + } + else + { + p_wpd->extConfig.cl.rStickXCenter = 0; + p_wpd->extConfig.cl.rStickYCenter = 0; + p_wpd->extConfig.cl.triggerLZero = 0; + p_wpd->extConfig.cl.triggerRZero = 0; + } + } + + if (p_wpd->devType != WPAD_DEV_TAIKO) + { + CLAMP_CL_STICK_LX(p_wpd, clStatus[0]->clLStickX, -512, 511); + CLAMP_CL_STICK_LY(p_wpd, clStatus[0]->clLStickY, -512, 511); + } + else + { + CLAMP_CL_STICK_LX(p_wpd, clStatus[0]->clLStickX, 0, 1024); + CLAMP_CL_STICK_LY(p_wpd, clStatus[0]->clLStickY, 0, 1024); + } + + if (p_wpd->devType == WPAD_DEV_CLASSIC) + { + CLAMP_CL_STICK_RX(p_wpd, clStatus[0]->clRStickX, -512, 511); + CLAMP_CL_STICK_RY(p_wpd, clStatus[0]->clRStickY, -512, 511); + + if (clStatus[0]->clTriggerL > 72) + clStatus[0]->clButton |= WPAD_BUTTON_CL_FULL_L; + + if (clStatus[0]->clTriggerR > 72) + clStatus[0]->clButton |= WPAD_BUTTON_CL_FULL_R; + + clStatus[0]->clTriggerL = 0; + clStatus[0]->clTriggerR = 0; + } + + if (_wpadCLCompt[chan]) + { + clStatus[0]->clRStickX = 0; + clStatus[0]->clRStickY = 0; + clStatus[0]->clTriggerL = 0; + clStatus[0]->clTriggerR = 0; + } +} + +static void __parse_bk_data(WPADChannel chan, WPADBKStatus **bkStatus, + u8 bkFormat __attribute__((unused)), byte_t *data, + u8 length) +{ + wpad_cb_st *p_wpd __attribute__((unused)) = __rvl_p_wpadcb[chan]; + + u16 i; + for (i = 0; i < length; i++) + bkStatus[0]->bulk[i] = data[i]; +} + +static void __parse_tr_data(WPADChannel chan __attribute__((unused)), + WPADTRStatus **trStatus, + u8 trFormat __attribute__((unused)), byte_t *data, + u8 length __attribute__((unused))) +{ + trStatus[0]->brake = data[2]; + trStatus[0]->mascon = data[3]; + trStatus[0]->trButton = MAKE_TR_BUTTON(data[6], data[7]); +} + +static void __parse_bl_data(WPADChannel chan, WPADBLStatus **blStatus, + u8 blFormat __attribute__((unused)), byte_t *data, + u8 length __attribute__((unused))) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + blStatus[0]->press[0] = MAKE_BL_WEIGHT_UL(data[0], data[1]); + blStatus[0]->press[1] = MAKE_BL_WEIGHT_UR(data[2], data[3]); + blStatus[0]->press[2] = MAKE_BL_WEIGHT_DL(data[4], data[5]); + blStatus[0]->press[3] = MAKE_BL_WEIGHT_DR(data[6], data[7]); + + blStatus[0]->temp = data[8]; + blStatus[0]->battery = (u8)data[10]; + + int battery = blStatus[0]->battery << 1; + + // what is this optimization??? x < n vs n >= x + if (battery >= 260) + p_wpd->blcBattery = 4; + else if (battery < 260 && battery >= 250) + p_wpd->blcBattery = 3; + else if (battery < 250 && battery >= 240) + p_wpd->blcBattery = 2; + else if (battery < 240 && battery >= 212) + p_wpd->blcBattery = 1; + else + p_wpd->blcBattery = 0; + + if (!p_wpd->calibrated) + p_wpd->calibrated = TRUE; +} + +static void __parse_vs_data(WPADChannel chan, WPADVSStatus **vsStatus, + u8 vsFormat __attribute__((unused)), byte_t *data, + u8 length __attribute__((unused))) +{ + +/* + +-------------------------------------------------------+ + | Bits | + +------+------+------+------+------+------+------+------+ + | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ++---+------+------+------+------+------+------+------+------+------+ +| | 0 | 0x40<7:0> | +| +------+-------------------------------------------------------+ +| | 1 | 0x36<9:2> | +| +------+-------------------------------------------------------+ +| | 2 | 0x38<9:2> | +| +------+-------------------------------------------------------+ +| | 3 | 0x3a<9:2> | +| +------+-------------------------------------------------------+ +| | 4 | 0x3c<9:2> | +| +------+-------------------------------------------------------+ +| | 5 | 0x3e<9:2> | +| +------+-------------+-------------+-------------+-------------+ +| | 6 | 0x36<1:0> | 0x38<1:0> | 0x3a<1:0> | 0x3c<1:0> | +| B +------+-------------+-------------+-------------+-------------+ +| y | 7 | 0x3e<1:0> | 0x42<9:4> | +| t +------+-------------+-----------------------------------------+ +| e | 8 | 0x34<7:0> | +| s +------+-------------------------------------------------------+ +| | 9 | 0x2a<9:2> | +| +------+-------------------------------------------------------+ +| | 10 | 0x2c<9:2> | +| +------+-------------------------------------------------------+ +| | 11 | 0x2e<9:2> | +| +------+-------------------------------------------------------+ +| | 12 | 0x30<9:2> | +| +------+-------------------------------------------------------+ +| | 13 | 0x32<9:2> | +| +------+-------------+-------------+-------------+-------------+ +| | 14 | 0x2a<1:0> | 0x2c<1:0> | 0x2e<1:0> | 0x30<1:0> | +| +------+-------------+-------------+-------------+-------------+ +| | 15 | 0x32<1:0> | 0x42<3:0> | 0x44<1:0> | ++---+------+-------------+---------------------------+-------------+ + +// likely a group of things +at_0x2a : 10; +at_0x2c : 10; +at_0x2e : 10; +at_0x30 : 10; +at_0x32 : 10; +at_0x34 : 8; + +// likely another instance of the above group of things +at_0x36 : 10; +at_0x38 : 10; +at_0x3a : 10; +at_0x3c : 10; +at_0x3e : 10; +at_0x40 : 8; + +// likely some other stuff +at_0x42 : 10; +at_0x44 : 2; // error code 255 if outside the range + +*/ + + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + vsStatus[0]->at_0x40 = data[0]; + vsStatus[0]->at_0x36[0] = MAKE_VS_SET_0(data[1], data[6]); + vsStatus[0]->at_0x36[1] = MAKE_VS_SET_1(data[2], data[6]); + vsStatus[0]->at_0x36[2] = MAKE_VS_SET_2(data[3], data[6]); + vsStatus[0]->at_0x36[3] = MAKE_VS_SET_3(data[4], data[6]); + vsStatus[0]->at_0x36[4] = MAKE_VS_SET_4(data[5], data[7]); + + vsStatus[0]->at_0x34 = data[8]; + vsStatus[0]->at_0x2a[0] = MAKE_VS_SET_0(data[9], data[14]); + vsStatus[0]->at_0x2a[1] = MAKE_VS_SET_1(data[10], data[14]); + vsStatus[0]->at_0x2a[2] = MAKE_VS_SET_2(data[11], data[14]); + vsStatus[0]->at_0x2a[3] = MAKE_VS_SET_3(data[12], data[14]); + vsStatus[0]->at_0x2a[4] = MAKE_VS_SET_4(data[13], data[15]); + + vsStatus[0]->at_0x42 = MAKE_VS_42(data[7], data[15]); + + if (p_wpd->unk_0xbbc < 8) + vsStatus[0]->at_0x44 = 255; + else + vsStatus[0]->at_0x44 = MAKE_VS_44(data[15]); +} + +static void __parse_mp_data(WPADChannel chan, WPADMPStatus **mpStatus, + u8 mpFormat, byte_t *data, + u8 length __attribute__((unused))) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + if (p_wpd->noParseMplsCount) + { + p_wpd->noParseMplsCount--; + mpStatus[0]->err = WPAD_EINVAL; + } + + if (mpStatus[0]->err != WPAD_ESUCCESS) + return; + + if (mpFormat == WPAD_DEV_MODE_MPLS_PT_MAIN) + { + if ((data[5] & 0x03) == 0x02) + { + mpStatus[0]->stat = MAKE_MP_MAIN_STAT(data[3], data[4]); + mpStatus[0]->pitch = MAKE_MP_MAIN_PITCH(data[5], data[2]); + mpStatus[0]->yaw = MAKE_MP_MAIN_YAW(data[3], data[0]); + mpStatus[0]->roll = MAKE_MP_MAIN_ROLL(data[4], data[1]); + } + else + { + mpStatus[0]->err = WPAD_EBADE; + } + } + else if (mpFormat == WPAD_DEV_MODE_MPLS_PT_FS + || mpFormat == WPAD_DEV_MODE_MPLS_PT_CLASSIC) + { + u8 bufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + WPADMPStatus *rxBuf = (WPADMPStatus *)(p_wpd->rxBufs[bufIndex]); + + if (data[5] & 0x01) + { + mpStatus[0]->stat = 0; + mpStatus[0]->err = WPAD_EBADE; + } + else if (!(data[5] & 0x02)) + { + mpStatus[0]->pitch = rxBuf->pitch; + mpStatus[0]->yaw = rxBuf->yaw; + mpStatus[0]->roll = rxBuf->roll; + mpStatus[0]->stat = rxBuf->stat; + + if ((data[0] == 0xff && data[1] == 0xff) || p_wpd->parseMPState != 5 + || (p_wpd->devType == WPAD_DEV_MPLS_PT_FS + && p_wpd->devMode != WPAD_DEV_MODE_MPLS_PT_FS) + || (p_wpd->devType == WPAD_DEV_MPLS_PT_CLASSIC + && p_wpd->devMode != WPAD_DEV_MODE_MPLS_PT_CLASSIC) + || p_wpd->devType == WPAD_DEV_MPLS_PT_UNKNOWN) + { + // ~WPAD_MPLS_STATUS_EXTENSION_DATA_VALID + mpStatus[0]->stat &= 0xbf; + } + else + { + CALC_MP_PT_EXT_STAT(mpStatus[0]->stat, data[4]); + + if (p_wpd->devType == WPAD_DEV_MPLS_PT_FS) + { + mpStatus[0]->ext.fs.fsStickX = data[0]; + mpStatus[0]->ext.fs.fsStickY = data[1]; + + mpStatus[0]->ext.fs.fsAccX = + MAKE_MP_FS_ACC_X(p_wpd, data[2], data[5]); + mpStatus[0]->ext.fs.fsAccY = + MAKE_MP_FS_ACC_Y(p_wpd, data[3], data[5]); + mpStatus[0]->ext.fs.fsAccZ = + MAKE_MP_FS_ACC_Z(p_wpd, data[4], data[5]); + + CALC_MP_FS_BUTTON(mpStatus[0]->button, data[5]); + + if (!p_wpd->calibrated) + { + p_wpd->calibrated = TRUE; + + p_wpd->extConfig.fs.stickXCenter = + mpStatus[0]->ext.fs.fsStickX; + p_wpd->extConfig.fs.stickYCenter = + mpStatus[0]->ext.fs.fsStickY; + } + + s16 fsStickXClampVal = (u8)mpStatus[0]->ext.fs.fsStickX + - (u8)p_wpd->extConfig.fs.stickXCenter; + s16 fsStickYClampVal = (u8)mpStatus[0]->ext.fs.fsStickY + - (u8)p_wpd->extConfig.fs.stickYCenter; + + if (fsStickXClampVal < -128) + mpStatus[0]->ext.fs.fsStickX = -128; + else if (127 < fsStickXClampVal) + mpStatus[0]->ext.fs.fsStickX = 127; + else + mpStatus[0]->ext.fs.fsStickX = fsStickXClampVal; + + if (fsStickYClampVal < -128) + { + mpStatus[0]->ext.fs.fsStickY = -128; + goto hack; + } + else if (127 < fsStickYClampVal) + { + mpStatus[0]->ext.fs.fsStickY = 127; + goto hack; + } + else + { + mpStatus[0]->ext.fs.fsStickY = fsStickYClampVal; + goto hack; + } + } + else if (p_wpd->devType == WPAD_DEV_MPLS_PT_CLASSIC) + { + mpStatus[0]->ext.cl.clLStickX = + MAKE_MP_CL_STICK_LX(data[0]); + mpStatus[0]->ext.cl.clLStickY = + MAKE_MP_CL_STICK_LY(data[1]); + mpStatus[0]->ext.cl.clRStickX = + MAKE_MP_CL_STICK_RX(data[0], data[1], data[2]); + mpStatus[0]->ext.cl.clRStickY = + MAKE_MP_CL_STICK_RY(data[2]); + mpStatus[0]->ext.cl.clTriggerL = + MAKE_MP_CL_TRIGGER_L(data[2], data[3]); + mpStatus[0]->ext.cl.clTriggerR = + MAKE_MP_CL_TRIGGER_R(data[3]); + mpStatus[0]->ext.cl.clButton = + MAKE_MP_CL_BUTTON(data[4], data[5], data[0], data[1]); + + mpStatus[0]->ext.cl.clLStickX -= (s16)0x200; + mpStatus[0]->ext.cl.clLStickY -= (s16)0x200; + mpStatus[0]->ext.cl.clRStickX -= (s16)0x200; + mpStatus[0]->ext.cl.clRStickY -= (s16)0x200; + + if (!p_wpd->calibrated) + { + p_wpd->calibrated = TRUE; + + p_wpd->extConfig.cl.lStickXCenter = + mpStatus[0]->ext.cl.clLStickX; + p_wpd->extConfig.cl.lStickYCenter = + mpStatus[0]->ext.cl.clLStickY; + p_wpd->extConfig.cl.rStickXCenter = + mpStatus[0]->ext.cl.clRStickX; + p_wpd->extConfig.cl.rStickYCenter = + mpStatus[0]->ext.cl.clRStickY; + p_wpd->extConfig.cl.triggerLZero = + mpStatus[0]->ext.cl.clTriggerL; + p_wpd->extConfig.cl.triggerRZero = + mpStatus[0]->ext.cl.clTriggerR; + } + + CLAMP_CL_STICK_LX(p_wpd, mpStatus[0]->ext.cl.clLStickX, + -512, 511); + CLAMP_CL_STICK_LY(p_wpd, mpStatus[0]->ext.cl.clLStickY, + -512, 511); + CLAMP_CL_STICK_RX(p_wpd, mpStatus[0]->ext.cl.clRStickX, + -512, 511); + CLAMP_CL_STICK_RY(p_wpd, mpStatus[0]->ext.cl.clRStickY, + -512, 511); + + if (mpStatus[0]->ext.cl.clTriggerL > 72) + mpStatus[0]->ext.cl.clButton |= WPAD_BUTTON_CL_FULL_L; + + if (mpStatus[0]->ext.cl.clTriggerR > 72) + mpStatus[0]->ext.cl.clButton |= WPAD_BUTTON_CL_FULL_R; + + mpStatus[0]->ext.cl.clTriggerL = 0; + mpStatus[0]->ext.cl.clTriggerR = 0; + } + } + } + else + { + mpStatus[0]->ext = rxBuf->ext; + CALC_MP_PT_MAIN_BUTTON(mpStatus[0]->button, rxBuf); + + mpStatus[0]->stat = MAKE_MP_PT_MAIN_STAT(data[3], data[4]); + if (mpStatus[0]->stat & WPAD_MPLS_STATUS_EXTENSION_CONNECTED) + RECALC_MP_PT_MAIN_STAT(mpStatus[0]->stat, rxBuf); + + mpStatus[0]->pitch = MAKE_MP_PT_MAIN_PITCH(data[5], data[2]); + mpStatus[0]->yaw = MAKE_MP_PT_MAIN_YAW(data[3], data[0]); + mpStatus[0]->roll = MAKE_MP_PT_MAIN_ROLL(data[4], data[1]); + } +hack:; // What + } + else + { + mpStatus[0]->err = WPAD_EBADE; + } + + if (mpStatus[0]->err != WPAD_ESUCCESS) + return; + + u8 hasReadExtType2 = p_wpd->hasReadExtType2; + + if (!(mpStatus[0]->stat & WPAD_MPLS_STATUS_EXTENSION_CONNECTED)) + { + if (p_wpd->parseMPState != 5) + hasReadExtType2 = FALSE; + + p_wpd->hasReadExtType2 = FALSE; + p_wpd->parseMPState = 0; + p_wpd->devType = WPAD_DEV_MOTION_PLUS; + + /* ~(WPAD_MPLS_STATUS_EXTENSION_DATA_VALID + * | WPAD_MPLS_STATUS_EXTENSION_CONNECTED) + */ + mpStatus[0]->stat &= 0xbe; + + if (hasReadExtType2 && p_wpd->extensionCB) + (*p_wpd->extensionCB)(chan, p_wpd->devType); + } + else if (!hasReadExtType2 && p_wpd->parseMPState == 0) + { + if (WPADiSendReadData(&p_wpd->extCmdQueue, p_wpd->wmReadDataBuf, 4, + WM_REG_EXTENSION_EXT_TYPE_2, NULL)) + { + p_wpd->hasReadExtType2 = TRUE; + p_wpd->parseMPState = 1; + } + } + + if (p_wpd->parseMPState == 2 || p_wpd->parseMPState == 9) + { + if (WPADiSendReadData(&p_wpd->extCmdQueue, p_wpd->wmReadDataBuf, 16, + WM_REG_EXTENSION_40, NULL)) + { + p_wpd->parseMPState++; + } + } + else if (p_wpd->parseMPState == 4) + { + p_wpd->parseMPState = 5; + + switch (_wpadDevType2[chan]) + { + case 0: + p_wpd->devType = WPAD_DEV_MPLS_PT_FS; + break; + + case 1: + p_wpd->devType = WPAD_DEV_MPLS_PT_CLASSIC; + break; + + case 3: + if (__OSInIPL) + p_wpd->devType = WPAD_DEV_MPLS_PT_CLASSIC; + else + p_wpd->devType = WPAD_DEV_MPLS_PT_UNKNOWN; + + break; + + default: + p_wpd->devType = WPAD_DEV_MPLS_PT_UNKNOWN; + break; + } + + if (p_wpd->extensionCB) + (*p_wpd->extensionCB)(chan, p_wpd->devType); + } + else if (p_wpd->parseMPState == 6) + { + if (WPADiIsAvailableCmdQueue(&p_wpd->extCmdQueue, 2)) + { + WPADiSendWriteDataCmd(&p_wpd->extCmdQueue, 0x01, + WM_REG_EXTENSION_F3, NULL); + WPADiSendReadData(&p_wpd->extCmdQueue, &p_wpd->parseMPBuf, 1, + WM_REG_EXTENSION_F3, NULL); + + p_wpd->parseMPState = 7; + } + } +} + +static void __parse_ext_data(WPADChannel chan, void *parseBuf, + u8 extFormat __attribute__((unused)), byte_t *data, + u8 length) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = parseBuf; + + if (p_wpd->extErr == WPAD_ENODEV) + { + p_wpd->extErr = status->err; + p_wpd->extDevType = p_wpd->devType; + p_wpd->extDataLength = length; + + memcpy(p_wpd->extDataBuf, data, length); + } + + if (status->err == WPAD_ESUCCESS) + { + if (memcmp(data, _cExtInvalidData2, length) == 0) + { + status->err = WPAD_EINVAL; + } + else if (memcmp(data, _cExtInvalidData, length) == 0) + { + status->err = WPAD_EBADE; + p_wpd->noParseExtCount = 3; + } + else if (!p_wpd->wpInfo.attach) + { + status->err = WPAD_EBADE; + p_wpd->noParseExtCount = 3; + } + else if (p_wpd->noParseExtCount) + { + status->err = WPAD_EBADE; + p_wpd->noParseExtCount--; + } + } + + if (p_wpd->extErr == WPAD_ESUCCESS && status->err == WPAD_EBADE) + p_wpd->extErr = WPAD_EBADE; + + if (p_wpd->extDevType != p_wpd->devType) + p_wpd->extErr = WPAD_EINVAL; + + if (p_wpd->extErr == WPAD_ESUCCESS) + { + p_wpd->noParseExtCount = 0; + + WPADiDecode(chan, p_wpd->extDataBuf, p_wpd->extDataLength, 0); + + if (p_wpd->devType == WPAD_DEV_FS) + { + __parse_fs_data(chan, (WPADFSStatus **)&parseBuf, p_wpd->devMode, + p_wpd->extDataBuf, p_wpd->extDataLength); + } + else if (p_wpd->devType == WPAD_DEV_CLASSIC + || p_wpd->devType == WPAD_DEV_GUITAR + || p_wpd->devType == WPAD_DEV_DRUM + || p_wpd->devType == WPAD_DEV_TURNTABLE + || p_wpd->devType == WPAD_DEV_TAIKO) + + { + __parse_cl_data(chan, (WPADCLStatus **)&parseBuf, p_wpd->devMode, + p_wpd->extDataBuf, p_wpd->extDataLength); + } + else if (p_wpd->devType == WPAD_DEV_BULK_1 + || p_wpd->devType == WPAD_DEV_BULK_2 + || p_wpd->devType == WPAD_DEV_BULK_3 + || p_wpd->devType == WPAD_DEV_BULK_4 + || p_wpd->devType == WPAD_DEV_BULK_5 + || p_wpd->devType == WPAD_DEV_BULK_6 + || p_wpd->devType == WPAD_DEV_BULK_7 + || p_wpd->devType == WPAD_DEV_BULK_8) + { + __parse_bk_data(chan, (WPADBKStatus **)&parseBuf, p_wpd->devMode, + p_wpd->extDataBuf, p_wpd->extDataLength); + } + else if (p_wpd->devType == WPAD_DEV_TRAIN) + { + __parse_tr_data(chan, (WPADTRStatus **)&parseBuf, p_wpd->devMode, + p_wpd->extDataBuf, p_wpd->extDataLength); + } + else if (p_wpd->devType == WPAD_DEV_BALANCE_CHECKER) + { + __parse_bl_data(chan, (WPADBLStatus **)&parseBuf, p_wpd->devMode, + p_wpd->extDataBuf, p_wpd->extDataLength); + } + else if (p_wpd->devType == WPAD_DEV_VSM) + { + // note the use of dataFormat instead of devMode here + __parse_vs_data(chan, (WPADVSStatus **)&parseBuf, p_wpd->dataFormat, + p_wpd->extDataBuf, p_wpd->extDataLength); + } + else if (p_wpd->devType == WPAD_DEV_MOTION_PLUS + || p_wpd->devType == WPAD_DEV_MPLS_PT_FS + || p_wpd->devType == WPAD_DEV_MPLS_PT_CLASSIC + || p_wpd->devType == WPAD_DEV_MPLS_PT_UNKNOWN) + { + __parse_mp_data(chan, (WPADMPStatus **)&parseBuf, p_wpd->devMode, + p_wpd->extDataBuf, p_wpd->extDataLength); + } + } + + s8 tempErr = status->err; + status->err = p_wpd->extErr; + p_wpd->extErr = tempErr; + + p_wpd->extDevType = p_wpd->devType; + p_wpd->extDataLength = length; + + memcpy(p_wpd->extDataBuf, data, length); +} + +static void __a1_30_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); +} + +static void __a1_31_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); + __parse_acc_data(chan, &status, ACC_FORMAT_STANDARD, + &hidReport[RPT_ACC_OFFSET], 0); +} + +static void __a1_32_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); + __parse_ext_data(chan, rxBuffer, p_wpd->devMode, + &hidReport[RPT32_EXT_OFFSET], RPT32_EXT_LENGTH); +} + +static void __a1_33_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); + __parse_acc_data(chan, &status, ACC_FORMAT_STANDARD, + &hidReport[RPT_ACC_OFFSET], 0); + __parse_dpd_data(chan, &status, p_wpd->currentDpdCommand, + &hidReport[RPT33_DPD_OFFSET], RPT33_DPD_LENGTH); +} + +static void __a1_34_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); + __parse_ext_data(chan, rxBuffer, p_wpd->devMode, + &hidReport[RPT34_EXT_OFFSET], RPT34_EXT_LENGTH); +} + +static void __a1_35_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); + __parse_acc_data(chan, &status, ACC_FORMAT_STANDARD, + &hidReport[RPT_ACC_OFFSET], 0); + __parse_ext_data(chan, rxBuffer, p_wpd->devMode, + &hidReport[RPT35_EXT_OFFSET], RPT35_EXT_LENGTH); +} + +static void __a1_36_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); + __parse_dpd_data(chan, &status, p_wpd->currentDpdCommand, + &hidReport[RPT36_DPD_OFFSET], RPT36_DPD_LENGTH); + __parse_ext_data(chan, rxBuffer, p_wpd->devMode, + &hidReport[RPT36_EXT_OFFSET], RPT36_EXT_LENGTH); +} + +static void __a1_37_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + __parse_btn_data(p_wpd, status, BTN_FORMAT_STANDARD, hidReport, 0); + __parse_acc_data(chan, &status, ACC_FORMAT_STANDARD, + &hidReport[RPT_ACC_OFFSET], 0); + __parse_dpd_data(chan, &status, p_wpd->currentDpdCommand, + &hidReport[RPT37_DPD_OFFSET], RPT37_DPD_LENGTH); + __parse_ext_data(chan, rxBuffer, p_wpd->devMode, + &hidReport[RPT37_EXT_OFFSET], RPT37_EXT_LENGTH); +} + +static void __a1_3d_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status __attribute__((unused)) = rxBuffer; + + __parse_ext_data(chan, rxBuffer, p_wpd->devMode, + &hidReport[RPT3D_EXT_OFFSET], RPT3D_EXT_LENGTH); +} + +static void __a1_3e_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + if (p_wpd->interleaveFlags == WPAD_ILBUF_NONE) + memset(rxBuffer, 0, RX_BUFFER_SIZE); + + __parse_btn_data(p_wpd, status, BTN_FORMAT_INTERLEAVED, hidReport, 0); + __parse_acc_data(chan, &status, ACC_FORMAT_INTERLEAVED0, + &hidReport[RPT_ACC_OFFSET], 0); + __parse_dpdex_data(chan, (WPADStatusEx **)&rxBuffer, RPT3E_DPD0, + &hidReport[RPT3E_DPD0_OFFSET], 0); + __parse_dpdex_data(chan, (WPADStatusEx **)&rxBuffer, RPT3E_DPD1, + &hidReport[RPT3E_DPD1_OFFSET], 0); + + BOOL intrStatus = OSDisableInterrupts(); + + p_wpd->interleaveFlags |= WPAD_ILBUF_BUF3E; + if (p_wpd->interleaveFlags == WPAD_ILBUF_ALL) + { + status->accZ -= (s16)p_wpd->devConfig.accZ0g; + p_wpd->rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + p_wpd->interleaveFlags = WPAD_ILBUF_NONE; + } + + OSRestoreInterrupts(intrStatus); +} + +static void __a1_3f_data_type(u8 chan, byte_t *hidReport, void *rxBuffer) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + WPADStatus *status = rxBuffer; + + if (p_wpd->interleaveFlags == WPAD_ILBUF_NONE) + memset(rxBuffer, 0, RX_BUFFER_SIZE); + + __parse_btn_data(p_wpd, status, BTN_FORMAT_INTERLEAVED, hidReport, 0); + __parse_acc_data(chan, &status, ACC_FORMAT_INTERLEAVED1, + &hidReport[RPT_ACC_OFFSET], 0); + __parse_dpdex_data(chan, (WPADStatusEx **)&rxBuffer, RPT3F_DPD2, + &hidReport[RPT3F_DPD2_OFFSET], 0); + __parse_dpdex_data(chan, (WPADStatusEx **)&rxBuffer, RPT3F_DPD3, + &hidReport[RPT3F_DPD3_OFFSET], 0); + + BOOL intrStatus = OSDisableInterrupts(); + + p_wpd->interleaveFlags |= WPAD_ILBUF_BUF3F; + if (p_wpd->interleaveFlags == WPAD_ILBUF_ALL) + { + status->accZ -= (s16)p_wpd->devConfig.accZ0g; + p_wpd->rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; + p_wpd->interleaveFlags = WPAD_ILBUF_NONE; + } + + OSRestoreInterrupts(intrStatus); +} + +static void __a1_unused_report(u8 chan __attribute__((unused)), + byte_t *hidReport __attribute__((unused)), + void *rxBuffer __attribute__((unused))) +{ + return; +} + +static void __wpadCertReset(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->certValidityStatus = WPAD_CERT_UNCHECKED; + p_wpd->certWorkBusy = FALSE; + p_wpd->certChallengeRandomBit = -1; + p_wpd->certState = WPAD_STATE_CERT_INVALID; + p_wpd->certStateWorkMs = 0; + p_wpd->certWorkCounter = 0; + p_wpd->certWorkMs = 0; + + memset(p_wpd->certBuf0, 0, sizeof p_wpd->certBuf0); + memset(p_wpd->certBuf1, 0, sizeof p_wpd->certBuf1); + memset(p_wpd->certBufBig, 0, sizeof p_wpd->certBufBig); + p_wpd->certBuf0[0] = p_wpd->certBuf1[0] = p_wpd->certBufBig[0] = 1; + + p_wpd->wmParamOffset = 0; +} diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPADHIDParser.h b/src/sdk/RVL_SDK/revolution/wpad/WPADHIDParser.h new file mode 100644 index 00000000..004b41e5 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPADHIDParser.h @@ -0,0 +1,223 @@ +#ifndef RVL_SDK_WPAD_INTERNAL_WPAD_HID_PARSER_H +#define RVL_SDK_WPAD_INTERNAL_WPAD_HID_PARSER_H + +/* no public header */ + +/******************************************************************************* + * headers + */ + +#include "context_bte.h" // UINT8 + +/******************************************************************************* + * macros + */ + +// a bunch of constants + +#define RPT_REPORT_ID 0 +#define RPT_MAX_SIZE 21 + +// Limits +#define RPTID_OUT_LO RPTID_SET_RUMBLE +#define RPTID_OUT_HI RPTID_SET_DPD_CSB + +#define RPTID_IN_LO RPTID_STATUS +#define RPTID_IN_HI RPTID_DATA_BTN_ACC_DPD18_2 + +// All outgoing reports +#define RPT_OUT_FLAGS 1 + +#define RPT_OUT_FLAG_ENABLE_FEATURE 2 +#define RPT_OUT_FLAG_REQUEST_ACK_RPT 1 +#define RPT_OUT_FLAG_RUMBLE 0 + +// All incoming reports with Button data (all except 0x3d) +#define RPT_BTN0 1 +#define RPT_BTN1 2 + +// All incoming reports with Accelerometer (Standard) data (0x31, 0x33, 0x35, 0x37) +#define RPT_ACC_OFFSET 1 +#define RPT_ACC_SIZE 3 + +/* + * Outgoing reports (from POV of the host) + */ + +// Report 0x10: Set rumble status +#define RPTID_SET_RUMBLE 0x10 +#define RPT10_SIZE 1 + +#define RPT10_RUMBLE 0 + +// Report 0x11: Set LED lights +#define RPTID_SET_PORT 0x11 // internally called SetPort +#define RPT11_SIZE 1 + +#define RPT11_LED 0 + +// Report 0x12: Set data reporting mode +#define RPTID_SET_DATA_REPORT_MODE 0x12 +#define RPT12_SIZE 2 + +#define RPT12_CONT_REPORT 0 +#define RPT12_DATA_REPORT_MODE 1 + +// Report 0x13: Enable IR camera +#define RPTID_ENABLE_DPD 0x13 // internally called the DPD +#define RPT13_SIZE 1 + +#define RPT13_DPD_ENABLE 0 + +// Report 0x14: Enable IR camera +#define RPTID_ENABLE_SPEAKER 0x14 +#define RPT14_SIZE 1 + +#define RPT14_SPEAKER_ENABLE 0 + +// Report 0x15: Request status report +#define RPTID_REQUEST_STATUS 0x15 +#define RPT15_SIZE 1 + +// Report 0x16: Write data +#define RPTID_WRITE_DATA 0x16 +#define RPT16_SIZE RPT_MAX_SIZE + +#define RPT16_DATA_DST_ADDRESS 0 +#define RPT16_DATA_LENGTH 4 +#define RPT16_DATA 5 + +// Report 0x17: Read data +#define RPTID_READ_DATA 0x17 +#define RPT17_SIZE 6 + +#define RPT17_DATA_SRC_ADDRESS 0 +#define RPT17_DATA_LENGTH 4 + +// Report 0x18: Send speaker data +#define RPTID_SEND_SPEAKER_DATA 0x18 +#define RPT18_SIZE RPT_MAX_SIZE + +#define RPT18_DATA_LENGTH 0 +#define RPT18_DATA 1 + +// Report 0x19: Mute speaker +#define RPTID_MUTE_SPEAKER 0x19 +#define RPT19_SIZE 1 + +#define RPT19_SPEAKER_MUTE 0 + +// Report 0x19: WPADiSendDPDCSB (?) +#define RPTID_SEND_DPD_CSB 0x1a +#define RPT1A_SIZE 1 + +#define RPT1A_DPD_CSB 0 + +/* + * Incoming reports (from POV of the host) + */ + +// Report 0x20: Status report +#define RPTID_STATUS 0x20 +#define RPT20_FLAGS 3 +#define RPT20_PROTO_FW 5 +#define RPT20_BATTERY 6 + +// Report 0x21: Read Wiimote data +#define RPTID_DATA_READ 0x21 +#define RPT21_SIZE_ERR 3 +#define RPT21_ADDR0 4 +#define RPT21_ADDR1 5 +#define RPT21_DATA 6 + +// Report 0x22: Acknowledgement and request result +#define RPTID_ACK 0x22 +#define RPT22_ACKED_RPT_ID 3 +#define RPT22_ERR_CODE 4 + +// Reports 0x23-0x2f: Unused + +// Report 0x30: Buttons +#define RPTID_DATA_BTN 0x30 + +// Report 0x31: Buttons, Accelerometer (Standard) +#define RPTID_DATA_BTN_ACC 0x31 + +// Report 0x32: Buttons, Extension (8 bytes) +#define RPTID_DATA_BTN_EXT8 0x32 +#define RPT32_EXT_OFFSET 3 +#define RPT32_EXT_LENGTH 8 + +/* Report 0x33: Buttons, Accelerometer (Standard), IR Camera (Standard, 12 + * bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD12 0x33 +#define RPT33_DPD_OFFSET 6 +#define RPT33_DPD_LENGTH 12 + +// Report 0x34: Buttons, Extension (19 bytes) +#define RPTID_DATA_BTN_EXT19 0x34 +#define RPT34_EXT_OFFSET 3 +#define RPT34_EXT_LENGTH 19 + +// Report 0x35: Buttons, Accelerometer (Standard), Extension (16 bytes) +#define RPTID_DATA_BTN_ACC_EXT16 0x35 +#define RPT35_EXT_OFFSET 6 +#define RPT35_EXT_LENGTH 16 + +// Report 0x36: Buttons, IR Camera (Basic, 10 bytes), Extension (9 bytes) +#define RPTID_DATA_BTN_DPD10_EXT9 0x36 +#define RPT36_DPD_OFFSET 3 +#define RPT36_DPD_LENGTH 10 +#define RPT36_EXT_OFFSET 13 +#define RPT36_EXT_LENGTH 9 + +/* Report 0x37: Buttons, Accelerometer (Standard), IR Camera (Basic, 10 + * bytes), Extension (6 bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD10_EXT9 0x37 +#define RPT37_DPD_OFFSET 6 +#define RPT37_DPD_LENGTH 10 +#define RPT37_EXT_OFFSET 16 +#define RPT37_EXT_LENGTH 6 + +// Report 0x38-0x3c: Unused + +// Report 0x3d: Extension (21 bytes) +#define RPTID_DATA_EXT21 0x3d +#define RPT3D_EXT_OFFSET 1 +#define RPT3D_EXT_LENGTH 21 + +/* Report 0x3e: Buttons, Accelerometer (Interleaved 1), IR Camera (Full 1, + * 18 bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD18_1 0x3e +#define RPT3E_DPD0 0 +#define RPT3E_DPD0_OFFSET 4 +#define RPT3E_DPD1 1 +#define RPT3E_DPD1_OFFSET 13 + +/* Report 0x3e: Buttons, Accelerometer (Interleaved 2), IR Camera (Full 2, + * 18 bytes) + */ +#define RPTID_DATA_BTN_ACC_DPD18_2 0x3f +#define RPT3F_DPD2 2 +#define RPT3F_DPD2_OFFSET 4 +#define RPT3F_DPD3 3 +#define RPT3F_DPD3_OFFSET 13 + +/******************************************************************************* + * functions + */ + +#ifdef __cplusplus + extern "C" { +#endif + +signed WPADiHIDParser(UINT8 port, UINT8 *p_rpt); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_INTERNAL_WPAD_HID_PARSER_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPADMem.c b/src/sdk/RVL_SDK/revolution/wpad/WPADMem.c new file mode 100644 index 00000000..57588cf9 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPADMem.c @@ -0,0 +1,71 @@ +#include +#include "WPADMem.h" + +/******************************************************************************* + * headers + */ + +#include + +#include "WPAD.h" + +#if 0 +#include +#endif + +#include "context_rvl.h" + +/******************************************************************************* + * functions + */ + +void WPADiClearMemBlock(WPADChannel chan) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + p_wpd->memBlock.at_0x00 = 0; + p_wpd->memBlock.at_0x04 = 0; + p_wpd->memBlock.at_0x08 = 0; + p_wpd->memBlock.at_0x0c = 0; + p_wpd->memBlock.at_0x10 = NULL; +} + +WPADResult WPADWriteExtReg(WPADChannel chan, const void *data, u16 length, + WPADExtRegType extReg, u16 address, WPADCallback *cb) +{ + wpad_cb_st *p_wpd = __rvl_p_wpadcb[chan]; + + BOOL success; + BOOL intrStatus; + BOOL handshakeFinished; + + WPADResult status = WPAD_ESUCCESS; + + intrStatus = OSDisableInterrupts(); + + status = p_wpd->status; + handshakeFinished = p_wpd->handshakeFinished; + + OSRestoreInterrupts(intrStatus); + + if (status == WPAD_ENODEV) + goto end; + + if (!handshakeFinished) + { + status = WPAD_ECOMM; + goto end; + } + + u32 finalAddress = (address & 0xffff) | (extReg << 16) | (1 << 26); + + success = + WPADiSendWriteData(&p_wpd->stdCmdQueue, data, length, finalAddress, cb); + status = success ? WPAD_CESUCCESS : WPAD_CECOMM; + +end: + if (status != WPAD_ESUCCESS && cb) + (*cb)(chan, status); + + return status; +} diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPADMem.h b/src/sdk/RVL_SDK/revolution/wpad/WPADMem.h new file mode 100644 index 00000000..e62a57d7 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPADMem.h @@ -0,0 +1,66 @@ +#ifndef RVL_SDK_WPAD_MEMORY_H +#define RVL_SDK_WPAD_MEMORY_H + +/******************************************************************************* + * headers + */ + +#include + +#include "WPAD.h" + +#include + +/******************************************************************************* + * macros + */ + +#define WM_MEM_ADDR(addr_) ((addr_) & 0xffff) +#define WM_EXT_REG_ADDR(type_, addr_) \ + (((addr_) & 0xffff) | ((WPAD_EXT_REG_ ## type_) << 16) | (1 << 26)) + +/******************************************************************************* + * types + */ + +#ifdef __cplusplus + extern "C" { +#endif + +typedef u8 WPADExtRegType; +enum WPADExtRegType_et +{ + WPAD_EXT_REG_SPEAKER = 0xa2, + WPAD_EXT_REG_EXTENSION = 0xa4, + WPAD_EXT_REG_MOTION_PLUS = 0xa6, + WPAD_EXT_REG_DPD = 0xb0, +}; + +// https://wiibrew.org/wiki/Wiimote#EEPROM_Memory +typedef struct WPADGameInfo +{ + OSTime timestamp; // size 0x08, offset 0x00 + u16 gameName[17]; // size 0x22, offset 0x08 + char gameID[4]; // size 0x04, offset 0x2a + u8 gameType; // size 0x01, offset 0x2e + u8 checksum; // size 0x01, offset 0x2f + + /* wiibrew says this exists in the header on the Wiimote but goes unused, + * which matches up with the code I see here + */ + byte_t unknown[8]; +} WPADGameInfo; // size 0x38 + +/******************************************************************************* + * functions + */ + +WPADResult WPADWriteExtReg(WPADChannel chan, const void *data, u16 length, + WPADExtRegType extReg, u16 address, + WPADCallback *cb); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_MEMORY_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/WPADMem2.h b/src/sdk/RVL_SDK/revolution/wpad/WPADMem2.h new file mode 100644 index 00000000..90691dcb --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WPADMem2.h @@ -0,0 +1,40 @@ +#ifndef RVL_SDK_WPAD_INTERNAL_MEMORY_H +#define RVL_SDK_WPAD_INTERNAL_MEMORY_H + +#include + +/******************************************************************************* + * headers + */ + +#include // WPADChannel + +/******************************************************************************* + * types + */ + +#ifdef __cplusplus + extern "C" { +#endif + +struct WPADMemBlock +{ + int signed at_0x00; // size 0x04, offset 0x00 + int signed at_0x04; // size 0x04, offset 0x04 + short signed at_0x08; // size 0x02, offset 0x08 + // 2 bytes padding (probably alignment, see WPADiClearMemBlock) + int signed at_0x0c; // size 0x04, offset 0x0c + WPADCallback *at_0x10; // size 0x04, offset 0x10 +}; // size 0x14 + +/******************************************************************************* + * functions + */ + +void WPADiClearMemBlock(WPADChannel chan); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_INTERNAL_MEMORY_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/WUD.c b/src/sdk/RVL_SDK/revolution/wpad/WUD.c new file mode 100644 index 00000000..b221be33 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WUD.c @@ -0,0 +1,4120 @@ +#include +#include "WUD.h" + +/* References: + * Bluetooth Assigned Numbers + * [1] https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Assigned_Numbers/out/en/Assigned_Numbers.pdf + */ + +/******************************************************************************* + * headers + */ + +#include + +#include +#include + +#include "WUDHidHost.h" // WUDiHidHostEventCallback + + +#include // OSSwitchFiberEx +#include +#include +#include +#include +#include +#include +#include + +#include "context_bte.h" + +/******************************************************************************* + * macros + */ + +// misspellings +#define __wudPowerManageEventStackCallback __wudPowerMangeEventStackCallback + +// Wii Fit callback things +#define WII_FIT_TITLE_ID "RFNJ" +#define RP_HEALTH_FILE_PATH "/title/00010004/52464e4a/data/RPHealth.dat" + +#define RP_HEALTH_FILE_OFFSET 0x4af18 // TODO: what is at this offset? +#define RP_HEALTH_FILE_WRITE_SIZE ((int)(128 + sizeof(u32))) // u32 crc; + +// VSC opcodes +#define BT_VSC_NINTENDO_SUPER_PEEK_POKE 0xFC0A +#define BT_VSC_NINTENDO_WRITE_PATCH 0xFC4C +#define BT_VSC_NINTENDO_INSTALL_PATCH 0xFC4F + +#define INSTALL_PATCH_SIZE 13 +#define INSTALL_PATCH_TOTAL_SIZE(count_) (INSTALL_PATCH_SIZE * (count_)) +// highest value of x where INSTALL_PATCH_TOTAL_SIZE(x) <= 256 +#define INSTALL_PATCH_MAX_NUM 19 +#define INSTALL_PATCH_MAX_BUF INSTALL_PATCH_TOTAL_SIZE(INSTALL_PATCH_MAX_NUM) + +// ? +#if defined(NDEBUG) +# define DEV_HANDLE_BOUNDS_CHECK(val_) ((UINT8)(val_) <= WUD_MAX_DEV_ENTRY - 1) +#else +# define DEV_HANDLE_BOUNDS_CHECK(val_) (0 <= (val_) && (val_) < WUD_MAX_DEV_ENTRY) +#endif // defined(NDEBUG) + +/******************************************************************************* + * types + */ + +typedef WUDState WUDNandState; +enum WUDNandState_et +{ + WUD_STATE_NAND_OPEN = 1, + WUD_STATE_NAND_SEEK = 2, + WUD_STATE_NAND_READ = 3, + WUD_STATE_NAND_GET_DEV_INFO = 4, + WUD_STATE_NAND_CLOSE = 5, + WUD_STATE_NAND_DONE = 6, +}; + +struct wud_patch_install_cmd_array +{ + u8 num; + byte_t installCmds[/* num */][INSTALL_PATCH_SIZE]; +}; + +struct wud_discovery_response +{ + BD_ADDR devAddr; // size 0x06, offset 0x000 + char at_0x006[64]; // size 0x40, offset 0x006 + byte_t __pad0[0xba]; + tBTA_SERVICE_MASK services; // size 0x04, offset 0x100 + byte_t __pad1[0x04]; // alignment? +}; // size 0x108 + +struct wud_nand_wbc_info +{ + SCBtDeviceInfo scDevInfo; // size 0x46, offset 0x00 + byte_t __pad0[0x5a]; +}; // size 0xa0 + +/******************************************************************************* + * local function declarations + */ + +// GKI callout functions +extern void *App_MEMalloc(size_t size); +extern int App_MEMfree(void *ptr); + +// --- + +static void __wudReverseAddr(BD_ADDR_PTR dst, BD_ADDR src); +static signed __wudSetPinCode(BD_ADDR dev_addr); +static void __wudClearDiscoverResult(void); +static BOOL __wudIsBusyLinkKeyCmd(void); +static BOOL __wudIsBusyScCmd(void); +static void __wudPrepareWBCDevInfo(BD_ADDR dev_addr, LINK_KEY link_key, void *); +static void __wudSyncFlushCallback(SCStatus result); +static WUDSyncState __wudSyncPrepareSearch(void); +static WUDSyncState __wudSyncWaitForStartSearch(void); +static WUDSyncState __wudSyncStartSearch(void); +static WUDSyncState __wudSyncWaitForSearchResult(void); +static WUDSyncState __wudSyncCheckSearchResult(void); +static WUDSyncState __wudSyncWaitForIncoming(void); +static WUDSyncState __wudSyncIsExistedDevice(void); +static WUDSyncState __wudSyncPrepareForExistedDevice(void); +static WUDSyncState __wudSyncPrepareForUnknownDevice(void); +static WUDSyncState __wudSyncTryConnect(void); +static WUDSyncState __wudSyncRegisterDevice(void); +static WUDSyncState __wudSyncVirginSimple(void); +static WUDSyncState __wudSyncVirginStandard(void); +static WUDSyncState __wudSyncChangeSmp2Std(void); +static WUDSyncState __wudSyncStoredLinkKeyToE2prom(void); +static WUDSyncState __wudSyncWaitForStoring(void); +static WUDSyncState __wudSyncStoredDevInfoToNand(void); +static void __wudOpenWiiFitCallback(NANDResult result, + NANDCommandBlock *cmdBlock); +static void __wudOpenWiiFitFile(void); +static void __wudSeekWiiFitCallback(NANDResult result, + NANDCommandBlock *cmdBlock); +static void __wudSeekWiiFitFile(void); +static void __wudUpdateWiiFitCallback(NANDResult result, + NANDCommandBlock *cmdBlock); +static void __wudUpdateWiiFitFile(void); +static void __wudCloseWiiFitCallback(NANDResult result, + NANDCommandBlock *cmdBlock); +static void __wudCloseWiiFit(void); +static void __wudSyncScFlush(void); +static WUDSyncState __wudSyncWaitForReading(void); +static WUDSyncState __wudSyncComplete(void); +static WUDSyncState __wudSyncError(void); +static WUDSyncState __wudSyncDone(void); +static void __wudSyncHandler(void); +static void __wudSyncHandler0(OSAlarm *alarm, OSContext *context); +static void __wudDeleteFlushCallback(SCStatus result); +static WUDDeleteState __wudDeleteDisallowIncoming(void); +static WUDDeleteState __wudDeleteDisconnectAll(void); +static WUDDeleteState __wudDeleteCleanupDatabase(void); +static void __wudDeleteCleanupSetting(void); +static WUDDeleteState __wudDeleteDone(void); +static void __wudDeleteHandler(void); +static void __wudDeleteHandler0(OSAlarm *alarm, OSContext *context); +static WUDStackState __wudStackGetStoredLinkKey(void); +static WUDStackState __wudStackCheckDeviceInfo(void); +static WUDStackState __wudStackDone(void); +static void __wudStackHandler(void); +static void __wudStackHandler0(OSAlarm *alarm, OSContext *context); +static void __wudInitFlushCallback(SCStatus result); +static WUDInitState __wudInitWaitForDeviceUp(void); +static WUDInitState __wudInitWaitForInitialization(void); +static BOOL __wudIsExistedDevice(BD_ADDR dev_addr); +static WUDInitState __wudInitDevInfo(void); +static WUDInitState __wudInitDone(void); +static void __wudNandResultCallback(NANDResult result, NANDCommandBlock *block); +static void __wudNandFlushCallback(SCStatus result); +static u32 __wudCalcWiiFitCrc1(void *data, u32 length); +static u32 __wudCalcWiiFitCrc2(void *data, u32 length, u32 crc); +static WUDInitState __wudGetDevInfoFromWiiFit(void); +static void __wudInitHandler(void); +static void __wudInitHandler0(OSAlarm *alarm, OSContext *context); +static void __wudShutdownFlushCallback(SCStatus result); +static void __wudShutdownStoreSetting(void); +static void __wudShutdownDone(void); +static void __wudShutdownHandler(void); +static void __wudShutdownHandler0(OSAlarm *alarm, OSContext *context); +static void __wudClearControlBlock(void); + +static BOOL __wudStartSyncDevice(WUDSyncType syncType, s8 syncLopNum, u8 target, + signed); +static BOOL __wudStartSyncStandard(signed); +static BOOL __wudStartSyncSimple(signed); + +static BOOL __wudStopSyncDevice(void); + +static void __wudModuleRebootCallback(void *p1); +static void __wudModuleReboot(void); +static void __wudInstallPatchCallback(tBTM_VSC_CMPL *p1); +static void __wudInstallPatch(void); +static void __wudWritePatchCallback(tBTM_VSC_CMPL *p1); +static void __wudWritePatch(void); +static void __wudRemovePatchCallback(tBTM_VSC_CMPL *p1); +static void __wudRemovePatch(void); +static void __wudSuperPeekPokeCallback(tBTM_VSC_CMPL *p1); +static void __wudSuperPeekPoke(void); +static void __wudAppendRuntimePatch(void); +static void __wudCheckFirmwareVersion(void); +static void __wudInitSub(void); +static void __wudEnableStack(void); +static void __wudProcSyncEvent(void); +static void __wudProcDeleteEvent(void); + +static WUDDevInfo *__wudGetDevInfoByIndex(int index); +static WUDDevInfo *__wudGetNewStdDevInfo(void); +static WUDDevInfo *__wudGetNewSmpDevInfo(void); +static WUDDevInfo *__wudGetNewDevInfo(void); +static void __wudRemoveDevInfo(BD_ADDR dev_addr); +static void __wudClearDevInfos(void); +static u8 __wudGetStdDevNumber(void); +static u8 __wudGetSmpDevNumber(void); +static u8 __wudGetConnectionNumber(void); +static u8 __wudGetLinkNumber(void); + +static WUDDevInfo *__wudGetOldestSmpDevice(void); +static WUDDevInfo *__wudGetOldestStdDevice(void); + +static void __wudCleanupStackCallback(tBTA_STATUS status); +static void __wudSecurityEventStackCallback(tBTA_DM_SEC_EVT event, + tBTA_DM_SEC *p_data); +static void __wudSearchEventStackCallback(tBTA_DM_SEARCH_EVT event, + tBTA_DM_SEARCH *p_data); +static void __wudVendorSpecificEventStackCallback(UINT8 len, UINT8 *p); +static void __wudDeviceStatusEventStackCallback(tBTM_DEV_STATUS status); +static void __wudLinkKeyEventStackCallback(void *p1); +static void __wudPowerManageEventStackCallback(BD_ADDR p_bda, + tBTM_PM_STATUS status, + UINT16 value, UINT8 hci_status); +static void __wudResetAuthFailCount(void); +static WUDDevInfo *__wudGetWbcDevice(void); + +/******************************************************************************* + * variables + */ + +// .data + +/* comments are from throwing the array into + * https://eleccelerator.com/usbdescreqparser + * so shout out to that website thank you + */ +static byte_t _wudWiiRemoteDescriptor[] = +{ + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, // Usage (Game Pad) + + 0xa1, 0x01, // Collection (Application) + + 0x85, 0x10, // Report ID (16) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xff, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x06, 0x00, 0xff, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x11, // Report ID (17) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x12, // Report ID (18) + 0x95, 0x02, // Report Count (2) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x13, // Report ID (19) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x14, // Report ID (20) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x15, // Report ID (21) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x16, // Report ID (22) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x17, // Report ID (23) + 0x95, 0x06, // Report Count (6) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x18, // Report ID (24) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x19, // Report ID (25) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x1a, // Report ID (26) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x20, // Report ID (32) + 0x95, 0x06, // Report Count (6) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x21, // Report ID (33) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x22, // Report ID (34) + 0x95, 0x04, // Report Count (4) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x30, // Report ID (48) + 0x95, 0x02, // Report Count (2) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x31, // Report ID (49) + 0x95, 0x05, // Report Count (5) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x32, // Report ID (50) + 0x95, 0x0a, // Report Count (10) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x33, // Report ID (51) + 0x95, 0x11, // Report Count (17) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x34, // Report ID (52) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x35, // Report ID (53) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x36, // Report ID (54) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x37, // Report ID (55) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x3d, // Report ID (61) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x3e, // Report ID (62) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x3f, // Report ID (63) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0xc0, // End Collection +}; + +static byte_t _wudSuperPeekPokeCmd[] = +{ + 0x05, 0x00, 0x9a, 0x0e, + 0x00, 0x01, 0x00, 0x00, + 0x00 +}; + +static byte_t _wudPatchData[] = +{ + 0x70, 0x99, 0x08, 0x00, // address (little-endian) + 0xb4, 0x00, 0x00, 0x00, // size (little-endian) + + // data + 0x88, 0x43, 0xd1, 0x07, + 0x09, 0x0c, 0x08, 0x43, + 0xa0, 0x62, 0x19, 0x23, + 0xdb, 0x01, 0x33, 0x80, + 0x7c, 0xf7, 0x88, 0xf8, + 0x28, 0x76, 0x80, 0xf7, + 0x17, 0xff, 0x43, 0x78, + 0xeb, 0x70, 0x19, 0x23, + 0xdb, 0x01, 0x33, 0x87, + 0x7c, 0xf7, 0xbc, 0xfb, + 0x0b, 0x60, 0xa3, 0x7b, + 0x01, 0x49, 0x0b, 0x60, + 0x90, 0xf7, 0x96, 0xfb, + 0xd8, 0x1d, 0x08, 0x00, + 0x00, 0xf0, 0x04, 0xf8, + 0x00, 0x23, 0x79, 0xf7, + 0xe3, 0xfa, 0x00, 0x00, + 0x00, 0xb5, 0x00, 0x23, + 0x11, 0x49, 0x0b, 0x60, + 0x1d, 0x21, 0xc9, 0x03, + 0x0b, 0x60, 0x7d, 0x20, + 0x80, 0x01, 0x01, 0x38, + 0xfd, 0xd1, 0x0e, 0x4b, + 0x0e, 0x4a, 0x13, 0x60, + 0x47, 0x20, 0x00, 0x21, + 0x96, 0xf7, 0x96, 0xff, + 0x46, 0x20, 0x00, 0x21, + 0x96, 0xf7, 0x92, 0xff, + 0x0a, 0x4a, 0x13, 0x68, + 0x0a, 0x48, 0x03, 0x40, + 0x13, 0x60, 0x0a, 0x4a, + 0x13, 0x68, 0x0a, 0x48, + 0x03, 0x40, 0x13, 0x60, + 0x09, 0x4a, 0x13, 0x68, + 0x09, 0x48, 0x03, 0x40, + 0x13, 0x60, 0x00, 0xbd, + 0x24, 0x80, 0x0e, 0x00, + 0x81, 0x03, 0x0f, 0xfe, + 0x5c, 0x00, 0x0f, 0x00, + 0x60, 0xfc, 0x0e, 0x00, + 0xfe, 0xff, 0x00, 0x00, + 0xfc, 0xfc, 0x0e, 0x00, + 0xff, 0x9f, 0x00, 0x00, + 0x30, 0xfc, 0x0e, 0x00, + 0x7f, 0xff, 0x00, 0x00 +}; + +static struct wud_patch_install_cmd_array _wudPatchInstallCmd = +{ + 7, + + { + {0x20, 0xbc, 0x65, 0x01, 0x00, 0x84, 0x42, 0x09, 0xd2, 0x84, 0x42, 0x09, 0xd1}, + {0x21, 0x84, 0x5a, 0x00, 0x00, 0x83, 0xf0, 0x74, 0xff, 0x09, 0x0c, 0x08, 0x43}, + {0x22, 0x00, 0x61, 0x00, 0x00, 0x83, 0xf0, 0x40, 0xfc, 0x00, 0x00, 0x00, 0x00}, + {0x23, 0xcc, 0x9f, 0x01, 0x00, 0x6f, 0xf0, 0xe4, 0xfc, 0x03, 0x28, 0x7d, 0xd1}, + {0x24, 0x3c, 0x62, 0x01, 0x00, 0x28, 0x20, 0x00, 0xe0, 0x60, 0x8d, 0x23, 0x68}, + {0x25, 0x04, 0x12, 0x01, 0x00, 0x20, 0x1c, 0x20, 0x1c, 0x24, 0xe0, 0xb0, 0x21}, + {0x26, 0x74, 0x2f, 0x00, 0x00, 0x86, 0xf0, 0x18, 0xfd, 0x21, 0x4f, 0x3b, 0x60} + } +}; + +static byte_t _wudResetAuthCountCmd[] = +{ + 0x30, 0x36, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +// .bss +wud_cb_st __rvl_wudcb; +static WUDDevInfo _wudDiscWork; +static struct wud_discovery_response _wudDiscResp; +static struct wud_nand_wbc_info _wudNandWbcInfo __attribute__((aligned(0x20))); +static SCBtDeviceInfoArray _scArray; +static NANDFileInfo _wudNandFileInfo; +static NANDCommandBlock _wudNandBlock; +static byte_t _wudHandlerStack[0x1000] __attribute__((aligned(0x20))); +static SCBtCmpDevInfoArray _spArray; +static BD_ADDR_PTR _dev_handle_to_bda[WUD_MAX_DEV_ENTRY]; +static u16 _dev_handle_queue_size[WUD_MAX_DEV_ENTRY]; +static u16 _dev_handle_notack_num[WUD_MAX_DEV_ENTRY]; + +// .sbss +static u8 _wudDiscNumResps; +static s8 _wudDiscRssi; +static u8 _wudTarget; +static u8 _scFlush; +static u32 _wudPatchSize; +static s32 _wudPatchOffset; +static u32 _wudPatchAddress; +static u8 _wudPatchNum; +static u8 _wudInstallNum; +static u8 _wudNandLocked; +static signed _wudNandPhase; +static u32 _wudNandWbcCrc; +__attribute__((weak)) BOOL _linkedWBC; +__attribute__((weak)) void (*_initWBC)(void); +static byte_t *_wudNandBufPtr; +static u8 __bte_trace_level; +static byte_t _wudPatchRemoveCmd; +static BOOL _wudAbortSync; +static BOOL _wudReadNand; +static BOOL _wudInitialized; + +/******************************************************************************* + * functions + */ + +BOOL WUDIsLinkedWBC(void) +{ + return _linkedWBC; +} + +extern void *App_MEMalloc(size_t size) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + void *buf = (*p_wcb->allocFunc)(size); + + return buf; +} + +extern int App_MEMfree(void *ptr) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + int ret = (*p_wcb->freeFunc)(ptr); + + return ret; +} + +static void __wudReverseAddr(BD_ADDR_PTR dst, BD_ADDR src) +{ + BOOL intrStatus = OSDisableInterrupts(); + + int i; + for (i = 0; i < BD_ADDR_LEN; i++) + dst[i] = src[(BD_ADDR_LEN - 1) - i]; + + OSRestoreInterrupts(intrStatus); +} + +static signed __wudSetPinCode(BD_ADDR dev_addr) +{ + BD_ADDR_PTR myAddr = __rvl_wudcb.syncType == WUD_SYNC_TYPE_STANDARD + ? __rvl_wudcb.hostAddr + : dev_addr; + + if (_wudDiscWork.at_0x5b == 4) + { + WUDiRemoveDevice(_wudDiscWork.devAddr); + btm_remove_acl(_wudDiscWork.devAddr); + } + + _wudDiscWork.at_0x5a = 1; + + BD_ADDR pin; + __wudReverseAddr(pin, myAddr); + + BTA_DmPinReply(dev_addr, TRUE, BD_ADDR_LEN, pin); + + return 0; +} + +static void __wudClearDiscoverResult(void) +{ + _wudDiscNumResps = 0; + memset(&_wudDiscResp, 0, sizeof _wudDiscResp); +} + +static BOOL __wudIsBusyLinkKeyCmd(void) +{ + return __rvl_wudcb.linkKeyState != WUD_STATE_START ? 1 : 0; +} + +static BOOL __wudIsBusyScCmd(void) +{ + return SCCheckStatus() == SC_STATUS_BUSY ? 1 : 0; +} + +static void __wudPrepareWBCDevInfo(BD_ADDR dev_addr, LINK_KEY link_key, + void *param_3) +{ + u8 offset = 0; + + if (dev_addr) + memcpy((void *)((u32)&_wudNandWbcInfo + offset), dev_addr, BD_ADDR_LEN); + + offset += BD_ADDR_LEN; + + if (link_key) + { + memcpy((void *)((u32)&_wudNandWbcInfo + offset), link_key, + LINK_KEY_LEN); + } + + offset += LINK_KEY_LEN; + + if (param_3) + memcpy((void *)((u32)&_wudNandWbcInfo + offset), param_3, 64); + + offset += 64; + + u32 crc = __wudCalcWiiFitCrc2(&_wudNandWbcInfo, 128, _wudNandWbcCrc); + memcpy((void *)((u32)&_wudNandWbcInfo + 128), &crc, sizeof crc); +} + +static void __wudSyncFlushCallback(SCStatus result) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (p_wcb->syncState == WUD_STATE_START) + return; + + if (result == SC_STATUS_READY) + p_wcb->syncState = WUD_STATE_SYNC_COMPLETE; + else + p_wcb->syncState = WUD_STATE_ERROR; +} + +static WUDSyncState __wudSyncPrepareSearch(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDSetVisibility(FALSE, FALSE); + + if (!p_wcb->syncLoopNum) + return WUD_STATE_SYNC_DONE; + + if (__wudGetLinkNumber() == WUD_MAX_CHANNELS + && __wudGetConnectionNumber() == WUD_MAX_CHANNELS) + { + return WUD_STATE_SYNC_DONE; + } + + int i; + WUDDevInfo *p_info; + if (p_wcb->syncSkipChecks) + { + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) + { + p_info = __wudGetDevInfoByIndex(i); + if (p_info->at_0x59 == 9) + { + WUDSetSniffMode(p_info->devAddr, 0); + return WUD_STATE_SYNC_PREPARE_SEARCH; + } + } + } + + if (p_wcb->syncLoopNum > 0) + p_wcb->syncLoopNum--; + + p_wcb->waitStartSearchFrames = 50; + + return WUD_STATE_SYNC_WAIT_FOR_START_SEARCH; +} + +static WUDSyncState __wudSyncWaitForStartSearch(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (!p_wcb->syncLoopNum) + return WUD_STATE_SYNC_DONE; + + if (__wudGetLinkNumber() == WUD_MAX_CHANNELS + && __wudGetConnectionNumber() == WUD_MAX_CHANNELS) + { + return WUD_STATE_SYNC_DONE; + } + + if (--p_wcb->waitStartSearchFrames < 0) + return WUD_STATE_SYNC_START_SEARCH; + else + return WUD_STATE_SYNC_WAIT_FOR_START_SEARCH; +} + +static WUDSyncState __wudSyncStartSearch(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + tBTA_DM_INQ dm_inq; + dm_inq.mode = BTM_LIMITED_INQUIRY; + dm_inq.max_resps = 1; + dm_inq.report_dup = FALSE; + + if (p_wcb->syncSkipChecks) + { + dm_inq.duration = 5 - 2; + } + else if (p_wcb->syncType == WUD_SYNC_TYPE_STANDARD) + { + dm_inq.duration = __wudGetLinkNumber() == 3 ? 10 : 5; + + dm_inq.duration -= p_wcb->syncLoopNum; + } + else + { + dm_inq.duration = __wudGetLinkNumber() == 3 ? 10 - 2 : 5 - 2; + } + + __wudClearDiscoverResult(); + BTA_DmSearch(&dm_inq, 0, &__wudSearchEventStackCallback); + + return WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT; +} + +static WUDSyncState __wudSyncWaitForSearchResult(void) +{ + if (__wudGetLinkNumber() == WUD_MAX_CHANNELS + && __wudGetConnectionNumber() == WUD_MAX_CHANNELS) + { + BTA_DmSearchCancel(); + return WUD_STATE_SYNC_26; + } + + return WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT; +} + +static WUDSyncState __wudSyncCheckSearchResult(void) +{ + WUDSyncState nextState = WUD_STATE_SYNC_PREPARE_SEARCH; + + if (_wudDiscNumResps > 0) + { + if (WUD_DEV_NAME_IS_CNT(_wudDiscResp.at_0x006)) + nextState = WUD_STATE_SYNC_IS_EXISTED_DEVICE; + + if (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_WBC(_wudDiscResp.at_0x006)) + nextState = WUD_STATE_SYNC_IS_EXISTED_DEVICE; + + if (_wudDiscRssi < __rvl_wudcb.syncRssi) + nextState = WUD_STATE_SYNC_PREPARE_SEARCH; + } + + if (__rvl_wudcb.syncType == WUD_SYNC_TYPE_STANDARD + && nextState == WUD_STATE_SYNC_PREPARE_SEARCH) + { + nextState = WUD_STATE_SYNC_WAIT_FOR_INCOMING; + + __rvl_wudcb.waitIncomingFrames = __wudGetLinkNumber() == 3 ? 200 : 100; + + WUDSetVisibility(FALSE, TRUE); + } + + return nextState; +} + +static WUDSyncState __wudSyncWaitForIncoming(void) +{ + WUDSyncState nextState = WUD_STATE_SYNC_WAIT_FOR_INCOMING; + + if (__wudGetLinkNumber() == WUD_MAX_CHANNELS + && __wudGetConnectionNumber() == WUD_MAX_CHANNELS) + { + nextState = WUD_STATE_SYNC_DONE; + } + + if (--__rvl_wudcb.waitIncomingFrames < 0) + nextState = WUD_STATE_SYNC_PREPARE_SEARCH; + + return nextState; +} + +static WUDSyncState __wudSyncIsExistedDevice(void) +{ + WUDDevInfo *ptr; + WUDSyncState nextState = WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE; + + ptr = WUDiGetDevInfo(_wudDiscResp.devAddr); + if (ptr) + { + memcpy(&_wudDiscWork, ptr, sizeof _wudDiscWork); + + nextState = WUD_STATE_SYNC_PREPARE_FOR_EXISTED_DEVICE; + } + + return nextState; +} + +static WUDSyncState __wudSyncPrepareForExistedDevice(void) +{ + WUDDevInfo *p_work = &_wudDiscWork; + + p_work->at_0x59 = 1; + + switch (p_work->at_0x5b) + { + case 0: + case 2: + case 4: + case 5: + if (__rvl_wudcb.syncType == WUD_SYNC_TYPE_STANDARD) + { + WUDiMoveBottomStdDevInfoPtr(p_work); + WUDiRemoveDevice(p_work->devAddr); + return WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE; + } + else + { + p_work->at_0x5b = 4; + } + + break; + + case 1: + case 3: + WUDiMoveBottomSmpDevInfoPtr(p_work); + WUDiRemoveDevice(__rvl_wudcb.smpListTail->devInfo->devAddr); + return WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE; + } + + return WUD_STATE_SYNC_TRY_CONNECT; +} + +static WUDSyncState __wudSyncPrepareForUnknownDevice(void) +{ + WUDDevInfo *p_work = &_wudDiscWork; + + p_work->at_0x59 = 1; + p_work->at_0x5b = __rvl_wudcb.syncType == WUD_SYNC_TYPE_STANDARD ? 0 : 1; + + WUD_BDCPY(p_work->devAddr, _wudDiscResp.devAddr); + memcpy(p_work, _wudDiscResp.at_0x006, 64); + memset(p_work->linkKey, 0, LINK_KEY_LEN); + + return WUD_STATE_SYNC_TRY_CONNECT; +} + +static WUDSyncState __wudSyncTryConnect(void) +{ + WUDSyncState nextState = WUD_STATE_ERROR; + + if (WUD_DEV_NAME_IS_CNT(_wudDiscResp.at_0x006)) + { + _wudDiscWork.at_0x59 = 2; + BTA_HhOpen(_wudDiscWork.devAddr, BTA_HH_PROTO_RPT_MODE, + BTA_SEC_AUTHENTICATE); + + nextState = WUD_STATE_SYNC_6; + } + + if (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_WBC(_wudDiscResp.at_0x006)) + { + WUDDevInfo *wbcInfo = __wudGetWbcDevice(); + if (wbcInfo) + { + if (wbcInfo->at_0x59 > 1) + return nextState; + + if (WUD_BDCMP(_wudDiscResp.devAddr, wbcInfo->devAddr) != 0) + { + WUDiMoveBottomStdDevInfoPtr(wbcInfo); + WUDiRemoveDevice(wbcInfo->devAddr); + } + } + + _wudDiscWork.at_0x59 = 2; + BTA_HhOpen(_wudDiscWork.devAddr, BTA_HH_PROTO_RPT_MODE, + BTA_SEC_AUTHENTICATE); + nextState = WUD_STATE_SYNC_6; + } + + return nextState; +} + +static WUDSyncState __wudSyncRegisterDevice(void) +{ + WUDSyncState nextState; + + switch (_wudDiscWork.at_0x5b) + { + case 1: + nextState = WUD_STATE_SYNC_VIRGIN_SIMPLE; + break; + + case 0: + nextState = WUD_STATE_SYNC_VIRGIN_STANDARD; + break; + + case 5: + nextState = WUD_STATE_SYNC_CHANGE_SIMPLE_TO_STANDARD; + break; + + case 3: + nextState = WUD_STATE_SYNC_COMPLETE; + break; + + case 4: + nextState = WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; + break; + + case 2: + nextState = WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; + break; + } + + /* ERRATA: nextState is undefined when 0 <= _wudDiscWork.at_0x5b <= 5 + * does not hold + */ + return nextState; +} + +static WUDSyncState __wudSyncVirginSimple(void) +{ + WUDDevInfo *p_info; + + if (__wudGetSmpDevNumber() == WUD_MAX_DEV_ENTRY_FOR_SMP) + { + p_info = __wudGetOldestSmpDevice(); + WUDiRemoveDevice(p_info->devAddr); + } + + p_info = __wudGetNewDevInfo(); + + if (!p_info) + return WUD_STATE_ERROR; + + if (p_info->at_0x59 != 0) + return WUD_STATE_ERROR; + + memcpy(p_info, &_wudDiscWork, sizeof *p_info); + WUDiRegisterDevice(p_info->devAddr); + WUDiMoveTopSmpDevInfoPtr(p_info); + + WUDiSetDevAddrForHandle(p_info->devHandle, p_info->devAddr); + + return WUD_STATE_SYNC_COMPLETE; +} + +static WUDSyncState __wudSyncVirginStandard(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + + if (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_CNT(_wudDiscWork.small.devName)) + { + p_info = __wudGetWbcDevice(); + + if (p_info && __wudGetStdDevNumber() == WUD_MAX_DEV_ENTRY_FOR_STD) + { + p_info = p_wcb->stdListTail->prev->devInfo; + WUDiMoveBottomStdDevInfoPtr(p_info); + WUDiRemoveDevice(p_info->devAddr); + } + } + + if (__wudGetStdDevNumber() == WUD_MAX_DEV_ENTRY_FOR_STD) + { + p_info = __wudGetOldestStdDevice(); + WUDiRemoveDevice(p_info->devAddr); + } + + p_info = __wudGetNewDevInfo(); + + if (!p_info) + return WUD_STATE_ERROR; + + if (p_info->at_0x59 != 0) + return WUD_STATE_ERROR; + + memcpy(p_info, &_wudDiscWork, sizeof *p_info); + WUDiRegisterDevice(p_info->devAddr); + WUDiMoveTopStdDevInfoPtr(p_info); + + if (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_WBC(p_info->small.devName)) + { + WUDiMoveTopOfUnusedStdDevice(p_info); + + memset(&_scArray.wbc, 0, sizeof _scArray.wbc); + WUD_BDCPY(&_scArray.wbc.devAddr, p_info->devAddr); + memcpy(&_scArray.wbc.small, p_info, sizeof _scArray.wbc.small); + + // Wait what + memcpy(&_scArray.wbc.small.at_0x14, p_info->linkKey, LINK_KEY_LEN); + __wudPrepareWBCDevInfo(p_info->devAddr, p_info->linkKey, p_info); + } + + WUDiSetDevAddrForHandle(p_info->devHandle, p_info->devAddr); + + return WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; +} + +static WUDSyncState __wudSyncChangeSmp2Std(void) +{ + WUDiMoveBottomSmpDevInfoPtr(&_wudDiscWork); + WUDiRemoveDevice(__rvl_wudcb.smpListTail->devInfo->devAddr); + return __wudSyncVirginStandard(); +} + +static WUDSyncState __wudSyncStoredLinkKeyToE2prom(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (__wudIsBusyLinkKeyCmd()) + return WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; + + if (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_WBC(_wudDiscWork.small.devName)) + return WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND; + + WUDDevInfo *p_info = WUDiGetDevInfo(_wudDiscWork.devAddr); + OSAssert_Line(1494, p_info != NULL); + + p_wcb->linkKeyState = WUD_STATE_LINK_KEY_WRITING; + BTM_WriteStoredLinkKey(1, &p_info->devAddr, &p_info->linkKey, + &__wudLinkKeyEventStackCallback); + + return WUD_STATE_SYNC_WAIT_FOR_STORING; +} + +static WUDSyncState __wudSyncWaitForStoring(void) +{ + return !__wudIsBusyLinkKeyCmd() ? WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND + : WUD_STATE_SYNC_WAIT_FOR_STORING; +} + +static WUDSyncState __wudSyncStoredDevInfoToNand(void) +{ + struct WUDDevInfoList *infoList; + u8 i; + WUDSyncState nextState = WUD_STATE_SYNC_COMPLETE; + + if (__wudIsBusyScCmd()) + return WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND; + + memset(&_scArray.devices, 0, + sizeof _scArray.devices[i] * WUD_MAX_DEV_ENTRY_FOR_STD); + _scArray.num = __wudGetStdDevNumber(); + + infoList = __rvl_wudcb.stdListHead; + i = 0; + while (infoList) + { + WUD_BDCPY(_scArray.devices[i].devAddr, infoList->devInfo->devAddr); + memcpy(&_scArray.devices[i].small, infoList->devInfo->small.devName, + sizeof _scArray.devices[i].small); + + i++; + infoList = infoList->next; + } + + BOOL scSuccess = SCSetBtDeviceInfoArray(&_scArray); + if (!scSuccess) + return WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND; + +// What +#if defined(NDEBUG) +# define RETURN_VAR i +#else +# define RETURN_VAR nextState +#endif // defined(NDEBUG) + + RETURN_VAR = WUD_STATE_SYNC_SC_FLUSH; + + if (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_WBC(_wudDiscWork.small.devName) + && SCGetProductGameRegion() == SC_PRD_GAME_REG_JP) + { + RETURN_VAR = WUD_STATE_WII_FIT_OPEN; + } + + return RETURN_VAR; +} + +static void __wudOpenWiiFitCallback(NANDResult result, + NANDCommandBlock *cmdBlock + __attribute__((unused))) +{ + if (__rvl_wudcb.syncState != WUD_STATE_START) + { + __rvl_wudcb.syncState = result == NAND_ESUCCESS + ? WUD_STATE_WII_FIT_SEEK + : WUD_STATE_SYNC_SC_FLUSH; + } + + if (__rvl_wudcb.deleteState != WUD_STATE_START) + { + __rvl_wudcb.deleteState = result == NAND_ESUCCESS + ? WUD_STATE_WII_FIT_SEEK + : WUD_STATE_DELETE_CLEANUP_SETTING; + } + + _wudNandLocked = FALSE; +} + +static void __wudOpenWiiFitFile(void) +{ + const char *rpHealthFilePath = RP_HEALTH_FILE_PATH; + + if (_wudNandLocked) + return; + + _wudNandLocked = TRUE; + NANDOpenAsync(rpHealthFilePath, &_wudNandFileInfo, NAND_OPEN_WRITE, + &__wudOpenWiiFitCallback, &_wudNandBlock); +} + +static void __wudSeekWiiFitCallback(NANDResult result, + NANDCommandBlock *cmdBlock + __attribute__((unused))) +{ + if (__rvl_wudcb.syncState != WUD_STATE_START) + { + __rvl_wudcb.syncState = result == RP_HEALTH_FILE_OFFSET + ? WUD_STATE_WII_FIT_UPDATE + : WUD_STATE_SYNC_SC_FLUSH; + } + + if (__rvl_wudcb.deleteState != WUD_STATE_START) + { + __rvl_wudcb.deleteState = result == RP_HEALTH_FILE_OFFSET + ? WUD_STATE_WII_FIT_UPDATE + : WUD_STATE_DELETE_CLEANUP_SETTING; + } + + _wudNandLocked = FALSE; +} + +static void __wudSeekWiiFitFile(void) +{ + if (_wudNandLocked) + return; + + _wudNandLocked = TRUE; + NANDSeekAsync(&_wudNandFileInfo, RP_HEALTH_FILE_OFFSET, NAND_SEEK_SET, + &__wudSeekWiiFitCallback, &_wudNandBlock); +} + +static void __wudUpdateWiiFitCallback(NANDResult result, + NANDCommandBlock *cmdBlock + __attribute__((unused))) +{ + if (__rvl_wudcb.syncState != WUD_STATE_START) + { + __rvl_wudcb.syncState = result == RP_HEALTH_FILE_WRITE_SIZE + ? WUD_STATE_WII_FIT_CLOSE + : WUD_STATE_SYNC_SC_FLUSH; + } + + if (__rvl_wudcb.deleteState != WUD_STATE_START) + { + __rvl_wudcb.deleteState = result == RP_HEALTH_FILE_WRITE_SIZE + ? WUD_STATE_WII_FIT_CLOSE + : WUD_STATE_DELETE_CLEANUP_SETTING; + } + + _wudNandLocked = FALSE; +} + +static void __wudUpdateWiiFitFile(void) +{ + if (_wudNandLocked) + return; + + _wudNandLocked = TRUE; + NANDWriteAsync(&_wudNandFileInfo, &_wudNandWbcInfo, + RP_HEALTH_FILE_WRITE_SIZE, &__wudUpdateWiiFitCallback, + &_wudNandBlock); +} + +static void __wudCloseWiiFitCallback(NANDResult result __attribute__((unused)), + NANDCommandBlock *cmdBlock + __attribute__((unused))) +{ + if (__rvl_wudcb.syncState != WUD_STATE_START) + __rvl_wudcb.syncState = WUD_STATE_SYNC_SC_FLUSH; + + if (__rvl_wudcb.deleteState != WUD_STATE_START) + __rvl_wudcb.deleteState = WUD_STATE_DELETE_CLEANUP_SETTING; + + _wudNandLocked = FALSE; +} + +static void __wudCloseWiiFit(void) +{ + if (_wudNandLocked) + return; + + _wudNandLocked = TRUE; + NANDCloseAsync(&_wudNandFileInfo, &__wudCloseWiiFitCallback, + &_wudNandBlock); +} + +static void __wudSyncScFlush(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + p_wcb->syncState = WUD_STATE_SYNC_13; + + OSRestoreInterrupts(intrStatus); + + SCFlushAsync(&__wudSyncFlushCallback); +} + +static WUDSyncState __wudSyncWaitForReading(void) +{ + WUDSyncState nextState = WUD_STATE_SYNC_WAIT_FOR_READING; + + if (!__wudIsBusyLinkKeyCmd()) + { + nextState = WUD_STATE_SYNC_VIRGIN_STANDARD; + WUDiRemoveDevice(__rvl_wudcb.pairAddr); + } + + return nextState; +} + +static WUDSyncState __wudSyncComplete(void) +{ + __rvl_wudcb.syncedNum++; + + memset(&_wudDiscWork, 0, sizeof _wudDiscWork); + return __rvl_wudcb.syncType == WUD_SYNC_TYPE_STANDARD + ? WUD_STATE_SYNC_DONE + : WUD_STATE_SYNC_PREPARE_SEARCH; +} + +static WUDSyncState __wudSyncError(void) +{ + memset(&_wudDiscWork, 0, sizeof _wudDiscWork); + return __rvl_wudcb.syncType == WUD_SYNC_TYPE_STANDARD + ? WUD_STATE_SYNC_DONE + : WUD_STATE_SYNC_PREPARE_SEARCH; +} + +static WUDSyncState __wudSyncDone(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDDevInfo *p_info; + int i; + if (p_wcb->syncSkipChecks) + { + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) + { + p_info = __wudGetDevInfoByIndex(i); + if (p_info->at_0x59 == 8) + { + WUDSetSniffMode(p_info->devAddr, 8); + return WUD_STATE_SYNC_DONE; + } + } + } + + OSCancelAlarm(&p_wcb->alarm); + + if (!_wudAbortSync) + WUDSetVisibility(FALSE, TRUE); + + WUDSyncDeviceCallback *syncCB = p_wcb->syncType == WUD_SYNC_TYPE_STANDARD + ? p_wcb->syncStdCB + : p_wcb->syncSmpCB; + + if (syncCB) + (*syncCB)(1, p_wcb->syncedNum); + + return WUD_STATE_START; +} + +static void __wudSyncHandler(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + switch (p_wcb->syncState) + { + case WUD_STATE_SYNC_PREPARE_SEARCH: + p_wcb->syncState = __wudSyncPrepareSearch(); + break; + + case WUD_STATE_SYNC_WAIT_FOR_START_SEARCH: + p_wcb->syncState = __wudSyncWaitForStartSearch(); + break; + + case WUD_STATE_SYNC_START_SEARCH: + p_wcb->syncState = __wudSyncStartSearch(); + break; + + case WUD_STATE_SYNC_CHECK_SEARCH_RESULT: + p_wcb->syncState = __wudSyncCheckSearchResult(); + break; + + case WUD_STATE_SYNC_IS_EXISTED_DEVICE: + p_wcb->syncState = __wudSyncIsExistedDevice(); + break; + + case WUD_STATE_SYNC_PREPARE_FOR_EXISTED_DEVICE: + p_wcb->syncState = __wudSyncPrepareForExistedDevice(); + break; + + case WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE: + p_wcb->syncState = __wudSyncPrepareForUnknownDevice(); + break; + + case WUD_STATE_SYNC_TRY_CONNECT: + p_wcb->syncState = __wudSyncTryConnect(); + break; + + case WUD_STATE_SYNC_REGISTER_DEVICE: + p_wcb->syncState = __wudSyncRegisterDevice(); + break; + + case WUD_STATE_SYNC_VIRGIN_SIMPLE: + p_wcb->syncState = __wudSyncVirginSimple(); + break; + + case WUD_STATE_SYNC_VIRGIN_STANDARD: + p_wcb->syncState = __wudSyncVirginStandard(); + break; + + case WUD_STATE_SYNC_CHANGE_SIMPLE_TO_STANDARD: + p_wcb->syncState = __wudSyncChangeSmp2Std(); + break; + + case WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM: + p_wcb->syncState = __wudSyncStoredLinkKeyToE2prom(); + break; + + case WUD_STATE_SYNC_WAIT_FOR_STORING: + p_wcb->syncState = __wudSyncWaitForStoring(); + break; + + case WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND: + p_wcb->syncState = __wudSyncStoredDevInfoToNand(); + break; + + case WUD_STATE_SYNC_SC_FLUSH: + __wudSyncScFlush(); + break; + + case WUD_STATE_SYNC_WAIT_FOR_READING: + p_wcb->syncState = __wudSyncWaitForReading(); + break; + + case WUD_STATE_SYNC_COMPLETE: + p_wcb->syncState = __wudSyncComplete(); + break; + + case WUD_STATE_ERROR: + p_wcb->syncState = __wudSyncError(); + break; + + case WUD_STATE_SYNC_DONE: + p_wcb->syncState = __wudSyncDone(); + break; + + case WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT: + p_wcb->syncState = __wudSyncWaitForSearchResult(); + break; + + case WUD_STATE_SYNC_WAIT_FOR_INCOMING: + p_wcb->syncState = __wudSyncWaitForIncoming(); + break; + + // Wii Fit states + + case WUD_STATE_WII_FIT_OPEN: + __wudOpenWiiFitFile(); + break; + + case WUD_STATE_WII_FIT_SEEK: + __wudSeekWiiFitFile(); + break; + + case WUD_STATE_WII_FIT_UPDATE: + __wudUpdateWiiFitFile(); + break; + + case WUD_STATE_WII_FIT_CLOSE: + __wudCloseWiiFit(); + break; + + // Actionless states (?) + + case WUD_STATE_SYNC_11: + case WUD_STATE_SYNC_12: + case WUD_STATE_SYNC_26: + break; + } +} + +static void __wudSyncHandler0(OSAlarm *alarm, OSContext *context) +{ + OSSwitchFiberEx((register_t)alarm, (register_t)context, 0, 0, + &__wudSyncHandler, + &_wudHandlerStack[sizeof _wudHandlerStack]); +} + +static void __wudDeleteFlushCallback(SCStatus result) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (p_wcb->deleteState != WUD_STATE_START) + { + // ? + if (result == SC_STATUS_READY) + p_wcb->deleteState = WUD_STATE_DELETE_DONE; + else + p_wcb->deleteState = WUD_STATE_DELETE_DONE; + } +} + +static WUDDeleteState __wudDeleteDisallowIncoming(void) +{ + // see notes about this prototype + BTA_DmSetVisibility(FALSE, FALSE); + + return WUD_STATE_DELETE_DISCONNECT_ALL; +} + +static WUDDeleteState __wudDeleteDisconnectAll(void) +{ + int i; + + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + p_info = &p_wcb->stdDevs[i]; + if (p_info->at_0x59 > 1) + btm_remove_acl(p_info->devAddr); + } + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + { + p_info = &p_wcb->smpDevs[i]; + if (p_info->at_0x59 > 1) + btm_remove_acl(p_info->devAddr); + } + + return WUD_STATE_DELETE_CLEANUP_DATABASE; +} + +static WUDDeleteState __wudDeleteCleanupDatabase(void) +{ + int i; + + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + + if (__wudGetLinkNumber() != 0) + return WUD_STATE_DELETE_CLEANUP_DATABASE; + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + p_info = &p_wcb->stdDevs[i]; + if (p_info->at_0x59 == 1) + WUDiRemoveDevice(p_info->devAddr); + } + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + { + p_info = &p_wcb->smpDevs[i]; + if (p_info->at_0x59 == 1) + WUDiRemoveDevice(p_info->devAddr); + } + + if (WUDIsLinkedWBC()) + { + if (SCGetProductGameRegion() == SC_PRD_GAME_REG_JP) + { + LINK_KEY link_key = {0}; + __wudPrepareWBCDevInfo(NULL, link_key, NULL); + + return WUD_STATE_WII_FIT_OPEN; + } + else + { + return WUD_STATE_DELETE_CLEANUP_SETTING; + } + } + else + { + return WUD_STATE_DELETE_CLEANUP_SETTING; + } +} + +static void __wudDeleteCleanupSetting(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + BOOL success = FALSE; + + if (SCCheckStatus() == SC_STATUS_BUSY) + return; + + memset(&_scArray, 0, sizeof _scArray); + memset(&_spArray, 0, sizeof _spArray); + + success |= SCSetBtDeviceInfoArray(&_scArray); + success |= SCSetBtCmpDevInfoArray(&_spArray); + + if (success) + { + p_wcb->deleteState = WUD_STATE_DELETE_6; + SCFlushAsync(&__wudDeleteFlushCallback); + } + else + { + p_wcb->deleteState = WUD_STATE_DELETE_DONE; + } +} + +static WUDDeleteState __wudDeleteDone(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDSetVisibility(FALSE, WUDGetConnectable()); + OSCancelAlarm(&p_wcb->alarm); + p_wcb->deleteState = WUD_STATE_START; + + if (p_wcb->clearDevCB) + (*p_wcb->clearDevCB)(1); + + return WUD_STATE_START; +} + +static void __wudDeleteHandler(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + p_wcb->syncState = WUD_STATE_START; + + switch (p_wcb->deleteState) + { + case WUD_STATE_DELETE_DISALLOW_INCOMING: + p_wcb->deleteState = __wudDeleteDisallowIncoming(); + break; + + case WUD_STATE_DELETE_DISCONNECT_ALL: + p_wcb->deleteState = __wudDeleteDisconnectAll(); + break; + + case WUD_STATE_DELETE_CLEANUP_DATABASE: + p_wcb->deleteState = __wudDeleteCleanupDatabase(); + break; + + case WUD_STATE_DELETE_CLEANUP_SETTING: + __wudDeleteCleanupSetting(); + break; + + case WUD_STATE_DELETE_DONE: + p_wcb->deleteState = __wudDeleteDone(); + break; + + // Wii Fit states + + case WUD_STATE_WII_FIT_OPEN: + __wudOpenWiiFitFile(); + break; + + case WUD_STATE_WII_FIT_SEEK: + __wudSeekWiiFitFile(); + break; + + case WUD_STATE_WII_FIT_UPDATE: + __wudUpdateWiiFitFile(); + break; + + case WUD_STATE_WII_FIT_CLOSE: + __wudCloseWiiFit(); + break; + + // Actionless states (?) + + case WUD_STATE_DELETE_7: + break; + } +} + +static void __wudDeleteHandler0(OSAlarm *alarm, OSContext *context) +{ + OSSwitchFiberEx((register_t)alarm, (register_t)context, 0, 0, + &__wudDeleteHandler, + &_wudHandlerStack[sizeof _wudHandlerStack]); +} + +static WUDStackState __wudStackGetStoredLinkKey(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + // see WUDiHidHostEventCallback, case BTA_HH_ENABLE_EVT + if (p_wcb->hhFlags == 1) + { + p_wcb->linkKeyState = WUD_STATE_LINK_KEY_READING; + BTM_ReadStoredLinkKey(NULL, &__wudLinkKeyEventStackCallback); + } + + return WUD_STATE_STACK_CHECK_DEVICE_INFO; +} + +static WUDStackState __wudStackCheckDeviceInfo(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + + int i; + if (p_wcb->linkKeyState == WUD_STATE_START) + { + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) + { + p_info = __wudGetDevInfoByIndex(i); + if (!p_info->at_0x59) + continue; + + if (p_info->at_0x5c == 1) + { + p_wcb->linkKeyState = WUD_STATE_LINK_KEY_DELETING; + BTM_DeleteStoredLinkKey(p_info->devAddr, + &__wudLinkKeyEventStackCallback); + p_info->at_0x5c = 0; + + return WUD_STATE_STACK_CHECK_DEVICE_INFO; + } + + if (p_info->at_0x5c != 3) + __wudRemoveDevInfo(p_info->devAddr); + } + + return WUD_STATE_STACK_DONE; + } + else + { + return WUD_STATE_STACK_CHECK_DEVICE_INFO; + } +} + +static WUDStackState __wudStackDone(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (p_wcb->linkKeyState == WUD_STATE_START) + { + OSCancelAlarm(&p_wcb->alarm); + __wudCheckFirmwareVersion(); + + return WUD_STATE_STACK_INITIALIZED; + } + else + { + return WUD_STATE_STACK_CHECK_DEVICE_INFO; + } +} + +static void __wudStackHandler(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + switch (p_wcb->stackState) + { + case WUD_STATE_STACK_GET_STORED_LINK_KEY: + p_wcb->stackState = __wudStackGetStoredLinkKey(); + break; + + case WUD_STATE_STACK_CHECK_DEVICE_INFO: + p_wcb->stackState = __wudStackCheckDeviceInfo(); + break; + + case WUD_STATE_STACK_DONE: + p_wcb->stackState = __wudStackDone(); + break; + } +} + +static void __wudStackHandler0(OSAlarm *alarm, OSContext *context) +{ + OSSwitchFiberEx((register_t)alarm, (register_t)context, 0, 0, + &__wudStackHandler, + &_wudHandlerStack[sizeof _wudHandlerStack]); +} + +static void __wudInitFlushCallback(SCStatus result __attribute__((unused))) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + p_wcb->initState = WUD_STATE_INIT_DONE; +} + +static WUDInitState __wudInitWaitForDeviceUp(void) +{ + WUDInitState nextState = WUD_STATE_INIT_WAIT_FOR_DEVICE_UP; + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (--p_wcb->initWaitDeviceUpFrames < 0) + WUDiShowFatalErrorMessage(); + + if (BTA_DmIsDeviceUp()) + nextState = WUD_STATE_INIT_WAIT_FOR_INITIALIZATION; + + return nextState; +} + +static WUDInitState __wudInitWaitForInitialization(void) +{ + s32 diff = 0; + WUDInitState nextState = WUD_STATE_INIT_WAIT_FOR_INITIALIZATION; + OSTime time = __OSGetSystemTime(); + + diff = 500 - OSTicksToMilliseconds(OSDiffTick(time, __OSStartTime)); + + if (diff < 0 && SCCheckStatus() != SC_STATUS_BUSY) + { + __wudClearControlBlock(); + + nextState = WUD_STATE_INIT_GET_DEV_INFO; + + if (WUDIsLinkedWBC() && SCGetProductGameRegion() == SC_PRD_GAME_REG_JP) + { + nextState = WUD_STATE_INIT_GET_DEV_INFO_FROM_WII_FIT; + + _wudNandLocked = FALSE; + _wudNandPhase = WUD_STATE_START; + } + } + + return nextState; +} + +static BOOL __wudIsExistedDevice(BD_ADDR dev_addr) +{ + int i; + for (i = 0; i < _scArray.num; i++) + if (WUD_BDCMP(_scArray.devices[i].devAddr, dev_addr) == 0) + return TRUE; + + return FALSE; +} + +static WUDInitState __wudInitDevInfo(void) +{ + BD_ADDR dev_addr; + + memset(&_scArray, 0, sizeof _scArray); + memset(&_spArray, 0, sizeof _spArray); + memset(dev_addr, 0, BD_ADDR_LEN); + + SCGetBtDeviceInfoArray(&_scArray); + SCGetBtCmpDevInfoArray(&_spArray); + + OSAssert_Line(2422, _scArray.num >= 0 && _scArray.num <= WUD_MAX_DEV_ENTRY_FOR_STD); + OSAssert_Line(2423, _spArray.num >= 0 && _spArray.num <= WUD_MAX_DEV_ENTRY_FOR_SMP); + + __rvl_wudcb.syncType = WUD_SYNC_TYPE_STANDARD; + int i, j; + u32 arrayNum; + u8 a; + + WUDDevInfo *p_info; + for (i = 0, arrayNum = _scArray.num, a = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; + i++) + { + if (!arrayNum) + break; + + if (!WUD_DEV_NAME_IS_CNT(_scArray.devices[i].small.devName)) + memset(&_scArray.devices[i], 0, sizeof _scArray.devices[i]); + + if (WUD_BDCMP(_scArray.devices[i].devAddr, dev_addr) == 0) + { + if (i < WUD_MAX_DEV_ENTRY_FOR_STD - 1) + { + for (j = i + 1; j < WUD_MAX_DEV_ENTRY_FOR_STD; j++) + { + if (WUD_DEV_NAME_IS_CNT(_scArray.devices[j].small.devName)) + { + memcpy(&_scArray.devices[i], &_scArray.devices[j], + sizeof _scArray.devices[i]); + memset(&_scArray.devices[j], 0, + sizeof _scArray.devices[i]); + + goto there; + } + } + } + } + else + { + // presumably what fucked over ghidra + there: + p_info = __wudGetNewDevInfo(); + if (p_info) + { + WUD_BDCPY(p_info->devAddr, _scArray.devices[i].devAddr); + memcpy(&p_info->small, &_scArray.devices[i].small, + sizeof p_info->small); + + p_info->at_0x59 = 1; + p_info->at_0x5b = 0; + p_info->at_0x5c = 2; + p_info->subclass = 2; // subclass 2 is marked as reserved + p_info->hhAttrMask = 0x8074; + p_info->appID = 3; + + a++; + arrayNum--; + } + } + } + + if (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_WBC(_scArray.wbc.small.devName)) + { + p_info = __wudGetNewDevInfo(); + if (!p_info) + { + p_info = __wudGetDevInfoByIndex(9); + a--; + } + + WUD_BDCPY(p_info->devAddr, _scArray.wbc.devAddr); + memcpy(p_info->small.devName, _scArray.wbc.small.devName, 19); // ? + memcpy(p_info->linkKey, _scArray.wbc.small.at_0x14, LINK_KEY_LEN); + + p_info->at_0x59 = 1; + p_info->at_0x5b = 0; + p_info->subclass = 2; + p_info->hhAttrMask = 0x8074; + p_info->appID = 3; + p_info->at_0x5c = 3; + + memset(&_scArray.devices[a], 0, sizeof _scArray.devices[a]); + WUD_BDCPY(_scArray.devices[a].devAddr, _scArray.wbc.devAddr); + // sizeof == 19? + memcpy(_scArray.devices[a].small.devName, _scArray.wbc.small.devName, + 19); + + a++; + } + + _scArray.num = a; + __rvl_wudcb.syncType = WUD_SYNC_TYPE_SIMPLE; + + for (i = 5, arrayNum = _spArray.num; i >= 0; i--) + { + if (!arrayNum) + break; + + if (WUD_BDCMP(_spArray.devices[i].devAddr, dev_addr) == 0) + continue; + + if (__wudIsExistedDevice(_spArray.devices[i].devAddr)) + continue; + + p_info = __wudGetNewDevInfo(); + if (p_info) + { + WUD_BDCPY(p_info->devAddr, _spArray.devices[i].devAddr); + memcpy(&p_info->small, &_spArray.devices[i].small, + sizeof p_info->small); + memcpy(p_info->linkKey, _spArray.devices[i].linkKey, LINK_KEY_LEN); + + p_info->at_0x59 = 1; + p_info->at_0x5b = 1; + p_info->at_0x5c = 3; + + if (WUD_DEV_NAME_IS_CNT_01(p_info->small.devName)) + { + p_info->subclass = 2; + p_info->hhAttrMask = 0x8074; + p_info->appID = 3; + } + + WUDiMoveTopSmpDevInfoPtr(p_info); + + arrayNum--; + } + } + + __rvl_wudcb.syncType = WUD_SYNC_TYPE_STANDARD; + __rvl_wudcb.initState = WUD_STATE_INIT_5; + + memset(&_spArray, 0, sizeof _spArray); + SCSetBtDeviceInfoArray(&_scArray); + SCSetBtCmpDevInfoArray(&_spArray); + SCFlushAsync(&__wudInitFlushCallback); + + return WUD_STATE_INIT_DONE; +} + +static WUDInitState __wudInitDone(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + OSCancelAlarm(&p_wcb->alarm); + + p_wcb->libStatus = WUD_LIB_STATUS_1; + + BTA_EnableBluetooth(&__wudSecurityEventStackCallback); + + return WUD_STATE_INIT_INITIALIZED; +} + +static void __wudNandResultCallback(NANDResult result, NANDCommandBlock *block + __attribute__((unused))) +{ + // ? +#if !defined(NDEBUG) + // clang-format off + const char *funcNames[6] __attribute__((unused)) = + { + "", + "NANDOpen", + "NANDSeek", + "NANDRead", + "", + "NANDClose" + }; + // clang-format on +#endif // !defined(NDEBUG) + + _wudNandLocked = FALSE; + + switch (_wudNandPhase) + { + case WUD_STATE_NAND_OPEN: + _wudNandPhase = + result == NAND_ESUCCESS ? _wudNandPhase + 1 : WUD_STATE_ERROR; + break; + + case WUD_STATE_NAND_SEEK: + _wudNandPhase = result == 0 ? _wudNandPhase + 1 : WUD_STATE_NAND_CLOSE; + break; + + case WUD_STATE_NAND_READ: + _wudNandPhase = + result == 0x4b000 ? _wudNandPhase + 1 : WUD_STATE_NAND_CLOSE; + break; + + default: + _wudNandPhase = WUD_STATE_NAND_DONE; + break; + } +} + +static void __wudNandFlushCallback(SCStatus result __attribute__((unused))) +{ + _wudNandLocked = FALSE; + _wudNandPhase++; +} + +static u32 __wudCalcWiiFitCrc1(void *data_, u32 length_) +{ + u16 *data = data_; + u32 crcHi = 0; + u16 crcLo = 0; + + u32 i; + u32 length = length_ / sizeof *data; + for (i = 0; i < length; ++i, ++data) + { + crcHi += *data; + crcLo += ~*data; + } + + return (u16)crcHi << 16 | crcLo; +} + +static u32 __wudCalcWiiFitCrc2(void *data_, u32 length_, u32 crc) +{ + u16 *data = data_; + u32 crcHi = (u16)(crc >> 16); + u16 crcLo = (u16)crc; + + u32 i; + u32 length = length_ / sizeof *data; + for (i = 0; i < length; ++i, ++data) + { + crcHi += *data; + crcLo += ~*data; + } + + return (u16)crcHi << 16 | crcLo; +} + +static WUDInitState __wudGetDevInfoFromWiiFit(void) +{ + const char *wfFilePath = RP_HEALTH_FILE_PATH; + const char *wfTitleID = WII_FIT_TITLE_ID; + byte_t zeroBuf[16] = {0}; + + WUDInitState nextState = WUD_STATE_INIT_GET_DEV_INFO_FROM_WII_FIT; + + if (_wudNandLocked) + return nextState; + + if (!_wudNandBufPtr || !IS_ALIGNED(_wudNandBufPtr, 0x20)) + { + OSError_Line(2745, "Error: the workarea for synchronizing WBC pairing " + "information is not allocated.\n"); + } + + NANDResult result; + u32 wfDataCrc; + u32 wfCalcCrc; + switch (_wudNandPhase) + { + case WUD_STATE_START: + result = NANDInit(); + _wudNandPhase = + result == NAND_ESUCCESS ? WUD_STATE_NAND_OPEN : WUD_STATE_ERROR; + break; + + case WUD_STATE_NAND_OPEN: + if (SCGetProductGameRegion() == SC_PRD_GAME_REG_JP) + { + _wudNandLocked = TRUE; + _wudNandWbcCrc = 0; + + result = + NANDOpenAsync(wfFilePath, &_wudNandFileInfo, NAND_OPEN_READ, + &__wudNandResultCallback, &_wudNandBlock); + } + else + { + _wudNandPhase = WUD_STATE_NAND_DONE; + } + + break; + + case WUD_STATE_NAND_SEEK: + _wudNandLocked = TRUE; + + result = NANDSeekAsync(&_wudNandFileInfo, 0, NAND_SEEK_SET, + &__wudNandResultCallback, &_wudNandBlock); + + break; + + case WUD_STATE_NAND_READ: + _wudNandLocked = TRUE; + + result = NANDReadAsync(&_wudNandFileInfo, _wudNandBufPtr, 0x4b000, + &__wudNandResultCallback, &_wudNandBlock); + + break; + + case WUD_STATE_NAND_GET_DEV_INFO: + memcpy(&_wudNandWbcInfo, _wudNandBufPtr + RP_HEALTH_FILE_OFFSET, 128); + memcpy(&wfDataCrc, _wudNandBufPtr + RP_HEALTH_FILE_OFFSET + 0x80, + sizeof wfDataCrc); + + _wudNandWbcCrc = + __wudCalcWiiFitCrc1(_wudNandBufPtr, RP_HEALTH_FILE_OFFSET); + wfCalcCrc = __wudCalcWiiFitCrc2(_wudNandBufPtr + RP_HEALTH_FILE_OFFSET, + 128, _wudNandWbcCrc); + if (wfDataCrc != wfCalcCrc) + { + _wudNandPhase = WUD_STATE_NAND_CLOSE; + break; + } + + if (WUD_BDCMP(_wudNandWbcInfo.scDevInfo.devAddr, zeroBuf) == 0) + { + _wudNandPhase = WUD_STATE_NAND_CLOSE; + break; + } + + if (memcmp(OSGetAppGamename(), wfTitleID, 4) != 0 + && memcmp(_wudNandWbcInfo.scDevInfo.small.devName, zeroBuf, 16) + == 0) + { + _wudNandPhase = WUD_STATE_NAND_CLOSE; + break; + } + + memset(_wudNandBufPtr, 0, 0x4b000); + + memset(&_scArray, 0, sizeof _scArray); + SCGetBtDeviceInfoArray(&_scArray); + + WUD_BDCPY(_scArray.wbc.devAddr, _wudNandWbcInfo.scDevInfo.devAddr); + + // TODO: what? + memcpy(&_scArray.wbc.small, (void *)((u32)&_wudNandWbcInfo + 22), + sizeof _scArray.wbc.small); + memcpy((void *)((u32)&_scArray.wbc + 26), + &_wudNandWbcInfo.scDevInfo.small.devName, 16); + SCSetBtDeviceInfoArray(&_scArray); + + _wudNandLocked = TRUE; + SCFlushAsync(__wudNandFlushCallback); + + break; + + case WUD_STATE_NAND_CLOSE: + _wudNandLocked = TRUE; + + result = NANDCloseAsync(&_wudNandFileInfo, &__wudNandResultCallback, + &_wudNandBlock); + + break; + + default: + // case WUD_STATE_NAND_DONE: + nextState = WUD_STATE_INIT_GET_DEV_INFO; + break; + } + + return nextState; +} + +static void __wudInitHandler(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + switch (p_wcb->initState) + { + case WUD_STATE_INIT_WAIT_FOR_DEVICE_UP: + p_wcb->initState = __wudInitWaitForDeviceUp(); + break; + + case WUD_STATE_INIT_WAIT_FOR_INITIALIZATION: + p_wcb->initState = __wudInitWaitForInitialization(); + break; + + case WUD_STATE_INIT_GET_DEV_INFO: + /* p_wcb->initState = */ __wudInitDevInfo(); // ? + break; + + case WUD_STATE_INIT_DONE: + p_wcb->initState = __wudInitDone(); + break; + + case WUD_STATE_INIT_GET_DEV_INFO_FROM_WII_FIT: + p_wcb->initState = __wudGetDevInfoFromWiiFit(); + break; + } +} + +static void __wudInitHandler0(OSAlarm *alarm, OSContext *context) +{ + OSSwitchFiberEx((register_t)alarm, (register_t)context, 0, 0, + &__wudInitHandler, + &_wudHandlerStack[sizeof _wudHandlerStack]); +} + +static void __wudShutdownFlushCallback(SCStatus result __attribute__((unused))) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + p_wcb->shutdownState = WUD_STATE_SHUTDOWN_DONE; +} + +static void __wudShutdownStoreSetting(void) +{ + BOOL success = _wudReadNand; + + if (SCCheckStatus() == SC_STATUS_BUSY) + return; + + success &= SCSetBtDeviceInfoArray(&_scArray); + success &= SCSetBtCmpDevInfoArray(&_spArray); + + if (success) + { + __rvl_wudcb.shutdownState = WUD_STATE_SHUTDOWN_FLUSH_SETTINGS; + + SCFlushAsync(&__wudShutdownFlushCallback); + } + else + { + __rvl_wudcb.shutdownState = WUD_STATE_SHUTDOWN_DONE; + } +} + +static void __wudShutdownDone(void) +{ + OSCancelAlarm(&__rvl_wudcb.alarm); + BTA_DisableBluetooth(); +} + +static void __wudShutdownHandler(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + switch (p_wcb->shutdownState) + { + case WUD_STATE_SHUTDOWN_STORE_SETTINGS: + __wudShutdownStoreSetting(); + break; + + case WUD_STATE_SHUTDOWN_DONE: + __wudShutdownDone(); + break; + } +} + +static void __wudShutdownHandler0(OSAlarm *alarm, OSContext *context) +{ + OSSwitchFiberEx((register_t)alarm, (register_t)context, 0, 0, + &__wudShutdownHandler, + &_wudHandlerStack[sizeof _wudHandlerStack]); +} + +static void __wudClearControlBlock(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) + { + WUDiSetDevAddrForHandle(i, NULL); + WUDiSetQueueSizeForHandle(i, 0); + WUDiSetNotAckNumForHandle(i, 0); + } + + p_wcb->smpListTail = &p_wcb->smpList[5]; + p_wcb->smpListHead = &p_wcb->smpList[0]; + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + { + p_wcb->smpList[i].devInfo = &p_wcb->smpDevs[5 - i]; + p_wcb->smpList[i].prev = i == 0 ? NULL : &p_wcb->smpList[i - 1]; + p_wcb->smpList[i].next = i == 5 ? NULL : &p_wcb->smpList[i + 1]; + } + + p_wcb->stdListTail = &p_wcb->stdList[9]; + p_wcb->stdListHead = &p_wcb->stdList[0]; + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + p_wcb->stdList[i].devInfo = &p_wcb->stdDevs[i]; + p_wcb->stdList[i].prev = i == 0 ? NULL : &p_wcb->stdList[i - 1]; + p_wcb->stdList[i].next = i == 9 ? NULL : &p_wcb->stdList[i + 1]; + } + + p_wcb->syncState = WUD_STATE_START; + p_wcb->linkKeyState = WUD_STATE_START; + p_wcb->deleteState = WUD_STATE_START; + p_wcb->stackState = WUD_STATE_START; + p_wcb->initState = WUD_STATE_START; + p_wcb->shutdownState = WUD_STATE_START; + + p_wcb->syncSkipChecks = FALSE; + p_wcb->syncType = WUD_SYNC_TYPE_STANDARD; + p_wcb->syncLoopNum = 1; + + p_wcb->connectable = FALSE; + p_wcb->discoverable = FALSE; + + p_wcb->libStatus = WUD_LIB_STATUS_0; + p_wcb->pmID = 0; + p_wcb->syncRssi = -65; + + memset(p_wcb->hostAddr, 0, BD_ADDR_LEN); + memset(p_wcb->pairAddr, 0, BD_ADDR_LEN); + + p_wcb->bufferStatus0 = 0; + p_wcb->bufferStatus1 = 10; + + __wudClearDevInfos(); +} + +BOOL WUDInit(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (_wudInitialized) + return FALSE; + + OSAssertMessage_Line(3086, p_wcb->allocFunc && p_wcb->freeFunc, + "No allocator is registered!\n" + "Please register allocator before initialization.\n"); + + BTA_Init(); + bta_sys_set_trace_level(__bte_trace_level); + L2CA_SetTraceLevel(__bte_trace_level); + SDP_SetTraceLevel(__bte_trace_level); + + p_wcb->syncStdCB = NULL; + p_wcb->syncSmpCB = NULL; + p_wcb->clearDevCB = NULL; + + p_wcb->hidConnCB = NULL; + p_wcb->hidRecvCB = NULL; + + p_wcb->initState = WUD_STATE_INIT_WAIT_FOR_DEVICE_UP; + p_wcb->initWaitDeviceUpFrames = 20; + + SCInit(); + + if (_linkedWBC && _initWBC) + (*_initWBC)(); + + OSCreateAlarm(&p_wcb->alarm); + OSSetPeriodicAlarm(&p_wcb->alarm, OSGetTime(), OSMillisecondsToTicks(10), + &__wudInitHandler0); + + _wudInitialized = TRUE; + _scFlush = FALSE; + + return TRUE; +} + +void WUDRegisterAllocator(WUDAllocFunc *alloc, WUDFreeFunc *free) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + OSAssert_Line(3137, alloc != NULL && free != NULL); + + BOOL intrStatus = OSDisableInterrupts(); + + p_wcb->allocFunc = alloc; + p_wcb->freeFunc = free; + + OSRestoreInterrupts(intrStatus); +} + +void WUDShutdown(BOOL saveSimpleDevs) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + if (WUDIsBusy()) + OSCancelAlarm(&p_wcb->alarm); + + memset(_scArray.devices, 0, + sizeof _scArray.devices[0] * WUD_MAX_DEV_ENTRY_FOR_STD); + + int i; + struct WUDDevInfoList *infoList; + + i = 0; + infoList = __rvl_wudcb.stdListHead; + while (infoList) + { + WUD_BDCPY(_scArray.devices[i].devAddr, infoList->devInfo->devAddr); + memcpy(&_scArray.devices[i].small, &infoList->devInfo->small, + sizeof _scArray.devices[i].small); + + infoList = infoList->next; + i++; + } + + _scArray.num = __wudGetStdDevNumber(); + + memset(_spArray.devices, 0, sizeof _spArray.devices); + + if (saveSimpleDevs) + { + i = 0; + infoList = __rvl_wudcb.smpListHead; + while (infoList) + { + WUD_BDCPY(_spArray.devices[i].devAddr, infoList->devInfo->devAddr); + memcpy(&_spArray.devices[i].small, &infoList->devInfo->small, + sizeof _spArray.devices[i].small); + + memcpy(&_spArray.devices[i].linkKey, &infoList->devInfo->linkKey, + LINK_KEY_LEN); + + infoList = infoList->next; + i++; + } + + _spArray.num = __wudGetSmpDevNumber(); + } + else + { + _spArray.num = 0; + } + + p_wcb->shutdownState = WUD_STATE_SHUTDOWN_STORE_SETTINGS; + + OSCreateAlarm(&p_wcb->alarm); + OSSetPeriodicAlarm(&p_wcb->alarm, OSGetTime(), OSMillisecondsToTicks(10), + &__wudShutdownHandler0); + + p_wcb->libStatus = WUD_LIB_STATUS_4; + + OSRestoreInterrupts(intrStatus); +} + +WUDLibStatus WUDGetStatus(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + s8 libStatus = p_wcb->libStatus; + + OSRestoreInterrupts(intrStatus); + + return libStatus; +} + +u8 WUDGetBufferStatus(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + u8 ret; + BOOL intrStatus = OSDisableInterrupts(); + + ret = p_wcb->bufferStatus1 - p_wcb->bufferStatus0; + + OSRestoreInterrupts(intrStatus); + + return ret; +} + +void WUDSetSniffMode(BD_ADDR dev_addr, int interval) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + tBTM_PM_PWR_MD block; + + if (interval > 0) + block.mode = BTM_PM_MD_SNIFF; + else + block.mode = BTM_PM_MD_ACTIVE; + + block.max = interval; + block.min = interval; + block.attempt = 1; + block.timeout = 0; + + tBTM_STATUS status __attribute__((unused)) = + BTM_SetPowerMode(p_wcb->pmID, dev_addr, &block); +} + +WUDSyncDeviceCallback *WUDSetSyncSimpleCallback(WUDSyncDeviceCallback *cb) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDSyncDeviceCallback *old; + BOOL intrStatus = OSDisableInterrupts(); + + old = p_wcb->syncSmpCB; + p_wcb->syncSmpCB = cb; + + OSRestoreInterrupts(intrStatus); + + return old; +} + +static BOOL __wudStartSyncDevice(WUDSyncType syncType, s8 syncLoopNum, + u8 target, signed param_4) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL ret = FALSE; + BOOL intrStatus = OSDisableInterrupts(); + + u32 libStatus = p_wcb->libStatus; + + OSRestoreInterrupts(intrStatus); + + if (libStatus == WUD_LIB_STATUS_3 && !WUDIsBusy()) + { + intrStatus = OSDisableInterrupts(); + + _wudTarget = target; + + p_wcb->syncState = WUD_STATE_SYNC_PREPARE_SEARCH; + p_wcb->syncLoopNum = syncLoopNum; + p_wcb->syncType = syncType; + p_wcb->syncSkipChecks = param_4 ? 1 : 0; + p_wcb->syncedNum = 0; + p_wcb->waitStartSearchFrames = 50; + p_wcb->waitIncomingFrames = 200; + + OSCreateAlarm(&p_wcb->alarm); + OSSetPeriodicAlarm(&p_wcb->alarm, OSGetTime(), + OSMillisecondsToTicks(20), &__wudSyncHandler0); + + OSRestoreInterrupts(intrStatus); + + ret = TRUE; + } + + return ret; +} + +static BOOL __wudStartSyncStandard(signed param_1) +{ + return __wudStartSyncDevice(WUD_SYNC_TYPE_STANDARD, 3, 0, param_1); +} + +static BOOL __wudStartSyncSimple(signed param_1) +{ + return __wudStartSyncDevice(WUD_SYNC_TYPE_SIMPLE, -1, 0, param_1); +} + +BOOL WUDStartSyncDevice(void) +{ + return __wudStartSyncStandard(0); +} + +BOOL WUDStartFastSyncSimple(void) +{ + return __wudStartSyncSimple(1); +} + +static BOOL __wudStopSyncDevice(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL success = FALSE; + BOOL intrStatus = OSDisableInterrupts(); + + if (p_wcb->libStatus == WUD_LIB_STATUS_3) + { + if (p_wcb->syncLoopNum) + { + if (p_wcb->syncState == WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT) + BTA_DmSearchCancel(); + + p_wcb->syncLoopNum = 0; + } + + success = TRUE; + } + + OSRestoreInterrupts(intrStatus); + + return success; +} + +BOOL WUDCancelSyncDevice(void) +{ + _wudAbortSync = TRUE; + + return __wudStopSyncDevice(); +} + +BOOL WUDStopSyncSimple(void) +{ + return __wudStopSyncDevice(); +} + +BOOL WUDStartClearDevice(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL success = FALSE; + BOOL intrStatus = OSDisableInterrupts(); + + u32 libStatus = p_wcb->libStatus; + + OSRestoreInterrupts(intrStatus); + + if (libStatus == WUD_LIB_STATUS_3 && !WUDIsBusy()) + { + intrStatus = OSDisableInterrupts(); + + p_wcb->deleteState = WUD_STATE_DELETE_DISALLOW_INCOMING; + + OSCreateAlarm(&p_wcb->alarm); + OSSetPeriodicAlarm(&p_wcb->alarm, OSGetTime(), + OSMillisecondsToTicks(20), &__wudDeleteHandler0); + + OSRestoreInterrupts(intrStatus); + + success = TRUE; + } + + return success; +} + +BOOL WUDSetDisableChannel(s8 afhChannel) +{ + int first = 0; + int last = 0; + + BOOL success = FALSE; + + wud_cb_st *p_wcb = &__rvl_wudcb; + +#if defined(NDEBUG) + if ((u8)afhChannel < 0 || 13 < (u8)afhChannel) +#else + if (afhChannel < 0 || 13 < afhChannel) +#endif + return success; + + BOOL intrStatus = OSDisableInterrupts(); + + u32 libStatus = p_wcb->libStatus; + + OSRestoreInterrupts(intrStatus); + + tBTM_STATUS result __attribute__((unused)); + if (libStatus == WUD_LIB_STATUS_3) + { + if (!afhChannel) + { + first = 255; + last = 255; + } + else + { + first = (afhChannel + 1) * 5 - 14; + last = (afhChannel + 1) * 5 + 14; + + if (first < 0) + first = 0; + + if (last > 78) + last = 78; + } + + result = BTM_SetAfhChannels(first, last); + + success = TRUE; + } + + return success; +} + +WUDHidReceiveCallback *WUDSetHidRecvCallback(WUDHidReceiveCallback *cb) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDHidReceiveCallback *old; + BOOL intrStatus = OSDisableInterrupts(); + + old = p_wcb->hidRecvCB; + p_wcb->hidRecvCB = cb; + + OSRestoreInterrupts(intrStatus); + + return old; +} + +WUDHidConnectCallback *WUDSetHidConnCallback(WUDHidConnectCallback *cb) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDHidConnectCallback *old; + BOOL intrStatus = OSDisableInterrupts(); + + old = p_wcb->hidConnCB; + p_wcb->hidConnCB = cb; + + OSRestoreInterrupts(intrStatus); + + return old; +} + +void WUDSetVisibility(u8 discoverable, u8 connectable) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + p_wcb->discoverable = discoverable; + p_wcb->connectable = connectable; + + OSRestoreInterrupts(intrStatus); + + // again, see notes about this prototype + BTA_DmSetVisibility(discoverable, connectable); +} + +u8 WUDGetConnectable(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + u8 connectable; + BOOL intrStatus = OSDisableInterrupts(); + + connectable = p_wcb->connectable; + + OSRestoreInterrupts(intrStatus); + + return connectable; +} + +static void __wudModuleRebootCallback(void *p1 __attribute__((unused))) +{ + __wudInitSub(); +} + +static void __wudModuleReboot(void) +{ + BTM_DeviceReset(&__wudModuleRebootCallback); +} + +static void __wudInstallPatchCallback(tBTM_VSC_CMPL *p1) +{ + if ((_wudPatchNum == _wudInstallNum && p1) || !p1) + __wudModuleReboot(); + else + __wudInstallPatch(); +} + +static void __wudInstallPatch(void) +{ + u8 num = MIN(_wudPatchNum - _wudInstallNum, INSTALL_PATCH_MAX_NUM); + + byte_t buf[INSTALL_PATCH_MAX_BUF]; + buf[offsetof(struct wud_patch_install_cmd_array, num)] = num; + memcpy(&buf[offsetof(struct wud_patch_install_cmd_array, installCmds)], + _wudPatchInstallCmd.installCmds[_wudInstallNum], + INSTALL_PATCH_TOTAL_SIZE(num)); + + _wudInstallNum += num; + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_INSTALL_PATCH, + (u8)sizeof num + INSTALL_PATCH_TOTAL_SIZE(num), + buf, &__wudInstallPatchCallback); +} + +static void __wudWritePatchCallback(tBTM_VSC_CMPL *p1) +{ + if (p1) + { + if (_wudPatchSize == (u32)_wudPatchOffset) + { + _wudInstallNum = 0; + _wudPatchNum = _wudPatchInstallCmd.num; + __wudInstallPatch(); + } + else + { + __wudWritePatch(); + } + } + else + { + __wudModuleReboot(); + } +} + +// TODO on release (fine in __wudWritePatchCallback, not in __wudRemovePatchCallback) + +static void __wudWritePatch(void) +{ + (void)_wudPatchOffset; // ok + + u8 length = MIN(_wudPatchSize - _wudPatchOffset, 255 - sizeof(u32)); + + int i; + byte_t buf[255]; + + // stwbrx op + for (i = 0; i < (int)sizeof(u32); i++) + buf[i] = (_wudPatchAddress + _wudPatchOffset) >> (i * 8); + + for (i = 0; i < (s32)length; i++) + { + buf[(int)sizeof(u32) + i] = + _wudPatchData[sizeof(_wudPatchSize) + sizeof(_wudPatchOffset) + + _wudPatchOffset + i]; + } + + _wudPatchOffset += length; + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_WRITE_PATCH, + (int)sizeof(u32) + length, buf, + &__wudWritePatchCallback); +} + +static void __wudRemovePatchCallback(tBTM_VSC_CMPL *p1) +{ + if (p1) + { + _wudPatchOffset = 0; + __wudWritePatch(); + } + else + { + __wudModuleReboot(); + } +} + +static void __wudRemovePatch(void) +{ + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_INSTALL_PATCH, + sizeof _wudPatchRemoveCmd, &_wudPatchRemoveCmd, + &__wudRemovePatchCallback); +} + +static void __wudSuperPeekPokeCallback(tBTM_VSC_CMPL *p1 + __attribute__((unused))) +{ + __wudRemovePatch(); +} + +static void __wudSuperPeekPoke(void) +{ + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_SUPER_PEEK_POKE, + sizeof _wudSuperPeekPokeCmd, _wudSuperPeekPokeCmd, + &__wudSuperPeekPokeCallback); +} + +static void __wudAppendRuntimePatch(void) +{ + _wudPatchSize = 0; + _wudPatchAddress = 0; + + int i; + for (i = 0; i < (int)sizeof(u32); i++) + { + // lwbrx ops + _wudPatchAddress <<= 8; + _wudPatchAddress += _wudPatchData[3 - i]; + + _wudPatchSize <<= 8; + _wudPatchSize += _wudPatchData[7 - i]; + } + + if (__OSInIPL) + __wudSuperPeekPoke(); + else + __wudRemovePatch(); +} + +static void __wudCheckFirmwareVersion(void) +{ + tBTM_VERSION_INFO version; + BTM_ReadLocalVersion(&version); + + if ((version.hci_revision & 0xfff) == 0xa7) + __wudAppendRuntimePatch(); + else + __wudInitSub(); +} + +static void __wudInitSub(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + char devName[] = "Wii"; + + // [1]: 2.8 Class of Device (p. 45) + DEV_CLASS devClass = + { + 0x00, // No designated Major Service Classes + 0x04, // Major Device Class 4 (Audio/Video) + 0x48 // Minor Device Class 18 (Audio/Video -> Gaming/Toy) + }; + + BTA_DmSetDeviceName(devName); + BTM_SetDeviceClass(devClass); + BTM_RegisterForVSEvents(&__wudVendorSpecificEventStackCallback); + BTM_RegisterForDeviceStatusNotif(&__wudDeviceStatusEventStackCallback); + BTM_PmRegister(BTM_PM_REG_SET | BTM_PM_REG_NOTIF, &p_wcb->pmID, + &__wudPowerManageEventStackCallback); + BTM_WritePageTimeout(0x8000); + BTM_SetDefaultLinkPolicy(HCI_ENABLE_MASTER_SLAVE_SWITCH + | HCI_ENABLE_SNIFF_MODE); + BTM_SetDefaultLinkSuperTout(3200); + + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + if (p_wcb->stdDevs[i].at_0x59 == 1) + WUDiRegisterDevice(p_wcb->stdDevs[i].devAddr); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + if (p_wcb->smpDevs[i].at_0x59 == 1) + WUDiRegisterDevice(p_wcb->smpDevs[i].devAddr); + + BOOL intrStatus = OSDisableInterrupts(); + + p_wcb->libStatus = WUD_LIB_STATUS_3; + _wudReadNand = TRUE; + + OSRestoreInterrupts(intrStatus); + + WUDSetVisibility(FALSE, TRUE); +} + +static void __wudEnableStack(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BTA_HhEnable(BTA_SEC_AUTHENTICATE, &WUDiHidHostEventCallback); + + p_wcb->stackState = WUD_STATE_STACK_GET_STORED_LINK_KEY; + + OSCreateAlarm(&p_wcb->alarm); + OSSetPeriodicAlarm(&p_wcb->alarm, OSGetTime(), OSMillisecondsToTicks(10), + &__wudStackHandler0); +} + +static void __wudProcSyncEvent(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (WUDIsBusy()) + return; + + WUDSyncDeviceCallback *cb; + BOOL intrStatus = OSDisableInterrupts(); + + cb = p_wcb->syncStdCB; + + OSRestoreInterrupts(intrStatus); + + if (cb) + (*cb)(0, 0); + else + WUDStartSyncDevice(); +} + +static void __wudProcDeleteEvent(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDClearDeviceCallback *cb; + signed arg; + BOOL intrStatus = OSDisableInterrupts(); + + cb = p_wcb->clearDevCB; + arg = WUDIsBusy() ? -1 : 0; + + OSRestoreInterrupts(intrStatus); + + if (cb) + (*cb)(arg); + else + WUDStartClearDevice(); +} + +void WUDiRegisterDevice(BD_ADDR dev_addr) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDDevInfo *p_info; + BOOL intrStatus = OSDisableInterrupts(); + p_info = WUDiGetDevInfo(dev_addr); + + OSAssert_Line(4215, p_info != NULL); + OSAssert_Line(4216, p_wcb->devNums <= WUD_MAX_DEV_ENTRY_FOR_STD); + OSAssert_Line(4217, p_wcb->devSmpNums <= WUD_MAX_DEV_ENTRY_FOR_SMP); + + tBTA_STATUS status __attribute__((unused)) = + BTA_DmAddDevice(p_info->devAddr, p_info->linkKey, 0, FALSE); + + if (WUD_DEV_NAME_IS_CNT(p_info->small.devName) + || (WUD_DEV_NAME_IS_WBC(p_info->small.devName) && WUDIsLinkedWBC())) + { + tBTA_HH_DEV_DESCR devDescInfo; + devDescInfo.dl_len = sizeof _wudWiiRemoteDescriptor; + devDescInfo.dsc_list = _wudWiiRemoteDescriptor; + + BTA_HhAddDev(p_info->devAddr, p_info->hhAttrMask, p_info->subclass, + p_info->appID, devDescInfo); + } + + if (p_info->at_0x5b == 0 || p_info->at_0x5b == 4 || p_info->at_0x5b == 2 + || p_info->at_0x5b == 5) + { + p_wcb->devNums++; + } + else + { + p_wcb->devSmpNums++; + } + + OSRestoreInterrupts(intrStatus); +} + +void WUDiRemoveDevice(BD_ADDR dev_addr) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + + BOOL intrStatus = OSDisableInterrupts(); + p_info = WUDiGetDevInfo(dev_addr); + if (!p_info) + goto end; + + if (WUD_DEV_NAME_IS_CNT(p_info->small.devName) + || (WUD_DEV_NAME_IS_WBC(p_info->small.devName) && WUDIsLinkedWBC())) + { + BTA_HhRemoveDev(p_info->devHandle); + } + + tBTM_STATUS status __attribute__((unused)) = + BTA_DmRemoveDevice(p_info->devAddr); + + if (p_info->at_0x5b == 0 || p_info->at_0x5b == 2 || p_info->at_0x5b == 4 + || p_info->at_0x5b == 5) + { + p_wcb->devNums--; + } + else + { + p_wcb->devSmpNums--; + } + + memset(p_info, 0, sizeof *p_info); + +end: + OSRestoreInterrupts(intrStatus); +} + +WUDDevInfo *WUDiGetDevInfo(BD_ADDR dev_addr) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info = NULL; + + BOOL intrStatus = OSDisableInterrupts(); + + int i; + for (i = 0; i < (int)ARRAY_LENGTH(p_wcb->stdDevs); i++) + { + if (WUD_BDCMP(p_wcb->stdDevs[i].devAddr, dev_addr) == 0) + { + p_info = &p_wcb->stdDevs[i]; + break; + } + } + + if (!p_info) + { + for (i = 0; i < (int)ARRAY_LENGTH(p_wcb->smpDevs); i++) + { + if (WUD_BDCMP(p_wcb->smpDevs[i].devAddr, dev_addr) == 0) + { + p_info = &p_wcb->smpDevs[i]; + break; + } + } + } + + OSRestoreInterrupts(intrStatus); + + return p_info; +} + +static WUDDevInfo *__wudGetDevInfoByIndex(int index) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + OSAssert_Line(4374, index >= 0 && index <= WUD_MAX_DEV_ENTRY); + + BOOL intrStatus = OSDisableInterrupts(); + + WUDDevInfo *p_info; + +// idk +#if defined(NDEBUG) + if (0 <= (u32)index && (u32)index <= 9) +#else + if (0 <= index && index < 10) +#endif // defined(NDEBUG) + p_info = &p_wcb->stdDevs[index]; + else + p_info = &p_wcb->smpDevs[index - ARRAY_LENGTH(p_wcb->stdDevs)]; + + OSRestoreInterrupts(intrStatus); + + return p_info; +} + +static WUDDevInfo *__wudGetNewStdDevInfo(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info = NULL; + + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + if (p_wcb->stdDevs[i].at_0x59 == 0) + { + p_info = &p_wcb->stdDevs[i]; + break; + } + } + + return p_info; +} + +static WUDDevInfo *__wudGetNewSmpDevInfo(void) +{ + return __rvl_wudcb.smpListTail->devInfo; +} + +static WUDDevInfo *__wudGetNewDevInfo(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + WUDDevInfo *p_info = NULL; + BOOL intrStatus = OSDisableInterrupts(); + + if (p_wcb->syncType == WUD_SYNC_TYPE_STANDARD) + p_info = __wudGetNewStdDevInfo(); + else + p_info = __wudGetNewSmpDevInfo(); + + OSRestoreInterrupts(intrStatus); + + return p_info; +} + +static void __wudRemoveDevInfo(BD_ADDR dev_addr) +{ + WUDDevInfo *p_info = WUDiGetDevInfo(dev_addr); + if (!p_info) + return; + + BOOL intrStatus = OSDisableInterrupts(); + + memset(p_info, 0, sizeof *p_info); + + OSRestoreInterrupts(intrStatus); +} + +static void __wudClearDevInfos(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + memset(p_wcb->stdDevs, 0, sizeof p_wcb->stdDevs); + memset(p_wcb->smpDevs, 0, sizeof p_wcb->smpDevs); + + p_wcb->devNums = 0; + p_wcb->devSmpNums = 0; + + p_wcb->connectedNum = 0; + p_wcb->linkedNum = 0; + p_wcb->syncedNum = 0; + + OSRestoreInterrupts(intrStatus); +} + +static u8 __wudGetStdDevNumber(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 num = p_wcb->devNums; + + OSRestoreInterrupts(intrStatus); + + return num; +} + +static u8 __wudGetSmpDevNumber(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 num = p_wcb->devSmpNums; + + OSRestoreInterrupts(intrStatus); + + return num; +} + +static u8 __wudGetConnectionNumber(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 num = p_wcb->connectedNum; + + OSRestoreInterrupts(intrStatus); + + return num; +} + +static u8 __wudGetLinkNumber(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 num = p_wcb->linkedNum; + + OSRestoreInterrupts(intrStatus); + + return num; +} + +void WUDiMoveTopSmpDevInfoPtr(WUDDevInfo *dev_info) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + { + if (WUD_BDCMP(p_wcb->smpList[i].devInfo->devAddr, dev_info->devAddr) + != 0) + { + continue; + } + + if (WUD_BDCMP(p_wcb->smpListHead->devInfo->devAddr, + p_wcb->smpList[i].devInfo->devAddr) + == 0) + { + break; + } + + p_wcb->smpList[i].prev->next = p_wcb->smpList[i].next; + + if (WUD_BDCMP(p_wcb->smpListTail->devInfo->devAddr, + p_wcb->smpList[i].devInfo->devAddr) + == 0) + { + p_wcb->smpListTail = p_wcb->smpList[i].prev; + } + else + { + p_wcb->smpList[i].next->prev = p_wcb->smpList[i].prev; + } + + p_wcb->smpList[i].next = p_wcb->smpListHead; + p_wcb->smpListHead->prev = &p_wcb->smpList[i]; + p_wcb->smpListHead = &p_wcb->smpList[i]; + + p_wcb->smpList[i].prev = NULL; + + break; + } + + OSRestoreInterrupts(intrStatus); +} + +void WUDiMoveBottomSmpDevInfoPtr(WUDDevInfo *dev_info) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + { + if (WUD_BDCMP(p_wcb->smpList[i].devInfo->devAddr, dev_info->devAddr) + != 0) + { + continue; + } + + if (WUD_BDCMP(p_wcb->smpListTail->devInfo->devAddr, + p_wcb->smpList[i].devInfo->devAddr) + == 0) + { + break; + } + + p_wcb->smpList[i].next->prev = p_wcb->smpList[i].prev; + + if (WUD_BDCMP(p_wcb->smpListHead->devInfo->devAddr, + p_wcb->smpList[i].devInfo->devAddr) + == 0) + { + p_wcb->smpListHead = p_wcb->smpList[i].next; + } + else + { + p_wcb->smpList[i].prev->next = p_wcb->smpList[i].next; + } + + p_wcb->smpList[i].prev = p_wcb->smpListTail; + p_wcb->smpListTail->next = &p_wcb->smpList[i]; + p_wcb->smpListTail = &p_wcb->smpList[i]; + + p_wcb->smpList[i].next = NULL; + + break; + } + + OSRestoreInterrupts(intrStatus); +} + +void WUDiMoveTopOfDisconnectedSmpDevice(WUDDevInfo *dev_info) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + int i; + + BOOL intrStatus = OSDisableInterrupts(); + + struct WUDDevInfoList *p_list; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + { + if (WUD_BDCMP(p_wcb->smpList[i].devInfo->devAddr, dev_info->devAddr) + != 0) + { + continue; + } + + for (p_list = p_wcb->smpListHead; p_list; p_list = p_list->next) + { + if (WUD_BDCMP(p_list->devInfo->devAddr, dev_info->devAddr) == 0) + continue; + + if (p_list->devInfo->at_0x59 != 1 && p_list->devInfo->at_0x59 != 0) + continue; + + if (WUD_BDCMP(p_wcb->smpListHead->devInfo->devAddr, + p_wcb->smpList[i].devInfo->devAddr) + == 0) + { + if (p_list == p_wcb->smpListHead->next) + break; + + p_wcb->smpListHead = p_wcb->smpList[i].next; + } + else + { + p_wcb->smpList[i].prev->next = p_wcb->smpList[i].next; + } + + p_wcb->smpList[i].next->prev = p_wcb->smpList[i].prev; + + if (p_list != p_wcb->smpListHead) + { + p_wcb->smpList[i].prev = p_list->prev; + p_wcb->smpList[i].next = p_list; + + p_list->prev->next = &p_wcb->smpList[i]; + p_list->prev = &p_wcb->smpList[i]; + } + else + { + p_wcb->smpList[i].prev = p_list; + p_wcb->smpList[i].next = p_list->next; + + p_list->next->prev = &p_wcb->smpList[i]; + p_list->next = &p_wcb->smpList[i]; + } + + break; + } + } + + OSRestoreInterrupts(intrStatus); +} + +void WUDiMoveTopStdDevInfoPtr(WUDDevInfo *dev_info) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + if (WUD_BDCMP(p_wcb->stdList[i].devInfo->devAddr, dev_info->devAddr) + != 0) + { + continue; + } + + if (WUD_BDCMP(p_wcb->stdListHead->devInfo->devAddr, + p_wcb->stdList[i].devInfo->devAddr) + == 0) + { + break; + } + + p_wcb->stdList[i].prev->next = p_wcb->stdList[i].next; + + if (WUD_BDCMP(p_wcb->stdListTail->devInfo->devAddr, + p_wcb->stdList[i].devInfo->devAddr) + == 0) + { + p_wcb->stdListTail = p_wcb->stdList[i].prev; + } + else + { + p_wcb->stdList[i].next->prev = p_wcb->stdList[i].prev; + } + + p_wcb->stdList[i].next = p_wcb->stdListHead; + p_wcb->stdListHead->prev = &p_wcb->stdList[i]; + p_wcb->stdListHead = &p_wcb->stdList[i]; + + p_wcb->stdList[i].prev = NULL; + + break; + } + + OSRestoreInterrupts(intrStatus); +} + +void WUDiMoveBottomStdDevInfoPtr(WUDDevInfo *dev_info) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + int i; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + if (WUD_BDCMP(p_wcb->stdList[i].devInfo->devAddr, dev_info->devAddr) + != 0) + { + continue; + } + + if (WUD_BDCMP(p_wcb->stdListTail->devInfo->devAddr, + p_wcb->stdList[i].devInfo->devAddr) + == 0) + { + break; + } + + p_wcb->stdList[i].next->prev = p_wcb->stdList[i].prev; + + if (WUD_BDCMP(p_wcb->stdListHead->devInfo->devAddr, + p_wcb->stdList[i].devInfo->devAddr) + == 0) + { + p_wcb->stdListHead = p_wcb->stdList[i].next; + } + else + { + p_wcb->stdList[i].prev->next = p_wcb->stdList[i].next; + } + + p_wcb->stdList[i].prev = p_wcb->stdListTail; + p_wcb->stdListTail->next = &p_wcb->stdList[i]; + p_wcb->stdListTail = &p_wcb->stdList[i]; + + p_wcb->stdList[i].next = NULL; + + break; + } + + OSRestoreInterrupts(intrStatus); +} + +void WUDiMoveTopOfDisconnectedStdDevice(WUDDevInfo *devInfo) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + int i; + + BOOL intrStatus = OSDisableInterrupts(); + + struct WUDDevInfoList *p_list; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + if (WUD_BDCMP(p_wcb->stdList[i].devInfo->devAddr, devInfo->devAddr) + != 0) + { + continue; + } + + for (p_list = p_wcb->stdListHead; p_list; p_list = p_list->next) + { + if (WUD_BDCMP(p_list->devInfo->devAddr, devInfo->devAddr) == 0) + continue; + + if (p_list->devInfo->at_0x59 != 1 && p_list->devInfo->at_0x59 != 0 + && (WUD_DEV_NAME_IS_CNT(p_list->devInfo->small.devName) + || !WUDIsLinkedWBC())) + { + continue; + } + + if (WUD_BDCMP(p_wcb->stdListHead->devInfo->devAddr, + p_wcb->stdList[i].devInfo->devAddr) + == 0) + { + if (p_list == p_wcb->stdListHead->next) + break; + + p_wcb->stdListHead = p_wcb->stdList[i].next; + } + else + { + p_wcb->stdList[i].prev->next = p_wcb->stdList[i].next; + } + + p_wcb->stdList[i].next->prev = p_wcb->stdList[i].prev; + + if (p_list != p_wcb->stdListHead) + { + p_wcb->stdList[i].prev = p_list->prev; + p_wcb->stdList[i].next = p_list; + + p_list->prev->next = &p_wcb->stdList[i]; + p_list->prev = &p_wcb->stdList[i]; + } + else + { + p_wcb->stdList[i].prev = p_list; + p_wcb->stdList[i].next = p_list->next; + + p_list->next->prev = &p_wcb->stdList[i]; + p_list->next = &p_wcb->stdList[i]; + } + + break; + } + } + + OSRestoreInterrupts(intrStatus); +} + +void WUDiMoveTopOfUnusedStdDevice(WUDDevInfo *dev_info) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + int i; + + BOOL intrStatus = OSDisableInterrupts(); + + struct WUDDevInfoList *p_list; + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) + { + if (WUD_BDCMP(p_wcb->stdList[i].devInfo->devAddr, dev_info->devAddr) + != 0) + { + continue; + } + + for (p_list = p_wcb->stdListHead; p_list; p_list = p_list->next) + { + if (WUD_BDCMP(p_list->devInfo->devAddr, dev_info->devAddr) == 0) + continue; + + if (p_list->devInfo->at_0x59 != 0 && p_list != p_wcb->stdListTail) + continue; + + if (WUD_BDCMP(p_wcb->stdListHead->devInfo->devAddr, + p_wcb->stdList[i].devInfo->devAddr) + == 0) + { + if (p_list == p_wcb->stdListHead->next) + break; + + p_wcb->stdListHead = p_wcb->stdList[i].next; + } + else + { + p_wcb->stdList[i].prev->next = p_wcb->stdList[i].next; + } + + p_wcb->stdList[i].next->prev = p_wcb->stdList[i].prev; + + if (p_list == p_wcb->stdListTail && p_list->devInfo->at_0x59 != 0) + { + p_wcb->stdList[i].prev = p_list; + p_wcb->stdList[i].next = NULL; + + p_list->next = &p_wcb->stdList[i]; + + p_wcb->stdListTail = &p_wcb->stdList[i]; + } + else if (p_list != p_wcb->stdListHead) + { + p_wcb->stdList[i].prev = p_list->prev; + p_wcb->stdList[i].next = p_list; + + p_list->prev->next = &p_wcb->stdList[i]; + p_list->prev = &p_wcb->stdList[i]; + } + else + { + p_wcb->stdList[i].prev = p_list; + p_wcb->stdList[i].next = p_list->next; + + p_list->next->prev = &p_wcb->stdList[i]; + p_list->next = &p_wcb->stdList[i]; + } + + break; + } + } + + OSRestoreInterrupts(intrStatus); +} + +static WUDDevInfo *__wudGetOldestSmpDevice(void) +{ + return __rvl_wudcb.smpListTail->devInfo; +} + +static WUDDevInfo *__wudGetOldestStdDevice(void) +{ + return __rvl_wudcb.stdListTail->devInfo; +} + +BOOL WUDIsBusy(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + if (p_wcb->syncState == WUD_STATE_START + && p_wcb->deleteState == WUD_STATE_START + && p_wcb->stackState == WUD_STATE_STACK_INITIALIZED + && p_wcb->initState == WUD_STATE_INIT_INITIALIZED) + { + OSRestoreInterrupts(intrStatus); + return FALSE; + } + else + { + OSRestoreInterrupts(intrStatus); + return TRUE; + } +} + +static void __wudCleanupStackCallback(tBTA_STATUS status) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (status == BTA_SUCCESS) + { + _wudInitialized = FALSE; + p_wcb->libStatus = WUD_LIB_STATUS_0; + } +} + +static void __wudSecurityEventStackCallback(tBTA_DM_SEC_EVT event, + tBTA_DM_SEC *p_data) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + u8 i; + + tBTA_DM_ENABLE *dmEnable; + tBTA_DM_LINK_UP *dmLinkUp; + tBTA_DM_LINK_DOWN *dmLinkDown; + tBTA_DM_PIN_REQ *dmPinReq; + tBTA_DM_AUTH_CMPL *dmAuthCmpl; + + switch (event) + { + case BTA_DM_ENABLE_EVT: + dmEnable = &p_data->enable; + WUD_BDCPY(p_wcb->hostAddr, dmEnable->bd_addr); + __wudEnableStack(); + + p_wcb->libStatus = WUD_LIB_STATUS_2; + + break; + + case BTA_DM_DISABLE_EVT: + BTA_CleanUp(__wudCleanupStackCallback); + + break; + + case BTA_DM_PIN_REQ_EVT: + dmPinReq = &p_data->pin_req; + __wudSetPinCode(dmPinReq->bd_addr); + + break; + + case BTA_DM_AUTH_CMPL_EVT: + dmAuthCmpl = &p_data->auth_cmpl; + + if (dmAuthCmpl->key_type == HCI_LKEY_TYPE_COMBINATION) + break; + + p_info = WUDiGetDevInfo(dmAuthCmpl->bd_addr); + + if (WUD_BDCMP(_wudDiscWork.devAddr, dmAuthCmpl->bd_addr) == 0) + { + _wudDiscWork.at_0x59 = 12; + + if (!p_info) + p_info = &_wudDiscWork; + } + + OSAssert_Line(5140, p_info != NULL); + + memcpy(p_info->linkKey, dmAuthCmpl->key, LINK_KEY_LEN); + break; + + case BTA_DM_AUTHORIZE_EVT: + { + tBTA_DM_AUTHORIZE *dmAuthorize __attribute__((unused)) = + &p_data->authorize; + } + break; + + case BTA_DM_LINK_UP_EVT: + dmLinkUp = &p_data->link_up; + + p_info = WUDiGetDevInfo(dmLinkUp->bd_addr); + + if (!p_info && WUD_BDCMP(dmLinkUp->bd_addr, _wudDiscWork.devAddr) == 0) + p_info = &_wudDiscWork; + + if (!p_info || __wudGetLinkNumber() == WUD_MAX_CHANNELS) + { + btm_remove_acl(dmLinkUp->bd_addr); + break; + } + + p_info->at_0x59 = p_info->at_0x59 == 2 ? 12 : 3; + p_wcb->linkedNum++; + + break; + + case BTA_DM_LINK_DOWN_EVT: + dmLinkDown = &p_data->link_down; + + p_info = WUDiGetDevInfo(dmLinkDown->bd_addr); + if (p_info) + { + p_info->at_0x59 = 1; + p_wcb->linkedNum--; + + if (WUD_BDCMP(_wudDiscWork.devAddr, dmLinkDown->bd_addr) == 0) + p_wcb->syncState = WUD_STATE_ERROR; + + if (dmLinkDown->status == HCI_ERR_PEER_POWER_OFF) + { + for (i = 0; i < WUD_MAX_CHANNELS; i++) + { + if (WUD_BDCMP(_scArray.devices[10 + i].devAddr, + dmLinkDown->bd_addr) + == 0) + { + memset(&_scArray.devices[10 + i], 0, + sizeof _scArray.devices[10 + i]); + _scFlush = TRUE; + } + } + } + } + else if (WUD_BDCMP(_wudDiscWork.devAddr, dmLinkDown->bd_addr) == 0) + { + p_wcb->syncState = WUD_STATE_ERROR; + p_wcb->linkedNum--; + } + + if (p_wcb->linkedNum <= 255 && p_wcb->linkedNum >= 250) + { + OSReport("WARNING: link num count is reset.\n"); + p_wcb->linkedNum = 0; + } + break; + + case BTA_DM_SIG_STRENGTH_EVT: + { + tBTA_DM_SIG_STRENGTH *dmSigStrength __attribute__((unused)) = + &p_data->sig_strength; + } + break; + + case BTA_DM_BUSY_LEVEL_EVT: + { + tBTA_DM_BUSY_LEVEL *dmBusyLevel __attribute__((unused)) = + &p_data->busy_level; + } + break; + } +} + +static void __wudSearchEventStackCallback(tBTA_DM_SEARCH_EVT event, + tBTA_DM_SEARCH *p_data) +{ + int timeout; + + switch (event) + { + case BTA_DM_INQ_RES_EVT: + { + tBTA_DM_INQ_RES *dmInqRes = &p_data->inq_res; + + _wudDiscRssi = dmInqRes->rssi; + + if (__rvl_wudcb.syncSkipChecks == 1 + || (__rvl_wudcb.syncSkipChecks == 0 && __wudGetLinkNumber() < 3)) + { + timeout = 0x1900; + } + else + { + timeout = 0x8000; + } + + BTM_WritePageTimeout(timeout); + } + break; + + case BTA_DM_DISC_RES_EVT: + { + tBTA_DM_DISC_RES *dmDiscRes = &p_data->disc_res; + + WUD_BDCPY(_wudDiscResp.devAddr, dmDiscRes->bd_addr); + memcpy(_wudDiscResp.at_0x006, dmDiscRes->bd_name, + sizeof _wudDiscResp.at_0x006); + + _wudDiscResp.services = dmDiscRes->services; + _wudDiscNumResps++; + } + break; + + case BTA_DM_DISC_BLE_RES_EVT: + __rvl_wudcb.syncState = WUD_STATE_SYNC_CHECK_SEARCH_RESULT; + break; + + case BTA_DM_DISC_CMPL_EVT: + __wudResetAuthFailCount(); + __wudClearDiscoverResult(); + + __rvl_wudcb.syncState = WUD_STATE_SYNC_CHECK_SEARCH_RESULT; + break; + } +} + +static void __wudVendorSpecificEventStackCallback(UINT8 len + __attribute__((unused)), + UINT8 *p) +{ + (void)len; // mhm + + u8 result = p[0]; + + wud_cb_st *p_wcb = &__rvl_wudcb; + + switch (result) + { + case 8: + __wudProcSyncEvent(); + break; + + case 9: + __wudProcDeleteEvent(); + break; + + case 10: + p_wcb->unk_0x709 = p[1]; + break; + + case 16: + OSError_Line(5387, "MODULE FATAL ERROR\n"); + } +} + +static void __wudDeviceStatusEventStackCallback(tBTM_DEV_STATUS status) +{ + if (status == BTM_DEV_STATUS_CMD_TOUT) + { + OSReport("---- WARNING: USB FATAL ERROR! ----\n"); // usb ??? + WUDiShowFatalErrorMessage(); + } +} + +static void __wudLinkKeyEventStackCallback(void *p1) +{ + tBTM_BD_ADDR_LINK_KEY_PAIR *p_pair; + + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + int i; + + tBTM_STORED_LINK_KEYS_EVT *data = p1; + + tBTM_READ_STORED_LINK_KEY_COMPLETE *p_r_cmpl __attribute__((unused)); + tBTM_WRITE_STORED_LINK_KEY_COMPLETE *p_w_cmpl; + tBTM_DELETE_STORED_LINK_KEY_COMPLETE *p_d_cmpl; + + tBTM_RETURN_LINK_KEYS_EVT *p_ret_cmpl; + + switch (data->event) + { + case BTM_CB_EVT_RETURN_LINK_KEYS: + p_ret_cmpl = p1; + + p_pair = (tBTM_BD_ADDR_LINK_KEY_PAIR *)(p_ret_cmpl + 1); + i = 0; + while (i < p_ret_cmpl->num_keys) + { + p_info = WUDiGetDevInfo(p_pair->bd_addr); + if (!p_info) + { + p_info = __wudGetNewDevInfo(); + if (!p_info) + { + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) + { + if (p_wcb->smpDevs[i].at_0x59 == 0) + { + p_info = &p_wcb->smpDevs[i]; + break; + } + } + } + + if (p_info) + { + p_info->at_0x5c = 1; + p_info->at_0x59 = 1; + + WUD_BDCPY(p_info->devAddr, p_pair->bd_addr); + memcpy(p_info->linkKey, p_pair->link_key, LINK_KEY_LEN); + } + } + else + { + WUD_BDCPY(p_info->devAddr, p_pair->bd_addr); + memcpy(p_info->linkKey, p_pair->link_key, LINK_KEY_LEN); + + if (p_info->at_0x5c == 2) + p_info->at_0x5c = 3; + + WUD_BDCPY(p_wcb->pairAddr, p_pair->bd_addr); + } + + p_pair++; + i++; + } + + break; + + case BTM_CB_EVT_READ_STORED_LINK_KEYS: + p_r_cmpl = p1; + + p_wcb->linkKeyState = WUD_STATE_START; + break; + + case BTM_CB_EVT_WRITE_STORED_LINK_KEYS: + p_w_cmpl = p1; + + OSAssert_Line(5527, p_w_cmpl->num_keys != 0); + p_wcb->linkKeyState = WUD_STATE_START; + break; + + case BTM_CB_EVT_DELETE_STORED_LINK_KEYS: + p_d_cmpl = p1; + + (void)!(u16)p_d_cmpl->num_keys; // What + + p_wcb->linkKeyState = WUD_STATE_START; + break; + + default: + OSError_Line(5544, "Unknown event\n"); + } +} + +static void __wudPowerManageEventStackCallback( + BD_ADDR p_bda, tBTM_PM_STATUS status, UINT16 value __attribute__((unused)), + UINT8 hci_status __attribute__((unused))) +{ + wud_cb_st *p_wcb __attribute__((unused)) = &__rvl_wudcb; + + WUDDevInfo *p_info = WUDiGetDevInfo(p_bda); + if (!p_info) + { + if (WUD_BDCMP(_wudDiscWork.devAddr, p_bda) == 0) + p_info = &_wudDiscWork; + else + return; + } + + OSAssert_Line(5584, p_info != NULL); + + switch (status) + { + case BTM_PM_STS_ACTIVE: + p_info->at_0x59 = 8; + break; + + case BTM_PM_STS_SNIFF: + p_info->at_0x59 = 9; + break; + } +} + +static void __wudResetAuthFailCount(void) +{ + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_WRITE_PATCH, + sizeof _wudResetAuthCountCmd, + _wudResetAuthCountCmd, NULL); +} + +static WUDDevInfo *__wudGetWbcDevice(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info = NULL; + struct WUDDevInfoList *p_list; + + BOOL intrStatus = OSDisableInterrupts(); + + for (p_list = p_wcb->stdListHead; p_list; p_list = p_list->next) + if (WUD_DEV_NAME_IS_WBC(p_list->devInfo->small.devName)) + p_info = p_list->devInfo; + + OSRestoreInterrupts(intrStatus); + + return p_info; +} + +BD_ADDR_PTR _WUDGetDevAddr(UINT8 dev_handle) +{ + BD_ADDR_PTR devAddr; + + BOOL intrStatus = OSDisableInterrupts(); + + if (dev_handle < WUD_MAX_DEV_ENTRY) + devAddr = WUDiGetDevAddrForHandle(dev_handle); + else + devAddr = NULL; + + OSRestoreInterrupts(intrStatus); + + return devAddr; +} + +u16 _WUDGetQueuedSize(WUDDevHandle dev_handle) +{ + u16 queuedSize; + + BOOL intrStatus = OSDisableInterrupts(); + + if (DEV_HANDLE_BOUNDS_CHECK(dev_handle)) + queuedSize = WUDiGetQueueSizeForHandle(dev_handle); + else + queuedSize = 0; + + OSRestoreInterrupts(intrStatus); + + return queuedSize; +} + +u16 _WUDGetNotAckedSize(WUDDevHandle dev_handle) +{ + u16 notAckedSize; + + BOOL intrStatus = OSDisableInterrupts(); + + if (DEV_HANDLE_BOUNDS_CHECK(dev_handle)) + notAckedSize = WUDiGetNotAckNumForHandle(dev_handle); + else + notAckedSize = 0; + + OSRestoreInterrupts(intrStatus); + + return notAckedSize; +} + +u8 _WUDGetLinkNumber(void) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + BOOL intrStatus = OSDisableInterrupts(); + + u8 linkedNum = p_wcb->linkedNum; + + OSRestoreInterrupts(intrStatus); + + return linkedNum; +} + +WUDDevInfo *WUDiGetDiscoverDevice(void) +{ + return &_wudDiscWork; +} + +void WUDSetDeviceHistory(WUDChannel chan, BD_ADDR dev_addr) +{ + if (!dev_addr) + { + memset(&_scArray.devices[10 + chan], 0, + sizeof _scArray.devices[10 + chan]); + } + else + { + WUD_BDCPY(_scArray.devices[10 + chan].devAddr, dev_addr); + } + + _scFlush = TRUE; +} + +BOOL WUDIsLatestDevice(WUDChannel chan, BD_ADDR devAddr) +{ + if (!devAddr) + return FALSE; + + if (WUD_BDCMP(_scArray.devices[10 + chan].devAddr, devAddr) == 0) + return TRUE; + else + return FALSE; +} + +void WUDUpdateSCSetting(void) +{ + if (!_scFlush) + return; + + if (SCSetBtDeviceInfoArray(&_scArray)) + { + SCFlushAsync(NULL); + _scFlush = FALSE; + } +} + +void WUDiSetDevAddrForHandle(UINT8 dev_handle, BD_ADDR dev_addr) +{ + _dev_handle_to_bda[dev_handle] = dev_addr; +} + +BD_ADDR_PTR WUDiGetDevAddrForHandle(UINT8 dev_handle) +{ + return _dev_handle_to_bda[dev_handle]; +} + +void WUDiSetQueueSizeForHandle(UINT8 dev_handle, u16 size) +{ + _dev_handle_queue_size[dev_handle] = size; +} + +u16 WUDiGetQueueSizeForHandle(UINT8 dev_handle) +{ + return _dev_handle_queue_size[dev_handle]; +} + +void WUDiSetNotAckNumForHandle(UINT8 dev_handle, u16 count) +{ + _dev_handle_notack_num[dev_handle] = count; +} + +u16 WUDiGetNotAckNumForHandle(UINT8 dev_handle) +{ + return _dev_handle_notack_num[dev_handle]; +} + +void WUDiShowFatalErrorMessage(void) +{ + return; +} diff --git a/src/sdk/RVL_SDK/revolution/wpad/WUD.h b/src/sdk/RVL_SDK/revolution/wpad/WUD.h new file mode 100644 index 00000000..8a716586 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WUD.h @@ -0,0 +1,123 @@ +#ifndef RVL_SDK_WPAD_WUD_H +#define RVL_SDK_WPAD_WUD_H + +/******************************************************************************* + * headers + */ + +#include + +#include "context_bte.h" + +/******************************************************************************* + * macros + */ + +#define WUD_MAX_DEV_ENTRY_FOR_STD 10 // name known from asserts +#define WUD_MAX_DEV_ENTRY_FOR_SMP 6 // name known from asserts + +#define WUD_MAX_DEV_ENTRY 16 // name known from asserts + +/******************************************************************************* + * types + */ + +#ifdef __cplusplus + extern "C" { +#endif + +typedef s8 WUDDevHandle; +#define WUD_DEV_HANDLE_INVALID (-1) + +typedef s32 WUDChannel; +enum WUDChannel_et +{ + WUD_CHAN0, + WUD_CHAN1, + WUD_CHAN2, + WUD_CHAN3, + + WUD_MAX_CHANNELS, + WUD_CHAN_INVALID = -1 +}; + +typedef s32 WUDLibStatus; +enum WUDLibStatus_et +{ + WUD_LIB_STATUS_0, + WUD_LIB_STATUS_1, + WUD_LIB_STATUS_2, + WUD_LIB_STATUS_3, + WUD_LIB_STATUS_4, +}; + +typedef u8 WUDSyncType; +enum WUDSyncType_et +{ + WUD_SYNC_TYPE_STANDARD, + WUD_SYNC_TYPE_SIMPLE, +}; + +typedef void *WUDAllocFunc(size_t size); +typedef int WUDFreeFunc(void *ptr); // signature from petari. not sure what the int is, though + +typedef void WUDSyncDeviceCallback(s32 result, s32 num); // what is result? +typedef void WUDClearDeviceCallback(signed); + +typedef struct WUDDevInfo WUDDevInfo; +typedef void WUDHidConnectCallback(WUDDevInfo *devInfo, u8 isOpenEvent); +typedef void WUDHidReceiveCallback(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len); + +struct WUDDevInfo +{ + struct small_dev_info small; // size 0x40, offset 0x00 + BD_ADDR devAddr; // size 0x06, offset 0x40 + LINK_KEY linkKey; // size 0x10, offset 0x46 + UINT8 devHandle; // size 0x01, offset 0x56 + UINT8 subclass; // size 0x01, offset 0x57 + UINT8 appID; // size 0x01, offset 0x58 + u8 at_0x59; // size 0x01, offset 0x59 + char signed at_0x5a; // size 0x01, offset 0x5a /* unknown */ + u8 at_0x5b; // size 0x01, offset 0x5b + u8 at_0x5c; // size 0x01, offset 0x5c + byte_t unk_0x5d[1]; // padding? + tBTA_HH_ATTR_MASK hhAttrMask; // size 0x02, offset 0x5e +}; // size 0x60 + +/******************************************************************************* + * functions + */ + +BOOL WUDIsLinkedWBC(void); + +BOOL WUDInit(void); +void WUDRegisterAllocator(WUDAllocFunc *alloc, WUDFreeFunc *free); +void WUDShutdown(BOOL saveSimpleDevs); +WUDLibStatus WUDGetStatus(void); +u8 WUDGetBufferStatus(void); +void WUDSetSniffMode(BD_ADDR addr, int interval); +WUDSyncDeviceCallback *WUDSetSyncSimpleCallback(WUDSyncDeviceCallback *cb); + +BOOL WUDStartSyncDevice(void); +BOOL WUDStartFastSyncSimple(void); + +BOOL WUDCancelSyncDevice(void); +BOOL WUDStopSyncSimple(void); +BOOL WUDStartClearDevice(void); +BOOL WUDSetDisableChannel(s8 afhChannel); +WUDHidConnectCallback *WUDSetHidConnCallback(WUDHidConnectCallback *hidConn); +WUDHidReceiveCallback *WUDSetHidRecvCallback(WUDHidReceiveCallback *hidRecv); +void WUDSetVisibility(u8 discoverable, u8 connectable); +u8 WUDGetConnectable(void); + +BOOL WUDIsBusy(void); + +void WUDSetDeviceHistory(WUDChannel chan, BD_ADDR addr); +BOOL WUDIsLatestDevice(WUDChannel chan, BD_ADDR addr); +void WUDUpdateSCSetting(void); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_WUD_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/WUDHidHost.c b/src/sdk/RVL_SDK/revolution/wpad/WUDHidHost.c new file mode 100644 index 00000000..6d03146c --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WUDHidHost.c @@ -0,0 +1,262 @@ +#include "WUDHidHost.h" + +/******************************************************************************* + * headers + */ + +#include + +#include "WUD.h" + +#if 0 +#include +#endif + +#include "context_bte.h" +#include "context_rvl.h" + +/******************************************************************************* + * macros + */ + +#define DEV_IS_NOT_WBC(dev_) \ + (!WUDIsLinkedWBC() || (WUDIsLinkedWBC() && WUD_DEV_NAME_IS_CNT((dev_)->small.devName))) + +/******************************************************************************* + * local function declarations + */ + +// callout functions +extern void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, + tBTA_HH_PROTO_MODE mode, UINT8 sub_class, + UINT8 app_id); +extern void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, UINT16 attr_mask, + UINT8 app_id); +extern void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id); +extern BOOLEAN bta_dm_co_get_compress_memory(tBTA_SYS_ID id, UINT8 **memory_p, + UINT32 *memory_size); + +/******************************************************************************* + * functions + */ + +void WUDiHidHostEventCallback(tBTA_HH_EVT event, tBTA_HH *p_data) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + WUDDevInfo *p_info; + + tBTA_HH_CONN *p_conn; + tBTA_HH_CBDATA *p_cb; + struct hh_event_15_data + { + u16 at_0x00; + u16 at_0x02; + u16 at_0x04; + struct + { + UINT8 handle; + // 1 byte padding (alignment? probably) + UINT16 queueSize; + UINT16 notAckNum; + } at_0x06[]; + } *p_hh_e15; + + int i; + switch (event) + { + case BTA_HH_ENABLE_EVT: + p_wcb->hhFlags |= 1; + break; + + case BTA_HH_OPEN_EVT: + p_conn = &p_data->conn; + + if (p_conn->status == BTA_HH_OK) + { + p_info = WUDiGetDiscoverDevice(); + + if (WUD_BDCMP(p_info->devAddr, p_conn->bda) != 0) + p_info = WUDiGetDevInfo(p_conn->bda); + + OSAssert_Line(206, p_info != NULL); + + switch (p_info->at_0x59) + { + case 12: + p_wcb->syncState = WUD_STATE_SYNC_REGISTER_DEVICE; + break; + + case 2: + p_wcb->syncState = WUD_STATE_SYNC_COMPLETE; + break; + } + + p_info->at_0x59 = 8; + p_info->devHandle = p_conn->handle; + + p_wcb->connectedNum++; + + OSAssert_Line(220, p_conn->handle >= 0 && p_conn->handle < WUD_MAX_DEV_ENTRY); + + p_info = WUDiGetDevInfo(p_conn->bda); + if (!p_info) + p_info = WUDiGetDiscoverDevice(); + + WUDiSetDevAddrForHandle(p_conn->handle, p_info->devAddr); + WUDiSetQueueSizeForHandle(p_conn->handle, 0); + WUDiSetNotAckNumForHandle(p_conn->handle, 0); + + if (p_info->at_0x5b == 3 || p_info->at_0x5b == 1) + WUDiMoveTopSmpDevInfoPtr(p_info); + else if (DEV_IS_NOT_WBC(p_info)) + WUDiMoveTopStdDevInfoPtr(p_info); + + WUDSetSniffMode(p_info->devAddr, 8); + + if (p_wcb->hidConnCB) + (*p_wcb->hidConnCB)(p_info, TRUE); + } + else + { + if (p_wcb->syncState != WUD_STATE_START) + { + p_info = WUDiGetDiscoverDevice(); + if (WUD_BDCMP(p_conn->bda, p_info->devAddr) == 0 + && p_info->at_0x59 == 2) + { + if (WUDiGetDevInfo(p_conn->bda) + && p_conn->status == BTA_HH_ERR_AUTH_FAILED) + { + WUDiRemoveDevice(p_conn->bda); + p_wcb->linkedNum--; + } + + p_wcb->syncState = WUD_STATE_ERROR; + } + } + else + { + if (WUDiGetDevInfo(p_conn->bda) + && p_conn->status == BTA_HH_ERR_AUTH_FAILED) + { + p_info = WUDiGetDevInfo(p_conn->bda); + if (p_info) + { + if (p_info->at_0x5b == 3 || p_info->at_0x5b == 1) + WUDiMoveBottomSmpDevInfoPtr(p_info); + else + WUDiMoveBottomStdDevInfoPtr(p_info); + } + + WUDiRemoveDevice(p_conn->bda); + p_wcb->linkedNum--; + } + } + } + break; + + case BTA_HH_CLOSE_EVT: + p_cb = &p_data->dev_status; + + p_wcb->connectedNum--; + + OSAssert_Line(305, p_cb->handle >= 0 && p_cb->handle < WUD_MAX_DEV_ENTRY); + + p_info = WUDiGetDevInfo(WUDiGetDevAddrForHandle(p_cb->handle)); + if (p_info) + { + if (p_info->at_0x5b == 3 || p_info->at_0x5b == 1) + WUDiMoveTopOfDisconnectedSmpDevice(p_info); + else if (DEV_IS_NOT_WBC(p_info)) + WUDiMoveTopOfDisconnectedStdDevice(p_info); + } + + WUDiSetDevAddrForHandle(p_cb->handle, NULL); + WUDiSetQueueSizeForHandle(p_cb->handle, 0); + WUDiSetNotAckNumForHandle(p_cb->handle, 0); + + if (p_wcb->hidConnCB) + (*p_wcb->hidConnCB)(p_info, FALSE); + + break; + + case BTA_HH_ADD_DEV_EVT: + p_conn = &p_data->dev_info; + + p_info = WUDiGetDevInfo(p_conn->bda); + OSAssert_Line(342, p_info != NULL); + + p_info->devHandle = p_conn->handle; + WUDiSetDevAddrForHandle(p_conn->handle, p_info->devAddr); + WUDiSetQueueSizeForHandle(p_conn->handle, 0); + WUDiSetNotAckNumForHandle(p_conn->handle, 0); + + break; + + case BTA_HH_RMV_DEV_EVT: + p_conn = &p_data->dev_info; + break; + + case 15: // BTA_HH_API_ERR_EVT??? + p_hh_e15 = (struct hh_event_15_data *)p_data; + + p_wcb->bufferStatus0 = p_hh_e15->at_0x00; + p_wcb->bufferStatus1 = p_hh_e15->at_0x02; + + if (p_wcb->linkedNum < p_hh_e15->at_0x04) + { + OSReport("WARNING: link num count is modified.\n"); + p_wcb->linkedNum = p_hh_e15->at_0x04; + } + + for (i = 0; i < p_hh_e15->at_0x04; i++) + { + if (p_hh_e15->at_0x06[i].handle < WUD_MAX_DEV_ENTRY) + { + WUDiSetQueueSizeForHandle(p_hh_e15->at_0x06[i].handle, + p_hh_e15->at_0x06[i].queueSize); + WUDiSetNotAckNumForHandle(p_hh_e15->at_0x06[i].handle, + p_hh_e15->at_0x06[i].notAckNum); + } + } + + break; + } +} + +extern void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, + tBTA_HH_PROTO_MODE mode __attribute__((unused)), + UINT8 sub_class __attribute__((unused)), + UINT8 app_id) +{ + wud_cb_st *p_wcb = &__rvl_wudcb; + + if (app_id == 3 && p_wcb->hidRecvCB) + (*p_wcb->hidRecvCB)(dev_handle, p_rpt, len); +} + +extern void bta_hh_co_open(UINT8 dev_handle __attribute__((unused)), + UINT8 sub_class __attribute__((unused)), + UINT16 attr_mask __attribute__((unused)), + UINT8 app_id __attribute__((unused))) +{ + return; +} + +extern void bta_hh_co_close(UINT8 dev_handle __attribute__((unused)), + UINT8 app_id __attribute__((unused))) +{ + return; +} + +extern BOOLEAN bta_dm_co_get_compress_memory(tBTA_SYS_ID id + __attribute__((unused)), + UINT8 **memory_p + __attribute__((unused)), + UINT32 *memory_size + __attribute__((unused))) +{ + BOOLEAN ret = FALSE; + + return ret; +} diff --git a/src/sdk/RVL_SDK/revolution/wpad/WUDHidHost.h b/src/sdk/RVL_SDK/revolution/wpad/WUDHidHost.h new file mode 100644 index 00000000..de1071c5 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/WUDHidHost.h @@ -0,0 +1,26 @@ +#ifndef RVL_SDK_WPAD_INTERNAL_WUD_HID_HOST_H +#define RVL_SDK_WPAD_INTERNAL_WUD_HID_HOST_H + +/* no public header */ + +/******************************************************************************* + * headers + */ + +#include "context_bte.h" + +/******************************************************************************* + * functions + */ + +#ifdef __cplusplus + extern "C" { +#endif + +void WUDiHidHostEventCallback(tBTA_HH_EVT event, tBTA_HH *p_data); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_INTERNAL_WUD_HID_HOST_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/context_bte.h b/src/sdk/RVL_SDK/revolution/wpad/context_bte.h new file mode 100644 index 00000000..758838a0 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/context_bte.h @@ -0,0 +1,1003 @@ +#ifndef CONTEXT_BTE_H +#define CONTEXT_BTE_H + +#include + +/* Contains the context of the BTE library that the WPAD library needs to + * compile. + * + * This is not the full context; the other half of the context is in + * "context_rvl.h". + * + * Most of this code is copyright (C) 2003-2012 Broadcom Corporation under the + * Apache 2.0 License; however, some of the code is modified. Comments will be + * marked with my name to show where and what I modified. + */ + +// from bluedroid source + +typedef uint8_t UINT8; +typedef uint16_t UINT16; +typedef uint32_t UINT32; +typedef uint8_t byte_t; + +typedef int8_t INT8; + +typedef unsigned char BOOLEAN; + +#define BD_ADDR_LEN 6 /* Device address length */ +typedef UINT8 BD_ADDR[BD_ADDR_LEN]; /* Device address */ +typedef UINT8 *BD_ADDR_PTR; /* Pointer to Device Address */ + +#define LINK_KEY_LEN 16 +typedef UINT8 LINK_KEY[LINK_KEY_LEN]; /* Link Key */ + +#define DEV_CLASS_LEN 3 +typedef UINT8 DEV_CLASS[DEV_CLASS_LEN]; /* Device class */ +typedef UINT8 *DEV_CLASS_PTR; /* Pointer to Device class */ + +/* muff1n: TODO: bta_dm_pin_cback looks mostly the same except that BD_NAME_LEN + * is 33 (or it was 32 and BD_NAME_LEN was not decreased by 1 in BCM_STRNCPY_S + * calls)? + * confirm this + * + * UPDATE: there is a case where it is 248 + */ +#define BD_NAME_LEN 248 +typedef UINT8 BD_NAME[BD_NAME_LEN]; /* Device name */ +typedef UINT8 *BD_NAME_PTR; /* Pointer to Device name */ + +#define BD_FEATURES_LEN 8 +typedef UINT8 BD_FEATURES[BD_FEATURES_LEN]; /* LMP features supported by device */ + +#define BT_DEVICE_TYPE_BREDR 0x01 +#define BT_DEVICE_TYPE_BLE 0x02 +#define BT_DEVICE_TYPE_DUMO 0x03 +typedef UINT8 tBT_DEVICE_TYPE; + +/* Maximum UUID size - 16 bytes, and structure to hold any type of UUID. */ +#define MAX_UUID_SIZE 16 +typedef struct +{ +#define LEN_UUID_16 2 +#define LEN_UUID_32 4 +#define LEN_UUID_128 16 + + UINT16 len; + + union + { + UINT16 uuid16; + UINT32 uuid32; + UINT8 uuid128[MAX_UUID_SIZE]; + } uu; + +} tBT_UUID; + +/* Status Return Value */ +#define BTA_SUCCESS 0 /* Successful operation. */ +#define BTA_FAILURE 1 /* Generic failure. */ +#define BTA_PENDING 2 /* API cannot be completed right now */ +#define BTA_BUSY 3 +#define BTA_NO_RESOURCES 4 +#define BTA_WRONG_MODE 5 + +typedef UINT8 tBTA_STATUS; + +/* + * Service ID + * + * NOTES: When you add a new Service ID for BTA AND require to change the value of BTA_MAX_SERVICE_ID, + * make sure that the correct security ID of the new service from Security service definitions (btm_api.h) + * should be added to bta_service_id_to_btm_srv_id_lkup_tbl table in bta_dm_act.c. + */ + +#define BTA_RES_SERVICE_ID 0 /* Reserved */ +#define BTA_SPP_SERVICE_ID 1 /* Serial port profile. */ +#define BTA_DUN_SERVICE_ID 2 /* Dial-up networking profile. */ +#define BTA_A2DP_SOURCE_SERVICE_ID 3 /* A2DP Source profile. */ +#define BTA_LAP_SERVICE_ID 4 /* LAN access profile. */ +#define BTA_HSP_SERVICE_ID 5 /* Headset profile. */ +#define BTA_HFP_SERVICE_ID 6 /* Hands-free profile. */ +#define BTA_OPP_SERVICE_ID 7 /* Object push */ +#define BTA_FTP_SERVICE_ID 8 /* File transfer */ +#define BTA_CTP_SERVICE_ID 9 /* Cordless Terminal */ +#define BTA_ICP_SERVICE_ID 10 /* Intercom Terminal */ +#define BTA_SYNC_SERVICE_ID 11 /* Synchronization */ +#define BTA_BPP_SERVICE_ID 12 /* Basic printing profile */ +#define BTA_BIP_SERVICE_ID 13 /* Basic Imaging profile */ +#define BTA_PANU_SERVICE_ID 14 /* PAN User */ +#define BTA_NAP_SERVICE_ID 15 /* PAN Network access point */ +#define BTA_GN_SERVICE_ID 16 /* PAN Group Ad-hoc networks */ +#define BTA_SAP_SERVICE_ID 17 /* SIM Access profile */ +#define BTA_A2DP_SERVICE_ID 18 /* A2DP Sink */ +#define BTA_AVRCP_SERVICE_ID 19 /* A/V remote control */ +#define BTA_HID_SERVICE_ID 20 /* HID */ +#define BTA_VDP_SERVICE_ID 21 /* Video distribution */ +#define BTA_PBAP_SERVICE_ID 22 /* PhoneBook Access Server*/ +#define BTA_HSP_HS_SERVICE_ID 23 /* HFP HS role */ +#define BTA_HFP_HS_SERVICE_ID 24 /* HSP HS role */ +#define BTA_MAP_SERVICE_ID 25 /* Message Access Profile */ +#define BTA_MN_SERVICE_ID 26 /* Message Notification Service */ +#define BTA_HDP_SERVICE_ID 27 /* Health Device Profile */ +#define BTA_PCE_SERVICE_ID 28 /* PhoneBook Access Client*/ + +#define BTA_USER_SERVICE_ID 29 /* User requested UUID */ +#define BTA_MAX_SERVICE_ID 30 + +/* service IDs (BTM_SEC_SERVICE_FIRST_EMPTY + 1) to (BTM_SEC_MAX_SERVICES - 1) + * are used by BTA JV */ +#define BTA_FIRST_JV_SERVICE_ID (BTM_SEC_SERVICE_FIRST_EMPTY + 1) +#define BTA_LAST_JV_SERVICE_ID (BTM_SEC_MAX_SERVICES - 1) + +typedef UINT8 tBTA_SERVICE_ID; + +/* Service ID Mask */ +#define BTA_RES_SERVICE_MASK 0x00000001 /* Reserved */ +#define BTA_SPP_SERVICE_MASK 0x00000002 /* Serial port profile. */ +#define BTA_DUN_SERVICE_MASK 0x00000004 /* Dial-up networking profile. */ +#define BTA_FAX_SERVICE_MASK 0x00000008 /* Fax profile. */ +#define BTA_LAP_SERVICE_MASK 0x00000010 /* LAN access profile. */ +#define BTA_HSP_SERVICE_MASK 0x00000020 /* HSP AG role. */ +#define BTA_HFP_SERVICE_MASK 0x00000040 /* HFP AG role */ +#define BTA_OPP_SERVICE_MASK 0x00000080 /* Object push */ +#define BTA_FTP_SERVICE_MASK 0x00000100 /* File transfer */ +#define BTA_CTP_SERVICE_MASK 0x00000200 /* Cordless Terminal */ +#define BTA_ICP_SERVICE_MASK 0x00000400 /* Intercom Terminal */ +#define BTA_SYNC_SERVICE_MASK 0x00000800 /* Synchronization */ +#define BTA_BPP_SERVICE_MASK 0x00001000 /* Print server */ +#define BTA_BIP_SERVICE_MASK 0x00002000 /* Basic Imaging */ +#define BTA_PANU_SERVICE_MASK 0x00004000 /* PAN User */ +#define BTA_NAP_SERVICE_MASK 0x00008000 /* PAN Network access point */ +#define BTA_GN_SERVICE_MASK 0x00010000 /* PAN Group Ad-hoc networks */ +#define BTA_SAP_SERVICE_MASK 0x00020000 /* PAN Group Ad-hoc networks */ +#define BTA_A2DP_SERVICE_MASK 0x00040000 /* Advanced audio distribution */ +#define BTA_AVRCP_SERVICE_MASK 0x00080000 /* A/V remote control */ +#define BTA_HID_SERVICE_MASK 0x00100000 /* HID */ +#define BTA_VDP_SERVICE_MASK 0x00200000 /* Video distribution */ +#define BTA_PBAP_SERVICE_MASK 0x00400000 /* Phone Book Server */ +#define BTA_HSP_HS_SERVICE_MASK 0x00800000 /* HFP HS role */ +#define BTA_HFP_HS_SERVICE_MASK 0x01000000 /* HSP HS role */ +#define BTA_MAS_SERVICE_MASK 0x02000000 /* Message Access Profile */ +#define BTA_MN_SERVICE_MASK 0x04000000 /* Message Notification Profile */ +#define BTA_HL_SERVICE_MASK 0x08000000 /* Health Device Profile */ +#define BTA_PCE_SERVICE_MASK 0x10000000 /* Phone Book Client */ + +// btla-specific ++ +#define BTA_USER_SERVICE_MASK 0x20000000 /* Message Notification Profile */ +// btla-specific -- + +#define BTA_ALL_SERVICE_MASK 0x1FFFFFFF /* All services supported by BTA. */ + +typedef UINT32 tBTA_SERVICE_MASK; + +/* SW sub-systems */ +#define BTA_ID_SYS 0 /* system manager */ +/* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */ +#define BTA_ID_DM 1 /* device manager */ +#define BTA_ID_DM_SEARCH 2 /* device manager search */ +#define BTA_ID_DM_SEC 3 /* device manager security */ +#define BTA_ID_DG 4 /* data gateway */ +#define BTA_ID_AG 5 /* audio gateway */ +#define BTA_ID_OPC 6 /* object push client */ +#define BTA_ID_OPS 7 /* object push server */ +#define BTA_ID_FTS 8 /* file transfer server */ +#define BTA_ID_CT 9 /* cordless telephony terminal */ +#define BTA_ID_FTC 10 /* file transfer client */ +#define BTA_ID_SS 11 /* synchronization server */ +#define BTA_ID_PR 12 /* Printer client */ +#define BTA_ID_BIC 13 /* Basic Imaging Client */ +#define BTA_ID_PAN 14 /* Personal Area Networking */ +#define BTA_ID_BIS 15 /* Basic Imaging Server */ +#define BTA_ID_ACC 16 /* Advanced Camera Client */ +#define BTA_ID_SC 17 /* SIM Card Access server */ +#define BTA_ID_AV 18 /* Advanced audio/video */ +#define BTA_ID_AVK 19 /* Audio/video sink */ +#define BTA_ID_HD 20 /* HID Device */ +#define BTA_ID_CG 21 /* Cordless Gateway */ +#define BTA_ID_BP 22 /* Basic Printing Client */ +#define BTA_ID_HH 23 /* Human Interface Device Host */ +#define BTA_ID_PBS 24 /* Phone Book Access Server */ +#define BTA_ID_PBC 25 /* Phone Book Access Client */ +#define BTA_ID_JV 26 /* Java */ +#define BTA_ID_HS 27 /* Headset */ +#define BTA_ID_MSE 28 /* Message Server Equipment */ +#define BTA_ID_MCE 29 /* Message Client Equipment */ +#define BTA_ID_HL 30 /* Health Device Profile*/ +#define BTA_ID_GATTC 31 /* GATT Client */ +#define BTA_ID_GATTS 32 /* GATT Client */ +#define BTA_ID_BLUETOOTH_MAX 33 /* last BT profile */ + +/* FM */ +#define BTA_ID_FM 34 /* FM */ +#define BTA_ID_FMTX 35 /* FM TX */ + +/* SENSOR */ +#define BTA_ID_SSR 36 /* Sensor */ + +/* GPS */ +#define BTA_ID_GPS 37 /* GPS */ + +/* GENERIC */ +#define BTA_ID_PRM 38 +#define BTA_ID_SYSTEM 39 /* platform-specific */ +#define BTA_ID_SWRAP 40 /* Insight script wrapper */ +#define BTA_ID_MIP 41 /* Multicase Individual Polling */ +#define BTA_ID_RT 42 /* Audio Routing module: This module is always on. */ + +/* JV */ +#define BTA_ID_JV1 43 /* JV1 */ +#define BTA_ID_JV2 44 /* JV2 */ + +#define BTA_ID_MAX (43 + BTA_DM_NUM_JV_ID) + +typedef UINT8 tBTA_SYS_ID; + +enum +{ + BTM_SUCCESS = 0, /* 0 Command succeeded */ + BTM_CMD_STARTED, /* 1 Command started OK. */ + BTM_BUSY, /* 2 Device busy with another command */ + BTM_NO_RESOURCES, /* 3 No resources to issue command */ + BTM_MODE_UNSUPPORTED, /* 4 Request for 1 or more unsupported modes */ + BTM_ILLEGAL_VALUE, /* 5 Illegal parameter value */ + BTM_WRONG_MODE, /* 6 Device in wrong mode for request */ + BTM_UNKNOWN_ADDR, /* 7 Unknown remote BD address */ + BTM_DEVICE_TIMEOUT, /* 8 Device timeout */ + BTM_BAD_VALUE_RET, /* 9 A bad value was received from HCI */ + BTM_ERR_PROCESSING, /* 10 Generic error */ + BTM_NOT_AUTHORIZED, /* 11 Authorization failed */ + BTM_DEV_RESET, /* 12 Device has been reset */ + BTM_CMD_STORED, /* 13 request is stored in control block */ + BTM_ILLEGAL_ACTION, /* 14 state machine gets illegal command */ + BTM_DELAY_CHECK, /* 15 delay the check on encryption */ + BTM_SCO_BAD_LENGTH, /* 16 Bad SCO over HCI data length */ + BTM_SUCCESS_NO_SECURITY, /* 17 security passed, no security set */ + BTM_FAILED_ON_SECURITY , /* 18 security failed */ + BTM_REPEATED_ATTEMPTS /* 19 repeated attempts for LE security requests */ +}; +typedef UINT8 tBTM_STATUS; + +typedef struct +{ + UINT16 event; + UINT16 len; + UINT16 offset; + UINT16 layer_specific; +} BT_HDR; + +#define BT_HDR_SIZE (sizeof (BT_HDR)) + +/* Security Service Levels [bit mask] (BTM_SetSecurityLevel) +** Encryption should not be used without authentication +*/ +#define BTM_SEC_NONE 0x0000 /* Nothing required */ +#define BTM_SEC_IN_AUTHORIZE 0x0001 /* Inbound call requires authorization */ +#define BTM_SEC_IN_AUTHENTICATE 0x0002 /* Inbound call requires authentication */ +#define BTM_SEC_IN_ENCRYPT 0x0004 /* Inbound call requires encryption */ +#define BTM_SEC_OUT_AUTHORIZE 0x0008 /* Outbound call requires authorization */ +#define BTM_SEC_OUT_AUTHENTICATE 0x0010 /* Outbound call requires authentication */ +#define BTM_SEC_OUT_ENCRYPT 0x0020 /* Outbound call requires encryption */ +#define BTM_SEC_BOND 0x0040 /* Bonding */ +#define BTM_SEC_BOND_CONN 0x0080 /* bond_created_connection */ +#define BTM_SEC_FORCE_MASTER 0x0100 /* Need to switch connection to be master */ +#define BTM_SEC_ATTEMPT_MASTER 0x0200 /* Try to switch connection to be master */ +#define BTM_SEC_FORCE_SLAVE 0x0400 /* Need to switch connection to be master */ +#define BTM_SEC_ATTEMPT_SLAVE 0x0800 /* Try to switch connection to be slave */ +#define BTM_SEC_IN_MITM 0x1000 /* inbound Do man in the middle protection */ +#define BTM_SEC_OUT_MITM 0x2000 /* outbound Do man in the middle protection */ + +/* Security Setting Mask */ +#define BTA_SEC_NONE BTM_SEC_NONE /* No security. */ +#define BTA_SEC_AUTHORIZE (BTM_SEC_IN_AUTHORIZE ) /* Authorization required (only needed for out going connection )*/ +#define BTA_SEC_AUTHENTICATE (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */ +#define BTA_SEC_ENCRYPT (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT) /* Encryption required. */ + +typedef UINT8 tBTA_SEC; + +/* Pairable Modes */ +#define BTA_DM_PAIRABLE 1 +#define BTA_DM_NON_PAIRABLE 0 + +/* Connectable Paired Only Mode */ +#define BTA_DM_CONN_ALL 0 +#define BTA_DM_CONN_PAIRED 1 + +/* Inquiry modes + * Note: These modes are associated with the inquiry active values (BTM_*ACTIVE) */ +#define BTM_GENERAL_INQUIRY 0 +#define BTM_LIMITED_INQUIRY 1 +#define BTM_BR_INQUIRY_MASK 0x0f +/* high byte of inquiry mode for BLE inquiry mode */ +#define BTM_BLE_INQUIRY_NONE 0x00 +#define BTM_BLE_GENERAL_INQUIRY 0x10 +#define BTM_BLE_LIMITED_INQUIRY 0x20 +#define BTM_BLE_INQUIRY_MASK (BTM_BLE_GENERAL_INQUIRY|BTM_BLE_LIMITED_INQUIRY) + +#define BTA_BLE_INQUIRY_NONE BTM_BLE_INQUIRY_NONE +#define BTA_BLE_GENERAL_INQUIRY BTM_BLE_GENERAL_INQUIRY /* Perform LE general inquiry. */ +#define BTA_BLE_LIMITED_INQUIRY BTM_BLE_LIMITED_INQUIRY /* Perform LE limited inquiry. */ +typedef UINT8 tBTA_DM_INQ_MODE; + +/* Inquiry Filter Type */ +#define BTA_DM_INQ_CLR BTM_CLR_INQUIRY_FILTER /* Clear inquiry filter. */ +#define BTA_DM_INQ_DEV_CLASS BTM_FILTER_COND_DEVICE_CLASS /* Filter on device class. */ +#define BTA_DM_INQ_BD_ADDR BTM_FILTER_COND_BD_ADDR /* Filter on a specific BD address. */ + +typedef UINT8 tBTA_DM_INQ_FILT; + +/* Inquiry filter device class condition */ +typedef struct +{ + DEV_CLASS dev_class; /* device class of interest */ + DEV_CLASS dev_class_mask; /* mask to determine the bits of device class of interest */ +} tBTA_DM_COD_COND; + +/* Inquiry Filter Condition */ +typedef union +{ + BD_ADDR bd_addr; /* BD address of device to filter. */ + tBTA_DM_COD_COND dev_class_cond; /* Device class filter condition */ +} tBTA_DM_INQ_COND; + +/* Inquiry Parameters */ +typedef struct +{ + tBTA_DM_INQ_MODE mode; /* Inquiry mode, limited or general. */ + UINT8 duration; /* Inquiry duration in 1.28 sec units. */ + UINT8 max_resps; /* Maximum inquiry responses. Set to zero for unlimited responses. */ + BOOLEAN report_dup; /* report duplicated inquiry response with higher RSSI value */ + tBTA_DM_INQ_FILT filter_type; /* Filter condition type. */ + tBTA_DM_INQ_COND filter_cond; /* Filter condition data. */ +} tBTA_DM_INQ; + +/* Security Callback Events */ +#define BTA_DM_ENABLE_EVT 0 /* Enable Event */ +#define BTA_DM_DISABLE_EVT 1 /* Disable Event */ +#define BTA_DM_PIN_REQ_EVT 2 /* PIN request. */ +#define BTA_DM_AUTH_CMPL_EVT 3 /* Authentication complete indication. */ +#define BTA_DM_AUTHORIZE_EVT 4 /* Authorization request. */ +#define BTA_DM_LINK_UP_EVT 5 /* Connection UP event */ +#define BTA_DM_LINK_DOWN_EVT 6 /* Connection DOWN event */ +#define BTA_DM_SIG_STRENGTH_EVT 7 /* Signal strength for bluetooth connection */ +#define BTA_DM_BUSY_LEVEL_EVT 8 /* System busy level */ +#define BTA_DM_BOND_CANCEL_CMPL_EVT 9 /* Bond cancel complete indication */ +#define BTA_DM_SP_CFM_REQ_EVT 10 /* Simple Pairing User Confirmation request. */ +#define BTA_DM_SP_KEY_NOTIF_EVT 11 /* Simple Pairing Passkey Notification */ +#define BTA_DM_SP_RMT_OOB_EVT 12 /* Simple Pairing Remote OOB Data request. */ +#define BTA_DM_SP_KEYPRESS_EVT 13 /* Key press notification event. */ +#define BTA_DM_ROLE_CHG_EVT 14 /* Role Change event. */ +#define BTA_DM_BLE_KEY_EVT 15 /* BLE SMP key event for peer device keys */ +#define BTA_DM_BLE_SEC_REQ_EVT 16 /* BLE SMP security request */ +#define BTA_DM_BLE_PASSKEY_NOTIF_EVT 17 /* SMP passkey notification event */ +#define BTA_DM_BLE_PASSKEY_REQ_EVT 18 /* SMP passkey request event */ +#define BTA_DM_BLE_OOB_REQ_EVT 19 /* SMP OOB request event */ +#define BTA_DM_BLE_LOCAL_IR_EVT 20 /* BLE local IR event */ +#define BTA_DM_BLE_LOCAL_ER_EVT 21 /* BLE local ER event */ +// btla-specific ++ +#define BTA_DM_BLE_AUTH_CMPL_EVT 22 /* BLE Auth complete */ +// btla-specific -- +#define BTA_DM_DEV_UNPAIRED_EVT 23 +#define BTA_DM_HW_ERROR_EVT 24 /* BT Chip H/W error */ +typedef UINT8 tBTA_DM_SEC_EVT; + +/* Structure associated with BTA_DM_ENABLE_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address of local device. */ + tBTA_STATUS status; +} tBTA_DM_ENABLE; + +/* Structure associated with BTA_DM_PIN_REQ_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + BD_NAME bd_name; /* Name of peer device. */ + DEV_CLASS dev_class; /* Class of Device */ +} tBTA_DM_PIN_REQ; + +/* Link Key Notification Event (Key Type) definitions */ +#define HCI_LKEY_TYPE_COMBINATION 0x00 +#define HCI_LKEY_TYPE_LOCAL_UNIT 0x01 +#define HCI_LKEY_TYPE_REMOTE_UNIT 0x02 +#define HCI_LKEY_TYPE_DEBUG_COMB 0x03 +#define HCI_LKEY_TYPE_UNAUTH_COMB 0x04 +#define HCI_LKEY_TYPE_AUTH_COMB 0x05 +#define HCI_LKEY_TYPE_CHANGED_COMB 0x06 + +/* Structure associated with BTA_DM_AUTH_CMPL_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + BD_NAME bd_name; /* Name of peer device. */ + BOOLEAN key_present; /* Valid link key value in key element */ + LINK_KEY key; /* Link key associated with peer device. */ + UINT8 key_type; /* The type of Link Key */ + BOOLEAN success; /* TRUE of authentication succeeded, FALSE if failed. */ + UINT8 fail_reason; /* The HCI reason/error code for when success=FALSE */ +} tBTA_DM_AUTH_CMPL; + +/* Structure associated with BTA_DM_AUTHORIZE_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + BD_NAME bd_name; /* Name of peer device. */ + tBTA_SERVICE_ID service; /* Service ID to authorize. */ +// btla-specific ++ + DEV_CLASS dev_class; +// btla-specific -- +} tBTA_DM_AUTHORIZE; + +/* Structure associated with BTA_DM_LINK_UP_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ +} tBTA_DM_LINK_UP; + +/* +** Defentions for HCI Error Codes that are past in the events +*/ +#define HCI_SUCCESS 0x00 +#define HCI_PENDING 0x00 +#define HCI_ERR_ILLEGAL_COMMAND 0x01 +#define HCI_ERR_NO_CONNECTION 0x02 +#define HCI_ERR_HW_FAILURE 0x03 +#define HCI_ERR_PAGE_TIMEOUT 0x04 +#define HCI_ERR_AUTH_FAILURE 0x05 +#define HCI_ERR_KEY_MISSING 0x06 +#define HCI_ERR_MEMORY_FULL 0x07 +#define HCI_ERR_CONNECTION_TOUT 0x08 +#define HCI_ERR_MAX_NUM_OF_CONNECTIONS 0x09 +#define HCI_ERR_MAX_NUM_OF_SCOS 0x0A +#define HCI_ERR_CONNECTION_EXISTS 0x0B +#define HCI_ERR_COMMAND_DISALLOWED 0x0C +#define HCI_ERR_HOST_REJECT_RESOURCES 0x0D +#define HCI_ERR_HOST_REJECT_SECURITY 0x0E +#define HCI_ERR_HOST_REJECT_DEVICE 0x0F +#define HCI_ERR_HOST_TIMEOUT 0x10 +#define HCI_ERR_UNSUPPORTED_VALUE 0x11 +#define HCI_ERR_ILLEGAL_PARAMETER_FMT 0x12 +#define HCI_ERR_PEER_USER 0x13 +#define HCI_ERR_PEER_LOW_RESOURCES 0x14 +#define HCI_ERR_PEER_POWER_OFF 0x15 +#define HCI_ERR_CONN_CAUSE_LOCAL_HOST 0x16 +#define HCI_ERR_REPEATED_ATTEMPTS 0x17 +#define HCI_ERR_PAIRING_NOT_ALLOWED 0x18 +#define HCI_ERR_UNKNOWN_LMP_PDU 0x19 +#define HCI_ERR_UNSUPPORTED_REM_FEATURE 0x1A +#define HCI_ERR_SCO_OFFSET_REJECTED 0x1B +#define HCI_ERR_SCO_INTERVAL_REJECTED 0x1C +#define HCI_ERR_SCO_AIR_MODE 0x1D +#define HCI_ERR_INVALID_LMP_PARAM 0x1E +#define HCI_ERR_UNSPECIFIED 0x1F +#define HCI_ERR_UNSUPPORTED_LMP_FEATURE 0x20 +#define HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21 +#define HCI_ERR_LMP_RESPONSE_TIMEOUT 0x22 +#define HCI_ERR_LMP_ERR_TRANS_COLLISION 0x23 +#define HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24 +#define HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE 0x25 +#define HCI_ERR_UNIT_KEY_USED 0x26 +#define HCI_ERR_QOS_NOT_SUPPORTED 0x27 +#define HCI_ERR_INSTANT_PASSED 0x28 +#define HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED 0x29 +#define HCI_ERR_DIFF_TRANSACTION_COLLISION 0x2A +#define HCI_ERR_UNDEFINED_0x2B 0x2B +#define HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2C +#define HCI_ERR_QOS_REJECTED 0x2D +#define HCI_ERR_CHAN_CLASSIF_NOT_SUPPORTED 0x2E +#define HCI_ERR_INSUFFCIENT_SECURITY 0x2F +#define HCI_ERR_PARAM_OUT_OF_RANGE 0x30 +#define HCI_ERR_UNDEFINED_0x31 0x31 +#define HCI_ERR_ROLE_SWITCH_PENDING 0x32 +#define HCI_ERR_UNDEFINED_0x33 0x33 +#define HCI_ERR_RESERVED_SLOT_VIOLATION 0x34 +#define HCI_ERR_ROLE_SWITCH_FAILED 0x35 +#define HCI_ERR_INQ_RSP_DATA_TOO_LARGE 0x36 +#define HCI_ERR_SIMPLE_PAIRING_NOT_SUPPORTED 0x37 +#define HCI_ERR_HOST_BUSY_PAIRING 0x38 +#define HCI_ERR_REJ_NO_SUITABLE_CHANNEL 0x39 +#define HCI_ERR_CONTROLLER_BUSY 0x3A +#define HCI_ERR_UNACCEPT_CONN_INTERVAL 0x3B +#define HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT 0x3C +#define HCI_ERR_CONN_TOUT_DUE_TO_MIC_FAILURE 0x3D +#define HCI_ERR_CONN_FAILED_ESTABLISHMENT 0x3E +#define HCI_ERR_MAC_CONNECTION_FAILED 0x3F + +#define HCI_ERR_MAX_ERR 0x40 + +#define HCI_HINT_TO_RECREATE_AMP_PHYS_LINK 0xFF + +/* Structure associated with BTA_DM_LINK_DOWN_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + UINT8 status; /* connection open/closed */ +} tBTA_DM_LINK_DOWN; + +typedef INT8 tBTA_DM_RSSI_VALUE; +typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE; + +/* signal strength mask */ +#define BTA_SIG_STRENGTH_RSSI_MASK 1 +#define BTA_SIG_STRENGTH_LINK_QUALITY_MASK 2 + +typedef UINT8 tBTA_SIG_STRENGTH_MASK; + +/* Structure associated with BTA_DM_SIG_STRENGTH_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + tBTA_SIG_STRENGTH_MASK mask; /* mask for the values that are valid */ + tBTA_DM_RSSI_VALUE rssi_value; + tBTA_DM_LINK_QUALITY_VALUE link_quality_value; + +} tBTA_DM_SIG_STRENGTH; + +/* Structure associated with BTA_DM_BUSY_LEVEL_EVT */ +typedef struct +{ + UINT8 level; /* when paging or inquiring, level is 10. + Otherwise, the number of ACL links */ +} tBTA_DM_BUSY_LEVEL; + +// muff1n: only filled with used members +typedef union +{ + tBTA_DM_ENABLE enable; /* BTA enabled */ + tBTA_DM_PIN_REQ pin_req; /* PIN request */ + tBTA_DM_AUTH_CMPL auth_cmpl; /* Authentication complete indication */ + tBTA_DM_AUTHORIZE authorize; /* Authorization request */ + tBTA_DM_LINK_UP link_up; /* ACL connection up event */ + tBTA_DM_LINK_DOWN link_down; /* ACL connection down event */ + tBTA_DM_SIG_STRENGTH sig_strength; /* rssi and link quality value */ + tBTA_DM_BUSY_LEVEL busy_level; /* System busy level */ +} tBTA_DM_SEC; + +typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data); + +/* Search callback events */ +#define BTA_DM_INQ_RES_EVT 0 /* Inquiry result for a peer device. */ +#define BTA_DM_INQ_CMPL_EVT 1 /* Inquiry complete. */ +#define BTA_DM_DISC_RES_EVT 2 /* Discovery result for a peer device. */ +#define BTA_DM_DISC_BLE_RES_EVT 3 /* Discovery result for BLE GATT based service on a peer device. */ +#define BTA_DM_DISC_CMPL_EVT 4 /* Discovery complete. */ +#define BTA_DM_DI_DISC_CMPL_EVT 5 /* Discovery complete. */ +#define BTA_DM_SEARCH_CANCEL_CMPL_EVT 6 /* Search cancelled */ + +typedef UINT8 tBTA_DM_SEARCH_EVT; + +#define BTA_DM_INQ_RES_IGNORE_RSSI BTM_INQ_RES_IGNORE_RSSI /* 0x7f RSSI value not supplied (ignore it) */ + +// muff1n: commented some fields out +/* Structure associated with BTA_DM_INQ_RES_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + DEV_CLASS dev_class; /* Device class of peer device. */ + //BOOLEAN remt_name_not_required; /* Application sets this flag if it already knows the name of the device */ + /* If the device name is known to application BTA skips the remote name request */ + //BOOLEAN is_limited; /* TRUE, if the limited inquiry bit is set in the CoD */ + INT8 rssi; /* The rssi value */ + UINT8 *p_eir; /* received EIR */ +} tBTA_DM_INQ_RES; + +/* Structure associated with BTA_DM_INQ_CMPL_EVT */ +typedef struct +{ + UINT8 num_resps; /* Number of inquiry responses. */ +} tBTA_DM_INQ_CMPL; + +/* Structure associated with BTA_DM_DI_DISC_CMPL_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + UINT8 num_record; /* Number of DI record */ + tBTA_STATUS result; +} tBTA_DM_DI_DISC_CMPL; + +/* Structure associated with BTA_DM_DISC_RES_EVT */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + BD_NAME bd_name; /* Name of peer device. */ + tBTA_SERVICE_MASK services; /* Services found on peer device. */ +// btla-specific ++ + UINT8 * p_raw_data; /* Raw data for discovery DB */ + UINT32 raw_data_size; /* size of raw data */ + tBT_DEVICE_TYPE device_type; /* device type in case it is BLE device */ + UINT32 num_uuids; + UINT8 *p_uuid_list; +// btla-specific -- + tBTA_STATUS result; +} tBTA_DM_DISC_RES; + +/* Structure associated with tBTA_DM_DISC_BLE_RES */ +typedef struct +{ + BD_ADDR bd_addr; /* BD address peer device. */ + BD_NAME bd_name; /* Name of peer device. */ + tBT_UUID service; /* GATT based Services UUID found on peer device. */ +} tBTA_DM_DISC_BLE_RES; + +/* Union of all search callback structures */ +typedef union +{ + tBTA_DM_INQ_RES inq_res; /* Inquiry result for a peer device. */ + tBTA_DM_INQ_CMPL inq_cmpl; /* Inquiry complete. */ + tBTA_DM_DISC_RES disc_res; /* Discovery result for a peer device. */ + tBTA_DM_DISC_BLE_RES disc_ble_res; /* discovery result for GATT based service */ + tBTA_DM_DI_DISC_CMPL di_disc; /* DI discovery result for a peer device */ +} tBTA_DM_SEARCH; + +/* Search callback */ +typedef void (tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); + +/* type of protocol mode */ +#define BTA_HH_PROTO_RPT_MODE (0x00) +#define BTA_HH_PROTO_BOOT_MODE (0x01) +#define BTA_HH_PROTO_UNKNOWN (0xff) +typedef UINT8 tBTA_HH_PROTO_MODE; + +/* BTA HID Host callback events */ +#define BTA_HH_ENABLE_EVT 0 /* HH enabled */ +#define BTA_HH_DISABLE_EVT 1 /* HH disabled */ +#define BTA_HH_OPEN_EVT 2 /* connection opened */ +#define BTA_HH_CLOSE_EVT 3 /* connection closed */ +#define BTA_HH_GET_RPT_EVT 4 /* BTA_HhGetReport callback */ +#define BTA_HH_SET_RPT_EVT 5 /* BTA_HhSetReport callback */ +#define BTA_HH_GET_PROTO_EVT 6 /* BTA_GetProtoMode callback */ +#define BTA_HH_SET_PROTO_EVT 7 /* BTA_HhSetProtoMode callback */ +#define BTA_HH_GET_IDLE_EVT 8 /* BTA_HhGetIdle comes callback */ +#define BTA_HH_SET_IDLE_EVT 9 /* BTA_HhSetIdle finish callback */ +#define BTA_HH_GET_DSCP_EVT 10 /* Get report descripotor */ +#define BTA_HH_ADD_DEV_EVT 11 /* Add Device callback */ +#define BTA_HH_RMV_DEV_EVT 12 /* remove device finished */ +#define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */ +#define BTA_HH_UPDATE_UCD_EVT 14 +#define BTA_HH_API_ERR_EVT 15 /* API error is caught */ + +typedef UINT16 tBTA_HH_EVT; + +enum +{ + BTA_HH_OK, + BTA_HH_HS_HID_NOT_READY, /* handshake error : device not ready */ + BTA_HH_HS_INVALID_RPT_ID, /* handshake error : invalid report ID */ + BTA_HH_HS_TRANS_NOT_SPT, /* handshake error : transaction not spt */ + BTA_HH_HS_INVALID_PARAM, /* handshake error : invalid paremter */ + BTA_HH_HS_ERROR, /* handshake error : unspecified HS error */ + BTA_HH_ERR, /* general BTA HH error */ + BTA_HH_ERR_SDP, /* SDP error */ + BTA_HH_ERR_PROTO, /* SET_Protocol error, + only used in BTA_HH_OPEN_EVT callback */ + BTA_HH_ERR_DB_FULL, /* device database full error, used in + BTA_HH_OPEN_EVT/BTA_HH_ADD_DEV_EVT */ + BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */ + BTA_HH_ERR_NO_RES, /* out of system resources */ + BTA_HH_ERR_AUTH_FAILED, /* authentication fail */ + BTA_HH_ERR_HDL +}; +typedef UINT8 tBTA_HH_STATUS; + +/* callback event data for BTA_HH_OPEN_EVT */ +typedef struct +{ + BD_ADDR bda; /* HID device bd address */ + tBTA_HH_STATUS status; /* operation status */ + UINT8 handle; /* device handle */ +} tBTA_HH_CONN; + +typedef tBTA_HH_CONN tBTA_HH_DEV_INFO; + +/* callback event data */ +typedef struct +{ + tBTA_HH_STATUS status; /* operation status */ + UINT8 handle; /* device handle */ +} tBTA_HH_CBDATA; + +// muff1n: only filled with used members +typedef union +{ + tBTA_HH_DEV_INFO dev_info; /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT */ + tBTA_HH_CONN conn; /* BTA_HH_OPEN_EVT */ + tBTA_HH_CBDATA dev_status; /* BTA_HH_CLOSE_EVT, + BTA_HH_SET_PROTO_EVT + BTA_HH_SET_RPT_EVT + BTA_HH_SET_IDLE_EVT */ +} tBTA_HH; + +/* BTA HH callback function */ +typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data); + +/* General callback function for notifying an application that a synchronous +** BTM function is complete. The pointer contains the address of any returned data. +*/ +typedef void (tBTM_CMPL_CB) (void *p1); +/* Structure returned with local version information */ + +typedef struct +{ + UINT8 hci_version; + UINT16 hci_revision; + UINT8 lmp_version; + UINT16 manufacturer; + UINT16 lmp_subversion; +} tBTM_VERSION_INFO; + +/* Structure returned with Vendor Specific Command complete callback */ +typedef struct +{ + UINT16 opcode; + UINT16 param_len; + UINT8 *p_param_buf; +} tBTM_VSC_CMPL; + +#define BTM_VSC_CMPL_DATA_SIZE (BTM_MAX_VENDOR_SPECIFIC_LEN + sizeof(tBTM_VSC_CMPL)) +/* Callback function for when device status changes. Appl must poll for +** what the new state is (BTM_IsDeviceUp). The event occurs whenever the stack +** has detected that the controller status has changed. This asynchronous event +** is enabled/disabled by calling BTM_RegisterForDeviceStatusNotif(). +*/ +enum +{ + BTM_DEV_STATUS_UP, + BTM_DEV_STATUS_DOWN, + BTM_DEV_STATUS_CMD_TOUT +}; +typedef UINT8 tBTM_DEV_STATUS; + +typedef void (tBTM_DEV_STATUS_CB) (tBTM_DEV_STATUS status); + +/* Callback function for when a vendor specific event occurs. The length and +** array of returned parameter bytes are included. This asynchronous event +** is enabled/disabled by calling BTM_RegisterForVSEvents(). +*/ +typedef void (tBTM_VS_EVT_CB) (UINT8 len, UINT8 *p); + +/* VSC callback function for notifying an application that a synchronous +** BTM function is complete. The pointer contains the address of any returned data. +*/ +typedef void (tBTM_VSC_CMPL_CB) (tBTM_VSC_CMPL *p1); + +/* Attributes mask values to be used in HID_HostAddDev API */ +#define HID_VIRTUAL_CABLE 0x0001 +#define HID_NORMALLY_CONNECTABLE 0x0002 +#define HID_RECONN_INIT 0x0004 +#define HID_SDP_DISABLE 0x0008 +#define HID_BATTERY_POWER 0x0010 +#define HID_REMOTE_WAKE 0x0020 +#define HID_SUP_TOUT_AVLBL 0x0040 +#define HID_SSR_MAX_LATENCY 0x0080 +#define HID_SSR_MIN_TOUT 0x0100 + +#define HID_SEC_REQUIRED 0x8000 + +#define BTA_HH_VIRTUAL_CABLE HID_VIRTUAL_CABLE +#define BTA_HH_NORMALLY_CONNECTABLE HID_NORMALLY_CONNECTABLE +#define BTA_HH_RECONN_INIT HID_RECONN_INIT +#define BTA_HH_SDP_DISABLE HID_SDP_DISABLE +#define BTA_HH_BATTERY_POWER HID_BATTERY_POWER +#define BTA_HH_REMOTE_WAKE HID_REMOTE_WAKE +#define BTA_HH_SUP_TOUT_AVLBL HID_SUP_TOUT_AVLBL +#define BTA_HH_SEC_REQUIRED HID_SEC_REQUIRED +typedef UINT16 tBTA_HH_ATTR_MASK; + +typedef struct desc_info +{ + UINT16 dl_len; + UINT8 *dsc_list; +} tHID_DEV_DSCP_INFO; + +typedef tHID_DEV_DSCP_INFO tBTA_HH_DEV_DESCR; + +/* Policy settings status */ +#define HCI_DISABLE_ALL_LM_MODES 0x0000 +#define HCI_ENABLE_MASTER_SLAVE_SWITCH 0x0001 +#define HCI_ENABLE_HOLD_MODE 0x0002 +#define HCI_ENABLE_SNIFF_MODE 0x0004 +#define HCI_ENABLE_PARK_MODE 0x0008 + +/* HCI mode defenitions */ +#define HCI_MODE_ACTIVE 0x00 +#define HCI_MODE_HOLD 0x01 +#define HCI_MODE_SNIFF 0x02 +#define HCI_MODE_PARK 0x03 + +/* BTM Power manager status codes */ +enum +{ + BTM_PM_STS_ACTIVE = HCI_MODE_ACTIVE, + BTM_PM_STS_HOLD = HCI_MODE_HOLD, + BTM_PM_STS_SNIFF = HCI_MODE_SNIFF, + BTM_PM_STS_PARK = HCI_MODE_PARK, + BTM_PM_STS_SSR, /* report the SSR parameters in HCI_SNIFF_SUB_RATE_EVT */ + BTM_PM_STS_PENDING, /* when waiting for status from controller */ + BTM_PM_STS_ERROR /* when HCI command status returns error */ +}; +typedef UINT8 tBTM_PM_STATUS; + +/* BTM Power manager modes */ + +enum +{ + BTM_PM_MD_ACTIVE = BTM_PM_STS_ACTIVE, + BTM_PM_MD_HOLD = BTM_PM_STS_HOLD, + BTM_PM_MD_SNIFF = BTM_PM_STS_SNIFF, + BTM_PM_MD_PARK = BTM_PM_STS_PARK, + BTM_PM_MD_FORCE = 0x10 /* OR this to force ACL link to a certain mode */ +}; +typedef UINT8 tBTM_PM_MODE; + +#define BTM_PM_SET_ONLY_ID 0x80 + +/* Operation codes */ +#define BTM_PM_REG_SET 1 /* The module wants to set the desired power mode */ +#define BTM_PM_REG_NOTIF 2 /* The module wants to receive mode change event */ +#define BTM_PM_DEREG 4 /* The module does not want to involve with PM anymore */ + +typedef struct +{ + UINT16 max; + UINT16 min; + UINT16 attempt; + UINT16 timeout; + tBTM_PM_MODE mode; +} tBTM_PM_PWR_MD; + +/************************************* +** Power Manager Callback Functions +**************************************/ +typedef void (tBTM_PM_STATUS_CBACK) (BD_ADDR p_bda, tBTM_PM_STATUS status, + UINT16 value, UINT8 hci_status); + +/************************ +** Stored Linkkey Types +*************************/ +#define BTM_CB_EVT_RETURN_LINK_KEYS 1 +#define BTM_CB_EVT_READ_STORED_LINK_KEYS 2 +#define BTM_CB_EVT_WRITE_STORED_LINK_KEYS 3 +#define BTM_CB_EVT_DELETE_STORED_LINK_KEYS 4 + +typedef struct +{ + UINT8 event; + +} tBTM_STORED_LINK_KEYS_EVT; + + +typedef struct +{ + UINT8 event; + UINT8 num_keys; + +} tBTM_RETURN_LINK_KEYS_EVT; + + +typedef struct +{ + BD_ADDR bd_addr; + LINK_KEY link_key; + +} tBTM_BD_ADDR_LINK_KEY_PAIR; + + +typedef struct +{ + UINT8 event; + UINT8 status; + UINT16 max_keys; + UINT16 read_keys; + +} tBTM_READ_STORED_LINK_KEY_COMPLETE; + + +typedef struct +{ + UINT8 event; + UINT8 status; + UINT8 num_keys; + +} tBTM_WRITE_STORED_LINK_KEY_COMPLETE; + + +typedef struct +{ + UINT8 event; + UINT8 status; + UINT16 num_keys; + +} tBTM_DELETE_STORED_LINK_KEY_COMPLETE; + +// --- + +tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback); +tBTA_STATUS BTA_DisableBluetooth(void); + +// muff1n: most changed prototype so far +tBTA_STATUS BTA_DmAddDevice(BD_ADDR bd_addr, LINK_KEY link_key, + tBTA_SERVICE_MASK trusted_mask, BOOLEAN is_trusted); +tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr); +void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services, tBTA_DM_SEARCH_CBACK *p_cback); +void BTA_DmSearchCancel(void); +void BTA_DmPinReply(BD_ADDR bd_addr, BOOLEAN accept, UINT8 pin_len, UINT8 *p_pin); +BOOLEAN BTA_DmIsDeviceUp(void); +void BTA_DmSetDeviceName(char *p_name); + +// muff1n: disc_mode and conn_mode might be the , based on usage +void BTA_DmSetVisibility(UINT8, UINT8); + +// muff1n: ucd_enabled might be the missing parameter +void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback); +// muff1n: possibly takes just a tBTA_HH_DEV_DESCR in this version? i wrote it like that +void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class, + UINT8 app_id, tBTA_HH_DEV_DESCR descr); +void BTA_HhRemoveDev(UINT8 dev_handle); +void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask); +void BTA_HhClose(UINT8 dev_handle); + +// muff1n: dev_bda is likely the missing parameter, as it is not used +void BTA_HhSendData(UINT8 dev_handle, BT_HDR *p_data); + +void bta_sys_set_trace_level(UINT8 level); + +void BTM_DeviceReset (tBTM_CMPL_CB *p_cb); + +tBTM_STATUS BTM_ReadStoredLinkKey(BD_ADDR bd_addr, tBTM_CMPL_CB *p_cb); +tBTM_STATUS BTM_WriteStoredLinkKey(UINT8 num_keys, + BD_ADDR *bd_addr, + LINK_KEY *link_key, + tBTM_CMPL_CB *p_cb); +tBTM_STATUS BTM_DeleteStoredLinkKey(BD_ADDR bd_addr, tBTM_CMPL_CB *p_cb); + +tBTM_STATUS BTM_SetPowerMode(UINT8 pm_id, BD_ADDR remote_bda, tBTM_PM_PWR_MD *p_mode); +tBTM_STATUS BTM_SetAfhChannels(UINT8 first, UINT8 last); + +tBTM_STATUS BTM_VendorSpecificCommand(UINT16 opcode, UINT8 param_len, + UINT8 *p_param_buf, tBTM_VSC_CMPL_CB *p_cb); + +tBTM_STATUS BTM_ReadLocalVersion(tBTM_VERSION_INFO *p_vers); +tBTM_STATUS BTM_SetDeviceClass(DEV_CLASS dev_class); + +tBTM_STATUS btm_remove_acl(BD_ADDR bd_addr); + +// muff1n: is_register is probably the missing parameter here +tBTM_STATUS BTM_RegisterForVSEvents(tBTM_VS_EVT_CB *p_cb); +tBTM_DEV_STATUS_CB *BTM_RegisterForDeviceStatusNotif(tBTM_DEV_STATUS_CB *p_cb); + +tBTM_STATUS BTM_PmRegister(UINT8 mask, UINT8 *p_pm_id, tBTM_PM_STATUS_CBACK *p_cb); +tBTM_STATUS BTM_WritePageTimeout(UINT16 timeout); +void BTM_SetDefaultLinkPolicy(UINT16 settings); +void BTM_SetDefaultLinkSuperTout(UINT16 timeout); + +BOOLEAN BTM_SecAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, + BD_FEATURES features, UINT32 trusted_mask[], + LINK_KEY link_key); + +void *GKI_getbuf(UINT16 size); + +UINT8 L2CA_SetTraceLevel(UINT8 trace_level); + +UINT8 SDP_SetTraceLevel(UINT8 new_level); + +/* muff1n: not in bluedroid source; might be older removed API functions */ +void BTA_DmSendHciReset(void); +void BTA_HhGetAclQueueInfo(void); +void BTA_Init(void); +void BTA_CleanUp(void (*p_cb)(tBTA_STATUS status)); // probably + +// --- +/* muff1n: I wrote this definition myself + * TODO: would this be part of BLE or WUD? + */ + +struct small_dev_info +{ + char devName[20]; // size 0x14? offset 0x00 // might be 0x13? + char at_0x14[1]; // size 0x??, offset 0x14? + char __pad0[0x20 - (0x14 + 0x01)]; + LINK_KEY linkKey; // size 0x10, offset 0x20 + char __pad1[0x10]; +}; // size 0x40 + +#endif // CONTEXT_BTE_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/lint.c b/src/sdk/RVL_SDK/revolution/wpad/lint.c new file mode 100644 index 00000000..9e13ff92 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/lint.c @@ -0,0 +1,212 @@ +#include "lint.h" + +/******************************************************************************* + * headers + */ + +#include +#include // memset + +/******************************************************************************* + * macros + */ + +#define ULONG_BIT (sizeof(ULONG) * CHAR_BIT) +#define ULLONG_BIT (sizeof(ULLONG) * CHAR_BIT) + +#define ULLONG_ULONG_BIT_DIFF (ULLONG_BIT - ULONG_BIT) + +/******************************************************************************* + * types + */ + +typedef unsigned long long ULLONG; + +/******************************************************************************* + * explanation + * + * so basically these LINT* functions operate on these buffers where + * + * struct LINTBuf + * { + * ULONG size; + * ULONG data[size]; + * ULONG terminator = 0; + * }; + * + * i also tried to make the functions here as type-generic as possible, but some + * assumptions within the functions may inherently remain that there is a 32-bit + * wide type and a 64-bit wide type on the machine + * + */ + +/******************************************************************************* + * functions + */ + +int LINTCmp(const ULONG *lhs, const ULONG *rhs) +{ + int i; + + ULONG lhsSize = lhs[0]; + ULONG rhsSize = rhs[0]; + + const ULONG *lhsData = lhs + 1; + const ULONG *rhsData = rhs + 1; + + if (lhsSize > rhsSize) + return 1; + + if (lhsSize < rhsSize) + return -1; + + for (i = lhsSize - 1; i >= 0; i--) + { + if (lhsData[i] > rhsData[i]) + return 1; + + if (lhsData[i] < rhsData[i]) + return -1; + } + + return 0; +} + +// const fucks up loop optimization on release +void LINTLshift(ULONG *dst, /* const */ ULONG *src, ULONG shift) +{ + // i being int here just fucks up release in general + ULONG i; + + ULONG size = src[0]; + + ULONG *srcData = src + 1; + ULONG *dstData = dst + 1; + + ULONG bigShift = shift / ULONG_BIT; + ULONG smallShift = shift % ULONG_BIT; + + for (i = 0; i < bigShift; i++) + dstData[i] = 0; + + ULLONG num = 0; + + for (i = 0; i < size; i++) + { + num += (ULLONG)srcData[i] << smallShift; + + dstData[i + bigShift] = num & ULONG_MAX; + num = (num >> ULLONG_ULONG_BIT_DIFF) & ULONG_MAX; + } + + dstData[i + bigShift] = num; + *dst = size + bigShift; + + if (num) + (*dst)++; +} + +int LINTMsb(const ULONG *data) +{ + int i; + + ULONG size = data[0]; + + ULONG last = LINTNextElement(data, size - 1); + ULONG msbPos = ULONG_BIT; + ULONG a __attribute__((unused)); + + i = 0; + while (i < ULONG_BIT) + { + if (((1ul << (ULONG_BIT - 1)) >> i) & last) + break; + + i++; + a = msbPos--; // ? + } + + return msbPos + (size - 1) * ULONG_BIT; +} + +void LINTSub(ULONG *dst, const ULONG *lhs, const ULONG *rhs) +{ + int i; + + ULONG lhsSize = lhs[0]; + ULONG rhsSize = rhs[0]; + + const ULONG *lhsData = lhs + 1; + const ULONG *rhsData = rhs + 1; + ULONG *dstData = dst + 1; + + ULLONG num = 0; + + for (i = 0; i < lhsSize; i++) + { + dstData[i] = lhsData[i] - (ULONG)num; + + if ((ULLONG)dstData[i] > ULONG_MAX - num) + num = 1; + else + num = 0; + + if (i < rhsSize) + dstData[i] -= rhsData[i]; + + if (dstData[i] > -1l - rhsData[i]) + num++; + } + + i = lhsSize; + while (i && !dstData[i]) + i--; + + *dst = i + 1; +} + +// TODO on release +void LINTMul(ULONG *dst, const ULONG *lhs, const ULONG *rhs) +{ + int i, j; + + const ULONG lhsSize = lhs[0]; + const ULONG rhsSize = rhs[0]; + + const ULONG *lhsData = lhs + 1; + const ULONG *rhsData = rhs + 1; + ULONG *dstData = dst + 1; + + ULLONG num = 0; + + dst[0] = 1; + + memset(dst + 1, 0, 128); // where is 128 from? + + // buffer was cleared + if ((lhs[0] == 1 && lhs[1] == 0) || (rhs[0] == 1 && rhs[1] == 0)) + return; + + for (i = 0; i < rhsSize; i++) + { + num = 0; + + for (j = 0; j < lhsSize; j++) + { + num = (ULLONG)lhsData[j] * rhsData[i] + num + + dstData[i + j]; + + dstData[i + j] = num & ULONG_MAX; + num = ((num >> ULLONG_ULONG_BIT_DIFF) & ULONG_MAX) + % (1ull << ULLONG_ULONG_BIT_DIFF); + } + + dstData[i + j] = num; + } + + ULONG a __attribute__((unused)); // ? + if (num == 0) + a = *dst = lhsSize + rhsSize - 1; + else + a = *dst = lhsSize + rhsSize; +} diff --git a/src/sdk/RVL_SDK/revolution/wpad/lint.h b/src/sdk/RVL_SDK/revolution/wpad/lint.h new file mode 100644 index 00000000..bde55fa4 --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/lint.h @@ -0,0 +1,36 @@ +#ifndef RVL_SDK_WPAD_INTERNAL_LINT_H +#define RVL_SDK_WPAD_INTERNAL_LINT_H + +/* no public header */ + +/******************************************************************************* + * macros + */ + +#define LINTNextElement(a, b) ((&((a)[b]))[1]) + +/******************************************************************************* + * types + */ + +#ifdef __cplusplus + extern "C" { +#endif + +typedef unsigned long ULONG; + +/******************************************************************************* + * functions + */ + +int LINTCmp(const ULONG *lhs, const ULONG *rhs); +void LINTLshift(ULONG *dst, ULONG *src, ULONG shift); +int LINTMsb(const ULONG *data); +void LINTSub(ULONG *dst, const ULONG *lhs, const ULONG *rhs); +void LINTMul(ULONG *dst, const ULONG *lhs, const ULONG *rhs); + +#ifdef __cplusplus + } +#endif + +#endif // RVL_SDK_WPAD_INTERNAL_LINT_H diff --git a/src/sdk/RVL_SDK/revolution/wpad/src.txt b/src/sdk/RVL_SDK/revolution/wpad/src.txt new file mode 100644 index 00000000..9d1bb17c --- /dev/null +++ b/src/sdk/RVL_SDK/revolution/wpad/src.txt @@ -0,0 +1 @@ +.c and .h files courtesy of https://github.com/muff1n1634/wpad_11dec2009 diff --git a/src/system/meta/StoreEnumeration.cpp b/src/system/meta/StoreEnumeration.cpp index f823f48a..6cd1e4bc 100644 --- a/src/system/meta/StoreEnumeration.cpp +++ b/src/system/meta/StoreEnumeration.cpp @@ -16,3 +16,9 @@ bool WiiEnumeration::IsSuccess() const { int WiiEnumeration::IsEnumerating() const { return (mState != kSuccess && mState != kFail) ? true : false; } + +void WiiEnumeration::Poll() { + if (mState == kEnumWaiting) { + + } +} diff --git a/src/system/obj/Data.h b/src/system/obj/Data.h index 2505b464..0d49ff2a 100644 --- a/src/system/obj/Data.h +++ b/src/system/obj/Data.h @@ -111,6 +111,7 @@ class DataNode { ~DataNode(); DataType Type() const { return mType; } + DataNodeValue RawVal() { return mValue; } bool CompatibleType(DataType) const; DataNode& Evaluate() const; diff --git a/src/system/obj/DataFunc.cpp b/src/system/obj/DataFunc.cpp index 488c4482..26da8f79 100644 --- a/src/system/obj/DataFunc.cpp +++ b/src/system/obj/DataFunc.cpp @@ -35,9 +35,11 @@ static DataNode Data##name(DataArray* da) code DECOMP_FORCEDTOR(DataFunc, MergeFilter); void DataRegisterFunc(Symbol s, DataFunc* func){ +#ifdef MILO_DEBUG const std::map::iterator it = gDataFuncs.find(s); if(it != gDataFuncs.end() && it->second != func) MILO_FAIL("Can't register different func %s", s); +#endif gDataFuncs[s] = func; } @@ -720,21 +722,27 @@ static DataNode DataRandomSeed(DataArray *da) { } static DataNode DataNotify(DataArray* da){ +#ifdef MILO_DEBUG class String str; for(int i = 1; i < da->Size(); i++){ da->Evaluate(i).Print(str, true); } TheDebug.Notify(str.c_str()); +#endif return DataNode(0); } static DataNode DataNotifyBeta(DataArray* da) { +#ifdef MILO_DEBUG class String s; for (int i = 1; i < da->Size(); i++) { da->Evaluate(i).Print(s, true); } TheDebug << MakeString(s.c_str()); return DataNode(); +#else + return DataNode(0); +#endif } // DataNode DataNotifyBeta(DataArray *da) @@ -773,16 +781,19 @@ static DataNode DataNotifyBeta(DataArray* da) { // } static DataNode DataFail(DataArray* da){ +#ifdef MILO_DEBUG class String str; for(int i = 1; i < da->Size(); i++){ da->Evaluate(i).Print(str, true); } TheDebug << MakeString("%d\n", da->Line()); TheDebug.Fail(str.c_str()); +#endif return DataNode(0); } static DataNode DataNotifyOnce(DataArray *da) { +#ifdef MILO_DEBUG class String s; for (int i = 1; i < da->Size(); i++) { da->Evaluate(i).Print(s, true); @@ -790,6 +801,9 @@ static DataNode DataNotifyOnce(DataArray *da) { MILO_NOTIFY_ONCE(s.c_str()) return DataNode(); +#else + return DataNode(0); +#endif } static DataNode DataCond(DataArray* da){ @@ -994,7 +1008,7 @@ static DataNode DataHandle(DataArray* da) { DataArray* handlo = da->Array(i); DataNode& n = handlo->Evaluate(0); Hmx::Object* obj; - if (n.Type() == kDataObject) obj = n.mValue.object; + if (n.Type() == kDataObject) obj = n.RawVal().object; else if (n.Type() == kDataInt) obj = NULL; else obj = gDataDir->FindObject(n.LiteralStr(da), true); if (obj) obj->Handle(handlo, false); @@ -1003,19 +1017,21 @@ static DataNode DataHandle(DataArray* da) { return DataNode(0); } -DefDataFunc(HandleRet, { - DataArray* a = da->Array(1); - Hmx::Object* o; - DataNode& n = a->Evaluate(0); - if (n.Type() == kDataObject) o = n.mValue.object; +static DataNode DataHandleRet(DataArray *da) { + DataArray *a = da->Array(1); + Hmx ::Object *o; + DataNode &n = a->Evaluate(0); + if (n.Type() == kDataObject) o = n.RawVal().object; else o = gDataDir->FindObject(n.LiteralStr(da), true); +#ifdef MILO_DEBUG if (!o) { class String str; n.Print(str, true); MILO_FAIL("Object %s not found (file %s, line %d)", str.c_str(), da->File(), da->Line()); } +#endif return o->Handle(a, false); -}) +} static DataNode DataRun(DataArray* da) { const char* e = FileMakePath(FileExecRoot(), da->Str(1), NULL); @@ -1023,7 +1039,7 @@ static DataNode DataRun(DataArray* da) { DataNode ret; if (read) { ret = read->ExecuteScript(0, gDataThis, NULL, 1); - read->mRefs -= 1; if (read->mRefs == 0) delete read; + read->Release(); } return ret; } diff --git a/src/system/obj/DataNode.cpp b/src/system/obj/DataNode.cpp index 4c896eec..38b4ba4d 100644 --- a/src/system/obj/DataNode.cpp +++ b/src/system/obj/DataNode.cpp @@ -78,43 +78,51 @@ DataNode& DataNode::Evaluate() const { int DataNode::Int(const DataArray* a) const { DataNode& n = Evaluate(); +#ifdef MILO_DEBUG if(n.mType != kDataInt){ String s; n.Print(s, true); if(a) MILO_FAIL("Data %s is not Int (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Int", String(s)); } +#endif return n.mValue.integer; } int DataNode::LiteralInt(const DataArray* a) const { +#ifdef MILO_DEBUG if(mType != kDataInt){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not Int (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Int", String(s)); } +#endif return mValue.integer; } Symbol DataNode::Sym(const DataArray* a) const { DataNode& n = Evaluate(); +#ifdef MILO_DEBUG if(n.mType != kDataSymbol){ String s; n.Print(s, true); if(a) MILO_FAIL("Data %s is not Symbol (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Symbol", String(s)); } +#endif return STR_TO_SYM(n.mValue.symbol); } Symbol DataNode::LiteralSym(const DataArray* a) const { +#ifdef MILO_DEBUG if(mType != kDataSymbol){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not Symbol (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Symbol", String(s)); } +#endif return STR_TO_SYM((char*)mValue.symbol); } @@ -124,12 +132,14 @@ Symbol DataNode::ForceSym(const DataArray* a) const { return STR_TO_SYM(n.mValue.symbol); } else { +#ifdef MILO_DEBUG if(n.mType != kDataString){ String s; n.Print(s, true); if(a) MILO_FAIL("Data %s is not String (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not String", String(s)); } +#endif return Symbol(n.mValue.var->mValue.symbol); } } @@ -140,12 +150,14 @@ const char* DataNode::Str(const DataArray* a) const { return n.mValue.symbol; } else { +#ifdef MILO_DEBUG if(n.mType != kDataString){ String s; n.Print(s, true); if(a) MILO_FAIL("Data %s is not String (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not String", String(s)); } +#endif return n.mValue.var->mValue.symbol; } } @@ -155,20 +167,24 @@ const char* DataNode::LiteralStr(const DataArray* a) const { return mValue.symbol; } else { +#ifdef MILO_DEBUG if(mType != kDataString){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not String (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not String", String(s)); } +#endif return mValue.var->mValue.symbol; } } +#ifdef MILO_DEBUG DECOMP_FORCEACTIVE(DataNode, "Data %s is not Glob (file %s, line %d)", "Data %s is not Glob" ) +#endif float DataNode::Float(const DataArray* a) const { DataNode& n = Evaluate(); @@ -176,12 +192,14 @@ float DataNode::Float(const DataArray* a) const { return n.mValue.integer; } else { +#ifdef MILO_DEBUG if(n.mType != kDataFloat){ String s; n.Print(s, true); if(a) MILO_FAIL("Data %s is not Float (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Float", String(s)); } +#endif return n.mValue.real; } } @@ -191,40 +209,46 @@ float DataNode::LiteralFloat(const DataArray* a) const { return mValue.integer; } else { +#ifdef MILO_DEBUG if(mType != kDataFloat){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not Float (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Float", String(s)); } +#endif return mValue.real; } } DataFunc* DataNode::Func(const DataArray* a) const { +#ifdef MILO_DEBUG if(mType != kDataFunc){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not Func (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Func", String(s)); } +#endif return mValue.func; } Hmx::Object* DataNode::GetObj(const DataArray* da) const { DataNode& n = Evaluate(); - if(n.Type() == kDataObject) return n.mValue.object; + if(n.mType == kDataObject) return n.mValue.object; else { const char* str = n.LiteralStr(da); Hmx::Object* ret = 0; if(*str != '\0'){ ret = gDataDir->FindObject(str, true); +#ifdef MILO_DEBUG if(ret == 0){ const char* msg; if(PathName(gDataDir) != 0) msg = PathName(gDataDir); else msg = "**no file**"; TheDebug.Fail(MakeString(kNotObjectMsg, str, msg)); } +#endif } return ret; @@ -233,47 +257,57 @@ Hmx::Object* DataNode::GetObj(const DataArray* da) const { DataArray* DataNode::Array(const DataArray* a) const { DataNode& n = Evaluate(); +#ifdef MILO_DEBUG if(n.mType != kDataArray){ String s; n.Print(s, true); if(a) MILO_FAIL("Data %s is not Array (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Array", String(s)); } +#endif return n.mValue.array; } DataArray* DataNode::LiteralArray(const DataArray* a) const { +#ifdef MILO_DEBUG if(mType != kDataArray){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not Array (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Array", String(s)); } +#endif return mValue.array; } +#ifdef MILO_DEBUG DECOMP_FORCEACTIVE(DataNode, "Data %s is not Property (file %s, line %d)", "Data %s is not Property" ) +#endif DataArray* DataNode::Command(const DataArray* a) const { +#ifdef MILO_DEBUG if(mType != kDataCommand){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not Command (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Command", String(s)); } +#endif return mValue.array; } DataNode* DataNode::Var(const DataArray* a) const { +#ifdef MILO_DEBUG if(mType != kDataVar){ String s; Print(s, true); if(a) MILO_FAIL("Data %s is not Var (file %s, line %d)", s.c_str(), a->mFile.mStr, (int)a->mLine); else MILO_FAIL("Data %s is not Var", String(s)); } +#endif return mValue.var; } @@ -534,7 +568,9 @@ void DataNode::Load(BinStream& d){ d >> sym; const std::map::iterator it = gDataFuncs.find(sym); if(it == gDataFuncs.end()){ + #ifdef MILO_DEBUG TheDebug.Fail(MakeString("Couldn't bind %s", sym)); + #endif } mValue.func = it->second; break; @@ -568,9 +604,11 @@ void DataNode::Load(BinStream& d){ case kDataObject: d.ReadString(buf, 0x80); mValue.object = gDataDir->FindObject(buf, true); + #ifdef MILO_DEBUG if(mValue.object == 0 && *buf){ TheDebug.Notify(MakeString("Couldn't find %s from %s", buf, gDataDir->Name())); } + #endif break; case kDataVar: { Symbol sym; @@ -592,7 +630,9 @@ void DataNode::Load(BinStream& d){ d >> mValue.integer; break; default: + #ifdef MILO_DEBUG TheDebug.Fail(MakeString("Unrecognized node type: %x", mType)); + #endif break; } } diff --git a/src/system/obj/TextFile.cpp b/src/system/obj/TextFile.cpp index e1ffec76..efc3942f 100644 --- a/src/system/obj/TextFile.cpp +++ b/src/system/obj/TextFile.cpp @@ -21,11 +21,12 @@ void TextFile::SetName(const char* c, class ObjectDir* dir){ Hmx::Object::SetName(c, dir); delete mFile; mFile = 0; - +#ifdef MILO_DEBUG bool holmes = UsingHolmes(4); if(c != 0 && *c != '\0' && holmes){ GetAppendFile(c, "_append", sizeof("_append") - 1); } +#endif } void TextFile::Print(const char* str){ diff --git a/src/system/os/NetStream.cpp b/src/system/os/NetStream.cpp index 4f083f70..d04fca96 100644 --- a/src/system/os/NetStream.cpp +++ b/src/system/os/NetStream.cpp @@ -17,6 +17,12 @@ void NetStream::ClientConnect(const NetAddress& addr){ MILO_ASSERT(mSocket, 0x37); Timer timer; timer.Restart(); + mSocket->Connect(addr.mIP, addr.mPort); + if (mSocket->Fail()) { + mFail = true; + } else { + + } } EofType NetStream::Eof(){ diff --git a/src/system/os/UsbMidiGuitar.cpp b/src/system/os/UsbMidiGuitar.cpp index e9844acd..7421bc06 100644 --- a/src/system/os/UsbMidiGuitar.cpp +++ b/src/system/os/UsbMidiGuitar.cpp @@ -69,11 +69,13 @@ UsbMidiGuitar::UsbMidiGuitar(){ UsbMidiGuitar::~UsbMidiGuitar(){ CritSecTracker tracker(&gCritSection); + mTimer.Stop(); } void UsbMidiGuitar::Init(){ MILO_ASSERT(TheGuitar == NULL, 0x64); TheGuitar = new UsbMidiGuitar(); + TheDebug.AddExitCallback(UsbMidiGuitar::Terminate); } void UsbMidiGuitar::Terminate(){ diff --git a/src/system/rndobj/Bitmap.h b/src/system/rndobj/Bitmap.h index dba04eeb..6ef2e5c9 100644 --- a/src/system/rndobj/Bitmap.h +++ b/src/system/rndobj/Bitmap.h @@ -64,8 +64,8 @@ class RndBitmap { // 0x1c void Create(const RndBitmap&, int, int, void*); void AllocateBuffer(); void Create(int, int, int, int, int, void*, void*, void*); - void Create(void*); - void PixelColor(int, int, unsigned char&, unsigned char&, unsigned char&, unsigned char&) const; + void Create(void*); + void PixelColor(int x, int y, u8& r, u8& g, u8& b, u8& a) const; int PixelOffset(int, int, bool&) const; int PixelIndex(int, int) const; void SetPixelIndex(int, int, unsigned char); diff --git a/src/system/rndobj/Mesh.cpp b/src/system/rndobj/Mesh.cpp index 1ad01c50..b1db6ded 100644 --- a/src/system/rndobj/Mesh.cpp +++ b/src/system/rndobj/Mesh.cpp @@ -279,7 +279,9 @@ BEGIN_HANDLERS(RndMesh) HANDLE(unitize_normals, OnUnitizeNormals) HANDLE(point_collide, OnPointCollide) HANDLE(configure_mesh, OnConfigureMesh) +#ifdef MILO_DEBUG HANDLE_EXPR(estimated_size_kb, EstimatedSizeKb()) +#endif HANDLE_ACTION(clear_bones, CopyBones(NULL)) HANDLE_ACTION(copy_geom_from_owner, CopyGeometryFromOwner()) HANDLE_SUPERCLASS(RndDrawable) diff --git a/src/system/rndobj/Rnd.cpp b/src/system/rndobj/Rnd.cpp index 5f21d988..e95e5a4b 100644 --- a/src/system/rndobj/Rnd.cpp +++ b/src/system/rndobj/Rnd.cpp @@ -134,9 +134,15 @@ Rnd::Rnd() : mClearColor(0.3f, 0.3f, 0.3f), mWidth(640), mHeight(480), mScreenBp mTimersOverlay(0), mRateOverlay(0), mHeapOverlay(0), mStatsOverlay(0), unk84(0), unk88(0), unk8c(0), mDefaultCam(0), unk94(0), unk98(0), unk9c(0), unkc0(0.0f), unkc8(6), mFrameID(0), unkd0(" "), mSync(1), mGsTiming(0), mShowSafeArea(0), unkde(0), unkdf(1), mAspect(kWidescreen), unk_0xE4(0), unke8(0), unke9(0), mShrinkToSafe(1), mInGame(0), unkec(0), mDisablePostProc(0), unkee(0), unkef(0), unkf0(0), unkf4(0), unkf8(0), mPostProcOverride(0), - unk110(this, kObjListNoNull), mDraws(this, kObjListNoNull), unk130(0), unk131(1), mProcCounter(), mProcCmds(kProcessAll), mLastProcCmds(kProcessAll), mForceCharLod(-1) { + unk110(this, kObjListNoNull), mDraws(this, kObjListNoNull), unk130(0), unk131(1), mProcCounter(), mProcCmds(kProcessAll), mLastProcCmds(kProcessAll) +#ifdef MILO_DEBUG + , mForceCharLod(-1) // jank it up! +#endif + { for(int i = 0; i < 8; i++) unk_arr[i] = 0; +#ifdef MILO_DEBUG gpDbgFrameID = (int*)&mFrameID; +#endif } float Rnd::YRatio() { diff --git a/src/system/zlib/zutil.c b/src/system/zlib/zutil.c index 93808bec..0ef4f99f 100644 --- a/src/system/zlib/zutil.c +++ b/src/system/zlib/zutil.c @@ -28,10 +28,10 @@ const char * const z_errmsg[10] = { ""}; -// const char * ZEXPORT zlibVersion() -// { -// return ZLIB_VERSION; -// } +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} uLong ZEXPORT zlibCompileFlags() {