From f5dbf1d8276b249b114b2ed08f0f7b095911e97c Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Sun, 1 Feb 2026 20:33:08 -0500 Subject: [PATCH] Revolution WPAD work (#3078) * WPAD mostly matching, likely equivalent * Implement WPADEncrypt (mostly taken from SMG1 decomp) * Implement WPADHidParser * Add wpad_debug_msg stub * Fix WUD file paths in splits * Fix WPAD regressions in Shield/ShieldD --- config/DZDE01/config.yml | 3 + config/DZDE01/splits.txt | 8 +- config/DZDE01/symbols.txt | 32 +- config/RZDE01_00/config.yml | 1 + config/RZDE01_00/splits.txt | 6 +- config/RZDE01_00/symbols.txt | 32 +- config/RZDE01_02/config.yml | 1 + config/RZDE01_02/splits.txt | 6 +- config/RZDE01_02/symbols.txt | 32 +- config/RZDJ01/config.yml | 1 + config/RZDJ01/splits.txt | 6 +- config/RZDJ01/symbols.txt | 32 +- config/RZDP01/config.yml | 1 + config/RZDP01/splits.txt | 8 +- config/RZDP01/symbols.txt | 32 +- config/Shield/splits.txt | 2 +- config/ShieldD/splits.txt | 2 +- config/ShieldD/symbols.txt | 2 +- configure.py | 12 +- include/revolution/dsp.h | 6 +- include/revolution/hw_regs.h | 10 + include/revolution/os.h | 1 + include/revolution/sc.h | 9 + include/revolution/vi/vifuncs.h | 3 + include/revolution/wpad.h | 341 ++- include/revolution/wpad/bte.h | 22 + include/revolution/wud/WUD.h | 256 ++ include/revolution/wud/debug_msg.h | 14 + .../homebuttonLib/HBMController.cpp | 24 +- src/revolution/os/OSStateTM.c | 4 - src/revolution/sc/scapi.c | 24 + src/revolution/vi/__vi.h | 2 + src/revolution/vi/vi.c | 13 +- src/revolution/wpad/WPAD.c | 2649 +++++++++++++++-- src/revolution/wpad/WPADEncrypt.c | 265 ++ src/revolution/wpad/WPADHIDParser.c | 1667 +++++++++++ src/revolution/wpad/WPADMem.c | 3 + src/revolution/wpad/__wpad.h | 450 ++- src/revolution/wpad/wpad_debug_msg.c | 5 + src/revolution/{wpad => wud}/WUD.c | 14 +- src/revolution/{wpad => wud}/__wud.h | 1 - src/revolution/wud/debug_msg.c | 6 + 42 files changed, 5328 insertions(+), 680 deletions(-) create mode 100644 include/revolution/wud/WUD.h create mode 100644 include/revolution/wud/debug_msg.h create mode 100644 src/revolution/wpad/WPADEncrypt.c create mode 100644 src/revolution/wpad/WPADHIDParser.c create mode 100644 src/revolution/wpad/WPADMem.c create mode 100644 src/revolution/wpad/wpad_debug_msg.c rename src/revolution/{wpad => wud}/WUD.c (88%) rename src/revolution/{wpad => wud}/__wud.h (98%) create mode 100644 src/revolution/wud/debug_msg.c diff --git a/config/DZDE01/config.yml b/config/DZDE01/config.yml index e3d4ef9b94..9e0afc3a22 100644 --- a/config/DZDE01/config.yml +++ b/config/DZDE01/config.yml @@ -13,6 +13,9 @@ force_active: [ _MetroTRK_Has_Framing, ] +block_relocations: +- source: .data:0x80402814 + modules: - object: files/RELS.arc:rels/mmem/f_pc_profile_lst.rel hash: 41ba85f7b9ce10916ef321b987c42d715d7ffab0 diff --git a/config/DZDE01/splits.txt b/config/DZDE01/splits.txt index 717fdf7f91..949f92ebbd 100644 --- a/config/DZDE01/splits.txt +++ b/config/DZDE01/splits.txt @@ -3377,7 +3377,7 @@ revolution/wpad/WPADHIDParser.c: .text start:0x80349C6C end:0x8034E508 .data start:0x804022E0 end:0x80402740 .bss start:0x804BD608 end:0x804BD620 - .sbss start:0x804FB9D0 end:0x804FB9E0 + .sbss start:0x804FB9D0 end:0x804FB9D8 .sdata2 start:0x80500538 end:0x80500560 revolution/wpad/WPADMem.c: @@ -3385,10 +3385,12 @@ revolution/wpad/WPADMem.c: revolution/wpad/WPADEncrypt.c: .text start:0x8034E508 end:0x8034EDA0 - .data start:0x80402740 end:0x804030C0 + .data start:0x80402740 end:0x80403070 + .sbss start:0x804FB9D8 end:0x804FB9E0 revolution/kpad/KPAD.c: .text start:0x8034EDF0 end:0x80351B24 + .data start:0x80403070 end:0x804030C0 .bss start:0x804BD670 end:0x804BE680 .sdata start:0x804FA768 end:0x804FA7D8 .sbss start:0x804FB9E0 end:0x804FBA18 @@ -3404,7 +3406,7 @@ revolution/usb/usb.c: .sdata start:0x804FA7D8 end:0x804FA7E8 .sbss start:0x804FBA28 end:0x804FBA38 -revolution/wpad/WUD.c: +revolution/wud/WUD.c: .text start:0x80352F34 end:0x80356AEC .data start:0x80403678 end:0x80404440 .bss start:0x804BE680 end:0x804C03E0 diff --git a/config/DZDE01/symbols.txt b/config/DZDE01/symbols.txt index 5766704521..e915d532a5 100644 --- a/config/DZDE01/symbols.txt +++ b/config/DZDE01/symbols.txt @@ -27847,30 +27847,30 @@ RecalibrateBits = .sbss:0x804FB994; // type:object size:0x4 scope:global align:4 ResettingBits = .sbss:0x804FB998; // type:object size:0x4 scope:global align:4 data:4byte EnabledBits = .sbss:0x804FB99C; // type:object size:0x4 scope:global align:4 data:4byte Initialized = .sbss:0x804FB9A0; // type:object size:0x4 scope:global align:4 data:4byte -lbl_804FB9A8 = .sbss:0x804FB9A8; // type:object size:0x1 data:byte +_regShutdown = .sbss:0x804FB9A8; // type:object size:0x1 data:byte _senseCnt = .sbss:0x804FB9AA; // type:object size:0x2 scope:global align:2 data:2byte -lbl_804FB9AC = .sbss:0x804FB9AC; // type:object size:0x1 data:byte -lbl_804FB9AD = .sbss:0x804FB9AD; // type:object size:0x1 data:byte +_checkCnt = .sbss:0x804FB9AC; // type:object size:0x1 data:byte +_extCnt = .sbss:0x804FB9AD; // type:object size:0x1 data:byte _afhCnt = .sbss:0x804FB9AE; // type:object size:0x2 scope:global align:2 data:2byte _rumbleCnt = .sbss:0x804FB9B0; // type:object size:0x4 scope:global align:4 data:byte -lbl_804FB9B4 = .sbss:0x804FB9B4; // type:object size:0x1 data:byte -lbl_804FB9B5 = .sbss:0x804FB9B5; // type:object size:0x1 data:byte -lbl_804FB9B6 = .sbss:0x804FB9B6; // type:object size:0x1 data:byte +_afhChannel = .sbss:0x804FB9B4; // type:object size:0x1 data:byte +_shutdown = .sbss:0x804FB9B5; // type:object size:0x1 data:byte +_scSetting = .sbss:0x804FB9B6; // type:object size:0x1 data:byte _chan_active_state = .sbss:0x804FB9B8; // type:object size:0x4 scope:global align:4 data:byte _gamecode = .sbss:0x804FB9BC; // type:object size:0x4 scope:global align:4 data:4byte -lbl_804FB9C0 = .sbss:0x804FB9C0; // type:object size:0x1 data:byte -lbl_804FB9C1 = .sbss:0x804FB9C1; // type:object size:0x1 data:byte -lbl_804FB9C2 = .sbss:0x804FB9C2; // type:object size:0x1 data:byte +_gametype = .sbss:0x804FB9C0; // type:object size:0x1 data:byte +_scFlush = .sbss:0x804FB9C1; // type:object size:0x1 data:byte +_speakerVolume = .sbss:0x804FB9C2; // type:object size:0x1 data:byte _rumble = .sbss:0x804FB9C4; // type:object size:0x4 scope:global align:4 data:4byte -lbl_804FB9C8 = .sbss:0x804FB9C8; // type:object size:0x1 data:byte -lbl_804FB9C9 = .sbss:0x804FB9C9; // type:object size:0x1 data:byte -lbl_804FB9CA = .sbss:0x804FB9CA; // type:object size:0x1 data:byte +_sensorBarPos = .sbss:0x804FB9C8; // type:object size:0x1 data:byte +_dpdSensitivity = .sbss:0x804FB9C9; // type:object size:0x1 data:byte +_sleepTime = .sbss:0x804FB9CA; // type:object size:0x1 data:byte _recv_3e = .sbss:0x804FB9D0; // type:object size:0x4 scope:global align:4 _recv_3f = .sbss:0x804FB9D4; // type:object size:0x4 scope:global align:4 -lbl_804FB9D8 = .sbss:0x804FB9D8; // type:object size:0x1 data:byte -lbl_804FB9D9 = .sbss:0x804FB9D9; // type:object size:0x1 data:byte -lbl_804FB9DA = .sbss:0x804FB9DA; // type:object size:0x1 data:byte -lbl_804FB9DB = .sbss:0x804FB9DB; // type:object size:0x1 data:byte +NUM_C = .sbss:0x804FB9D8; // type:object size:0x1 data:byte +NUM_B = .sbss:0x804FB9D9; // type:object size:0x1 data:byte +NUM_A = .sbss:0x804FB9DA; // type:object size:0x1 data:byte +SEED = .sbss:0x804FB9DB; // type:object size:0x1 data:byte icenter_org = .sbss:0x804FB9E0; // type:object size:0x8 scope:global align:4 data:4byte Vec2_0 = .sbss:0x804FB9E8; // type:object size:0x8 scope:global align:4 data:4byte kp_dist_vv1 = .sbss:0x804FB9F0; // type:object size:0x4 scope:global align:4 data:float diff --git a/config/RZDE01_00/config.yml b/config/RZDE01_00/config.yml index 70a4a964fa..02e52a720e 100644 --- a/config/RZDE01_00/config.yml +++ b/config/RZDE01_00/config.yml @@ -16,6 +16,7 @@ force_active: [ block_relocations: - source: .text:0x80344978 - source: .text:0x803449f0 +- source: .data:0x80440ebc modules: - object: files/RELS.arc:rels/mmem/f_pc_profile_lst.rel diff --git a/config/RZDE01_00/splits.txt b/config/RZDE01_00/splits.txt index 4d9d3acace..9de906be2f 100644 --- a/config/RZDE01_00/splits.txt +++ b/config/RZDE01_00/splits.txt @@ -3626,7 +3626,7 @@ revolution/wpad/WPADHIDParser.c: .text start:0x80381AE4 end:0x80386380 .data start:0x80440988 end:0x80440DE8 .bss start:0x804FD368 end:0x804FD380 - .sbss start:0x8053B8A8 end:0x8053B8B8 + .sbss start:0x8053B8A8 end:0x8053B8B0 .sdata2 start:0x805405C8 end:0x805405F0 revolution/wpad/WPADMem.c: @@ -3634,13 +3634,15 @@ revolution/wpad/WPADMem.c: revolution/wpad/WPADEncrypt.c: .text start:0x80386380 end:0x80386C18 - .data start:0x80440DE8 end:0x80441768 + .data start:0x80440DE8 end:0x80441718 + .sbss start:0x8053B8B0 end:0x8053B8B8 revolution/wpad/wpad_debug_msg.c: .text start:0x80386C18 end:0x80386C68 revolution/kpad/KPAD.c: .text start:0x80386C68 end:0x8038999C + .data start:0x80441718 end:0x80441768 .bss start:0x804FD3D0 end:0x804FE3E0 .sdata start:0x8053A5B0 end:0x8053A620 .sbss start:0x8053B8B8 end:0x8053B8F0 diff --git a/config/RZDE01_00/symbols.txt b/config/RZDE01_00/symbols.txt index 921709fb97..b8c6c157e3 100644 --- a/config/RZDE01_00/symbols.txt +++ b/config/RZDE01_00/symbols.txt @@ -29030,30 +29030,30 @@ RecalibrateBits = .sbss:0x8053B86C; // type:object size:0x4 scope:global align:4 ResettingBits = .sbss:0x8053B870; // type:object size:0x4 scope:global align:4 data:4byte EnabledBits = .sbss:0x8053B874; // type:object size:0x4 scope:global align:4 data:4byte Initialized = .sbss:0x8053B878; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8053b880 = .sbss:0x8053B880; // type:object size:0x1 scope:global align:1 data:byte +_regShutdown = .sbss:0x8053B880; // type:object size:0x1 scope:global align:1 data:byte _senseCnt = .sbss:0x8053B882; // type:object size:0x2 scope:global align:2 data:2byte -lbl_8053B884 = .sbss:0x8053B884; // type:object size:0x1 data:byte -lbl_8053B885 = .sbss:0x8053B885; // type:object size:0x1 data:byte +_checkCnt = .sbss:0x8053B884; // type:object size:0x1 data:byte +_extCnt = .sbss:0x8053B885; // type:object size:0x1 data:byte _afhCnt = .sbss:0x8053B886; // type:object size:0x2 scope:global align:2 data:2byte _rumbleCnt = .sbss:0x8053B888; // type:object size:0x4 scope:global align:4 data:byte -lbl_8053B88C = .sbss:0x8053B88C; // type:object size:0x1 data:byte -lbl_8053B88D = .sbss:0x8053B88D; // type:object size:0x1 data:byte -lbl_8053B88E = .sbss:0x8053B88E; // type:object size:0x1 data:byte +_afhChannel = .sbss:0x8053B88C; // type:object size:0x1 data:byte +_shutdown = .sbss:0x8053B88D; // type:object size:0x1 data:byte +_scSetting = .sbss:0x8053B88E; // type:object size:0x1 data:byte _chan_active_state = .sbss:0x8053B890; // type:object size:0x4 scope:global align:4 data:byte _gamecode = .sbss:0x8053B894; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8053B898 = .sbss:0x8053B898; // type:object size:0x1 data:byte -lbl_8053B899 = .sbss:0x8053B899; // type:object size:0x1 data:byte -lbl_8053B89A = .sbss:0x8053B89A; // type:object size:0x1 data:byte +_gametype = .sbss:0x8053B898; // type:object size:0x1 data:byte +_scFlush = .sbss:0x8053B899; // type:object size:0x1 data:byte +_speakerVolume = .sbss:0x8053B89A; // type:object size:0x1 data:byte _rumble = .sbss:0x8053B89C; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8053B8A0 = .sbss:0x8053B8A0; // type:object size:0x1 data:byte -lbl_8053B8A1 = .sbss:0x8053B8A1; // type:object size:0x1 data:byte -lbl_8053B8A2 = .sbss:0x8053B8A2; // type:object size:0x1 data:byte +_sensorBarPos = .sbss:0x8053B8A0; // type:object size:0x1 data:byte +_dpdSensitivity = .sbss:0x8053B8A1; // type:object size:0x1 data:byte +_sleepTime = .sbss:0x8053B8A2; // type:object size:0x1 data:byte _recv_3e = .sbss:0x8053B8A8; // type:object size:0x4 scope:global align:4 _recv_3f = .sbss:0x8053B8AC; // type:object size:0x4 scope:global align:4 -lbl_8053B8B0 = .sbss:0x8053B8B0; // type:object size:0x1 data:byte -lbl_8053B8B1 = .sbss:0x8053B8B1; // type:object size:0x1 data:byte -lbl_8053B8B2 = .sbss:0x8053B8B2; // type:object size:0x1 data:byte -lbl_8053B8B3 = .sbss:0x8053B8B3; // type:object size:0x1 data:byte +NUM_C = .sbss:0x8053B8B0; // type:object size:0x1 data:byte +NUM_B = .sbss:0x8053B8B1; // type:object size:0x1 data:byte +NUM_A = .sbss:0x8053B8B2; // type:object size:0x1 data:byte +SEED = .sbss:0x8053B8B3; // type:object size:0x1 data:byte icenter_org = .sbss:0x8053B8B8; // type:object size:0x8 scope:global align:4 data:4byte Vec2_0 = .sbss:0x8053B8C0; // type:object size:0x8 scope:global align:4 data:4byte kp_dist_vv1 = .sbss:0x8053B8C8; // type:object size:0x4 scope:global align:4 data:float diff --git a/config/RZDE01_02/config.yml b/config/RZDE01_02/config.yml index 9b51685334..db7280b5b0 100644 --- a/config/RZDE01_02/config.yml +++ b/config/RZDE01_02/config.yml @@ -16,6 +16,7 @@ force_active: [ block_relocations: - source: .text:0x8032f348 - source: .text:0x8032f3c0 +- source: .data:0x8042839c modules: - object: files/RELS.arc:rels/mmem/f_pc_profile_lst.rel diff --git a/config/RZDE01_02/splits.txt b/config/RZDE01_02/splits.txt index ed96c0fed3..84de438bfd 100644 --- a/config/RZDE01_02/splits.txt +++ b/config/RZDE01_02/splits.txt @@ -3588,7 +3588,7 @@ revolution/wpad/WPADHIDParser.c: .text start:0x8036C51C end:0x80370DB8 .data start:0x80427E68 end:0x804282C8 .bss start:0x804E33E8 end:0x804E3400 - .sbss start:0x805218A0 end:0x805218B0 + .sbss start:0x805218A0 end:0x805218A8 .sdata2 start:0x80526648 end:0x80526670 revolution/wpad/WPADMem.c: @@ -3596,10 +3596,12 @@ revolution/wpad/WPADMem.c: revolution/wpad/WPADEncrypt.c: .text start:0x80370DB8 end:0x80371650 - .data start:0x804282C8 end:0x80428C48 + .data start:0x804282C8 end:0x80428BF8 + .sbss start:0x805218A8 end:0x805218B0 revolution/kpad/KPAD.c: .text start:0x80371650 end:0x803743D4 + .data start:0x80428BF8 end:0x80428C48 .bss start:0x804E3450 end:0x804E4460 .sdata start:0x805205C0 end:0x80520630 .sbss start:0x805218B0 end:0x805218E8 diff --git a/config/RZDE01_02/symbols.txt b/config/RZDE01_02/symbols.txt index 9c8485cd7b..32d5938dd8 100644 --- a/config/RZDE01_02/symbols.txt +++ b/config/RZDE01_02/symbols.txt @@ -28550,30 +28550,30 @@ RecalibrateBits = .sbss:0x80521864; // type:object size:0x4 scope:global align:4 ResettingBits = .sbss:0x80521868; // type:object size:0x4 scope:global align:4 data:4byte EnabledBits = .sbss:0x8052186C; // type:object size:0x4 scope:global align:4 data:4byte Initialized = .sbss:0x80521870; // type:object size:0x4 scope:global align:4 data:4byte -lbl_80521878 = .sbss:0x80521878; // type:object size:0x1 data:byte +_regShutdown = .sbss:0x80521878; // type:object size:0x1 data:byte _senseCnt = .sbss:0x8052187A; // type:object size:0x2 scope:global align:2 data:2byte -lbl_8052187C = .sbss:0x8052187C; // type:object size:0x1 data:byte -lbl_8052187D = .sbss:0x8052187D; // type:object size:0x1 data:byte +_checkCnt = .sbss:0x8052187C; // type:object size:0x1 data:byte +_extCnt = .sbss:0x8052187D; // type:object size:0x1 data:byte _afhCnt = .sbss:0x8052187E; // type:object size:0x2 scope:global align:2 data:2byte _rumbleCnt = .sbss:0x80521880; // type:object size:0x4 scope:global align:4 data:byte -lbl_80521884 = .sbss:0x80521884; // type:object size:0x1 data:byte -lbl_80521885 = .sbss:0x80521885; // type:object size:0x1 data:byte -lbl_80521886 = .sbss:0x80521886; // type:object size:0x1 data:byte +_afhChannel = .sbss:0x80521884; // type:object size:0x1 data:byte +_shutdown = .sbss:0x80521885; // type:object size:0x1 data:byte +_scSetting = .sbss:0x80521886; // type:object size:0x1 data:byte _chan_active_state = .sbss:0x80521888; // type:object size:0x4 scope:global align:4 data:byte _gamecode = .sbss:0x8052188C; // type:object size:0x4 scope:global align:4 data:4byte -lbl_80521890 = .sbss:0x80521890; // type:object size:0x1 data:byte -lbl_80521891 = .sbss:0x80521891; // type:object size:0x1 data:byte -lbl_80521892 = .sbss:0x80521892; // type:object size:0x1 data:byte +_gametype = .sbss:0x80521890; // type:object size:0x1 data:byte +_scFlush = .sbss:0x80521891; // type:object size:0x1 data:byte +_speakerVolume = .sbss:0x80521892; // type:object size:0x1 data:byte _rumble = .sbss:0x80521894; // type:object size:0x4 scope:global align:4 data:4byte -lbl_80521898 = .sbss:0x80521898; // type:object size:0x1 data:byte -lbl_80521899 = .sbss:0x80521899; // type:object size:0x1 data:byte -lbl_8052189A = .sbss:0x8052189A; // type:object size:0x1 data:byte +_sensorBarPos = .sbss:0x80521898; // type:object size:0x1 data:byte +_dpdSensitivity = .sbss:0x80521899; // type:object size:0x1 data:byte +_sleepTime = .sbss:0x8052189A; // type:object size:0x1 data:byte _recv_3e = .sbss:0x805218A0; // type:object size:0x4 scope:global align:4 _recv_3f = .sbss:0x805218A4; // type:object size:0x4 scope:global align:4 -lbl_805218A8 = .sbss:0x805218A8; // type:object size:0x1 data:byte -lbl_805218A9 = .sbss:0x805218A9; // type:object size:0x1 data:byte -lbl_805218AA = .sbss:0x805218AA; // type:object size:0x1 data:byte -lbl_805218AB = .sbss:0x805218AB; // type:object size:0x1 data:byte +NUM_C = .sbss:0x805218A8; // type:object size:0x1 data:byte +NUM_B = .sbss:0x805218A9; // type:object size:0x1 data:byte +NUM_A = .sbss:0x805218AA; // type:object size:0x1 data:byte +SEED = .sbss:0x805218AB; // type:object size:0x1 data:byte icenter_org = .sbss:0x805218B0; // type:object size:0x8 scope:global align:4 data:4byte Vec2_0 = .sbss:0x805218B8; // type:object size:0x8 scope:global align:4 data:4byte kp_dist_vv1 = .sbss:0x805218C0; // type:object size:0x4 scope:global align:4 data:float diff --git a/config/RZDJ01/config.yml b/config/RZDJ01/config.yml index 7cd94dd0b4..e91f4e311e 100644 --- a/config/RZDJ01/config.yml +++ b/config/RZDJ01/config.yml @@ -16,6 +16,7 @@ force_active: [ block_relocations: - source: .text:0x80330e68 - source: .text:0x80330ee0 +- source: .data:0x8042621c modules: - object: files/RELS.arc:rels/mmem/f_pc_profile_lst.rel diff --git a/config/RZDJ01/splits.txt b/config/RZDJ01/splits.txt index 929ba6916f..6849b350e9 100644 --- a/config/RZDJ01/splits.txt +++ b/config/RZDJ01/splits.txt @@ -3584,7 +3584,7 @@ revolution/wpad/WPADHIDParser.c: .text start:0x8036DFD4 end:0x80372870 .data start:0x80425CE8 end:0x80426148 .bss start:0x804E1268 end:0x804E1280 - .sbss start:0x8051F710 end:0x8051F720 + .sbss start:0x8051F710 end:0x8051F718 .sdata2 start:0x805244A0 end:0x805244C8 revolution/wpad/WPADMem.c: @@ -3592,10 +3592,12 @@ revolution/wpad/WPADMem.c: revolution/wpad/WPADEncrypt.c: .text start:0x80372870 end:0x80373108 - .data start:0x80426148 end:0x80426AC8 + .data start:0x80426148 end:0x80426A78 + .sbss start:0x8051F718 end:0x8051F720 revolution/kpad/KPAD.c: .text start:0x80373158 end:0x80375E8C + .data start:0x80426A78 end:0x80426AC8 .bss start:0x804E12D0 end:0x804E22E0 .sdata start:0x8051E430 end:0x8051E4A0 .sbss start:0x8051F720 end:0x8051F758 diff --git a/config/RZDJ01/symbols.txt b/config/RZDJ01/symbols.txt index 3c20082df4..6ed5b5431e 100644 --- a/config/RZDJ01/symbols.txt +++ b/config/RZDJ01/symbols.txt @@ -28554,30 +28554,30 @@ RecalibrateBits = .sbss:0x8051F6D4; // type:object size:0x4 scope:global align:4 ResettingBits = .sbss:0x8051F6D8; // type:object size:0x4 scope:global align:4 data:4byte EnabledBits = .sbss:0x8051F6DC; // type:object size:0x4 scope:global align:4 data:4byte Initialized = .sbss:0x8051F6E0; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8051F6E8 = .sbss:0x8051F6E8; // type:object size:0x1 data:byte +_regShutdown = .sbss:0x8051F6E8; // type:object size:0x1 data:byte _senseCnt = .sbss:0x8051F6EA; // type:object size:0x2 scope:global align:2 data:2byte -lbl_8051F6EC = .sbss:0x8051F6EC; // type:object size:0x1 data:byte -lbl_8051F6ED = .sbss:0x8051F6ED; // type:object size:0x1 data:byte +_checkCnt = .sbss:0x8051F6EC; // type:object size:0x1 data:byte +_extCnt = .sbss:0x8051F6ED; // type:object size:0x1 data:byte _afhCnt = .sbss:0x8051F6EE; // type:object size:0x2 scope:global align:2 data:2byte _rumbleCnt = .sbss:0x8051F6F0; // type:object size:0x4 scope:global align:4 data:byte -lbl_8051F6F4 = .sbss:0x8051F6F4; // type:object size:0x1 data:byte -lbl_8051F6F5 = .sbss:0x8051F6F5; // type:object size:0x1 data:byte -lbl_8051F6F6 = .sbss:0x8051F6F6; // type:object size:0x1 data:byte +_afhChannel = .sbss:0x8051F6F4; // type:object size:0x1 data:byte +_shutdown = .sbss:0x8051F6F5; // type:object size:0x1 data:byte +_scSetting = .sbss:0x8051F6F6; // type:object size:0x1 data:byte _chan_active_state = .sbss:0x8051F6F8; // type:object size:0x4 scope:global align:4 data:byte _gamecode = .sbss:0x8051F6FC; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8051F700 = .sbss:0x8051F700; // type:object size:0x1 data:byte -lbl_8051F701 = .sbss:0x8051F701; // type:object size:0x1 data:byte -lbl_8051F702 = .sbss:0x8051F702; // type:object size:0x1 data:byte +_gametype = .sbss:0x8051F700; // type:object size:0x1 data:byte +_scFlush = .sbss:0x8051F701; // type:object size:0x1 data:byte +_speakerVolume = .sbss:0x8051F702; // type:object size:0x1 data:byte _rumble = .sbss:0x8051F704; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8051F708 = .sbss:0x8051F708; // type:object size:0x1 data:byte -lbl_8051F709 = .sbss:0x8051F709; // type:object size:0x1 data:byte -lbl_8051F70A = .sbss:0x8051F70A; // type:object size:0x1 data:byte +_sensorBarPos = .sbss:0x8051F708; // type:object size:0x1 data:byte +_dpdSensitivity = .sbss:0x8051F709; // type:object size:0x1 data:byte +_sleepTime = .sbss:0x8051F70A; // type:object size:0x1 data:byte _recv_3e = .sbss:0x8051F710; // type:object size:0x4 scope:global align:4 _recv_3f = .sbss:0x8051F714; // type:object size:0x4 scope:global align:4 -lbl_8051F718 = .sbss:0x8051F718; // type:object size:0x1 data:byte -lbl_8051F719 = .sbss:0x8051F719; // type:object size:0x1 data:byte -lbl_8051F71A = .sbss:0x8051F71A; // type:object size:0x1 data:byte -lbl_8051F71B = .sbss:0x8051F71B; // type:object size:0x1 data:byte +NUM_C = .sbss:0x8051F718; // type:object size:0x1 data:byte +NUM_B = .sbss:0x8051F719; // type:object size:0x1 data:byte +NUM_A = .sbss:0x8051F71A; // type:object size:0x1 data:byte +SEED = .sbss:0x8051F71B; // type:object size:0x1 data:byte icenter_org = .sbss:0x8051F720; // type:object size:0x8 scope:global align:4 data:4byte Vec2_0 = .sbss:0x8051F728; // type:object size:0x8 scope:global align:4 data:4byte kp_dist_vv1 = .sbss:0x8051F730; // type:object size:0x4 scope:global align:4 data:float diff --git a/config/RZDP01/config.yml b/config/RZDP01/config.yml index 2439a78d64..9aa718fc8c 100644 --- a/config/RZDP01/config.yml +++ b/config/RZDP01/config.yml @@ -16,6 +16,7 @@ force_active: [ block_relocations: - source: .text:0x8032f778 - source: .text:0x8032f7f0 +- source: .data:0x80428c9c modules: - object: files/RELS.arc:mmem/f_pc_profile_lst.rel diff --git a/config/RZDP01/splits.txt b/config/RZDP01/splits.txt index 72c1dfd514..286cab9f6a 100644 --- a/config/RZDP01/splits.txt +++ b/config/RZDP01/splits.txt @@ -3584,7 +3584,7 @@ revolution/wpad/WPADHIDParser.c: .text start:0x8036C9A0 end:0x8037123C .data start:0x80428768 end:0x80428BC8 .bss start:0x804E3CE8 end:0x804E3D00 - .sbss start:0x80522060 end:0x80522070 + .sbss start:0x80522060 end:0x80522068 .sdata2 start:0x80526E18 end:0x80526E40 revolution/wpad/WPADMem.c: @@ -3592,10 +3592,12 @@ revolution/wpad/WPADMem.c: revolution/wpad/WPADEncrypt.c: .text start:0x8037123C end:0x80371AD4 - .data start:0x80428BC8 end:0x80429548 + .data start:0x80428BC8 end:0x804294F8 + .sbss start:0x80522068 end:0x80522070 revolution/kpad/KPAD.c: .text start:0x80371B24 end:0x80374858 + .data start:0x804294F8 end:0x80429548 .bss start:0x804E3D50 end:0x804E4D60 .sdata start:0x80520D68 end:0x80520DD8 .sbss start:0x80522070 end:0x805220A8 @@ -3611,7 +3613,7 @@ revolution/usb/usb.c: .sdata start:0x80520DD8 end:0x80520DE8 .sbss start:0x805220B8 end:0x805220C8 -revolution/wpad/WUD.c: +revolution/wud/WUD.c: .text start:0x80375C68 end:0x80379994 .data start:0x80429B00 end:0x8042A8C8 .bss start:0x804E4D60 end:0x804E6AC0 diff --git a/config/RZDP01/symbols.txt b/config/RZDP01/symbols.txt index 94995a4e99..21623bcd87 100644 --- a/config/RZDP01/symbols.txt +++ b/config/RZDP01/symbols.txt @@ -28441,30 +28441,30 @@ RecalibrateBits = .sbss:0x80522024; // type:object size:0x4 scope:global align:4 ResettingBits = .sbss:0x80522028; // type:object size:0x4 scope:global align:4 data:4byte EnabledBits = .sbss:0x8052202C; // type:object size:0x4 scope:global align:4 data:4byte Initialized = .sbss:0x80522030; // type:object size:0x4 scope:global align:4 data:4byte -lbl_80522038 = .sbss:0x80522038; // type:object size:0x1 data:byte +_regShutdown = .sbss:0x80522038; // type:object size:0x1 data:byte _senseCnt = .sbss:0x8052203A; // type:object size:0x2 scope:global align:2 data:2byte -lbl_8052203C = .sbss:0x8052203C; // type:object size:0x1 data:byte -lbl_8052203D = .sbss:0x8052203D; // type:object size:0x1 data:byte +_checkCnt = .sbss:0x8052203C; // type:object size:0x1 data:byte +_extCnt = .sbss:0x8052203D; // type:object size:0x1 data:byte _afhCnt = .sbss:0x8052203E; // type:object size:0x2 scope:global align:2 data:2byte _rumbleCnt = .sbss:0x80522040; // type:object size:0x4 scope:global align:4 data:byte -lbl_80522044 = .sbss:0x80522044; // type:object size:0x1 data:byte -lbl_80522045 = .sbss:0x80522045; // type:object size:0x1 data:byte -lbl_80522046 = .sbss:0x80522046; // type:object size:0x1 data:byte +_afhChannel = .sbss:0x80522044; // type:object size:0x1 data:byte +_shutdown = .sbss:0x80522045; // type:object size:0x1 data:byte +_scSetting = .sbss:0x80522046; // type:object size:0x1 data:byte _chan_active_state = .sbss:0x80522048; // type:object size:0x4 scope:global align:4 data:byte _gamecode = .sbss:0x8052204C; // type:object size:0x4 scope:global align:4 data:4byte -lbl_80522050 = .sbss:0x80522050; // type:object size:0x1 data:byte -lbl_80522051 = .sbss:0x80522051; // type:object size:0x1 data:byte -lbl_80522052 = .sbss:0x80522052; // type:object size:0x1 data:byte +_gametype = .sbss:0x80522050; // type:object size:0x1 data:byte +_scFlush = .sbss:0x80522051; // type:object size:0x1 data:byte +_speakerVolume = .sbss:0x80522052; // type:object size:0x1 data:byte _rumble = .sbss:0x80522054; // type:object size:0x4 scope:global align:4 data:4byte -lbl_80522058 = .sbss:0x80522058; // type:object size:0x1 data:byte -lbl_80522059 = .sbss:0x80522059; // type:object size:0x1 data:byte -lbl_8052205A = .sbss:0x8052205A; // type:object size:0x1 data:byte +_sensorBarPos = .sbss:0x80522058; // type:object size:0x1 data:byte +_dpdSensitivity = .sbss:0x80522059; // type:object size:0x1 data:byte +_sleepTime = .sbss:0x8052205A; // type:object size:0x1 data:byte _recv_3e = .sbss:0x80522060; // type:object size:0x4 scope:global align:4 _recv_3f = .sbss:0x80522064; // type:object size:0x4 scope:global align:4 -lbl_80522068 = .sbss:0x80522068; // type:object size:0x1 data:byte -lbl_80522069 = .sbss:0x80522069; // type:object size:0x1 data:byte -lbl_8052206A = .sbss:0x8052206A; // type:object size:0x1 data:byte -lbl_8052206B = .sbss:0x8052206B; // type:object size:0x1 data:byte +NUM_C = .sbss:0x80522068; // type:object size:0x1 data:byte +NUM_B = .sbss:0x80522069; // type:object size:0x1 data:byte +NUM_A = .sbss:0x8052206A; // type:object size:0x1 data:byte +SEED = .sbss:0x8052206B; // type:object size:0x1 data:byte icenter_org = .sbss:0x80522070; // type:object size:0x8 scope:global align:4 data:4byte Vec2_0 = .sbss:0x80522078; // type:object size:0x8 scope:global align:4 data:4byte kp_dist_vv1 = .sbss:0x80522080; // type:object size:0x4 scope:global align:4 data:float diff --git a/config/Shield/splits.txt b/config/Shield/splits.txt index 005f4f7ce8..1d83673188 100644 --- a/config/Shield/splits.txt +++ b/config/Shield/splits.txt @@ -3723,7 +3723,7 @@ revolution/wpad/WPADMem.c: revolution/wpad/lint.c: .text start:0x8043CE50 end:0x8043D6C0 -revolution/wpad/WUD.c: +revolution/wud/WUD.c: .text start:0x8043D6C0 end:0x80442DE0 .data start:0x804FD9C8 end:0x804FDD10 .sdata start:0x80508790 end:0x805087A0 diff --git a/config/ShieldD/splits.txt b/config/ShieldD/splits.txt index 84bc90722e..34a59afb88 100644 --- a/config/ShieldD/splits.txt +++ b/config/ShieldD/splits.txt @@ -4485,7 +4485,7 @@ revolution/wpad/WPAD.c: .sdata2 start:0x80752E78 end:0x80752E80 .bss start:0x8080DC20 end:0x8080DC40 -revolution/wpad/WUD.c: +revolution/wud/WUD.c: .text start:0x80619BD0 end:0x80619DD0 .bss start:0x8080DC40 end:0x8080E3D0 diff --git a/config/ShieldD/symbols.txt b/config/ShieldD/symbols.txt index 4a381dbae9..9a9c234c83 100644 --- a/config/ShieldD/symbols.txt +++ b/config/ShieldD/symbols.txt @@ -65269,7 +65269,7 @@ RecalibrateBits = .sbss:0x8074D664; // type:object size:0x4 scope:global data:4b ResettingBits = .sbss:0x8074D668; // type:object size:0x4 scope:global data:4byte hash:0x8B753108 EnabledBits = .sbss:0x8074D66C; // type:object size:0x4 scope:global data:4byte hash:0x239E8E6C Initialized = .sbss:0x8074D670; // type:object size:0x4 scope:global data:4byte hash:0x99FD6509 -lbl_8074D678 = .sbss:0x8074D678; // type:object size:0x1 data:byte hash:0x92D2D836 +_speakerVolume = .sbss:0x8074D678; // type:object size:0x1 data:byte hash:0x92D2D836 __EUARTInitialized = .sbss:0x8074D680; // type:object size:0x4 scope:global data:4byte hash:0x1E294A9E __EUARTLastErrorCode = .sbss:0x8074D684; // type:object size:0x4 scope:global data:4byte hash:0xA09C238D __EUARTSendStop = .sbss:0x8074D688; // type:object size:0x4 scope:global data:4byte hash:0xA9B34056 diff --git a/configure.py b/configure.py index 52c12f573f..7e1e12f274 100755 --- a/configure.py +++ b/configure.py @@ -1854,7 +1854,17 @@ config.libs = [ "wpad", [ Object(NonMatching, "revolution/wpad/WPAD.c"), - Object(NonMatching, "revolution/wpad/WUD.c"), + Object(NonMatching, "revolution/wpad/WPADEncrypt.c"), + Object(NonMatching, "revolution/wpad/WPADHIDParser.c"), + Object(NonMatching, "revolution/wpad/WPADMem.c"), + ] + ), + RevolutionLib( + "wud", + [ + Object(NonMatching, "revolution/wud/WUD.c"), + Object(NonMatching, "revolution/wud/WUDHidHost.c"), + Object(NonMatching, "revolution/wud/debug_msg.c"), ], ), RevolutionLib( diff --git a/include/revolution/dsp.h b/include/revolution/dsp.h index b78b870474..43061f5ab1 100644 --- a/include/revolution/dsp.h +++ b/include/revolution/dsp.h @@ -8,7 +8,7 @@ extern "C" { #endif typedef void (*DSPCallback)(void* task); -typedef struct STRUCT_DSP_TASK DSPTaskInfo; +struct STRUCT_DSP_TASK; typedef struct STRUCT_DSP_TASK { /* 0x00 */ volatile u32 state; @@ -26,8 +26,8 @@ typedef struct STRUCT_DSP_TASK { /* 0x2C */ DSPCallback res_cb; /* 0x30 */ DSPCallback done_cb; /* 0x34 */ DSPCallback req_cb; - /* 0x38 */ DSPTaskInfo* next; - /* 0x3C */ DSPTaskInfo* prev; + /* 0x38 */ struct STRUCT_DSP_TASK* next; + /* 0x3C */ struct STRUCT_DSP_TASK* prev; /* 0x40 */ OSTime t_context; /* 0x48 */ OSTime t_task; } DSPTaskInfo; diff --git a/include/revolution/hw_regs.h b/include/revolution/hw_regs.h index b1f8a2c4e5..bab143f1ee 100644 --- a/include/revolution/hw_regs.h +++ b/include/revolution/hw_regs.h @@ -12,6 +12,7 @@ volatile u32 __DIRegs[] AT_ADDRESS(0xCD006000); volatile u32 __SIRegs[0x100] AT_ADDRESS(0xCD006400); volatile u32 __EXIRegs[0x40] AT_ADDRESS(0xCD006800); volatile u32 __AIRegs[8] AT_ADDRESS(0xCD006C00); +volatile u32 __ACRRegs[89] AT_ADDRESS(0xCD000000); volatile u32 __IPCRegs[4] AT_ADDRESS(0xCD000000); #else #define __VIRegs ((volatile u16 *)0xCC002000) @@ -22,6 +23,7 @@ volatile u32 __IPCRegs[4] AT_ADDRESS(0xCD000000); #define __SIRegs ((volatile u32 *)0xCD006400) #define __EXIRegs ((volatile u32 *)0xCD006800) #define __AIRegs ((volatile u32 *)0xCD006C00) +#define __ACRRegs ((volatile u32 *)0xCD000000) #define __IPCRegs ((volatile u32 *)0xCD000000) #endif @@ -115,4 +117,12 @@ volatile u32 __IPCRegs[4] AT_ADDRESS(0xCD000000); #define DSP_DMA_START_FLAG (0x8000) // set to start DSP +inline void ACRWriteReg(u32 offset, u32 val) { + __ACRRegs[offset >> 2] = val; +} + +inline u32 ACRReadReg(u32 offset) { + return __ACRRegs[offset >> 2]; +} + #endif diff --git a/include/revolution/os.h b/include/revolution/os.h index 703891f29b..7fcffb8f5f 100644 --- a/include/revolution/os.h +++ b/include/revolution/os.h @@ -109,6 +109,7 @@ u8 __gUnknown800030E3 AT_ADDRESS(OS_BASE_CACHED | 0x30E3); u32 OSGetConsoleType(void); void OSInit(void); void OSRegisterVersion(const char* id); +const char* OSGetAppGamename(void); void* OSGetArenaHi(void); void* OSGetArenaLo(void); diff --git a/include/revolution/sc.h b/include/revolution/sc.h index 35bf4c639f..89b205cec4 100644 --- a/include/revolution/sc.h +++ b/include/revolution/sc.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -128,6 +129,12 @@ u8 SCGetProgressiveMode(void); u8 SCGetScreenSaverMode(void); u8 SCGetSoundMode(void); u32 SCGetCounterBias(void); +u8 SCGetWpadSensorBarPosition(void); +u8 SCGetWpadMotorMode(void); +u8 SCGetWpadSpeakerVolume(void); +u8 SCGetBtDpdSensibility(void); +BOOL SCSetWpadSpeakerVolume(u8 volume); +BOOL SCSetWpadMotorMode(u8 mode); // scapi_prdinfo BOOL SCGetProductAreaString(char* buf, u32 bufSize); @@ -144,6 +151,8 @@ BOOL SCFindU8Item(u8* data, SCItemID id); BOOL SCFindS8Item(s8* data, SCItemID id); BOOL SCFindU32Item(u32* data, SCItemID id); BOOL SCReplaceU8Item(u8 data, SCItemID id); +void SCFlushAsync(SCFlushCallback callback); +BOOL SCSetBtDeviceInfoArray(const SCBtDeviceInfoArray*); u32 SCCheckStatus(void); s32 SCReloadConfFileAsync(u8* bufp, u32 bufSize, SCReloadConfFileCallback callback); diff --git a/include/revolution/vi/vifuncs.h b/include/revolution/vi/vifuncs.h index b3cea5622d..e4c4239226 100644 --- a/include/revolution/vi/vifuncs.h +++ b/include/revolution/vi/vifuncs.h @@ -35,6 +35,9 @@ void VISetGamma(VIGamma); void VISetRGBModeImm(void); BOOL VIEnableDVDStopMotor(BOOL enable); +BOOL VIResetDimmingCount(void); +BOOL VIResetRFIdle(void); + #ifdef __cplusplus } #endif diff --git a/include/revolution/wpad.h b/include/revolution/wpad.h index 82f259b95b..c2b23c436a 100644 --- a/include/revolution/wpad.h +++ b/include/revolution/wpad.h @@ -1,98 +1,58 @@ #ifndef _REVOLUTION_WPAD_H_ #define _REVOLUTION_WPAD_H_ +#include #include -#include +#include "types.h" #ifdef __cplusplus extern "C" { #endif -#define WPAD_BUTTON_LEFT 0x0001 -#define WPAD_BUTTON_RIGHT 0x0002 -#define WPAD_BUTTON_DOWN 0x0004 -#define WPAD_BUTTON_UP 0x0008 -#define WPAD_BUTTON_PLUS 0x0010 -#define WPAD_BUTTON_2 0x0100 -#define WPAD_BUTTON_1 0x0200 -#define WPAD_BUTTON_B 0x0400 -#define WPAD_BUTTON_A 0x0800 -#define WPAD_BUTTON_MINUS 0x1000 -#define WPAD_BUTTON_Z 0x2000 -#define WPAD_BUTTON_C 0x4000 -#define WPAD_BUTTON_HOME 0x8000 +#define WPAD_BUTTON_LEFT (1 << 0) +#define WPAD_BUTTON_RIGHT (1 << 1) +#define WPAD_BUTTON_DOWN (1 << 2) +#define WPAD_BUTTON_UP (1 << 3) +#define WPAD_BUTTON_PLUS (1 << 4) +#define WPAD_BUTTON_2 (1 << 8) +#define WPAD_BUTTON_1 (1 << 9) +#define WPAD_BUTTON_B (1 << 10) +#define WPAD_BUTTON_A (1 << 11) +#define WPAD_BUTTON_MINUS (1 << 12) +#define WPAD_BUTTON_Z (1 << 13) +#define WPAD_BUTTON_C (1 << 14) +#define WPAD_BUTTON_HOME (1 << 15) -#define WPAD_BUTTON_CL_UP (1 << 0) -#define WPAD_BUTTON_CL_LEFT (1 << 1) -#define WPAD_BUTTON_CL_ZR (1 << 2) -#define WPAD_BUTTON_CL_X (1 << 3) -#define WPAD_BUTTON_CL_A (1 << 4) -#define WPAD_BUTTON_CL_Y (1 << 5) -#define WPAD_BUTTON_CL_B (1 << 6) -#define WPAD_BUTTON_CL_ZL (1 << 7) -#define WPAD_BUTTON_CL_FULL_R (1 << 9) -#define WPAD_BUTTON_CL_PLUS (1 << 10) -#define WPAD_BUTTON_CL_HOME (1 << 11) -#define WPAD_BUTTON_CL_MINUS (1 << 12) -#define WPAD_BUTTON_CL_FULL_L (1 << 13) -#define WPAD_BUTTON_CL_DOWN (1 << 14) -#define WPAD_BUTTON_CL_RIGHT (1 << 15) +#define WPAD_CL_BUTTON_UP (1 << 0) +#define WPAD_CL_BUTTON_LEFT (1 << 1) +#define WPAD_CL_TRIGGER_ZR (1 << 2) +#define WPAD_CL_BUTTON_X (1 << 3) +#define WPAD_CL_BUTTON_A (1 << 4) +#define WPAD_CL_BUTTON_Y (1 << 5) +#define WPAD_CL_BUTTON_B (1 << 6) +#define WPAD_CL_TRIGGER_ZL (1 << 7) +#define WPAD_CL_RESERVED (1 << 8) +#define WPAD_CL_TRIGGER_R (1 << 9) +#define WPAD_CL_BUTTON_PLUS (1 << 10) +#define WPAD_CL_BUTTON_HOME (1 << 11) +#define WPAD_CL_BUTTON_MINUS (1 << 12) +#define WPAD_CL_TRIGGER_L (1 << 13) +#define WPAD_CL_BUTTON_DOWN (1 << 14) +#define WPAD_CL_BUTTON_RIGHT (1 << 15) -#define WPAD_MAX_DPD_OBJECTS 4 - -#define WPAD_CHAN0 0 -#define WPAD_CHAN1 1 -#define WPAD_CHAN2 2 -#define WPAD_CHAN3 3 -#define WPAD_CHAN_INVALID -1 - -#define WPAD_MAX_CONTROLLERS 4 - -enum WPADResult_et { - WPAD_ERR_OK = 0, - - WPAD_ERR_NO_CONTROLLER = -1, - WPAD_ERR_BUSY = -2, - WPAD_ERR_TRANSFER = -3, - WPAD_ERR_INVALID = -4, - WPAD_ERR_5 = -5, - WPAD_ERR_6 = -6, - WPAD_ERR_CORRUPTED = -7, -}; - -#define WPAD_ESUCCESS WPAD_ERR_OK -#define WPAD_ENODEV WPAD_ERR_NO_CONTROLLER -#define WPAD_EBUSY WPAD_ERR_BUSY -#define WPAD_ETRANSFER WPAD_ERR_TRANSFER // I don't know what the POSIX equivalent is -#define WPAD_EINVAL WPAD_ERR_INVALID -#define WPAD_E5 WPAD_ERR_5 -#define WPAD_E6 WPAD_ERR_6 -#define WPAD_EBADE WPAD_ERR_CORRUPTED - -// apparently enum vs constant is a thing. cool -#define WPAD_CESUCCESS (WPAD_ESUCCESS + 0) -#define WPAD_CENODEV (WPAD_ENODEV + 0) -#define WPAD_CEBUSY (WPAD_EBUSY + 0) -#define WPAD_CETRANSFER (WPAD_ETRANSFER + 0) -#define WPAD_CEINVAL (WPAD_EINVAL + 0) -#define WPAD_CE5 (WPAD_E5 + 0) -#define WPAD_CE6 (WPAD_E6 + 0) -#define WPAD_CEBADE (WPAD_EBADE + 0) - -#define WPAD_DEV_CORE 0 -#define WPAD_DEV_FS 1 -#define WPAD_DEV_CLASSIC 2 -#define WPAD_DEV_BALANCE_CHECKER 3 -#define WPAD_DEV_VSM 4 -#define WPAD_DEV_MOTION_PLUS 5 -#define WPAD_DEV_MPLS_PT_FS 6 -#define WPAD_DEV_MPLS_PT_CLASSIC 7 - -#define WPAD_DEV_TRAIN 16 -#define WPAD_DEV_GUITAR 17 -#define WPAD_DEV_DRUM 18 -#define WPAD_DEV_TAIKO 19 -#define WPAD_DEV_TURNTABLE 20 +#define WPAD_DEV_CORE 0 +#define WPAD_DEV_FS 1 +#define WPAD_DEV_CLASSIC 2 +#define WPAD_DEV_BALANCE_CHECKER 3 +#define WPAD_DEV_VSM 4 +#define WPAD_DEV_MOTION_PLUS 5 +#define WPAD_DEV_MPLS_PT_FS 6 +#define WPAD_DEV_MPLS_PT_CLASSIC 7 +#define WPAD_DEV_TRAIN 16 +#define WPAD_DEV_GUITAR 17 +#define WPAD_DEV_DRUM 18 +#define WPAD_DEV_TAIKO 19 +#define WPAD_DEV_TURNTABLE 20 // seems to be like maybe general purpose non-specific device types // maybe this was for testing or something? idk @@ -105,18 +65,103 @@ enum WPADResult_et { #define WPAD_DEV_BULK_7 27 #define WPAD_DEV_BULK_8 28 -#define WPAD_DEV_MPLS_PT_UNKNOWN 250 -#define WPAD_DEV_251 251 -#define WPAD_DEV_252 252 // invalid device mode? -#define WPAD_DEV_NONE 253 // sort of like WPAD_ENODEV (see __wpadAbortInitExtension in WPADHIDParser.c) -#define WPAD_DEV_INITIALIZING 255 // see __a1_20_status_report +#define WPAD_DEV_MPLS_PT_FUTURE 250 +#define WPAD_DEV_FUTURE 251 +#define WPAD_DEV_NOT_SUPPORTED 252 // invalid device mode? +#define WPAD_DEV_NONE 253 // sort of like WPAD_ENODEV (see __wpadAbortInitExtension in WPADHIDParser.c) +#define WPAD_DEV_INITIALIZING 255 // see __a1_20_status_report + +enum WPADResult_et { + WPAD_ERR_OK = 0, + + WPAD_ERR_NO_CONTROLLER = -1, + WPAD_ERR_BUSY = -2, + WPAD_ERR_TRANSFER = -3, + WPAD_ERR_INVALID = -4, + WPAD_ERR_NOPERM = -5, + WPAD_ERR_BROKEN = -6, + WPAD_ERR_CORRUPTED = -7, +}; + +#define WPAD_ESUCCESS WPAD_ERR_OK +#define WPAD_ENODEV WPAD_ERR_NO_CONTROLLER +#define WPAD_EBUSY WPAD_ERR_BUSY +#define WPAD_ETRANSFER WPAD_ERR_TRANSFER // I don't know what the POSIX equivalent is +#define WPAD_EINVAL WPAD_ERR_INVALID +#define WPAD_ENOPERM WPAD_ERR_NOPERM +#define WPAD_EBROKEN WPAD_ERR_BROKEN +#define WPAD_EBADE WPAD_ERR_CORRUPTED + +// apparently enum vs constant is a thing. cool +#define WPAD_CESUCCESS (WPAD_ESUCCESS + 0) +#define WPAD_CENODEV (WPAD_ENODEV + 0) +#define WPAD_CEBUSY (WPAD_EBUSY + 0) +#define WPAD_CETRANSFER (WPAD_ETRANSFER + 0) +#define WPAD_CEINVAL (WPAD_EINVAL + 0) +#define WPAD_CENOPERM (WPAD_ENOPERM + 0) +#define WPAD_CEBROKEN (WPAD_EBROKEN + 0) +#define WPAD_CEBADE (WPAD_EBADE + 0) + +#define WPAD_DPD_MAX_OBJECTS 4 + +#define WPAD_CHAN0 0 +#define WPAD_CHAN1 1 +#define WPAD_CHAN2 2 +#define WPAD_CHAN3 3 +#define WPAD_CHAN_INVALID -1 + +#define WPAD_MAX_CONTROLLERS 4 + +#define WPAD_HIDREP_BASE 0x10 +#define WPAD_HIDREP_VIBRATOR 0x10 +#define WPAD_HIDREP_PORT 0x11 +#define WPAD_HIDREP_REPTYPE 0x12 +#define WPAD_HIDREP_ENDPD 0x13 +#define WPAD_HIDREP_ENSPK 0x14 +#define WPAD_HIDREP_GETSTAT 0x15 +#define WPAD_HIDREP_WRDATA 0x16 +#define WPAD_HIDREP_RDDATA 0x17 +#define WPAD_HIDREP_STRM 0x18 +#define WPAD_HIDREP_MUTE 0x19 +#define WPAD_HIDREP_DPDCSB 0x1A +#define WPAD_HIDREP_WAIT 0xFF + +#define WPAD_BTN_HCURSOR_MASK (WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT) +#define WPAD_BTN_VCURSOR_MASK (WPAD_BUTTON_UP | WPAD_BUTTON_DOWN) +#define WPAD_CLB_HCURSOR_MASK (WPAD_CL_BUTTON_LEFT | WPAD_CL_BUTTON_RIGHT) +#define WPAD_CLB_VCURSOR_MASK (WPAD_CL_BUTTON_UP | WPAD_CL_BUTTON_DOWN) typedef void (*WPADInitFunc)(void); typedef void (*WPADCallback)(s32 chan, s32 result); typedef void (*WPADExtensionCallback)(s32 chan, s32 devType); +typedef void* (*WPADAlloc)(u32 size); +typedef u8 (*WPADFree)(void* ptr); +typedef void (*WPADSyncDeviceCallback)(s32 result, s32 num); typedef void (*WPADSamplingCallback)(s32 chan); typedef void (*WPADConnectCallback)(s32 chan, s32 result); typedef void (*WPADSimpleSyncCallback)(s32 result, s32 num); +typedef void (*WPADFlushCallback)(u32 result); + +typedef u32 WPADDeviceType; +typedef s32 WPADChannel; + +typedef struct WPADInfo { + /* 0x00 */ BOOL dpd; + /* 0x04 */ BOOL speaker; + /* 0x08 */ BOOL attach; + /* 0x0C */ BOOL lowBat; + /* 0x10 */ BOOL nearempty; + /* 0x14 */ u8 battery; + /* 0x15 */ u8 led; + /* 0x16 */ u8 protocol; + /* 0x17 */ u8 firmware; +} WPADInfo; + +typedef struct WPADAcc { + /* 0x00 */ s16 x; + /* 0x02 */ s16 y; + /* 0x04 */ s16 z; +} WPADAcc; typedef struct DPDObject { /* 0x00 */ s16 x; @@ -130,7 +175,7 @@ typedef struct WPADStatus { /* 0x02 */ s16 accX; /* 0x04 */ s16 accY; /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; + /* 0x08 */ DPDObject obj[WPAD_DPD_MAX_OBJECTS]; /* 0x28 */ u8 dev; /* 0x29 */ s8 err; } WPADStatus; @@ -145,54 +190,37 @@ typedef struct DPDObjEx { } DPDObjEx; typedef struct WPADStatusEx { - /* 0x00 */ u16 button; - /* 0x02 */ s16 accX; - /* 0x04 */ s16 accY; - /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; - /* 0x28 */ u8 dev; - /* 0x29 */ s8 err; - /* 0x2a */ DPDObjEx exp[WPAD_MAX_DPD_OBJECTS]; + /* 0x00 */ WPADStatus base; + /* 0x2A */ DPDObjEx exp[WPAD_DPD_MAX_OBJECTS]; } WPADStatusEx; typedef struct WPADFSStatus { - /* 0x00 */ u16 button; - /* 0x02 */ s16 accX; - /* 0x04 */ s16 accY; - /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; - /* 0x28 */ u8 dev; - /* 0x29 */ s8 err; - /* 0x2a */ s16 fsAccX; - /* 0x2c */ s16 fsAccY; - /* 0x2e */ s16 fsAccZ; + /* 0x00 */ WPADStatus base; + /* 0x2A */ s16 fsAccX; + /* 0x2C */ s16 fsAccY; + /* 0x2E */ s16 fsAccZ; /* 0x30 */ s8 fsStickX; /* 0x31 */ s8 fsStickY; } WPADFSStatus; typedef struct WPADCLStatus { - /* 0x00 */ u16 button; - /* 0x02 */ s16 accX; - /* 0x04 */ s16 accY; - /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; - /* 0x28 */ u8 dev; - /* 0x29 */ s8 err; - /* 0x2a */ u16 clButton; - /* 0x2c */ s16 clLStickX; - /* 0x2e */ s16 clLStickY; + /* 0x00 */ WPADStatus base; + /* 0x2A */ u16 clButton; + /* 0x2C */ s16 clLStickX; + /* 0x2E */ s16 clLStickY; /* 0x30 */ s16 clRStickX; /* 0x32 */ s16 clRStickY; /* 0x34 */ u8 clTriggerL; /* 0x35 */ u8 clTriggerR; } WPADCLStatus; +#if SDK_AUG2010 typedef struct WPADBKStatus { /* 0x00 */ u16 button; /* 0x02 */ s16 accX; /* 0x04 */ s16 accY; /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; + /* 0x08 */ DPDObject obj[WPAD_DPD_MAX_OBJECTS]; /* 0x28 */ u8 dev; /* 0x29 */ s8 err; /* 0x2a */ u8 bulk[21]; @@ -204,7 +232,7 @@ typedef struct WPADTRStatus { /* 0x02 */ s16 accX; /* 0x04 */ s16 accY; /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; + /* 0x08 */ DPDObject obj[WPAD_DPD_MAX_OBJECTS]; /* 0x28 */ u8 dev; /* 0x29 */ s8 err; /* 0x2a */ u16 trButton; @@ -217,7 +245,7 @@ typedef struct WPADVSStatus { /* 0x02 */ s16 accX; /* 0x04 */ s16 accY; /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; + /* 0x08 */ DPDObject obj[WPAD_DPD_MAX_OBJECTS]; /* 0x28 */ u8 dev; /* 0x29 */ s8 err; /* 0x2a */ u16 at_0x2a[5]; @@ -233,7 +261,7 @@ typedef struct WPADMPStatus { /* 0x02 */ s16 accX; /* 0x04 */ s16 accY; /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; + /* 0x08 */ DPDObject obj[WPAD_DPD_MAX_OBJECTS]; /* 0x28 */ u8 dev; /* 0x29 */ s8 err; union { @@ -255,7 +283,6 @@ typedef struct WPADMPStatus { } cl; } ext; /* 0x36 */ u8 stat; - /* 0x37 */ u8 reserved; /* 0x38 */ s16 pitch; /* 0x3a */ s16 yaw; /* 0x3c */ s16 roll; @@ -266,25 +293,14 @@ typedef struct WPADBLStatus { /* 0x02 */ s16 accX; /* 0x04 */ s16 accY; /* 0x06 */ s16 accZ; - /* 0x08 */ DPDObject obj[WPAD_MAX_DPD_OBJECTS]; + /* 0x08 */ DPDObject obj[WPAD_DPD_MAX_OBJECTS]; /* 0x28 */ u8 dev; /* 0x29 */ s8 err; /* 0x2a */ u16 press[4]; /* 0x32 */ s8 temp; /* 0x33 */ u8 battery; } WPADBLStatus; - -typedef struct WPADInfo { - /* 0x00 */ BOOL dpd; - /* 0x04 */ BOOL speaker; - /* 0x08 */ BOOL attach; - /* 0x0C */ BOOL lowBat; - /* 0x10 */ BOOL nearempty; - /* 0x14 */ u8 battery; - /* 0x15 */ u8 led; - /* 0x16 */ u8 protocol; - /* 0x17 */ u8 firmware; -} WPADInfo; +#endif #define WPAD_FMT_CORE_BTN 0 #define WPAD_FMT_CORE_BTN_ACC 1 @@ -306,6 +322,7 @@ typedef struct WPADInfo { #define WPAD_FMT_TAIKO 17 #define WPAD_FMT_TURNTABLE 18 #define WPAD_FMT_BULK 19 +#define WPAD_FMT_UNK_20 20 #define WPAD_SPEAKER_DISABLE 0 #define WPAD_SPEAKER_ENABLE 1 // might be ON? see HBMRemoteSpk.cpp @@ -317,8 +334,21 @@ typedef struct WPADInfo { #define WPAD_MOTOR_STOP 0 #define WPAD_MOTOR_RUMBLE 1 +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, +}; + s32 WPADProbe(s32 chan, u32* devType); u8 WPADGetRadioSensitivity(s32 chan); +BOOL WPADSetAcceptConnection(u8 accept); +BOOL WPADGetAcceptConnection(void); void WPADRead(s32 chan, WPADStatus* status); BOOL WPADIsSpeakerEnabled(s32 chan); s32 WPADControlSpeaker(s32 chan, u32 command, WPADCallback cb); @@ -327,20 +357,53 @@ s32 WPADSendStreamData(s32 chan, void* p_buf, u16 len); WPADConnectCallback WPADSetConnectCallback(s32 chan, WPADConnectCallback cb); WPADExtensionCallback WPADSetExtensionCallback(s32 chan, WPADExtensionCallback cb); WPADSimpleSyncCallback WPADSetSimpleSyncCallback(WPADSimpleSyncCallback cb); +WPADSamplingCallback WPADSetSamplingCallback(s32 chan, WPADSamplingCallback cb); BOOL WPADIsUsedCallbackByKPAD(void); void WPADSetCallbackByKPAD(BOOL isKPAD); -s32 WPADGetInfoAsync(s32 chan, WPADInfo* info, WPADCallback cb); +s32 WPADGetInfoAsync(s32 chan, WPADInfo* info, WPADCallback callback); void WPADControlMotor(s32 chan, u32 command); BOOL WPADCanSendStreamData(s32 chan); BOOL WPADStopSimpleSync(void); void WPADDisconnect(s32 chan); +BOOL WPADStartSimpleSync(); BOOL WPADStartFastSimpleSync(void); -BOOL WPADSaveConfig(SCFlushCallback* cb); -void WPADSetSpeakerVolume(u8 volume); +BOOL WPADSaveConfig(WPADFlushCallback cb); u8 WPADGetSpeakerVolume(void); +void WPADSetSpeakerVolume(u8 volume); void WPADEnableMotor(BOOL enabled); BOOL WPADIsMotorEnabled(void); +BOOL IsBusyStream(s32 chan); + +void WPADRegisterAllocator(WPADAlloc alloc, WPADFree free); +u32 WPADGetWorkMemorySize(void); + +void WPADGetAccGravityUnit(s32 chan, u32 type, WPADAcc* acc); + +BOOL WPADIsDpdEnabled(s32 chan); +s32 WPADControlDpd(s32 chan, u32 command, WPADCallback callback); +u32 WPADGetDataFormat(s32 chan); +s32 WPADSetDataFormat(s32 chan, u32 fmt); +void WPADSetAutoSleepTime(u8 minute); +u8 WPADGetSensorBarPosition(void); +s32 WPADGetStatus(void); + +void WPADInit(void); +BOOL OnShutdown(BOOL final, u32 event); +u8 WPADGetDpdSensitivity(void); + +void __WPADShutdown(void); +void __WPADReconnect(BOOL); + +BOOL WPADCancelSyncDevice(); + +void WPADSetAutoSamplingBuf(s32 chan, void* buf, u32); + +s32 WPADControlLed(s32 chan, u8 pattern, WPADCallback callback); +void WPADGetAddress(s32 chan, u8* addr); + +#define WPADStartMotor(chan) WPADControlMotor((chan), WPAD_MOTOR_RUMBLE) +#define WPADStopMotor(chan) WPADControlMotor((chan), WPAD_MOTOR_STOP) #ifdef __cplusplus } diff --git a/include/revolution/wpad/bte.h b/include/revolution/wpad/bte.h index 1751d8998b..a09000a254 100644 --- a/include/revolution/wpad/bte.h +++ b/include/revolution/wpad/bte.h @@ -2,6 +2,7 @@ #define CONTEXT_BTE_H #include +#include "types.h" // taken from https://github.com/doldecomp/sdk_2009-12-11/blob/main/include/context_bte.h @@ -1041,4 +1042,25 @@ struct small_dev_info char __pad1[0x10]; }; // size 0x40 +typedef struct { + BD_ADDR bd_addr; + u8 bd_name[64]; + u8 link_key[16]; +} SCBtCmpDevInfoSingle; + +typedef struct { + BD_ADDR bd_addr; + u8 bd_name[64]; +} SCBtDeviceInfoSingle; + +typedef struct { + u8 num; + SCBtCmpDevInfoSingle info[6]; +} SCBtCmpDevInfoArray; + +typedef struct { + u8 num; + SCBtDeviceInfoSingle info[16]; +} SCBtDeviceInfoArray; + #endif // CONTEXT_BTE_H diff --git a/include/revolution/wud/WUD.h b/include/revolution/wud/WUD.h new file mode 100644 index 0000000000..138733f1f0 --- /dev/null +++ b/include/revolution/wud/WUD.h @@ -0,0 +1,256 @@ +#ifndef _REVOLUTION_WUD_WUD_H_ +#define _REVOLUTION_WUD_WUD_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define WUD_CHAN0 0 +#define WUD_CHAN1 1 +#define WUD_CHAN2 2 +#define WUD_CHAN3 3 +#define WUD_MAX_CHANNELS 4 + +#define WUD_CHAN_INVALID -1 + +typedef void* WUDAllocFunc(u32 size); +typedef int WUDFreeFunc(void* ptr); // signature from petari. not sure what the int is, though + +typedef struct WUDDevInfo { + /* 0x00 */ struct small_dev_info small; + /* 0x40 */ BD_ADDR devAddr; + /* 0x46 */ LINK_KEY linkKey; + /* 0x56 */ u8 devHandle; + /* 0x57 */ u8 subclass; + /* 0x58 */ u8 appID; + /* 0x59 */ u8 at_0x59; + /* 0x5a */ u8 at_0x5a; /* unknown */ + /* 0x5b */ u8 at_0x5b; + /* 0x5c */ u8 at_0x5c; + u8 at_0x5d[1]; // padding? + /* 0x5e */ tBTA_HH_ATTR_MASK hhAttrMask; +} WUDDevInfo; // size 0x60 + +typedef void WUDHidConnectCallback(WUDDevInfo* devInfo, u8 isOpenEvent); +typedef void WUDHidReceiveCallback(u8 dev_handle, u8* p_rpt, u16 len); + +u8 WUDGetBufferStatus(void); +u8 _WUDGetLinkNumber(void); +u16 _WUDGetQueuedSize(s8 dev_handle); +u16 _WUDGetNotAckedSize(s8 dev_handle); + +typedef u8 BTD_NAME[64]; +typedef u8 BTD_ADDR[6]; +typedef u8 LINKKEY[16]; + +typedef enum { + WUD_STATE_SYNC_START = 0, + WUD_STATE_SYNC_PREPARE_SEARCH = 1, + WUD_STATE_SYNC_START_SEARCH = 2, + WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT = 3, + WUD_STATE_SYNC_CHECK_SEARCH_RESULT = 4, + WUD_STATE_SYNC_IS_EXISTED_DEVICE = 5, + WUD_STATE_SYNC_6 = 6, + WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM = 7, + WUD_STATE_SYNC_WAIT_FOR_STORING = 8, + WUD_STATE_SYNC_WAIT_FOR_READING = 10, + WUD_STATE_SYNC_11 = 11, + WUD_STATE_SYNC_12 = 12, + WUD_STATE_SYNC_13 = 13, + WUD_STATE_SYNC_DONE = 14, + WUD_STATE_SYNC_TRY_CONNECT = 15, + WUD_STATE_SYNC_PREPARE_FOR_EXISTED_DEVICE = 16, + WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE = 17, + WUD_STATE_SYNC_REGISTER_DEVICE = 18, + WUD_STATE_SYNC_VIRGIN_SIMPLE = 19, + WUD_STATE_SYNC_VIRGIN_STANDARD = 20, + WUD_STATE_SYNC_CHANGE_SIMPLE_TO_STANDARD = 21, + WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND = 22, + WUD_STATE_SYNC_COMPLETE = 23, + WUD_STATE_SYNC_WAIT_FOR_INCOMING = 24, + WUD_STATE_SYNC_SC_FLUSH = 25, + WUD_STATE_SYNC_CANCEL_SEARCH = 26, + WUD_STATE_SYNC_WAIT_FOR_START_SEARCH = 29, + WUD_STATE_SYNC_ERROR = 255, +} WUDSyncState; + +typedef enum { + WUD_STATE_DELETE_START = 0, + WUD_STATE_DELETE_DISALLOW_INCOMING = 1, + WUD_STATE_DELETE_DISCONNECT_ALL = 2, + WUD_STATE_DELETE_CLEANUP_DATABASE = 3, + WUD_STATE_DELETE_CLEANUP_SETTING = 5, + WUD_STATE_DELETE_6 = 6, + WUD_STATE_DELETE_7 = 7, + WUD_STATE_DELETE_DONE = 8 +} WUDDeleteState; + +typedef enum { + WUD_RESULT_DELETE_BUSY = -1, + WUD_RESULT_DELETE_WAITING, + WUD_RESULT_DELETE_COMPLETE, +} WUDDeleteResult; + +typedef enum { + WUD_STATE_LINK_KEY_START = 0, + WUD_STATE_LINK_KEY_READING = 1, + WUD_STATE_LINK_KEY_WRITING = 2, + WUD_STATE_LINK_KEY_DELETING = 3, + WUD_STATE_LINK_KEY_ERROR = 255, +} WUDLinkKeyState; + +typedef enum { + WUD_STATE_STACK_START = 0, + WUD_STATE_STACK_GET_STORED_LINK_KEY = 1, + WUD_STATE_STACK_CHECK_DEVICE_INFO = 2, + WUD_STATE_STACK_DONE = 3, + WUD_STATE_STACK_INITIALIZED = 4, + WUD_STATE_STACK_ERROR = 255, +} WUDStackState; + +typedef enum { + WUD_STATE_INIT_START = 0, + WUD_STATE_INIT_WAIT_FOR_INITIALIZATION = 1, + WUD_STATE_INIT_GET_DEV_INFO = 2, + WUD_STATE_INIT_DONE = 3, + WUD_STATE_INIT_INITIALIZED = 4, + WUD_STATE_INIT_ERROR = 255, +} WUDInitState; + +typedef enum { + WUD_STATE_SHUTDOWN_START = 0, + WUD_STATE_SHUTDOWN_STORE_SETTINGS = 1, + WUD_STATE_SHUTDOWN_FLUSH_SETTINGS = 2, + WUD_STATE_SHUTDOWN_DONE = 3, + WUD_STATE_SHUTDOWN_ERROR = 255, +} WUDShutdownState; + +typedef enum { + WUD_VSE_INITIATE_PAIRING = 8, + WUD_VSE_DELETE_ALL_KEYS, + WUD_VSE_SI_PORT_STATUS, + WUD_VSE_WATCH_DOG_RESET_HW = 16, +} WUDVendorSpecificEvent; + +typedef struct WUDDeviceInfo { + BTD_NAME bd_name; + BTD_ADDR bd_addr; + LINKKEY link_key; + u8 handle; + u8 sub_class; + u8 app_id; + u8 status; + u8 overwrite; + u8 sync_type; + u8 reg; + u16 attr_mask; +} WUDDeviceInfo; + +typedef void* (*WUDAlloc)(u32); +typedef u8 (*WUDFree)(void*); +typedef void (*WUDSyncDeviceCallback)(s32 result, s32 num); // what is result? +typedef void (*WUDClearDeviceCallback)(s32); +typedef void (*WUDHidRecvCallback)(u8, u8*, u16); +typedef void (*WUDHidConnCallback)(u8, u8); +typedef void (*WUDStoredCallback)(void*); + +typedef struct DeviceList { + WUDDeviceInfo* info; + void* prev; + void* next; +} DeviceList; + +typedef struct WUDControlBlock { + WUDSyncDeviceCallback syncCallback; + WUDSyncDeviceCallback syncSmpCallback; + WUDClearDeviceCallback clearCallback; + u8 syncStatus; + u8 delStatus; + u8 keyStatus; + u8 profStatus; + u8 initStatus; + u8 shutStatus; + u8 devNums; + u8 devSmpNums; + DeviceList* smpListHead; + DeviceList* smpListTail; + DeviceList smpList[6]; + DeviceList* stdListHead; + DeviceList* stdListTail; + DeviceList stdList[10]; + WUDDeviceInfo devInfo[10]; + WUDDeviceInfo devSmpInfo[6]; + u8 connNums; + u8 linkNums; + u8 pairNums; + u8 syncFast; + s8 syncLoop; + u8 syncMode; + u8 connectable; + u8 discoverable; + WUDHidRecvCallback hidRecvCallback; + WUDHidConnCallback hidConnCallback; + WUDAlloc alloc; + WUDFree free; + BTD_ADDR lastAddr; + BTD_ADDR hostAddr; + s8 status; + u8 siStatus; + u8 pmId; + s8 rssi; + OSAlarm evtAlarm; + u32 profileMask; + u16 aclAvailBufSize; + u16 aclMaxBufSize; + s16 delayCnt; + s16 incomeCnt; +} WUDControlBlock; + +BOOL WUDInit(); +BOOL WUDStartSyncSimple(void); +BOOL WUDStartFastSyncSimple(void); +u32 WUDGetAllocatedMemSize(void); +WUDSyncDeviceCallback WUDSetSyncSimpleCallback(WUDSyncDeviceCallback); +void WUDiMoveTopSmpDevInfoPtr(WUDDeviceInfo*); +void WUDiMoveTopStdDevInfoPtr(WUDDeviceInfo*); +void WUDSetSniffMode(BTD_ADDR, s32); +void WUDiRemoveDevice(BTD_ADDR); +void WUDiMoveBottomSmpDevInfoPtr(WUDDeviceInfo*); +void WUDiMoveTopSmpDevInfoPtr(WUDDeviceInfo*); +void WUDiMoveBottomStdDevInfoPtr(WUDDeviceInfo*); +void WUDiMoveTopOfDisconnectedSmpDevice(WUDDeviceInfo*); +void WUDiMoveTopOfDisconnectedStdDevice(WUDDeviceInfo*); +WUDDeviceInfo* WUDiGetDevInfo(BTD_ADDR); + +BOOL WUDCancelSyncDevice(void); +BOOL WUDStopSyncSimple(void); +s32 WUDGetStatus(void); +void WUDShutdown(); +void WUDSetVisibility(u8, u8); +u8 WUDGetConnectable(void); +BOOL WUDIsBusy(void); +WUDHidRecvCallback WUDSetHidRecvCallback(WUDHidRecvCallback); +WUDHidConnCallback WUDSetHidConnCallback(WUDHidConnCallback); +void WUDRegisterAllocator(WUDAlloc, WUDFree); +u8* _WUDGetDevAddr(u8); +BOOL WUDSetDisableChannel(s8); +u8 WUDGetBufferStatus(void); +u8 _WUDGetLinkNumber(void); +u16 _WUDGetQueuedSize(s8); +u16 _WUDGetNotAckedSize(s8); + +extern WUDControlBlock _wcb; +extern WUDDeviceInfo _work; +extern u8* _dev_handle_to_bda[16]; +extern u16 _dev_handle_queue_size[16]; +extern u16 _dev_handle_notack_num[16]; +extern SCBtDeviceInfoArray _scArray; + +#ifdef __cplusplus +} +#endif + +#endif /* _REVOLUTION_WUD_WUD_H_ */ diff --git a/include/revolution/wud/debug_msg.h b/include/revolution/wud/debug_msg.h new file mode 100644 index 0000000000..550bf9a0ba --- /dev/null +++ b/include/revolution/wud/debug_msg.h @@ -0,0 +1,14 @@ +#ifndef _REVOLUTION_WUD_DEBUG_MSG_H_ +#define _REVOLUTION_WUD_DEBUG_MSG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void WUD_DEBUGPrint(const char*, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* _REVOLUTION_WUD_DEBUG_MSG_H_ */ diff --git a/src/revolution/homebuttonLib/HBMController.cpp b/src/revolution/homebuttonLib/HBMController.cpp index 207ee57130..a41bcfdf04 100644 --- a/src/revolution/homebuttonLib/HBMController.cpp +++ b/src/revolution/homebuttonLib/HBMController.cpp @@ -126,43 +126,43 @@ namespace homebutton { u32 t = con->kpad->ex_status.cl.trig; u32 r = con->kpad->ex_status.cl.release; - if (h & WPAD_BUTTON_CL_A) { + if (h & WPAD_CL_BUTTON_A) { mHBController.hold |= WPAD_BUTTON_A; } - if (t & WPAD_BUTTON_CL_A) { + if (t & WPAD_CL_BUTTON_A) { mHBController.trig |= WPAD_BUTTON_A; } - if (r & WPAD_BUTTON_CL_A) { + if (r & WPAD_CL_BUTTON_A) { mHBController.release |= WPAD_BUTTON_A; } - if (h & WPAD_BUTTON_CL_PLUS) { + if (h & WPAD_CL_BUTTON_PLUS) { mHBController.hold |= WPAD_BUTTON_PLUS; } - if (t & WPAD_BUTTON_CL_PLUS) { + if (t & WPAD_CL_BUTTON_PLUS) { mHBController.trig |= WPAD_BUTTON_PLUS; } - if (r & WPAD_BUTTON_CL_PLUS) { + if (r & WPAD_CL_BUTTON_PLUS) { mHBController.release |= WPAD_BUTTON_PLUS; } - if (h & WPAD_BUTTON_CL_MINUS) { + if (h & WPAD_CL_BUTTON_MINUS) { mHBController.hold |= WPAD_BUTTON_MINUS; } - if (t & WPAD_BUTTON_CL_MINUS) { + if (t & WPAD_CL_BUTTON_MINUS) { mHBController.trig |= WPAD_BUTTON_MINUS; } - if (r & WPAD_BUTTON_CL_MINUS) { + if (r & WPAD_CL_BUTTON_MINUS) { mHBController.release |= WPAD_BUTTON_MINUS; } - if (h & WPAD_BUTTON_CL_HOME) { + if (h & WPAD_CL_BUTTON_HOME) { mHBController.hold |= WPAD_BUTTON_HOME; } - if (t & WPAD_BUTTON_CL_HOME) { + if (t & WPAD_CL_BUTTON_HOME) { mHBController.trig |= WPAD_BUTTON_HOME; } - if (r & WPAD_BUTTON_CL_HOME) { + if (r & WPAD_CL_BUTTON_HOME) { mHBController.release |= WPAD_BUTTON_HOME; } } diff --git a/src/revolution/os/OSStateTM.c b/src/revolution/os/OSStateTM.c index 3961ff7d98..a81de612cf 100644 --- a/src/revolution/os/OSStateTM.c +++ b/src/revolution/os/OSStateTM.c @@ -210,10 +210,6 @@ s32 __OSUnRegisterStateEvent(void) { return ret; } -void ACRWriteReg(u32 param_0, u32 param_1) { - __IPCRegs[param_0 >> 2] = param_1; -} - // NONMATCHING - extra branch static int AccessVIDimRegs(void) { int res; diff --git a/src/revolution/sc/scapi.c b/src/revolution/sc/scapi.c index 9aa57e7ec1..3acfef055f 100644 --- a/src/revolution/sc/scapi.c +++ b/src/revolution/sc/scapi.c @@ -121,3 +121,27 @@ u32 SCGetCounterBias(void) { return bias; } + +u8 SCGetWpadSensorBarPosition(void) { + // NONMATCHING +} + +u8 SCGetWpadMotorMode(void) { + // NONMATCHING +} + +u8 SCGetWpadSpeakerVolume(void) { + // NONMATCHING +} + +u8 SCGetBtDpdSensibility(void) { + // NONMATCHING +} + +BOOL SCSetWpadSpeakerVolume(u8 volume) { + // NONMATCHING +} + +BOOL SCSetWpadMotorMode(u8 mode) { + // NONMATCHING +} diff --git a/src/revolution/vi/__vi.h b/src/revolution/vi/__vi.h index e061de3369..1411ca9294 100644 --- a/src/revolution/vi/__vi.h +++ b/src/revolution/vi/__vi.h @@ -17,6 +17,8 @@ void __VIInit(VITVMode mode); void __VISetAdjustingValues(s16 x, s16 y); void __VIGetAdjustingValues(s16* x, s16* y); void __VIGetCurrentPosition(s16* x, s16* y); +BOOL __VIResetSIIdle(); +BOOL __VIResetRFIdle(); BOOL __VIResetDev0Idle(); /* vi3in1.c */ diff --git a/src/revolution/vi/vi.c b/src/revolution/vi/vi.c index 057ba805b4..647bbec498 100644 --- a/src/revolution/vi/vi.c +++ b/src/revolution/vi/vi.c @@ -1682,8 +1682,12 @@ BOOL VIEnableDimming(BOOL enable) { return old; } -void VIResetDimmingCount() { - __VIResetDev0Idle(); +BOOL VIResetDimmingCount() { + return __VIResetDev0Idle(); +} + +BOOL VIResetRFIdle() { + return __VIResetRFIdle(); } BOOL VIEnableDVDStopMotor(BOOL enable) { @@ -1697,6 +1701,11 @@ BOOL __VIResetSIIdle() { return TRUE; } +BOOL __VIResetRFIdle() { + __VIDimmingFlag_RF_IDLE = 0; + return TRUE; +} + BOOL __VIResetDev0Idle() { __VIDimmingFlag_DEV_IDLE[0] = 0; return TRUE; diff --git a/src/revolution/wpad/WPAD.c b/src/revolution/wpad/WPAD.c index bdd1531617..6f01d6e459 100644 --- a/src/revolution/wpad/WPAD.c +++ b/src/revolution/wpad/WPAD.c @@ -1,25 +1,1843 @@ -#include #include -#include +#include +#include +#include +#include +#include +#include +#include #include -#include "__wpad.h" +extern volatile BOOL __OSIsReturnToIdle; -wpad_cb_st* __rvl_p_wpadcb[WPAD_MAX_CONTROLLERS]; +//TODO: this apparently should be aligned to 32 bytes, but +// adding ATTRIBUTE_ALIGN breaks codegen in WPADInit +WPADControlBlock _wpd[WPAD_MAX_CONTROLLERS]; +WPADControlBlock* _wpdcb[WPAD_MAX_CONTROLLERS]; -static u8 _wpadSpeakerVol; +u8 _sleepTime; +u8 _dpdSensitivity; +u8 _sensorBarPos; +BOOL _rumble; +u8 _speakerVolume; +u8 _scFlush; +u8 _gametype; +u16 _gameTitle[17]; +const char* _gamecode; -static s8 __wpadGetQueueSize(struct WPADCmdQueue* cmdQueue); -static u16 __wpadGetBTEBufferStatus(s32 chan); -static u16 __wpadGetBTMBufferStatus(s32 chan); -static BOOL __wpadPushCommand(struct WPADCmdQueue* cmdQueue, struct WPADCmd cmdBlk); +s8 _dev_handle_index[16]; +u8 _chan_active_state[WPAD_MAX_CONTROLLERS]; +OSAlarm _managerAlarm; -void dummyString(void* p_buf) { - ASSERTLINE(0, p_buf != NULL); +DVDDiskID _diskId; + +static u8 _scSetting; +static vu8 _shutdown; +static s8 _afhChannel; +static u8 _regShutdown = 0; + +static u16 _senseCnt = 0; +static u8 _checkCnt = 0; +static u8 _extCnt = 0; +static u16 _afhCnt = 0; + +static u8 _rumbleCnt[WPAD_MAX_CONTROLLERS] = {0, 0, 0, 0}; + +static s8 _infRes[4]; + +static BOOL _initialized; +static BOOL _startup = FALSE; +static int _recFlag = -1; +static int _recCnt = 0; + +static const char* __WPADVersion = "<< RVL_SDK - WPAD \trelease build: Oct 3 2006 03:58:38 (0x4200_60422) >>"; + +#define WPAD_DEFAULT_ACC_DIFF_COUNT_THRESHOLD (u16)(6) +#define WPAD_DEFAULT_ACC_HYST_COUNT_THRESHOLD (u16)(30) + +#define WPAD_DEFAULT_DPD_DIFF_COUNT_THRESHOLD (u16)(4) +#define WPAD_DEFAULT_DPD_HYST_COUNT_THRESHOLD (u16)(30) + +static u16 __WPAD_acc_diff_count_threshold = WPAD_DEFAULT_ACC_DIFF_COUNT_THRESHOLD; +static u16 __WPAD_dpd_diff_count_threshold = WPAD_DEFAULT_DPD_DIFF_COUNT_THRESHOLD; + +static u16 __WPAD_acc_hyst_count_threshold = WPAD_DEFAULT_ACC_HYST_COUNT_THRESHOLD; +static u16 __WPAD_dpd_hyst_count_threshold = WPAD_DEFAULT_DPD_HYST_COUNT_THRESHOLD; + +static OSShutdownFunctionInfo ShutdownFunctionInfo = {OnShutdown, 127}; + +extern void DEBUGPrint(const char*, ...); + +static void __ClearControlBlock(s32 chan); + +BOOL OnShutdown(BOOL final, u32 event) { + s32 i; + BOOL ret; + s32 status; + + ret = FALSE; + status = WUDGetStatus(); + + if (!final) { + if (status == 2 || status == 3) { + switch (event) { + case 0: + case 2: + case 3: + if (!_shutdown) { + _shutdown = TRUE; + WUDSetVisibility(0, 0); + for (i = 10; i < 14; i++) { + memset(&_scArray.info[i], 0, sizeof(_scArray.info[i])); + } + OSCancelAlarm(&_managerAlarm); + WUDSetHidRecvCallback(NULL); + WUDShutdown(); + } + ret = FALSE; + break; + case 1: + case 4: + case 5: + case 6: + if (!_shutdown) { + _shutdown = TRUE; + BTA_DmSendHciReset(); + OSCancelAlarm(&_managerAlarm); + WUDSetHidRecvCallback(NULL); + WUDShutdown(); + } + ret = FALSE; + break; + } + } else if (status == 4 || status == 1) { + ret = FALSE; + } else if (status == 0) { + ret = TRUE; + } + } else { + ret = TRUE; + } + + return ret; } -static u32 __wpadFmt2Size(u32 fmt) { +s32 WPADiGetStatus(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + s32 status; + + enable = OSDisableInterrupts(); + status = p_wpd->status; + OSRestoreInterrupts(enable); + + return status; +} + +BOOL __SetSensorBarPower(BOOL flag) { + u32 reg; + u32 regBak; + BOOL enable; + BOOL result; + + enable = OSDisableInterrupts(); + + regBak = ACRReadReg(0xC0); + + if (flag) { + reg = regBak | 0x100; + } else { + reg = regBak & ~0x100; + } + + ACRWriteReg(0xC0, reg); + result = (regBak & 0x100) ? TRUE : FALSE; + OSRestoreInterrupts(enable); + return result; +} + +static u8 __GetDpdSensitivity() { + u8 level; + + level = (u8)SCGetBtDpdSensibility(); + if (level < 1) { + level = 1; + } + if (level > 5) { + level = 5; + } + + return level; +} + +static u8 __GetSensorBarPosition() { + u8 pos; + + if (1 == SCGetWpadSensorBarPosition()) { + pos = WPAD_SENSOR_BAR_POS_TOP; + } else { + pos = WPAD_SENSOR_BAR_POS_BOTTOM; + } + return pos; +} + +static BOOL __GetMotorMode() { + BOOL rumble; + + if (1 == SCGetWpadMotorMode()) { + rumble = TRUE; + } else { + rumble = FALSE; + } + return rumble; +} + +static u8 __ClampSpeakerVolume(u8 vol) { + u8 v = vol; + + if (vol < 0) { + v = 0; + } + if (vol > 127) { + v = 127; + } + + return v; +} + +static u8 __GetSpeakerVolume() { + u8 vol; + vol = SCGetWpadSpeakerVolume(); + vol = __ClampSpeakerVolume(vol); + return vol; +} + +void WPADiManageHandler(OSAlarm*, OSContext*) { + s32 chan; + s32 status; + BOOL sendCmd; + + status = WPADGetStatus(); + + if (status != WPAD_STATE_SETUP) { + return; + } + + for (chan = 0; chan < WPAD_MAX_CONTROLLERS; chan++) { + sendCmd = FALSE; + if (_extCnt == 5) { + sendCmd |= WPADiProcessExtCommand(chan); + } + sendCmd |= WPADiProcessCommand(chan); + + WPADiRumbleMotor(chan, sendCmd); + + if (_checkCnt == 5) { + WPADiCheckContInputs(chan); + } + + if (_senseCnt == 10) { + WPADiRadioSensitivity(chan); + } + } + + if (_afhCnt == 60000) { + WPADiAfh(); + } + + _senseCnt = (u16)((_senseCnt == 10) ? 0 : _senseCnt + 1); + _checkCnt = (u8)((_checkCnt == 5) ? 0 : _checkCnt + 1); + _extCnt = (u16)((_extCnt == 5) ? 0 : _extCnt + 1); + _afhCnt = (u16)((_afhCnt == 60000) ? 0 : _afhCnt + 1); + + WPADiContMapTableUpdate(); + WPADiGetScSettings(); + BTA_HhGetAclQueueInfo(); +} + +u8 __WPADiManageHandlerStack[4096] ATTRIBUTE_ALIGN(32); + +void WPADiManageHandler0(OSAlarm* alarm, OSContext* context) { + OSSwitchFiberEx((u32)alarm, (u32)context, 0, 0, (u32)WPADiManageHandler, (u32)(__WPADiManageHandlerStack + sizeof(__WPADiManageHandlerStack))); +} + +inline void WPADiInitSub() { + s32 i; + + __SetSensorBarPower(TRUE); + + for (i = 0; i < 16; i++) { + _dev_handle_index[i] = -1; + } + + //TODO: this gets placed in .data incorrectly with the inline keyword, + // might be fixed when we figure out -ipa program + DEBUGPrint("WPADInit()\n"); + + for (i = 0; i < WPAD_MAX_CONTROLLERS; i++) { + _wpdcb[i] = &_wpd[i]; + _chan_active_state[i] = 0; + _wpdcb[i]->connectCallback = NULL; + + __ClearControlBlock(i); + OSInitThreadQueue(&_wpd[i].threadQueue); + } + + _sleepTime = 5; + _gamecode = OSGetAppGamename(); + _gametype = OSGetAppType(); + _dpdSensitivity = __GetDpdSensitivity(); + _sensorBarPos = __GetSensorBarPosition(); + _rumble = __GetMotorMode(); + _speakerVolume = __GetSpeakerVolume(); + + WUDSetHidConnCallback(WPADiConnCallback); + WUDSetHidRecvCallback(WPADiRecvCallback); + + _senseCnt = 0; + _checkCnt = 0; + _extCnt = 0; + _afhCnt = 0; + _rumbleCnt[0] = _rumbleCnt[1] = _rumbleCnt[2] = _rumbleCnt[3] = 0; + + OSCreateAlarm(&_managerAlarm); + OSSetPeriodicAlarm(&_managerAlarm, __OSGetSystemTime(), OSMillisecondsToTicks(1), + WPADiManageHandler0); + + _shutdown = 0; + _scFlush = 0; + _scSetting = 1; + _afhChannel = -1; + + OSRegisterVersion(__WPADVersion); +} + +void WPADInit(void) { + BOOL result; + + if (_regShutdown == 0) { + OSRegisterShutdownFunction(&ShutdownFunctionInfo); + _regShutdown = 1; + } + + result = WUDInit(); + + if (result) { + WPADiInitSub(); + } +} + +void WPADiRadioSensitivity(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + u32 packet = 2; + u16 rs; + + rs = (u16)(p_wpd->radioSensitivity * (10 - 1)); + rs += (u16)((p_wpd->packetCnt * 100) / packet); + rs /= 10; + rs = (u16)((rs > 100) ? 100 : rs); + + p_wpd->radioSensitivity = (u8)rs; + p_wpd->packetCnt = 0; + + if (p_wpd->radioQuality) { + if (rs > 85) { + p_wpd->radioQuality = 0; + p_wpd->radioQualityOkMs = 0; + } else if (rs > 80) { + p_wpd->radioQualityOkMs++; + if (p_wpd->radioQualityOkMs >= 20) { + p_wpd->radioQuality = 0; + p_wpd->radioQualityOkMs = 0; + } + } + } else { + if (rs < 75) { + p_wpd->radioQuality = 1; + p_wpd->radioQualityOkMs = 0; + } else if (rs < 80) { + p_wpd->radioQualityOkMs++; + if (p_wpd->radioQualityOkMs >= 1) { + p_wpd->radioQuality = 1; + p_wpd->radioQualityOkMs = 0; + } + } + } +} + +BOOL WPADiIsCoreFormat(u32 fmt) { + if (fmt == WPAD_FMT_CORE_BTN || fmt == WPAD_FMT_CORE_BTN_ACC || fmt == WPAD_FMT_CORE_BTN_ACC_DPD) { + return TRUE; + } else { + return FALSE; + } +} + +BOOL WPADiIsFsFormat(u32 fmt) { + if (fmt == WPAD_FMT_FS_BTN || fmt == WPAD_FMT_FS_BTN_ACC || fmt == WPAD_FMT_FS_BTN_ACC_DPD) { + return TRUE; + } else { + return FALSE; + } +} +BOOL WPADiIsClFormat(u32 fmt) { + if (fmt == WPAD_FMT_CLASSIC_BTN || fmt == WPAD_FMT_CLASSIC_BTN_ACC || fmt == WPAD_FMT_CLASSIC_BTN_ACC_DPD) { + return TRUE; + } else { + return FALSE; + } +} + +static u8 IsButtonChanged(u16 curr, u16 prev) { + return (u8)((curr != prev) ? 1 : 0); +} + +static u8 IsAnalogChanged(s32 curr, s32 prev, s32 threshold) { + s32 diff = ((curr - prev) < 0) ? prev - curr : curr - prev; + return (u8)((diff > threshold) ? 1 : 0); +} + +BOOL IsControllerDataChanged(WPADControlBlock* p_wpd, void* p_curr, void* p_prev) { + u32 fmt; + u8 mode, result = 0; + int i; + + mode = p_wpd->devMode; + fmt = p_wpd->dataFormat; + + if (WPADiIsCoreFormat(fmt)) { + WPADStatus* curr = (WPADStatus*)p_curr; + WPADStatus* prev = (WPADStatus*)p_prev; + result |= IsButtonChanged(curr->button, prev->button); + if (curr->err == WPAD_ERR_OK && prev->err == WPAD_ERR_OK) { + if (IsAnalogChanged((s32)(curr->accX), (s32)(prev->accX), 12) | IsAnalogChanged((s32)(curr->accY), (s32)(prev->accY), 12) | + IsAnalogChanged((s32)(curr->accZ), (s32)(prev->accZ), 12)) { + DIFF_COUNT_ACC(p_wpd)++; + if (DIFF_COUNT_ACC(p_wpd) > __WPAD_acc_diff_count_threshold) { + DIFF_COUNT_ACC(p_wpd) = 0; + HYST_COUNT_ACC(p_wpd) = 0; + result |= 1; + } + + } else { + HYST_COUNT_ACC(p_wpd) = (u16)((HYST_COUNT_ACC(p_wpd) + 1) % __WPAD_acc_hyst_count_threshold); + if (HYST_COUNT_ACC(p_wpd) == __WPAD_acc_hyst_count_threshold - 1) { + if (DIFF_COUNT_ACC(p_wpd) > 0) { + DIFF_COUNT_ACC(p_wpd)--; + } + } + } + + for (i = 0; i < WPAD_DPD_MAX_OBJECTS; i++) { + if (IsAnalogChanged((s32)(curr->obj[i].x), (s32)(prev->obj[i].x), 2) | + IsAnalogChanged((s32)(curr->obj[i].y), (s32)(prev->obj[i].y), 2)) { + DIFF_COUNT_DPD(p_wpd)++; + if (DIFF_COUNT_DPD(p_wpd) > __WPAD_dpd_diff_count_threshold) { + DIFF_COUNT_DPD(p_wpd) = 0; + result |= 1; + } + } else { + HYST_COUNT_DPD(p_wpd) = (u16)((HYST_COUNT_DPD(p_wpd) + 1) % __WPAD_dpd_hyst_count_threshold); + if (HYST_COUNT_DPD(p_wpd) == __WPAD_dpd_hyst_count_threshold - 1) { + if (DIFF_COUNT_DPD(p_wpd) > 0) { + DIFF_COUNT_DPD(p_wpd)--; + } + } + } + } + } + + } else if (WPADiIsFsFormat(fmt)) { + WPADFSStatus* curr = (WPADFSStatus*)p_curr; + WPADFSStatus* prev = (WPADFSStatus*)p_prev; + + result |= IsButtonChanged(curr->base.button, prev->base.button); + if (curr->base.err == WPAD_ERR_OK && prev->base.err == WPAD_ERR_OK) { + if (IsAnalogChanged((s32)(curr->base.accX), (s32)(prev->base.accX), 12) | IsAnalogChanged((s32)(curr->base.accY), (s32)(prev->base.accY), 12) | + IsAnalogChanged((s32)(curr->base.accZ), (s32)(prev->base.accZ), 12)) { + DIFF_COUNT_ACC(p_wpd)++; + if (DIFF_COUNT_ACC(p_wpd) > __WPAD_acc_diff_count_threshold) { + DIFF_COUNT_ACC(p_wpd) = 0; + HYST_COUNT_ACC(p_wpd) = 0; + result |= 1; + } + + } else { + HYST_COUNT_ACC(p_wpd) = (u16)((HYST_COUNT_ACC(p_wpd) + 1) % __WPAD_acc_hyst_count_threshold); + if (HYST_COUNT_ACC(p_wpd) == __WPAD_acc_hyst_count_threshold - 1) { + if (DIFF_COUNT_ACC(p_wpd) > 0) { + DIFF_COUNT_ACC(p_wpd)--; + } + } + } + + for (i = 0; i < WPAD_DPD_MAX_OBJECTS; i++) { + if (IsAnalogChanged((s32)(curr->base.obj[i].x), (s32)(prev->base.obj[i].x), 2) | + IsAnalogChanged((s32)(curr->base.obj[i].y), (s32)(prev->base.obj[i].y), 2)) { + DIFF_COUNT_DPD(p_wpd)++; + if (DIFF_COUNT_DPD(p_wpd) > __WPAD_dpd_diff_count_threshold) { + DIFF_COUNT_DPD(p_wpd) = 0; + result |= 1; + } + } else { + HYST_COUNT_DPD(p_wpd) = (u16)((HYST_COUNT_DPD(p_wpd) + 1) % __WPAD_dpd_hyst_count_threshold); + if (HYST_COUNT_DPD(p_wpd) == __WPAD_dpd_hyst_count_threshold - 1) { + if (DIFF_COUNT_DPD(p_wpd) > 0) { + DIFF_COUNT_DPD(p_wpd)--; + } + } + } + } + + if (IsAnalogChanged((s32)(curr->fsAccX), (s32)(prev->fsAccX), 12) | IsAnalogChanged((s32)(curr->fsAccY), (s32)(prev->fsAccY), 12) | + IsAnalogChanged((s32)(curr->fsAccZ), (s32)(prev->fsAccZ), 12)) { + DIFF_COUNT_FS_ACC(p_wpd)++; + if (DIFF_COUNT_FS_ACC(p_wpd) > __WPAD_acc_diff_count_threshold) { + DIFF_COUNT_FS_ACC(p_wpd) = 0; + HYST_COUNT_FS_ACC(p_wpd) = 0; + result |= 1; + } + + } else { + HYST_COUNT_FS_ACC(p_wpd) = (u16)((HYST_COUNT_FS_ACC(p_wpd) + 1) % __WPAD_acc_hyst_count_threshold); + if (HYST_COUNT_FS_ACC(p_wpd) == __WPAD_acc_hyst_count_threshold - 1) { + if (DIFF_COUNT_FS_ACC(p_wpd) > 0) { + DIFF_COUNT_FS_ACC(p_wpd)--; + } + } + } + + result |= IsAnalogChanged((s32)(curr->fsStickX), (s32)(prev->fsStickX), 1); + result |= IsAnalogChanged((s32)(curr->fsStickY), (s32)(prev->fsStickY), 1); + } + } else if (WPADiIsClFormat(fmt)) { + WPADCLStatus* curr = (WPADCLStatus*)p_curr; + WPADCLStatus* prev = (WPADCLStatus*)p_prev; + s32 lstk; + s32 rstk; + s32 trig; + + switch (mode) { + case 1: + lstk = 16; + rstk = 32; + trig = 8; + break; + case 3: + lstk = 4; + rstk = 4; + trig = 1; + break; + default: + lstk = 1; + rstk = 1; + trig = 1; + break; + } + + result |= IsButtonChanged(curr->base.button, prev->base.button); + if (curr->base.err == WPAD_ERR_OK && prev->base.err == WPAD_ERR_OK) { + if (IsAnalogChanged((s32)(curr->base.accX), (s32)(prev->base.accX), 12) | IsAnalogChanged((s32)(curr->base.accY), (s32)(prev->base.accY), 12) | + IsAnalogChanged((s32)(curr->base.accZ), (s32)(prev->base.accZ), 12)) { + DIFF_COUNT_ACC(p_wpd)++; + if (DIFF_COUNT_ACC(p_wpd) > __WPAD_acc_diff_count_threshold) { + DIFF_COUNT_ACC(p_wpd) = 0; + HYST_COUNT_ACC(p_wpd) = 0; + result |= 1; + } + + } else { + HYST_COUNT_ACC(p_wpd) = (u16)((HYST_COUNT_ACC(p_wpd) + 1) % __WPAD_acc_hyst_count_threshold); + if (HYST_COUNT_ACC(p_wpd) == __WPAD_acc_hyst_count_threshold - 1) { + if (DIFF_COUNT_ACC(p_wpd) > 0) { + DIFF_COUNT_ACC(p_wpd)--; + } + } + } + + for (i = 0; i < WPAD_DPD_MAX_OBJECTS; i++) { + if (IsAnalogChanged((s32)(curr->base.obj[i].x), (s32)(prev->base.obj[i].x), 2) | + IsAnalogChanged((s32)(curr->base.obj[i].y), (s32)(prev->base.obj[i].y), 2)) { + DIFF_COUNT_DPD(p_wpd)++; + if (DIFF_COUNT_DPD(p_wpd) > __WPAD_dpd_diff_count_threshold) { + DIFF_COUNT_DPD(p_wpd) = 0; + result |= 1; + } + } else { + HYST_COUNT_DPD(p_wpd) = (u16)((HYST_COUNT_DPD(p_wpd) + 1) % __WPAD_dpd_hyst_count_threshold); + if (HYST_COUNT_DPD(p_wpd) == __WPAD_dpd_hyst_count_threshold - 1) { + if (DIFF_COUNT_DPD(p_wpd) > 0) { + DIFF_COUNT_DPD(p_wpd)--; + } + } + } + } + result |= IsButtonChanged(curr->clButton, prev->clButton); + result |= IsAnalogChanged((s32)(curr->clLStickX / lstk), (s32)(prev->clLStickX / lstk), 1); + result |= IsAnalogChanged((s32)(curr->clLStickY / lstk), (s32)(prev->clLStickY / lstk), 1); + result |= IsAnalogChanged((s32)(curr->clRStickX / rstk), (s32)(prev->clRStickX / rstk), 1); + result |= IsAnalogChanged((s32)(curr->clRStickY / rstk), (s32)(prev->clRStickY / rstk), 1); + result |= IsAnalogChanged((s32)(curr->clTriggerL / trig), (s32)(prev->clTriggerL / trig), 1); + result |= IsAnalogChanged((s32)(curr->clTriggerR / trig), (s32)(prev->clTriggerR / trig), 1); + } + } else { + WPADStatusEx* curr = (WPADStatusEx*)p_curr; + WPADStatusEx* prev = (WPADStatusEx*)p_prev; + + result |= IsButtonChanged(curr->base.button, prev->base.button); + if (curr->base.err == WPAD_ERR_OK && prev->base.err == WPAD_ERR_OK) { + if (IsAnalogChanged((s32)(curr->base.accX), (s32)(prev->base.accX), 12) | + IsAnalogChanged((s32)(curr->base.accY), (s32)(prev->base.accY), 12) | + IsAnalogChanged((s32)(curr->base.accZ), (s32)(prev->base.accZ), 12)) { + DIFF_COUNT_ACC(p_wpd)++; + if (DIFF_COUNT_ACC(p_wpd) > __WPAD_acc_diff_count_threshold) { + DIFF_COUNT_ACC(p_wpd) = 0; + HYST_COUNT_ACC(p_wpd) = 0; + result |= 1; + } + + } else { + HYST_COUNT_ACC(p_wpd) = (u16)((HYST_COUNT_ACC(p_wpd) + 1) % __WPAD_acc_hyst_count_threshold); + if (HYST_COUNT_ACC(p_wpd) == __WPAD_acc_hyst_count_threshold - 1) { + if (DIFF_COUNT_ACC(p_wpd) > 0) { + DIFF_COUNT_ACC(p_wpd)--; + } + } + } + + for (i = 0; i < WPAD_DPD_MAX_OBJECTS; i++) { + if (IsAnalogChanged((s32)(curr->base.obj[i].x), (s32)(prev->base.obj[i].x), 2) | + IsAnalogChanged((s32)(curr->base.obj[i].y), (s32)(prev->base.obj[i].y), 2)) { + DIFF_COUNT_DPD(p_wpd)++; + if (DIFF_COUNT_DPD(p_wpd) > __WPAD_dpd_diff_count_threshold) { + DIFF_COUNT_DPD(p_wpd) = 0; + result |= 1; + } + } else { + HYST_COUNT_DPD(p_wpd) = (u16)((HYST_COUNT_DPD(p_wpd) + 1) % __WPAD_dpd_hyst_count_threshold); + if (HYST_COUNT_DPD(p_wpd) == __WPAD_dpd_hyst_count_threshold - 1) { + if (DIFF_COUNT_DPD(p_wpd) > 0) { + DIFF_COUNT_DPD(p_wpd)--; + } + } + } + } + } + } + + return result; +} + +void WPADRecalibrate(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable = OSDisableInterrupts(); + p_wpd->calibrated = 0; + OSRestoreInterrupts(enable); +} + +inline void CheckButtonCombination(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + WPADCLStatus* status; + BOOL enable; + u8 index; + s8 cnt = 0; + + enable = OSDisableInterrupts(); + index = p_wpd->rxBufIndex == 0; + status = (WPADCLStatus*)(p_wpd->rxBufs + index); + + if (status->base.button == 0x1C10) { + cnt = 1; + } + + if (WPADiIsClFormat(p_wpd->dataFormat)) { + if (status->clButton == 0x1450) { + cnt = 1; + } + } + + p_wpd->recalibrateCount = cnt != 0 ? p_wpd->recalibrateCount + 1 : 0; + + OSRestoreInterrupts(enable); + + if (p_wpd->recalibrateCount > 600) { + WPADRecalibrate(chan); + } +} + +static void __SetScreenSaverFlag(BOOL flag) { + if (flag) { + VIResetRFIdle(); + } +} + +void WPADiCheckContInputs(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL diff = FALSE; + BOOL enable; + BOOL screen = FALSE; + void* p_data; + u8 index; + + if (p_wpd->status == WPAD_ERR_NO_CONTROLLER) { + return; + } + + enable = OSDisableInterrupts(); + index = (u8)((p_wpd->rxBufIndex) ? 0 : 1); + p_data = (void*)(p_wpd->rxBufs + index); + diff = IsControllerDataChanged(p_wpd, p_data, p_wpd->prBuf); + + if (diff) { + memcpy(p_wpd->prBuf, p_data, WPAD_RX_DATASIZE); + } + if (((WPADStatus*)p_wpd->prBuf)->err != WPAD_ERR_OK) { + memset(p_wpd->prBuf, 0, WPAD_RX_DATASIZE); + } + + OSRestoreInterrupts(enable); + CheckButtonCombination(chan); + + if (diff) { + screen = TRUE; + p_wpd->lastUpdateTime = __OSGetSystemTime(); + } else { + if (_sleepTime > 0) { + int sec = (int)OSTicksToSeconds(__OSGetSystemTime() - p_wpd->lastUpdateTime); + + if (sec > 60 * _sleepTime) { + WPADiDisconnect(chan, TRUE); + } + } + } + + __SetScreenSaverFlag(screen); +} + +s8 __wpadGetQueueSize(WPADCmdQueue* queue) { + BOOL enable; + s8 num; + + enable = OSDisableInterrupts(); + + num = (s8)(queue->tail - queue->head); + if (num < 0) { + num += queue->cmdlen; + } + + OSRestoreInterrupts(enable); + return num; +} + +BOOL WPADiIsAvailableCmdQueue(WPADCmdQueue* queue, s8 cmd_num) { + s8 curr = __wpadGetQueueSize(queue); + + if (curr + cmd_num <= queue->cmdlen - 1) { + return TRUE; + } else { + return FALSE; + } +} + +void WPADiClearQueue(WPADCmdQueue* queue) { + BOOL enable; + + enable = OSDisableInterrupts(); + + queue->head = 0; + queue->tail = 0; + memset(queue->cmd, 0, queue->cmdlen * sizeof(WPADCommand)); + + OSRestoreInterrupts(enable); +} + +BOOL __wpadPushCommand(WPADCmdQueue* queue, WPADCommand cmd) { + BOOL enable; + + enable = OSDisableInterrupts(); + + if (__wpadGetQueueSize(queue) == queue->cmdlen - 1) { + OSRestoreInterrupts(enable); + return FALSE; + } + + memset(queue->cmd + queue->tail, 0, sizeof(WPADCommand)); + memcpy(queue->cmd + queue->tail, &cmd, sizeof(WPADCommand)); + queue->tail = (s8)((queue->tail == queue->cmdlen - 1) ? 0 : queue->tail + 1); + OSRestoreInterrupts(enable); + return TRUE; +} + +BOOL WPADiSendDPDCSB(WPADCmdQueue* queue, BOOL enable, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + + cmd.command = WPAD_HIDREP_DPDCSB; + cmd.len = 1; + cmd.data[0] = enable ? 4 : 0; + cmd.callback = callback; + + result = __wpadPushCommand(queue, cmd); + return result; +} + +BOOL WPADiSendReadData(WPADCmdQueue* queue, void* p_buf, u16 len, u32 addr, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + + ASSERT(p_buf != NULL); + + cmd.command = WPAD_HIDREP_RDDATA; + cmd.len = 6; + cmd.callback = callback; + + memcpy(cmd.data, &addr, sizeof(addr)); + memcpy(cmd.data + 4, &len, sizeof(len)); + + cmd.readBuf = p_buf; + cmd.readLen = len; + cmd.readAddr = addr; + + result = __wpadPushCommand(queue, cmd); + return result; +} + +u16 __wpadGetBTEBufferStatus(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + s32 status; + s8 handle; + + enable = OSDisableInterrupts(); + status = p_wpd->status; + handle = p_wpd->devHandle; + OSRestoreInterrupts(enable); + + if (status == WPAD_ERR_NO_CONTROLLER) { + return 0; + } else { + return _WUDGetQueuedSize(handle); + } +} + +u16 __wpadGetBTMBufferStatus(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + s32 status; + s8 handle; + + enable = OSDisableInterrupts(); + status = p_wpd->status; + handle = p_wpd->devHandle; + OSRestoreInterrupts(enable); + + if (status == WPAD_ERR_NO_CONTROLLER) { + return 0; + } else { + return _WUDGetNotAckedSize(handle); + } +} + +void WPADiGetScSettings() { + if (_scSetting) { + if (SCCheckStatus() == 0) { + _dpdSensitivity = __GetDpdSensitivity(); + _sensorBarPos = __GetSensorBarPosition(); + _rumble = __GetMotorMode(); + _speakerVolume = __GetSpeakerVolume(); + _scSetting = 0; + } + } +} + +void WPADiAfh() { + BOOL enable; + u8* channel = (u8*)OSPhysicalToCached(0x31A2); + + DCInvalidateRange(channel, 1); + DEBUGPrint("WiFi uses channel = %d\n", *channel); + + if (_afhChannel != *channel) { + enable = OSDisableInterrupts(); + _afhChannel = (s8)*channel; + OSRestoreInterrupts(enable); + WUDSetDisableChannel(_afhChannel); + } +} + +void WPADiContMapTableUpdate() { + if (_scFlush) { + if (SCCheckStatus() == 0) { + if (TRUE == SCSetBtDeviceInfoArray(&_scArray)) { + SCFlushAsync(NULL); + _scFlush = 0; + } + } + } +} + +BOOL WPADiProcessExtCommand(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + WPADCommand cmd; + s32 err; + + if (p_wpd->used && p_wpd->info.attach) { + if (WPADiGetCommand(&p_wpd->extCmdQueue, &cmd)) { + err = WPADiSendData(chan, cmd); + if (err == WPAD_ERR_OK) { + WPADiPopCommand(&p_wpd->extCmdQueue); + return TRUE; + } + } + } + return FALSE; +} + +#if SDK_AUG2010 +BOOL WPADiSendGetContStat(WPADCmdQueue* queue, WPADInfo* info, WPADCallback callback) { +#else +BOOL WPADiSendGetContStat(WPADCmdQueue* queue, WPADInfo* info, u32 addr, WPADCallback callback) { +#endif + WPADCommand cmd; + BOOL result; + + cmd.command = WPAD_HIDREP_GETSTAT; + cmd.len = 1; + cmd.data[0] = 0; + cmd.callback = callback; + cmd.info = info; + + result = __wpadPushCommand(queue, cmd); + return result; +} + +BOOL WPADiSendWriteDataCmd(WPADCmdQueue* queue, u8 cmd, u32 addr, WPADCallback callback) { + return WPADiSendWriteData(queue, &cmd, 1, addr, callback); +} + +BOOL WPADiSendWriteData(WPADCmdQueue* queue, void* p_buf, u16 len, u32 addr, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + u8 length = (u8)(len & WPAD_WRITE_LEN_MASK); + ASSERTLINE(5830, len > 0 && len <= 16); + ASSERTLINE(5831, p_buf != NULL); + cmd.command = WPAD_HIDREP_WRDATA; + cmd.len = 21; + cmd.callback = callback; + memcpy(cmd.data, &addr, sizeof(addr)); + memcpy(cmd.data + 4, &length, sizeof(length)); + memcpy(cmd.data + 5, p_buf, len); + + result = __wpadPushCommand(queue, cmd); + return result; +} + +BOOL WPADiSendSetPort(WPADCmdQueue* queue, u8 pattern, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + + cmd.command = WPAD_HIDREP_PORT; + cmd.len = 1; + cmd.data[0] = (u8)(pattern << 4); + cmd.callback = callback; + + result = __wpadPushCommand(queue, cmd); + return result; +} + +static void setupCallback(s32 chan, s32 result) { + u16 size; + u32 addr; + WPADControlBlock* p_wpd = _wpdcb[chan]; + + if (result == WPAD_ERR_NO_CONTROLLER) { + return; + } + + if (result == WPAD_ESUCCESS) { + p_wpd->handshakeFinished = TRUE; + + if (p_wpd->connectCallback) { + p_wpd->connectCallback(chan, result); + } + } else { + size = p_wpd->oldFw != 0 ? 20 : 42; + addr = p_wpd->oldFw != 0 ? WM_ADDR_MEM_176C : 0; + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, size, addr, setupCallback); + } +} + +static void gameInfoCallback(s32 chan, s32 result) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + + if (result != WPAD_ETRANSFER) { + return; + } + + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, sizeof(WPADMEMGameInfo), 0x2A, gameInfoCallback); +} + +static void gameInfoCallback2(s32 chan, s32 result) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + + if (result != WPAD_ETRANSFER) { + return; + } + + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, sizeof(WPADMEMGameInfo), 0x62, gameInfoCallback2); +} + +static void firmwareCheckCallback(s32 chan, s32 result) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + u16 size; + u32 addr; + u8 port; + BOOL enable; + + if (result == WPAD_ERR_NO_CONTROLLER) { + return; + } + + enable = OSDisableInterrupts(); + p_wpd->oldFw = (result == WPAD_ERR_OK) ? TRUE : FALSE; + p_wpd->status = WPAD_ERR_OK; + OSRestoreInterrupts(enable); + size = (u16)((result == WPAD_ERR_OK) ? 20 : 42); + addr = (u32)((result == WPAD_ERR_OK) ? WM_ADDR_MEM_176C : 0); + + DEBUGPrint(" ==>this error means that the firmware is for NDEV %s\n", + p_wpd->oldFw != 0 ? "2.0" : "2.1 or later"); + WPADiSendSetReportType(&p_wpd->stdCmdQueue, WPAD_FMT_CORE_BTN, NULL); + WPADiSendDPDCSB(&p_wpd->stdCmdQueue, FALSE, NULL); + WPADiSendSetPort(&p_wpd->stdCmdQueue, 0x01 << chan, NULL); + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, sizeof(WPADMEMGameInfo), + WM_ADDR_MEM_GAME_INFO_0, gameInfoCallback); + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, sizeof(WPADMEMGameInfo), + WM_ADDR_MEM_GAME_INFO_0 + sizeof(WPADMEMGameInfo), gameInfoCallback2); + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, size, addr, setupCallback); +#if SDK_AUG2010 + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, NULL); +#else + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, 0, NULL); +#endif +} + +s32 WPADiRetrieveChannel(u8 dev_handle) { + u8* devAddr; + s32 i; + + devAddr = _WUDGetDevAddr(dev_handle); + + for (i = 0; i < WPAD_MAX_CONTROLLERS; i++) { + if (!memcmp(_scArray.info[i + 10].bd_addr, devAddr, 6)) { + if (_chan_active_state[i] == 0) { + _chan_active_state[i] = 1; + return i; + } + } + } + for (i = 0; i < WPAD_MAX_CONTROLLERS; i++) { + if (_chan_active_state[i] == 0) { + _chan_active_state[i] = 1; + memcpy(_scArray.info[i + 10].bd_addr, devAddr, 6); + _scFlush = 1; + return i; + } + } + + return -1; +} + +void WPADiConnCallback(u8 dev_handle, u8 open) { + s32 chan = -1; + WPADControlBlock* p_wpd; + BOOL isCmdExist; + WPADCommand cmd; + + if (open) { + DEBUGPrint("connection is opened\n"); + chan = WPADiRetrieveChannel(dev_handle); + p_wpd = _wpdcb[chan]; + _dev_handle_index[dev_handle] = (s8)(chan & 0xff); + __ClearControlBlock(chan); + + p_wpd->devHandle = (s8)dev_handle; + p_wpd->devType = WPAD_DEV_CORE; + p_wpd->dataFormat = WPAD_FMT_CORE_BTN; + p_wpd->used = TRUE; + p_wpd->status = WPAD_ERR_OK; + p_wpd->radioSensitivity = 100; + p_wpd->disconnect = 0; + WPADiSendReadData(&p_wpd->stdCmdQueue, p_wpd->wmReadDataBuf, 1, WM_ADDR_MEM_1770, firmwareCheckCallback); + __SetScreenSaverFlag(TRUE); + } else { + DEBUGPrint("connection is closed\n"); + chan = _dev_handle_index[dev_handle]; + _dev_handle_index[dev_handle] = -1; + + if (chan != -1) { + p_wpd = _wpdcb[chan]; + p_wpd->status = WPAD_ERR_NO_CONTROLLER; + + if (p_wpd->cmdBlkCallback) { + p_wpd->cmdBlkCallback(chan, WPAD_ERR_NO_CONTROLLER); + } else if (_wmb[chan].callback) { + _wmb[chan].callback(chan, WPAD_ERR_NO_CONTROLLER); + } + do { + isCmdExist = WPADiGetCommand(&p_wpd->stdCmdQueue, &cmd); + if (isCmdExist) { + if (cmd.callback) { + cmd.callback(chan, WPAD_ERR_NO_CONTROLLER); + } + WPADiPopCommand(&p_wpd->stdCmdQueue); + } + } while (isCmdExist); + DEBUGPrint("clean up command queue\n"); + + if (p_wpd->samplingBufs_ptr) { + WPADSetAutoSamplingBuf(chan, p_wpd->samplingBufs_ptr, p_wpd->samplingBufLength); + } + + __ClearControlBlock(chan); + _chan_active_state[chan] = 0; + + if (p_wpd->connectCallback) { + p_wpd->connectCallback(chan, WPAD_ERR_NO_CONTROLLER); + } + } else { + DEBUGPrint("WARNING: disconnection for device handle not assigned to channel.\n"); + } + } +} + +void WPADiRecvCallback(u8 dev_handle, u8* p_rpt, u16) { + u8 chan; + s32 err; + + chan = (u8)_dev_handle_index[dev_handle]; + + if ((chan >= 0) && (chan <= WPAD_MAX_CONTROLLERS)) { + err = WPADiHIDParser(chan, p_rpt); + if (err) { + DEBUGPrint("HID Parser reports: %d\n", err); + } + } else { + DEBUGPrint("WPADiRecvCallback(): Unknown channel %d\n", chan); + } +} + +void WPADGetAccGravityUnit(s32 chan, u32 type, WPADAcc* acc) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + + enable = OSDisableInterrupts(); + if (acc) { + switch (type) { + case WPAD_DEV_CORE: + acc->x = (s16)(p_wpd->devConf.acc_1g.x - p_wpd->devConf.acc_0g.x); + acc->y = (s16)(p_wpd->devConf.acc_1g.y - p_wpd->devConf.acc_0g.y); + acc->z = (s16)(p_wpd->devConf.acc_1g.z - p_wpd->devConf.acc_0g.z); + break; + + case WPAD_DEV_FS: + acc->x = (s16)(p_wpd->extConf.fs.acc_1g.x - p_wpd->extConf.fs.acc_0g.x); + acc->y = (s16)(p_wpd->extConf.fs.acc_1g.y - p_wpd->extConf.fs.acc_0g.y); + acc->z = (s16)(p_wpd->extConf.fs.acc_1g.z - p_wpd->extConf.fs.acc_0g.z); + break; + } + } + OSRestoreInterrupts(enable); +} + +BOOL WPADiGetCommand(WPADCmdQueue* queue, WPADCommand* cmd) { + BOOL enable = OSDisableInterrupts(); + + if (__wpadGetQueueSize(queue) == 0) { + OSRestoreInterrupts(enable); + return FALSE; + } + + memcpy(cmd, queue->cmd + queue->head, sizeof(WPADCommand)); + + OSRestoreInterrupts(enable); + return TRUE; +} + +BOOL WPADiPopCommand(WPADCmdQueue* queue) { + BOOL enable = OSDisableInterrupts(); + + if (__wpadGetQueueSize(queue) == 0) { + OSRestoreInterrupts(enable); + return FALSE; + } + + memset(queue->cmd + queue->head, 0, sizeof(WPADCommand)); + queue->head = (s8)((queue->head == queue->cmdlen - 1) ? 0 : queue->head + 1); + + OSRestoreInterrupts(enable); + return TRUE; +} + +BOOL WPADiProcessCommand(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + WPADCommand cmd; + s32 err; + + if (p_wpd->used) { + if (WPADiGetCommand(&p_wpd->stdCmdQueue, &cmd)) { + err = WPADiSendData(chan, cmd); + if (err == WPAD_ERR_OK) { + WPADiPopCommand(&p_wpd->stdCmdQueue); + return TRUE; + } + } + } + return FALSE; +} + +static void __ClearControlBlock(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + + p_wpd->rxBufIndex = 0; + + p_wpd->infoOut = NULL; + p_wpd->motorRunning = FALSE; + + p_wpd->cmdBlkCallback = NULL; + p_wpd->extensionCallback = NULL; + p_wpd->samplingCallback = NULL; + p_wpd->samplingBufs_ptr = NULL; + p_wpd->samplingBufIndex = 0; + p_wpd->samplingBufLength = 0; + p_wpd->dataFormat = WPAD_FMT_CORE_BTN; + p_wpd->status = WPAD_ERR_NO_CONTROLLER; + p_wpd->devType = WPAD_DEV_NONE; + p_wpd->devMode = 0; + p_wpd->calibrated = 0; + p_wpd->recalibrateCount = 0; + p_wpd->statusReqBusy = 0; + p_wpd->dpdDummyObjSize = 12; + + DIFF_COUNT_DPD(p_wpd) = 0; + HYST_COUNT_DPD(p_wpd) = 0; + DIFF_COUNT_ACC(p_wpd) = 0; + HYST_COUNT_ACC(p_wpd) = 0; + DIFF_COUNT_FS_ACC(p_wpd) = 0; + HYST_COUNT_FS_ACC(p_wpd) = 0; + + p_wpd->lastUpdateTime = __OSGetSystemTime(); + p_wpd->lastReportSendTime = __OSGetSystemTime(); + p_wpd->cmdTimeoutAction = 0; +#if SDK_SEP2006 + p_wpd->reqVolume = 0; + p_wpd->reqVolCb = NULL; +#endif + + p_wpd->wmReadDataPtr = NULL; + p_wpd->wmReadAddr = 0; + p_wpd->wmReadLength = 0; + p_wpd->wmReadErr = 0; + + p_wpd->devHandle = -1; + p_wpd->used = FALSE; + p_wpd->handshakeFinished = FALSE; + p_wpd->oldFw = FALSE; + p_wpd->radioQuality = 1; + p_wpd->radioQualityOkMs = 0; + p_wpd->audioFrames = 0; + + p_wpd->keyIdx = 0; + p_wpd->radioSensitivity = 0; + p_wpd->packetCnt = 0; + p_wpd->disconnect = 1; + + memset(&p_wpd->info, 0, sizeof(WPADInfo)); + memset(p_wpd->wmReadDataBuf, 0, sizeof(p_wpd->wmReadDataBuf)); + memset(p_wpd->rxBufs, 0, WPAD_RX_DATASIZE * 2); + memset(p_wpd->prBuf, 0, WPAD_RX_DATASIZE); + memset(&p_wpd->devConf, 0, sizeof(WPADDevConfig)); + memset(&p_wpd->extConf, 0, sizeof(WPADExtConfig)); + memset(&p_wpd->key, 0, sizeof(p_wpd->key)); + memset(&p_wpd->ft, 0, sizeof(p_wpd->ft)); + memset(&p_wpd->sb, 0, sizeof(p_wpd->sb)); + memset(&p_wpd->gameInfo, 0, sizeof(WPADMEMGameInfo)); + + p_wpd->gameInfoErr[0] = WPAD_ERR_NO_CONTROLLER; + p_wpd->gameInfoErr[1] = WPAD_ERR_NO_CONTROLLER; + p_wpd->stdCmdQueue.cmd = p_wpd->stdCmdQueueList; + p_wpd->stdCmdQueue.cmdlen = ARRAY_SIZE(p_wpd->stdCmdQueueList); + p_wpd->extCmdQueue.cmd = p_wpd->extCmdQueueList; + p_wpd->extCmdQueue.cmdlen = ARRAY_SIZE(p_wpd->extCmdQueueList); + WPADiClearQueue(&p_wpd->stdCmdQueue); + WPADiClearQueue(&p_wpd->extCmdQueue); + + _wmb[chan].used = FALSE; + _wmb[chan].p_buf = NULL; + _wmb[chan].len = 0; + _wmb[chan].addr = 0; + _wmb[chan].callback = NULL; +} + +BOOL WPADStartSimpleSync() { + WUDStartSyncSimple(); +} + +BOOL WPADStartFastSimpleSync() { + return WUDStartFastSyncSimple(); +} + +BOOL WPADStopSimpleSync() { + return WUDStopSyncSimple(); +} + +WPADSyncDeviceCallback WPADSetSimpleSyncCallback(WPADSyncDeviceCallback callback) { + return WUDSetSyncSimpleCallback(callback); +} + +void WPADRegisterAllocator(WPADAlloc alloc, WPADFree free) { + WUDRegisterAllocator(alloc, free); +} + +u32 WPADGetWorkMemorySize(void) { + return WUDGetAllocatedMemSize(); +} + +s32 WPADGetStatus() { + return WUDGetStatus(); +} + +u8 WPADGetSensorBarPosition() { + BOOL enable; + u8 pos; + + enable = OSDisableInterrupts(); + pos = _sensorBarPos; + OSRestoreInterrupts(enable); + return pos; +} + +void WPADDisconnect(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + memset(&_scArray.info[chan + 10], 0, sizeof(SCBtDeviceInfoSingle)); + _scFlush = 1; + WPADiDisconnect(chan, TRUE); +} + +void WPADSetAutoSleepTime(u8 minute) { + BOOL enable = OSDisableInterrupts(); + _sleepTime = minute; + OSRestoreInterrupts(enable); +} + +s32 WPADProbe(s32 chan, u32* devType) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + s32 status; + BOOL enable = OSDisableInterrupts(); + if (devType != NULL) { + *devType = p_wpd->devType; + } + status = p_wpd->status; + if (status != WPAD_ERR_NO_CONTROLLER) { + if (p_wpd->devType == WPAD_DEV_NONE) { + status = WPAD_ERR_NO_CONTROLLER; + } else if (!p_wpd->handshakeFinished) { + status = WPAD_ERR_BUSY; + } + } + OSRestoreInterrupts(enable); + return status; +} + +WPADSamplingCallback WPADSetSamplingCallback(s32 chan, WPADSamplingCallback cb) { + WPADControlBlock* p_wpd; + WPADSamplingCallback prev; + BOOL enable; + + DEBUGPrint("WPADSetSamplingCallback()\n"); + + enable = OSDisableInterrupts(); + p_wpd = _wpdcb[chan]; + prev = p_wpd->samplingCallback; + p_wpd->samplingCallback = cb; + OSRestoreInterrupts(enable); + return prev; +} + +WPADConnectCallback WPADSetConnectCallback(s32 chan, WPADConnectCallback cb) { + WPADControlBlock* p_wpd; + WPADConnectCallback prev; + BOOL enable; + + DEBUGPrint("WPADSetConnectCallback()\n"); + + enable = OSDisableInterrupts(); + p_wpd = _wpdcb[chan]; + prev = p_wpd->connectCallback; + p_wpd->connectCallback = cb; + OSRestoreInterrupts(enable); + return prev; +} + +WPADExtensionCallback WPADSetExtensionCallback(s32 chan, WPADExtensionCallback cb) { + WPADControlBlock* p_wpd; + WPADExtensionCallback prev; + BOOL enable; + + DEBUGPrint("WPADSetExtensionCallback()\n"); + + enable = OSDisableInterrupts(); + p_wpd = _wpdcb[chan]; + prev = p_wpd->extensionCallback; + p_wpd->extensionCallback = cb; + OSRestoreInterrupts(enable); + + return prev; +} + +void WPADSetAutoSamplingBuf(s32 chan, void* buf, u32 cnt) { + WPADControlBlock* p_wpd; + BOOL enabled; + s8 err; + size_t step; + s32 i; + size_t off; + WPADStatus* status; + WPADStatus* base; + + DEBUGPrint("WPADSetAutoSamplingBuf()\n"); + enabled = OSDisableInterrupts(); + + p_wpd = _wpdcb[chan]; + err = p_wpd->status == WPAD_ERR_NO_CONTROLLER ? WPAD_ERR_NO_CONTROLLER : WPAD_ERR_INVALID; + + if (WPADiIsCoreFormat(p_wpd->dataFormat)) { + step = sizeof(WPADStatus); + } else if (WPADiIsFsFormat(p_wpd->dataFormat)) { + step = sizeof(WPADFSStatus); + } else if (WPADiIsClFormat(p_wpd->dataFormat)) { + step = sizeof(WPADCLStatus); + } else { + step = 0x5A; + } + + if (buf != NULL) { + memset(buf, 0, step * cnt); + + off = 0; + for (i = 0; i < cnt; i++) { + status = (WPADStatus*)((uintptr_t)buf + off); + off += step; + status->err = err; + } + + p_wpd->samplingBufIndex = -1; + p_wpd->samplingBufLength = cnt; + } + + p_wpd->samplingBufs_ptr = buf; + + OSRestoreInterrupts(enabled); +} + +u32 WPADGetLatestIndexInBuf(s32 chan, void* buf) { + BOOL enable; + u32 idx; + + enable = OSDisableInterrupts(); + idx = _wpdcb[chan]->samplingBufIndex; + OSRestoreInterrupts(enable); + + return idx == -1 ? 0 : idx; +} + +void WPADiExcludeButton(s32 chan) { + WPADControlBlock *cb = _wpdcb[chan]; + BOOL irq = OSDisableInterrupts(); + + WPADStatus* status = (WPADStatus*)&cb->rxBufs[(u8)(cb->rxBufIndex == 0)]; + + if ((status->button & 0x0003) == 0x0003) { + status->button &= ~0x0002; + } + + if ((status->button & 0x000C) == 0x000C) { + status->button &= ~0x0004; + } + + if (cb->dataFormat == WPAD_FMT_CLASSIC_BTN || + cb->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC || + cb->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC_DPD) { + WPADCLStatus* cl = (WPADCLStatus*)status; + if ((cl->clButton & 0x8002) == 0x8002) { + cl->clButton &= ~0x8000; + } + + if ((cl->clButton & 0x4001) == 0x4001) { + cl->clButton &= ~0x4000; + } + } + + OSRestoreInterrupts(irq); +} + +static void __SendData(s32 chan, WPADCommand cmd) { + BOOL enable; + BOOL motor; + BT_HDR* p_buf = NULL; + u8* ptr; + s8 handle; + s32 status; + WPADControlBlock* p_wpd; + u8 rep_id = (u8)cmd.command; + u8* p_data = cmd.data; + u16 len = cmd.len; + + enable = OSDisableInterrupts(); + p_wpd = _wpdcb[chan]; + status = p_wpd->status; + handle = p_wpd->devHandle; + if (handle < 0) { + OSRestoreInterrupts(enable); + return; + } + p_wpd->status = WPAD_ERR_BUSY; + motor = p_wpd->motorRunning & _rumble; + OSRestoreInterrupts(enable); + + if (rep_id == WPAD_HIDREP_VIBRATOR) { + enable = OSDisableInterrupts(); + p_wpd->status = status; + OSRestoreInterrupts(enable); + } else if (rep_id == WPAD_HIDREP_STRM) { + enable = OSDisableInterrupts(); + p_wpd->status = status; + p_wpd->audioFrames--; + OSRestoreInterrupts(enable); + } else { + enable = OSDisableInterrupts(); + switch (rep_id) { + case WPAD_HIDREP_WRDATA: + break; + + case WPAD_HIDREP_RDDATA: + p_wpd->wmReadErr = 0; + p_wpd->wmReadAddr = cmd.readAddr; + p_wpd->wmReadLength = cmd.readLen; + p_wpd->wmReadDataPtr = cmd.readBuf; + break; + + case WPAD_HIDREP_GETSTAT: + p_wpd->status = status; + p_wpd->infoOut = cmd.info; + p_wpd->statusReqBusy = 1; + break; + + case WPAD_HIDREP_WAIT: { + OSTick tick; + memcpy(&tick, cmd.data, sizeof(OSTick)); + p_wpd->lastReportSendTime = tick + __OSGetSystemTime(); + p_wpd->cmdTimeoutAction = 1; + return; + } + + default: + p_data[0] |= 0x2; + break; + } + + p_wpd->cmdBlkCallback = cmd.callback; + p_wpd->lastReportId = rep_id; + p_wpd->lastReportSendTime = OSSecondsToTicks(_sleepTime * 60) + __OSGetSystemTime(); + p_wpd->cmdTimeoutAction = 0; + OSRestoreInterrupts(enable); + } + + DEBUGPrint("handle = %d, repid = %02x\n", handle, rep_id); + + p_buf = GKI_getbuf((u8)(10 + len + sizeof(BT_HDR))); + p_buf->len = (u8)(len + 1); + p_buf->offset = 10; + ptr = (u8*)(p_buf + 1) + p_buf->offset; + + ptr[0] = rep_id; + + memcpy(ptr + 1, p_data, len); + + if (motor) { + ptr[1] |= 1; + } else { + ptr[1] &= ~1; + } + + BTA_HhSendData((u8)handle, p_buf); +} + +s32 WPADiSendData(s32 chan, WPADCommand cmd) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + s32 status; + BOOL enable; + BOOL getStat; + int t; + + status = WPADiGetStatus(chan); + + if (status == WPAD_ERR_OK) { + enable = OSDisableInterrupts(); + getStat = p_wpd->statusReqBusy; + OSRestoreInterrupts(enable); + + if (getStat) { + status = WPAD_ERR_BUSY; + } else { + __SendData(chan, cmd); + } + } else if (status != WPAD_ERR_BUSY) { + if (status == WPAD_ERR_TRANSFER) { + enable = OSDisableInterrupts(); + p_wpd->status = WPAD_ERR_OK; + OSRestoreInterrupts(enable); + } + } else { + t = (int)OSTicksToSeconds(__OSGetSystemTime() - p_wpd->lastReportSendTime); + if (t > 1 && _sleepTime > 0) { + if (p_wpd->cmdTimeoutAction == 0) { + p_wpd->lastReportSendTime = __OSGetSystemTime(); + WPADiDisconnect(chan, TRUE); + } else { + enable = OSDisableInterrupts(); + p_wpd->status = WPAD_ERR_TRANSFER; + OSRestoreInterrupts(enable); + } + } + } + return status; +} + +void WPADiRumbleMotor(s32 chan, BOOL sendCmd) { + WPADCommand cmd; + + if (_wpdcb[chan]->status == WPAD_ERR_NO_CONTROLLER) { + return; + } + + if (sendCmd == TRUE || __wpadGetQueueSize(&_wpdcb[chan]->stdCmdQueue) > 0) { + _wpdcb[chan]->motorBusy = FALSE; + } else if (_rumbleCnt[chan] == 5) { + _wpdcb[chan]->motorBusy = FALSE; + + cmd.command = WPAD_HIDREP_VIBRATOR; + cmd.len = 1; + cmd.data[0] = 0; + cmd.callback = NULL; + + __SendData(chan, cmd); + } + _rumbleCnt[chan] = (u8)((_wpdcb[chan]->motorBusy) ? _rumbleCnt[chan] + 1 : 0); +} + +u32 WPADGetDataFormat(s32 chan) { + WPADControlBlock* p_wpd; + u32 fmt; + BOOL enable = OSDisableInterrupts(); + p_wpd = _wpdcb[chan]; + fmt = p_wpd->dataFormat; + OSRestoreInterrupts(enable); + return fmt; +} + +s32 WPADSetDataFormat(s32 chan, u32 fmt) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + s32 ret; + BOOL busy; + BOOL enable; + BOOL setup; + u32 prevFmt; + + enable = OSDisableInterrupts(); + setup = p_wpd->handshakeFinished; + ret = p_wpd->status; + prevFmt = p_wpd->dataFormat; + OSRestoreInterrupts(enable); + + if (ret != WPAD_ERR_NO_CONTROLLER) { + if (!setup) { + ret = WPAD_ERR_BUSY; + } else if (prevFmt != fmt) { + busy = WPADiSendSetReportType(&p_wpd->stdCmdQueue, fmt, NULL); + if (!busy) { + ret = WPAD_ERR_BUSY; + } else { + enable = OSDisableInterrupts(); + p_wpd->dataFormat = fmt; + OSRestoreInterrupts(enable); + ret = WPAD_ERR_OK; + } + } else { + ret = WPAD_ERR_OK; + } + } + return ret; +} + +void WPADiDisconnect(s32 chan, BOOL polite) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + s32 status; + + status = WPADiGetStatus(chan); + + if (status != WPAD_ERR_NO_CONTROLLER) { + if (polite) { + enable = OSDisableInterrupts(); + if (p_wpd->disconnect) { + OSRestoreInterrupts(enable); + return; + } + p_wpd->disconnect = 1; + OSRestoreInterrupts(enable); + BTA_HhClose(p_wpd->devHandle); + } else { + u8 addr[6]; + WPADGetAddress(chan, addr); + btm_remove_acl(addr); + } + } +} + +s32 WPADGetInfoAsync(s32 chan, WPADInfo* info, WPADCallback callback) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + BOOL setup; + s32 result; + + enable = OSDisableInterrupts(); + setup = p_wpd->handshakeFinished; + result = p_wpd->status; + OSRestoreInterrupts(enable); + + if (result != WPAD_ERR_NO_CONTROLLER) { + if (!setup) { + result = WPAD_ERR_BUSY; + } else { +#if SDK_AUG2010 + if (WPADiSendGetContStat(&p_wpd->stdCmdQueue, info, callback)) { +#else + if (WPADiSendGetContStat(&p_wpd->stdCmdQueue, info, 0, callback)) { +#endif + result = WPAD_ERR_OK; + } else { + result = WPAD_ERR_BUSY; + } + } + } + + return result; +} + +void WPADControlMotor(s32 chan, u32 command) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + BOOL needed = FALSE; + s32 status; + + enable = OSDisableInterrupts(); + status = p_wpd->status; + + if (status == WPAD_ERR_NO_CONTROLLER) { + OSRestoreInterrupts(enable); + return; + } + + if (_rumble == FALSE) { + if (command != WPAD_MOTOR_STOP || p_wpd->motorRunning != TRUE) { + OSRestoreInterrupts(enable); + return; + } + } + + if ((command == WPAD_MOTOR_STOP && p_wpd->motorRunning == FALSE) || (command == WPAD_MOTOR_RUMBLE && p_wpd->motorRunning == TRUE)) { + OSRestoreInterrupts(enable); + return; + } + + p_wpd->motorRunning = (command == WPAD_MOTOR_STOP) ? FALSE : TRUE; + p_wpd->motorBusy = TRUE; + OSRestoreInterrupts(enable); +} + +void WPADEnableMotor(BOOL enable) { + BOOL intr = OSDisableInterrupts(); + _rumble = enable; + OSRestoreInterrupts(intr); +} + +BOOL WPADIsMotorEnabled() { + BOOL result; + BOOL enable = OSDisableInterrupts(); + result = _rumble; + OSRestoreInterrupts(enable); + return result; +} + +s32 WPADControlLed(s32 chan, u8 pattern, WPADCallback callback) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL busy; + BOOL enable; + BOOL setup; + s32 result = WPAD_ERR_OK; + + enable = OSDisableInterrupts(); + result = p_wpd->status; + setup = p_wpd->handshakeFinished; + OSRestoreInterrupts(enable); + + if (result != WPAD_ERR_NO_CONTROLLER) { + if (!setup) { + result = WPAD_ERR_BUSY; + } else { + busy = WPADiSendSetPort(&p_wpd->stdCmdQueue, pattern, callback); + result = (busy) ? WPAD_ERR_OK : WPAD_ERR_BUSY; + } + } + + if (result != WPAD_ERR_OK) { + if (callback) { + callback(chan, result); + } + } + return result; +} + +BOOL WPADSaveConfig(WPADFlushCallback callback) { + BOOL result = TRUE; + BOOL enable; + u8 volume; + u8 mode; + + if (SCCheckStatus() != 0) { + return FALSE; + } + + enable = OSDisableInterrupts(); + volume = _speakerVolume; + mode = (u8)((_rumble) ? 1 : 0); + OSRestoreInterrupts(enable); + + result &= SCSetWpadSpeakerVolume(volume); + result &= SCSetWpadMotorMode(mode); + + if (result) { + SCFlushAsync(callback); + } else if (callback) { + callback(2); + } + return result; +} + +#if SDK_AUG2010 +u32 __wpadFmt2Size(u32 fmt) { u32 fmtSize; switch (fmt) { @@ -65,9 +1883,10 @@ static u32 __wpadFmt2Size(u32 fmt) { return fmtSize; } +#endif u8 WPADGetRadioSensitivity(s32 chan) { - wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan]; + WPADControlBlock* p_wpd = _wpdcb[chan]; BOOL intrStatus = OSDisableInterrupts(); u8 radioSensitivity = p_wpd->radioSensitivity; @@ -75,8 +1894,28 @@ u8 WPADGetRadioSensitivity(s32 chan) { return radioSensitivity; } +BOOL WPADSetAcceptConnection(u8 accept) { + BOOL result = FALSE; + BOOL visible = accept ? TRUE : FALSE; + if (WUDGetStatus() == 3) { + WUDSetVisibility(0, visible); + result = TRUE; + } + + return result; +} + +BOOL WPADGetAcceptConnection(void) { + if ((u8)WUDGetConnectable() == TRUE) { + return TRUE; + } else { + return FALSE; + } +} + +#if SDK_AUG2010 void WPADRead(s32 chan, WPADStatus* status) { - wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan]; + WPADControlBlock* p_wpd = _wpdcb[chan]; BOOL intrStatus; u8 rxBufIndex; WPADStatus* rxStatus; @@ -88,7 +1927,7 @@ void WPADRead(s32 chan, WPADStatus* status) { intrStatus = OSDisableInterrupts(); rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1; - rxStatus = (WPADStatus*)p_wpd->rxBufs[rxBufIndex]; + rxStatus = (WPADStatus*)&p_wpd->rxBufs[rxBufIndex]; fmtSize = __wpadFmt2Size(p_wpd->dataFormat); if (rxStatus->err != WPAD_ESUCCESS) @@ -98,123 +1937,308 @@ void WPADRead(s32 chan, WPADStatus* status) { OSRestoreInterrupts(intrStatus); } +#else +void WPADRead(s32 chan, WPADStatus* status) { + WPADControlBlock* p_wpd; + BOOL intrStatus; + u8 step; + WPADUnkStatus* src; -BOOL WPADIsSpeakerEnabled(s32 chan) { - BOOL enabled; - wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan]; - BOOL intrStatus = OSDisableInterrupts(); + intrStatus = OSDisableInterrupts(); - enabled = p_wpd->info.speaker; + p_wpd = _wpdcb[chan]; + src = &p_wpd->rxBufs[(u8)(p_wpd->rxBufIndex == 0)]; + + if (p_wpd->status == WPAD_ERR_OK) { + if (WPADiIsCoreFormat(p_wpd->dataFormat)) + { + memcpy(status, src, sizeof(WPADStatus)); + } else if (WPADiIsFsFormat(p_wpd->dataFormat)) + { + memcpy(status, src, sizeof(WPADFSStatus)); + } else if (WPADiIsClFormat(p_wpd->dataFormat)) + { + memcpy(status, src, sizeof(WPADCLStatus)); + } else { + memcpy(status, src, 0x5A); + } + } else if (p_wpd->status == WPAD_ERR_BUSY) { + memcpy(status, src, sizeof(WPADStatus)); + } else { + if (WPADiIsCoreFormat(p_wpd->dataFormat)) + { + memset(status, 0, sizeof(WPADStatus)); + } else if (WPADiIsFsFormat(p_wpd->dataFormat)) + { + memset(status, 0, sizeof(WPADFSStatus)); + } else if (WPADiIsClFormat(p_wpd->dataFormat)) + { + memset(status, 0, sizeof(WPADCLStatus)); + } else { + memset(status, 0, 0x5A); + } + + status->err = p_wpd->status; + } OSRestoreInterrupts(intrStatus); - return enabled; +} +#endif + +void WPADiCopyOut(s32 chan) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + WPADUnkStatus* p_data; + u8 index; + u32 size; + + enable = OSDisableInterrupts(); + p_data = &p_wpd->rxBufs[(u8)(p_wpd->rxBufIndex == 0)]; + + if (p_wpd->samplingBufs_ptr) { + p_wpd->samplingBufIndex++; + if (p_wpd->samplingBufIndex >= p_wpd->samplingBufLength) { + p_wpd->samplingBufIndex = 0; + } + + if (WPADiIsCoreFormat(p_wpd->dataFormat)) { + WPADStatus* p_stat = (WPADStatus*)p_wpd->samplingBufs_ptr + p_wpd->samplingBufIndex; + size = sizeof(WPADStatus); + memcpy(p_stat, p_data, size); + } else if (WPADiIsFsFormat(p_wpd->dataFormat)) { + WPADFSStatus* p_stat = (WPADFSStatus*)p_wpd->samplingBufs_ptr + p_wpd->samplingBufIndex; + size = (p_data->base.err == WPAD_ERR_OK) ? sizeof(WPADFSStatus) : sizeof(WPADStatus); + memcpy(p_stat, p_data, size); + } else if (WPADiIsClFormat(p_wpd->dataFormat)) { + WPADCLStatus* p_stat = (WPADCLStatus*)p_wpd->samplingBufs_ptr + p_wpd->samplingBufIndex; + size = (p_data->base.err == WPAD_ERR_OK) ? sizeof(WPADCLStatus) : sizeof(WPADStatus); + memcpy(p_stat, p_data, size); + } else { + WPADStatusEx* p_stat = (WPADStatusEx*)p_wpd->samplingBufs_ptr + p_wpd->samplingBufIndex; + size = (p_data->base.err == WPAD_ERR_OK) ? sizeof(WPADStatusEx) : sizeof(WPADStatus); + memcpy(p_stat, p_data, size); + } + } + if (p_wpd->samplingCallback) { + p_wpd->samplingCallback(chan); + } + + p_wpd->packetCnt++; + OSRestoreInterrupts(enable); } -s32 WPADControlSpeaker(s32 chan, u32 command, WPADCallback cb) { - u8 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->info.speaker; - BOOL handshakeFinished; - s32 status = p_wpd->status; +BOOL WPADIsSpeakerEnabled(s32 chan) { + BOOL state; + BOOL enable; + WPADControlBlock* p_wpd = _wpdcb[chan]; + enable = OSDisableInterrupts(); + state = p_wpd->info.speaker; + OSRestoreInterrupts(enable); + return state; +} - handshakeFinished = p_wpd->handshakeFinished; +BOOL WPADiSendMuteSpeaker(WPADCmdQueue* queue, BOOL enable, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + cmd.command = WPAD_HIDREP_MUTE; + cmd.len = 1; + cmd.data[0] = (u8)((enable) ? (u8)4 : (u8)0); + cmd.callback = callback; + result = __wpadPushCommand(queue, cmd); + return result; +} - OSRestoreInterrupts(intrStatus); +BOOL WPADiSendEnableSpeaker(WPADCmdQueue* queue, BOOL enable, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + cmd.command = WPAD_HIDREP_ENSPK; + cmd.len = 1; + cmd.data[0] = (u8)((enable) ? (u8)4 : (u8)0); + cmd.callback = callback; + result = __wpadPushCommand(queue, cmd); + return result; +} - if (status == WPAD_ENODEV) - goto end; +s32 WPADControlSpeaker(s32 chan, u32 command, WPADCallback callback) { + BOOL enable; + BOOL spk; + BOOL setup; + s32 result; + u8 initCmd[] = {0x00, 0x00, 0xd0, 0x07, 0x40, 0x0c, 0x0e}; + WPADControlBlock* p_wpd = _wpdcb[chan]; - if (!handshakeFinished) { - status = WPAD_EBUSY; - goto end; + enable = OSDisableInterrupts(); + spk = p_wpd->info.speaker; + result = p_wpd->status; + setup = p_wpd->handshakeFinished; + OSRestoreInterrupts(enable); + + if (result != WPAD_ERR_NO_CONTROLLER) { + if (!setup) { + result = WPAD_ERR_BUSY; + } else if (command == 0) { + if (!spk) { + result = WPAD_ERR_OK; + } else { + enable = OSDisableInterrupts(); + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 5)) { + WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, SPK_DERESET, SPK_RST_REG, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, SPK_CLK_OFF, SPK_CLK_REG, NULL); +#if SDK_AUG2010 + WPADiSendEnableSpeaker(&p_wpd->stdCmdQueue, FALSE, NULL); +#else + WPADiSendEnableSpeaker(&p_wpd->stdCmdQueue, FALSE, callback); +#endif +#if SDK_AUG2010 + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, callback); +#else + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, 0, callback); +#endif + OSRestoreInterrupts(enable); + return WPAD_ERR_OK; + } else { + result = WPAD_ERR_BUSY; + } + OSRestoreInterrupts(enable); + } + } else { + switch (command) { + case 1: +#if SDK_AUG2010 + case 5: +#endif + enable = OSDisableInterrupts(); + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 7)) { + WPADiSendEnableSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, SPK_CLK_ON, SPK_CLK_REG, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, SPK_RESET, SPK_RST_REG, NULL); + initCmd[4] = _speakerVolume; +#if SDK_AUG2010 + WPADiSendWriteData(&p_wpd->stdCmdQueue, initCmd, sizeof(initCmd), SPK_RST_REG, NULL); +#else + WPADiSendWriteData(&p_wpd->stdCmdQueue, initCmd, sizeof(initCmd), SPK_RST_REG, callback); +#endif + WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, FALSE, NULL); +#if SDK_AUG2010 + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, callback); +#else + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, 0, NULL); +#endif + OSRestoreInterrupts(enable); + return WPAD_ERR_OK; + } else { + result = WPAD_ERR_BUSY; + } + OSRestoreInterrupts(enable); + break; + + case 2: + if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, callback)) { + result = WPAD_ERR_BUSY; + } else { + return WPAD_ERR_OK; + } + break; + + case 3: + if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, FALSE, callback)) { + result = WPAD_ERR_BUSY; + } else { + return WPAD_ERR_OK; + } + break; + + case 4: + if (!WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, SPK_CTRL_PLAY, SPK_CTRL_REG, callback)) { + result = WPAD_ERR_BUSY; + } else { + return WPAD_ERR_OK; + } + break; + } + } } - if (command == WPAD_SPEAKER_DISABLE) { - if (!speakerEnabled) { - status = WPAD_ESUCCESS; - goto end; - } + if (callback) { + callback(chan, result); + } - intrStatus = OSDisableInterrupts(); + return result; +} - 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); +u8 WPADGetSpeakerVolume() { + BOOL enable; + u8 vol; - OSRestoreInterrupts(intrStatus); + enable = OSDisableInterrupts(); + vol = _speakerVolume; + OSRestoreInterrupts(enable); - return WPAD_ESUCCESS; - } + return vol; +} - status = WPAD_EBUSY; - OSRestoreInterrupts(intrStatus); +void WPADSetSpeakerVolume(u8 volume) { + BOOL enable; + + enable = OSDisableInterrupts(); + _speakerVolume = volume; + OSRestoreInterrupts(enable); +} + +BOOL IsBusyStream(s32 chan) { + BOOL enable; + WPADControlBlock* p_wpd = _wpdcb[chan]; + u8 stop; + u32 devType; + u8 bufNum; + u16 qSize; + u16 notAck; + u8 frames; + s8 cmdNum; + u8 linkNum; + + enable = OSDisableInterrupts(); + stop = p_wpd->radioQuality; + devType = p_wpd->devType; + bufNum = WUDGetBufferStatus(); + cmdNum = __wpadGetQueueSize(&p_wpd->stdCmdQueue); + qSize = __wpadGetBTEBufferStatus(chan); + notAck = __wpadGetBTMBufferStatus(chan); + frames = p_wpd->audioFrames; + linkNum = _WUDGetLinkNumber(); + OSRestoreInterrupts(enable); + + if ((stop) || (notAck > 3) || (bufNum == 10) || (bufNum >= linkNum * 2 + 2) || (devType == WPAD_DEV_INITIALIZING) || + (cmdNum >= WPAD_COMMAND_CMD_MAX_LEN - 3) || (frames >= 1)) { + return TRUE; } 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_EBUSY; - - OSRestoreInterrupts(intrStatus); - break; - case WPAD_SPEAKER_MUTE: - if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, cb)) { - status = WPAD_EBUSY; - goto end; - } - - return WPAD_ESUCCESS; - case WPAD_SPEAKER_UNMUTE: - if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, FALSE, cb)) { - status = WPAD_EBUSY; - goto end; - } - - return WPAD_ESUCCESS; - case WPAD_SPEAKER_PLAY: - if (!WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, WM_REG_SPEAKER_08, cb)) { - status = WPAD_EBUSY; - goto end; - } - - return WPAD_ESUCCESS; - } + return FALSE; } +} -end: - if (cb) - (*cb)(chan, status); +BOOL WPADCanSendStreamData(s32 chan) { + BOOL enable; + BOOL setup; + s32 status; + WPADControlBlock* p_wpd = _wpdcb[chan]; - return status; + enable = OSDisableInterrupts(); + status = p_wpd->status; + setup = p_wpd->handshakeFinished; + OSRestoreInterrupts(enable); + + if ((status == WPAD_ERR_NO_CONTROLLER) || (setup == FALSE) || (IsBusyStream(chan))) { + return FALSE; + } else { + return TRUE; + } } BOOL __wpadIsBusyStream(s32 chan) { BOOL intrStatus; - wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan]; + WPADControlBlock* p_wpd = _wpdcb[chan]; u8 radioQuality; u32 devType; u8 bufferStatus; @@ -250,185 +2274,268 @@ BOOL __wpadIsBusyStream(s32 chan) { } } +BOOL WPADiSendStreamData(WPADCmdQueue* queue, void* p_buf, u16 len) { + WPADCommand cmd; + BOOL result; + u8 length = (u8)(len << 3); + ASSERTLINE(5873, len > 0 && len <= 20); + + cmd.command = WPAD_HIDREP_STRM; + cmd.len = 21; + cmd.data[0] = length; + cmd.callback = NULL; + memcpy(cmd.data + 1, p_buf, len); + result = __wpadPushCommand(queue, cmd); + return result; +} + s32 WPADSendStreamData(s32 chan, void* p_buf, u16 len) { - wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan]; - BOOL intrStatus; - BOOL handshakeFinished; + BOOL busy; + BOOL enable; + BOOL setup; s32 status; + WPADControlBlock* p_wpd = _wpdcb[chan]; ASSERTLINE(4528, p_buf != NULL); ASSERTLINE(4529, len >= 0 && len <= 20); - intrStatus = OSDisableInterrupts(); - + enable = OSDisableInterrupts(); status = p_wpd->status; - handshakeFinished = p_wpd->handshakeFinished; + setup = p_wpd->handshakeFinished; + OSRestoreInterrupts(enable); - OSRestoreInterrupts(intrStatus); - - if (status == WPAD_ENODEV) - return WPAD_ENODEV; - - if (!handshakeFinished) - return WPAD_EBUSY; - - if (__wpadIsBusyStream(chan)) - return WPAD_EBUSY; - - if (!WPADiSendStreamData(&p_wpd->stdCmdQueue, p_buf, len)) - return WPAD_EBUSY; - - intrStatus = OSDisableInterrupts(); - - ++p_wpd->audioFrames; - - OSRestoreInterrupts(intrStatus); - - return WPAD_ESUCCESS; -} - -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; -} - -BOOL WPADiSendGetContStat(struct WPADCmdQueue* cmdQueue, WPADInfo* infoOut, WPADCallback cb) { - BOOL success; - struct WPADCmd cmdBlk; - cmdBlk.reportID = RPTID_REQUEST_STATUS; - cmdBlk.dataLength = RPT15_SIZE; - cmdBlk.dataBuf[0] = 0; - cmdBlk.cmdCB = cb; - cmdBlk.statusReportOut = infoOut; - - 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, void const* p_buf, u16 len, u32 address, - WPADCallback cb) { - BOOL success; - u8 packedLen = len & 0x1f; - struct WPADCmd cmdBlk; - - ASSERTLINE(5830, len > 0 && len <= 16); - ASSERTLINE(5831, p_buf != NULL); - - 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 WPADiSendStreamData(struct WPADCmdQueue* cmdQueue, void const* p_buf, u16 len) { - BOOL success; - u8 packedLen = len << 3; - struct WPADCmd cmdBlk; - - ASSERTLINE(5873, len > 0 && len <= 20); - - 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 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; -} - -static BOOL __wpadPushCommand(struct WPADCmdQueue* cmdQueue, struct WPADCmd cmdBlk) { - BOOL intrStatus = OSDisableInterrupts(); - - if (cmdQueue->length - 1 == (u32)__wpadGetQueueSize(cmdQueue)) { - OSRestoreInterrupts(intrStatus); - - return FALSE; + if (status == WPAD_ERR_NO_CONTROLLER) { + return WPAD_ERR_NO_CONTROLLER; } - memset(&cmdQueue->queue[cmdQueue->indexIn], 0, sizeof cmdQueue->queue[cmdQueue->indexIn]); - memcpy(&cmdQueue->queue[cmdQueue->indexIn], &cmdBlk, sizeof cmdQueue->queue[cmdQueue->indexIn]); + if (!setup) { + return WPAD_ERR_BUSY; + } - cmdQueue->indexIn = (u32)cmdQueue->indexIn == ((cmdQueue->length) - 1) ? 0 : cmdQueue->indexIn + 1; + if (IsBusyStream(chan)) { + return WPAD_ERR_BUSY; + } - OSRestoreInterrupts(intrStatus); - return TRUE; + if (!WPADiSendStreamData(&p_wpd->stdCmdQueue, p_buf, len)) { + return WPAD_ERR_BUSY; + } + enable = OSDisableInterrupts(); + p_wpd->audioFrames++; + OSRestoreInterrupts(enable); + return WPAD_ERR_OK; } -static u16 __wpadGetBTEBufferStatus(s32 chan) { - wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan]; - BOOL intrStatus = OSDisableInterrupts(); - s32 status = p_wpd->status; - s8 dev_handle = p_wpd->devHandle; - - OSRestoreInterrupts(intrStatus); - - if (status == WPAD_ENODEV) - return 0; - - return _WUDGetQueuedSize(dev_handle); +u8 WPADGetDpdSensitivity() { + return _dpdSensitivity; } -static u16 __wpadGetBTMBufferStatus(s32 chan) { - wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan]; - BOOL intrStatus = OSDisableInterrupts(); - s32 status = p_wpd->status; - s8 dev_handle = p_wpd->devHandle; +BOOL WPADIsDpdEnabled(s32 chan) { + BOOL state; + BOOL enable; + WPADControlBlock* p_wpd = _wpdcb[chan]; - OSRestoreInterrupts(intrStatus); - - if (status == WPAD_ENODEV) - return 0; - - return _WUDGetNotAckedSize(dev_handle); + enable = OSDisableInterrupts(); + state = p_wpd->info.dpd; + OSRestoreInterrupts(enable); + return state; +} + +BOOL WPADiSendEnableDPD(WPADCmdQueue* queue, BOOL enable, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + + cmd.command = WPAD_HIDREP_ENDPD; + cmd.len = 1; + cmd.data[0] = (u8)((enable) ? (u8)4 : (u8)0); + cmd.callback = callback; + + return __wpadPushCommand(queue, cmd); +} + +s32 WPADControlDpd(s32 chan, u32 command, WPADCallback callback) { + BOOL enable; + BOOL dpd; + BOOL setup; + s32 result; + WPADControlBlock* p_wpd = _wpdcb[chan]; + + static const u8 cfg1[5][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 u8 cfg2[5][2] = { + 0xfd, 0x05, 0xb3, 0x04, 0x63, 0x03, 0x35, 0x03, + 0x1f, 0x03, + }; + + enable = OSDisableInterrupts(); + dpd = p_wpd->info.dpd; + result = p_wpd->status; + setup = p_wpd->handshakeFinished; + OSRestoreInterrupts(enable); + + if (result != WPAD_ERR_NO_CONTROLLER) { + if (!setup) { + result = WPAD_ERR_BUSY; + } else if (command == 0) { + if (!dpd) { + result = WPAD_ERR_OK; + } else { + enable = OSDisableInterrupts(); + + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 3)) { + WPADiSendEnableDPD(&p_wpd->stdCmdQueue, FALSE, NULL); + WPADiSendDPDCSB(&p_wpd->stdCmdQueue, FALSE, NULL); +#if SDK_AUG2010 + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, callback); +#else + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, 0, callback); +#endif + + OSRestoreInterrupts(enable); + return WPAD_ERR_OK; + } else { + result = WPAD_ERR_BUSY; + } + + OSRestoreInterrupts(enable); + } + } else { + enable = OSDisableInterrupts(); + + if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 8)) { + WPADiSendEnableDPD(&p_wpd->stdCmdQueue, TRUE, NULL); + WPADiSendDPDCSB(&p_wpd->stdCmdQueue, TRUE, NULL); +#if SDK_AUG2010 + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, NULL); +#else + WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, WM_REG_DPD_30, NULL); +#endif + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 1, WM_REG_DPD_30, NULL); + WPADiSendWriteData(&p_wpd->stdCmdQueue, (void*)cfg1[_dpdSensitivity - 1], 9, + WM_REG_DPD_CONFIG_BLOCK_1, NULL); + WPADiSendWriteData(&p_wpd->stdCmdQueue, (void*)cfg2[_dpdSensitivity - 1], 2, + WM_REG_DPD_CONFIG_BLOCK_2, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, (u8)command, + WM_REG_DPD_DATA_FORMAT, NULL); + WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 8, WM_REG_DPD_30, callback); + + OSRestoreInterrupts(enable); + return WPAD_ERR_OK; + } else { + result = WPAD_ERR_BUSY; + } + OSRestoreInterrupts(enable); + } + } + + if (callback) { + callback(chan, result); + } + + return result; +} + +BOOL WPADiSendSetReportType(WPADCmdQueue* queue, u32 fmt, WPADCallback callback) { + WPADCommand cmd; + BOOL result; + + cmd.command = WPAD_HIDREP_REPTYPE; + cmd.len = 2; + cmd.data[0] = 4; + cmd.callback = callback; + + switch (fmt) { + case WPAD_FMT_CORE_BTN: + cmd.data[1] = RPTID_DATA_BTN; + break; + case WPAD_FMT_CORE_BTN_ACC: + cmd.data[1] = RPTID_DATA_BTN_ACC; + break; + case WPAD_FMT_CORE_BTN_ACC_DPD: + cmd.data[1] = RPTID_DATA_BTN_ACC_DPD12; + break; + case WPAD_FMT_FS_BTN: + cmd.data[1] = RPTID_DATA_BTN_EXT8; + break; + case WPAD_FMT_FS_BTN_ACC: + cmd.data[1] = RPTID_DATA_BTN_ACC_EXT16; + break; + case WPAD_FMT_FS_BTN_ACC_DPD: + cmd.data[1] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + case WPAD_FMT_CLASSIC_BTN: + cmd.data[1] = RPTID_DATA_BTN_EXT8; + break; + case WPAD_FMT_CLASSIC_BTN_ACC: + cmd.data[1] = RPTID_DATA_BTN_ACC_EXT16; + break; + case WPAD_FMT_CLASSIC_BTN_ACC_DPD: + cmd.data[1] = RPTID_DATA_BTN_ACC_DPD10_EXT9; + break; + case WPAD_FMT_BTN_ACC_DPD_EXTENDED: + cmd.data[1] = RPTID_DATA_BTN_ACC_DPD18_1; + break; + } + + return __wpadPushCommand(queue, cmd); +} + +void WPADGetAddress(s32 chan, u8* addr) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + BOOL enable; + s8 handle; + u8* devAddr; + + enable = OSDisableInterrupts(); + handle = p_wpd->devHandle; + OSRestoreInterrupts(enable); + + devAddr = _WUDGetDevAddr((u8)handle); + + if (devAddr) { + memcpy(addr, devAddr, 6); + } else { + memset(addr, 0, 6); + } +} + +void WPADShutdown() { + return; +} + +void __WPADShutdown() { + BOOL enable; + int i; + + enable = OSDisableInterrupts(); + + if (_shutdown) { + OSRestoreInterrupts(enable); + return; + } + + _shutdown = 1; + WUDSetVisibility(0, 0); + + for (i = 10; i < 14; i++) { + memset(&_scArray.info[i], 0, sizeof(SCBtDeviceInfoSingle)); + } + + WPADiShutdown(FALSE); + OSRestoreInterrupts(enable); +} + +void WPADiShutdown(BOOL exec) { + OSCancelAlarm(&_managerAlarm); + WUDSetHidRecvCallback(NULL); + WUDShutdown(exec); +} + +BOOL WPADCancelSyncDevice() { + return WUDCancelSyncDevice(); } diff --git a/src/revolution/wpad/WPADEncrypt.c b/src/revolution/wpad/WPADEncrypt.c new file mode 100644 index 0000000000..9852cc6162 --- /dev/null +++ b/src/revolution/wpad/WPADEncrypt.c @@ -0,0 +1,265 @@ +#include + +#include "cstring" + +static u8 SEED; +static u8 NUM_A; +static u8 NUM_B; +static u8 NUM_C; + +static u8 base[0x2A] = { + 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 u8 tb[0x900] = { + 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, +}; + +static u8 random() { + SEED = (u8)(((u32)SEED * NUM_A + NUM_B) % NUM_C); + return SEED; +} + +static u8 ror(u8 src, u8 rot) { + u8 ret; + u8 rt; + + rt = (u8)(rot % 8); + ret = (u8)(src >> rt | src << (8 - rt)); + + return ret; +} + +static u8 rol(u8 src, u8 rol) { + u8 ret; + u8 rl; + + rl = (u8)(rol % 8); + ret = (u8)(src << rl | src >> (8 - rl)); + + return ret; +} + +void WPADiCreateKey(s32 chan) { + BOOL enable; + WPADControlBlock* p_wpd = _wpdcb[chan]; + + u8 idx; + u8 baseIdx; + u8 tblRnd[10]; + u8 ft[8]; + u8 sb[8]; + u8 key[6]; + u8 i; + + SEED = (u8)((OSGetTick() >> 8) & 0xff); + NUM_A = (u8)((OSGetTick() >> 16) & 0x3f); + NUM_B = (u8)((OSGetTick() >> 24) & 0x4c); + NUM_C = 0xff; + + idx = (u8)(random() % 7); + baseIdx = (u8)(idx * 6); + + for (i = 0; i < 10; i++) { + tblRnd[i] = tb[random()]; + } + + enable = OSDisableInterrupts(); + key[0] = (u8)((ror((u8)(base[baseIdx] ^ tb[tblRnd[5]]), tb[tblRnd[2]]) - tb[tblRnd[9]]) ^ tb[tblRnd[4]]); + key[1] = (u8)((ror((u8)(base[baseIdx + 1] ^ tb[tblRnd[1]]), tb[tblRnd[0]]) - tb[tblRnd[5]]) ^ tb[tblRnd[7]]); + key[2] = (u8)((ror((u8)(base[baseIdx + 2] ^ tb[tblRnd[6]]), tb[tblRnd[8]]) - tb[tblRnd[2]]) ^ tb[tblRnd[0]]); + key[3] = (u8)((ror((u8)(base[baseIdx + 3] ^ tb[tblRnd[4]]), tb[tblRnd[7]]) - tb[tblRnd[3]]) ^ tb[tblRnd[2]]); + key[4] = (u8)((ror((u8)(base[baseIdx + 4] ^ tb[tblRnd[1]]), tb[tblRnd[6]]) - tb[tblRnd[3]]) ^ tb[tblRnd[4]]); + key[5] = (u8)((ror((u8)(base[baseIdx + 5] ^ tb[tblRnd[7]]), tb[tblRnd[8]]) - tb[tblRnd[5]]) ^ tb[tblRnd[9]]); + + ft[0] = (u8)(tb[(idx + 1) * 256 + key[4]] ^ tb[(idx + 2) * 256 + tblRnd[3]]); + ft[1] = (u8)(tb[(idx + 1) * 256 + key[2]] ^ tb[(idx + 2) * 256 + tblRnd[5]]); + ft[2] = (u8)(tb[(idx + 1) * 256 + key[5]] ^ tb[(idx + 2) * 256 + tblRnd[7]]); + ft[3] = (u8)(tb[(idx + 1) * 256 + key[0]] ^ tb[(idx + 2) * 256 + tblRnd[2]]); + ft[4] = (u8)(tb[(idx + 1) * 256 + key[1]] ^ tb[(idx + 2) * 256 + tblRnd[4]]); + ft[5] = (u8)(tb[(idx + 1) * 256 + key[3]] ^ tb[(idx + 2) * 256 + tblRnd[9]]); + ft[6] = (u8)(tb[(idx + 1) * 256 + tblRnd[0]] ^ tb[(idx + 2) * 256 + tblRnd[6]]); + ft[7] = (u8)(tb[(idx + 1) * 256 + tblRnd[1]] ^ tb[(idx + 2) * 256 + tblRnd[8]]); + sb[0] = (u8)(tb[(idx + 1) * 256 + key[0]] ^ tb[(idx + 2) * 256 + tblRnd[1]]); + sb[1] = (u8)(tb[(idx + 1) * 256 + key[5]] ^ tb[(idx + 2) * 256 + tblRnd[4]]); + sb[2] = (u8)(tb[(idx + 1) * 256 + key[3]] ^ tb[(idx + 2) * 256 + tblRnd[0]]); + sb[3] = (u8)(tb[(idx + 1) * 256 + key[2]] ^ tb[(idx + 2) * 256 + tblRnd[9]]); + sb[4] = (u8)(tb[(idx + 1) * 256 + key[4]] ^ tb[(idx + 2) * 256 + tblRnd[7]]); + sb[5] = (u8)(tb[(idx + 1) * 256 + key[1]] ^ tb[(idx + 2) * 256 + tblRnd[8]]); + sb[6] = (u8)(tb[(idx + 1) * 256 + tblRnd[3]] ^ tb[(idx + 2) * 256 + tblRnd[5]]); + sb[7] = (u8)(tb[(idx + 1) * 256 + tblRnd[2]] ^ tb[(idx + 2) * 256 + tblRnd[6]]); + + for (i = 0; i < 10; i++) { + p_wpd->key[i] = tblRnd[9 - i]; + } + + for (i = 0; i < 6; i++) { + p_wpd->key[i + 10] = key[5 - i]; + } + + memcpy(p_wpd->ft, ft, 8); + memcpy(p_wpd->sb, sb, 8); + OSRestoreInterrupts(enable); +} + +void WPADiDecode(s32 chan, void* p_buf, u16 len, u16 offset) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + u8 idx; + u8* ptr; + u16 i; + + ptr = (u8*)p_buf; + + for (i = 0; i < len; i++) { + idx = (u8)((offset + i) % 8); + ptr[i] = (u8)((ptr[i] ^ p_wpd->sb[idx]) + p_wpd->ft[idx]); + } +} diff --git a/src/revolution/wpad/WPADHIDParser.c b/src/revolution/wpad/WPADHIDParser.c new file mode 100644 index 0000000000..4b8b774b7c --- /dev/null +++ b/src/revolution/wpad/WPADHIDParser.c @@ -0,0 +1,1667 @@ +#include +#include +#include + +extern void DEBUGPrint(const char*, ...); + +void __a1_20_status_report(u8 chan, u8* data); +void __a1_21_user_data(u8 chan, u8* data); +void __a1_22_ack(u8 chan, u8* data); +void __a1_30_data_type(u8 chan, u8* data); +void __a1_31_data_type(u8 chan, u8* data); +void __a1_32_data_type(u8 chan, u8* data); +void __a1_33_data_type(u8 chan, u8* data); +void __a1_34_data_type(u8 chan, u8* data); +void __a1_35_data_type(u8 chan, u8* data); +void __a1_36_data_type(u8 chan, u8* data); +void __a1_37_data_type(u8 chan, u8* data); +void __a1_3d_data_type(u8 chan, u8* data); +void __a1_3e_data_type(u8 chan, u8* data); +void __a1_3f_data_type(u8 chan, u8* data); +void __a1_unused_report(u8 chan, u8* data); + +#define HID_WPAD_BUTTON_MASK (u16)(0x9F1F) +#define HID_WPAD_BUTTON_CLEAR (u16)(0x60E0) +#define HID_NEAREMPTY_MASK (u8)(0x80) +#define HID_DPD_MASK (u8)(0x8) +#define HID_SPEAKER_MASK (u8)(0x4) +#define HID_ATTACH_MASK (u8)(0x2) +#define HID_LOWBAT_MASK (u8)(0x1) +#define HID_LED_MASK (u8)(0xF0) +#define HID_FW_MASK (u8)(0xF0) +#define HID_PRT_MASK (u8)(0xF) + +#define HID_IDX_BYTE7 1 +#define HID_IDX_BYTE8 2 +#define HID_IDX_BYTE9 3 +#define HID_IDX_BYTE10 4 +#define HID_IDX_BYTE11 5 +#define HID_IDX_BYTE12 6 +#define HID_IDX_BYTE13 7 +#define HID_IDX_BYTE14 8 +#define HID_IDX_BYTE15 9 +#define HID_IDX_BYTE16 10 +#define HID_IDX_BYTE17 11 +#define HID_IDX_BYTE18 12 +#define HID_IDX_BYTE19 13 +#define HID_IDX_BYTE20 14 +#define HID_IDX_BYTE21 15 +#define HID_IDX_BYTE22 16 +#define HID_IDX_BYTE23 17 +#define HID_IDX_BYTE24 18 +#define HID_IDX_BYTE25 19 +#define HID_IDX_BYTE26 20 +#define HID_IDX_BYTE27 21 + +void (*__a1_input_reports_array[])(u8 chan, u8* data) = { + __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 +}; + +static u8 checkInvalidData[21] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, +}; +static u8 checkBuffer[21]; + +WPADExtensionCallback initExtension(s32 chan, WPADControlBlock*); + +void abortInitExtension(s32 chan, s32 result) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + u32 type; + + if (result != WPAD_ERR_OK) { + WPADiClearQueue(&p_wpd->extCmdQueue); + + if (result == WPAD_ERR_NO_CONTROLLER) { + type = WPAD_DEV_NONE; + } else if (p_wpd->info.attach) { + type = WPAD_DEV_NOT_SUPPORTED; + } else { + type = WPAD_DEV_CORE; + } + + p_wpd->devType = (u8)type; + if (p_wpd->extensionCallback) { + p_wpd->extensionCallback(chan, (s32)type); + } + } +} + +#define PI 3.141592f + +// Copied from Petari - this is likely close to the correct implementation, +// but loop unrolling is not happening so it ends up completely mismatching. +// Not sure if it's supposed to be manually unrolled in code? But then the +// bit-twiddling instructions end up mismatching. +static inline void __parse_dpd_data(s32 chan, WPADStatus** p_status, u8 fmt, u8* p_data, u8 len) { + u8 i; + u8 x; + u8 y; + u8 xy; + + if (fmt == WPAD_DPD_STANDARD) { + for (i = 0; i < WPAD_DPD_MAX_OBJECTS; ++i) { + if (i * 3 + 2 < len) { + x = *(p_data + i * 3); + y = *(p_data + i * 3 + 1); + xy = *(p_data + i * 3 + 2); + + (*p_status)->obj[i].x = (s16)((s16)((s16)(((u16)x) & 0xFF) | (u16)(((u16)xy & 0x30) << 4))); + (*p_status)->obj[i].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)y) & 0xFF) | (u16)(((u16)xy & 0xC0) << 2))); + (*p_status)->obj[i].size = (u16)(((xy & 0xF) & 0xFF)); + (*p_status)->obj[i].size = (u8)((f32)((*p_status)->obj[i].size) * (f32)((*p_status)->obj[i].size) * PI); + if ((*p_status)->obj[i].size == 0 || (*p_status)->obj[i].x == (s16)(WPAD_DPD_IMG_RESO_WX - 1) || + (*p_status)->obj[i].y == (s16)(WPAD_DPD_IMG_RESO_WY - 1)) { + (*p_status)->obj[i].x = (s16)0; + (*p_status)->obj[i].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1); + (*p_status)->obj[i].size = 0; + } + (*p_status)->obj[i].traceId = i; + } else { + (*p_status)->obj[i].x = (s16)0; + (*p_status)->obj[i].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1); + (*p_status)->obj[i].size = 0; + (*p_status)->obj[i].traceId = i; + } + } + } else if (fmt == WPAD_DPD_BASIC) { + for (i = 0; i < WPAD_DPD_MAX_OBJECTS; ++i) { + x = *(p_data + i * 3 - (i / 2)); + y = *(p_data + i * 3 - (i / 2) + 1); + xy = *(p_data + (i / 2) * 5 + 2); + + if ((i % 2) == 0) { + (*p_status)->obj[i].x = (s16)((s16)((s16)(((u16)x) & 0xFF) | (u16)(((u16)(xy & 0x30)) << 4))); + (*p_status)->obj[i].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)y) & 0xFF) | (u16)(((u16)(xy & 0xC0)) << 2))); + } else { + (*p_status)->obj[i].x = (s16)((s16)((s16)(((u16)x) & 0xFF) | (u16)(((u16)(xy & (u8)(0x30 >> 4))) << 8))); + (*p_status)->obj[i].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)y) & 0xFF) | (u16)(((u16)(xy & (u8)(0xC0 >> 4))) << 6))); + } + if ((*p_status)->obj[i].x == (s16)(WPAD_DPD_IMG_RESO_WX - 1) || (*p_status)->obj[i].y == (s16)(WPAD_DPD_IMG_RESO_WY - 1)) { + (*p_status)->obj[i].x = (s16)0; + (*p_status)->obj[i].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1); + (*p_status)->obj[i].size = 0; + } else { + (*p_status)->obj[i].size = 12; + } + (*p_status)->obj[i].traceId = i; + } + } +} + +void getDevConfig(s32 chan, s32 result, WPADStatus* p_status, u8* data) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + u8* p_buf = p_wpd->wmReadDataPtr; + u8 checkSum; + u8 i; + int j; + int index; + DPDObject obj[WPAD_DPD_MAX_OBJECTS]; + const s16 dummyObjX[] = {0x7F, 0x7F, 0x380, 0x380}; + const s16 dummyObjY[] = {0x5D, 0x2A2, 0x2A2, 0x5D}; + + for (i = 0; i < WPAD_DPD_MAX_OBJECTS; i++) { + p_wpd->devConf.obj[i].x = dummyObjX[i]; + p_wpd->devConf.obj[i].y = dummyObjY[i]; + p_wpd->devConf.obj[i].size = (u16)p_wpd->dpdDummyObjSize; + p_wpd->devConf.obj[i].traceId = i; + } + + p_wpd->devConf.acc_0g.x = 530; + p_wpd->devConf.acc_0g.y = 530; + p_wpd->devConf.acc_0g.z = 530; + p_wpd->devConf.acc_1g.x = 636; + p_wpd->devConf.acc_1g.y = 636; + p_wpd->devConf.acc_1g.z = 636; + p_wpd->devConf.volume = 0; + p_wpd->devConf.motor = 0; + + if (result != WPAD_ERR_OK) { + return; + } + + if (!p_wpd->oldFw) { + for (i = 0; i < 2; i++) { + checkSum = 0; + index = i * (11); + for (j = index; j < index + 10; j++) { + checkSum += p_buf[j]; + } + checkSum = (u8)(checkSum + 0x55); + + if (checkSum == p_buf[index + 10]) { + DEBUGPrint("Dpd Setting is ok.\n"); + + __parse_dpd_data(chan, &p_status, WPAD_DPD_BASIC, p_buf, index + 11); + + obj[0].x = (s16)((s16)((u16)p_buf[index] & 0xFF) | + (u16)((u16)(p_buf[index + 2] & 0x30) << 4)); + obj[0].y = + (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)(p_buf[index + 1])) & 0xFF) | (u16)(((u16)(p_buf[index + 2] & 0xC0)) << 2))); + obj[0].size = p_wpd->dpdDummyObjSize; + obj[0].traceId = 0; + + obj[1].x = (s16)((s16)((u16)p_buf[index + 3] & 0xFF) | + (u16)((u16)(p_buf[index + 2] & (u8)(0x30 >> 4)) << 8)); + obj[1].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1 - + (s16)((s16)(((u16)(p_buf[index + 4])) & 0xFF) | (u16)(((u16)(p_buf[index + 2] & (u8)(0xC0 >> 4))) << 6))); + obj[1].size = p_wpd->dpdDummyObjSize; + obj[1].traceId = 1; + + obj[2].x = (s16)((s16)((u16)p_buf[index + 5] & 0xFF) | + (u16)((u16)(p_buf[index + 7] & 0x30) << 4)); + obj[2].y = + (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)(p_buf[index + 6])) & 0xFF) | (u16)(((u16)(p_buf[index + 7] & 0xC0)) << 2))); + obj[2].size = p_wpd->dpdDummyObjSize; + obj[2].traceId = 2; + + obj[3].x = (s16)((s16)((u16)p_buf[index + 8] & 0xFF) | + (u16)((u16)(p_buf[index + 7] & (u8)(0x30 >> 4)) << 8)); + obj[3].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1 - + (s16)((s16)(((u16)(p_buf[index + 9])) & 0xFF) | (u16)(((u16)(p_buf[index + 7] & (u8)(0xC0 >> 4))) << 6))); + obj[3].size = p_wpd->dpdDummyObjSize; + obj[3].traceId = 3; + + break; + } else { + DEBUGPrint("Dpd Setting is broken.\n"); + } + } + } else { + DEBUGPrint("Old Firmware uses default values because it has no Dpd Setting.\n"); + } + + for (i = 0; i < 2; i++) { + checkSum = 0; + + index = i * (10); + if (!p_wpd->oldFw) { + index += 22; + } + + for (j = index; j < index + 9; j++) { + checkSum += p_buf[j]; + } + checkSum = (u8)(checkSum + 0x55); + if (checkSum == p_buf[index + 9]) { + DEBUGPrint("Acc is ok.\n"); + p_wpd->devConf.acc_0g.x = (s16)((u16)(((u16)(p_buf[index + 0]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 3]) >> 4) & 3)); + p_wpd->devConf.acc_0g.y = (s16)((u16)(((u16)(p_buf[index + 1]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 3]) >> 2) & 3)); + p_wpd->devConf.acc_0g.z = (s16)((u16)(((u16)(p_buf[index + 2]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 3])) & 3)); + p_wpd->devConf.acc_1g.x = (s16)((u16)(((u16)(p_buf[index + 4]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 7]) >> 4) & 3)); + p_wpd->devConf.acc_1g.y = (s16)((u16)(((u16)(p_buf[index + 5]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 7]) >> 2) & 3)); + p_wpd->devConf.acc_1g.z = (s16)((u16)(((u16)(p_buf[index + 6]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 7])) & 3)); + p_wpd->devConf.volume = (u8)(p_buf[index + 8] & (u8)0x7F); + p_wpd->devConf.motor = (u8)(p_buf[index + 8] & (u8)0x80); + break; + } else { + DEBUGPrint("Acc is broken.\n"); + } + } + DEBUGPrint("0G: accX = %d, accY = %d, accZ = %d\n", p_wpd->devConf.acc_0g.x, p_wpd->devConf.acc_0g.y, p_wpd->devConf.acc_0g.z); + DEBUGPrint("1G: accX = %d, accY = %d, accZ = %d\n", p_wpd->devConf.acc_1g.x, p_wpd->devConf.acc_1g.y, p_wpd->devConf.acc_1g.z); + DEBUGPrint("Volume: %d, Motor: %d\n", p_wpd->devConf.volume, p_wpd->devConf.motor); +} + +void getExtConfig(s32 chan, s32 result) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + u8* p_buf = p_wpd->wmReadDataPtr; + int i, j, k; + int index = -1; + int checksum; + + if (result != WPAD_ERR_OK) { + p_wpd->devType = WPAD_DEV_NOT_SUPPORTED; + } else if (p_wpd->devType == WPAD_DEV_FS || p_wpd->devType == WPAD_DEV_CLASSIC) { + WPADiDecode(chan, p_buf, 0x20, 0x20); + + for (i = 0; i < 2; i++) { + checksum = 0; + k = i * 16; + for (j = k; j < k + 14; j++) { + checksum += p_buf[j]; + } + + if (((u8)(checksum + 0x55) == p_buf[k + 14]) && ((u8)(checksum + 0xaa) == p_buf[k + 15])) { + index = k; + } + } + + switch (p_wpd->devType) { + case WPAD_DEV_FS: + if (index < 0) { + DEBUGPrint("check sum error.\n"); + p_wpd->extConf.fs.acc_0g.x = 512; + p_wpd->extConf.fs.acc_0g.y = 512; + p_wpd->extConf.fs.acc_0g.z = 512; + p_wpd->extConf.fs.acc_1g.x = 716; + p_wpd->extConf.fs.acc_1g.y = 716; + p_wpd->extConf.fs.acc_1g.z = 716; + } else { + p_wpd->extConf.fs.acc_0g.x = (s16)((u16)(((u16)(p_buf[index + 0]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 3]) >> 4) & 3)); + p_wpd->extConf.fs.acc_0g.y = (s16)((u16)(((u16)(p_buf[index + 1]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 3]) >> 2) & 3)); + p_wpd->extConf.fs.acc_0g.z = (s16)((u16)(((u16)(p_buf[index + 2]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 3])) & 3)); + p_wpd->extConf.fs.acc_1g.x = (s16)((u16)(((u16)(p_buf[index + 4]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 7]) >> 4) & 3)); + p_wpd->extConf.fs.acc_1g.y = (s16)((u16)(((u16)(p_buf[index + 5]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 7]) >> 2) & 3)); + p_wpd->extConf.fs.acc_1g.z = (s16)((u16)(((u16)(p_buf[index + 6]) << 2) & 0xFFFC) | (u16)(((u16)(p_buf[index + 7])) & 3)); + p_wpd->extConf.fs.stick.x_max = (s8)p_buf[index + 8]; + p_wpd->extConf.fs.stick.x_min = (s8)p_buf[index + 9]; + p_wpd->extConf.fs.stick.x = (s8)p_buf[index + 10]; + p_wpd->extConf.fs.stick.y_max = (s8)p_buf[index + 11]; + p_wpd->extConf.fs.stick.y_min = (s8)p_buf[index + 12]; + p_wpd->extConf.fs.stick.y = (s8)p_buf[index + 13]; + + DEBUGPrint("0G: fsaccX = %d, fsaccY = %d, fsaccZ = %d\n", p_wpd->extConf.fs.acc_0g.x, p_wpd->extConf.fs.acc_0g.y, + p_wpd->extConf.fs.acc_0g.z); + DEBUGPrint("1G: fsaccX = %d, fsaccY = %d, fsaccZ = %d\n", p_wpd->extConf.fs.acc_1g.x, p_wpd->extConf.fs.acc_1g.y, + p_wpd->extConf.fs.acc_1g.z); + DEBUGPrint("FS: X = %d, X max = %d, X min = %d\n", p_wpd->extConf.fs.stick.x, p_wpd->extConf.fs.stick.x_max, + p_wpd->extConf.fs.stick.x_min); + DEBUGPrint("FS: Y = %d, Y max = %d, Y min = %d\n", p_wpd->extConf.fs.stick.y, p_wpd->extConf.fs.stick.y_max, + p_wpd->extConf.fs.stick.y_min); + } + break; + + case WPAD_DEV_CLASSIC: + p_wpd->extConf.cl.lstk.x_max = (s8)p_buf[index + 0]; + p_wpd->extConf.cl.lstk.x_min = (s8)p_buf[index + 1]; + p_wpd->extConf.cl.lstk.x = (s8)p_buf[index + 2]; + p_wpd->extConf.cl.lstk.y_max = (s8)p_buf[index + 3]; + p_wpd->extConf.cl.lstk.y_min = (s8)p_buf[index + 4]; + p_wpd->extConf.cl.lstk.y = (s8)p_buf[index + 5]; + p_wpd->extConf.cl.rstk.x_max = (s8)p_buf[index + 6]; + p_wpd->extConf.cl.rstk.x_min = (s8)p_buf[index + 7]; + p_wpd->extConf.cl.rstk.x = (s8)p_buf[index + 8]; + p_wpd->extConf.cl.rstk.y_max = (s8)p_buf[index + 9]; + p_wpd->extConf.cl.rstk.y_min = (s8)p_buf[index + 10]; + p_wpd->extConf.cl.rstk.y = (s8)p_buf[index + 11]; + p_wpd->extConf.cl.triggerL = p_buf[index + 12]; + p_wpd->extConf.cl.triggerR = p_buf[index + 13]; + + DEBUGPrint("CL: X = %d, X max = %d, X min = %d\n", p_wpd->extConf.cl.lstk.x, p_wpd->extConf.cl.lstk.x_max, + p_wpd->extConf.cl.lstk.x_min); + DEBUGPrint("CL: Y = %d, Y max = %d, Y min = %d\n", p_wpd->extConf.cl.lstk.y, p_wpd->extConf.cl.lstk.y_max, + p_wpd->extConf.cl.lstk.y_min); + DEBUGPrint("CR: X = %d, X max = %d, X min = %d\n", p_wpd->extConf.cl.rstk.x, p_wpd->extConf.cl.rstk.x_max, + p_wpd->extConf.cl.rstk.x_min); + DEBUGPrint("CR: Y = %d, Y max = %d, Y min = %d\n", p_wpd->extConf.cl.rstk.y, p_wpd->extConf.cl.rstk.y_max, + p_wpd->extConf.cl.rstk.y_min); + DEBUGPrint("LR: L = %d, R = %d\n", p_wpd->extConf.cl.triggerL, p_wpd->extConf.cl.triggerR); + break; + } + p_wpd->calibrated = 0; + } + + if (p_wpd->cmdBlkCallback) { + p_wpd->cmdBlkCallback(chan, p_wpd->devType); + p_wpd->cmdBlkCallback = NULL; + } +} + +static BOOL isExtEncMain(u8 type) { + if (type == WPAD_DEV_FS || type == WPAD_DEV_CLASSIC) { + return TRUE; + } else { + return FALSE; + } +} + +extern BOOL __OSInIPL; + +void getExtType(s32 chan, s32 result) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + WPADCmdQueue* cmdq = &p_wpd->extCmdQueue; + u8* p_buf = (u8*)p_wpd->wmReadDataPtr; + + if (result == WPAD_ERR_OK) { + WPADiDecode(chan, p_buf, 2, 0xfe); + + p_wpd->devMode = p_buf[0]; + + switch (p_buf[1]) { + case 0x00: + p_wpd->devType = WPAD_DEV_FS; + break; + case 0x01: + p_wpd->devType = WPAD_DEV_CLASSIC; + break; + default: + p_wpd->devType = WPAD_DEV_FUTURE; + break; + } + + //_devCmpt[chan] = 0; + //_devMode[chan] = p_buf[4]; + if (p_wpd->devType == WPAD_DEV_CLASSIC) { + if (p_wpd->devMode < 1 || p_wpd->devMode > 3) { + p_wpd->devType = WPAD_DEV_NOT_SUPPORTED; + } + } + + DEBUGPrint("type : %d\n", p_wpd->devType); + DEBUGPrint("mode : %d\n", p_wpd->devMode); + } else { + p_wpd->devType = WPAD_DEV_NOT_SUPPORTED; + p_wpd->devMode = 0; + } +} + +void getGameInfo(s32 chan, s32 result, u8 index) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + WPADMEMGameInfo* p_info = p_wpd->wmReadDataPtr; + u8* p_buf = p_wpd->wmReadDataPtr; + int i; + u8 sum = 0; + + if (result == WPAD_ERR_OK) { + for (i = 0; i < 47; i++) { + sum += p_buf[i]; + } + sum += 0x55; + + if (p_info->checkSum == sum) { + memcpy(&p_wpd->gameInfo, p_buf, sizeof(WPADMEMGameInfo)); + p_wpd->gameInfoErr[index] = WPAD_ERR_OK; + } else { + p_wpd->gameInfoErr[index] = WPAD_ERR_INVALID; + } + } +} + +WPADExtensionCallback initExtension(s32 chan, WPADControlBlock* p_wpd) { + WPADCmdQueue* cmdQueue = &p_wpd->extCmdQueue; + WPADExtensionCallback extCallback = p_wpd->extensionCallback; + + WPADiSendSetReportType(cmdQueue, p_wpd->dataFormat, NULL); + WPADiSendWriteDataCmd(cmdQueue, 0xAA, WM_REG_EXTENSION_F0, abortInitExtension); + + WPADiCreateKey(chan); + WPADiSendWriteData(cmdQueue, p_wpd->key, 6, WM_REG_EXTENSION_40, abortInitExtension); + WPADiSendWriteData(cmdQueue, p_wpd->key + 6, 6, WM_REG_EXTENSION_46, abortInitExtension); + WPADiSendWriteData(cmdQueue, p_wpd->key + 12, 4, WM_REG_EXTENSION_4C, abortInitExtension); + + WPADiSendReadData(cmdQueue, p_wpd->wmReadDataBuf, 2, WM_REG_EXTENSION_DEV_MODE, abortInitExtension); + WPADiSendReadData(cmdQueue, p_wpd->wmReadDataBuf, 0x20, WM_REG_EXTENSION_CONFIG, extCallback); + + return extCallback; +} + +s32 WPADiHIDParser(u8 chan, u8* data) { + int enable; + s32 ret = 0; + + if ((data[0] >= 0x20) && (data[0] <= 0x3F)) { + enable = OSDisableInterrupts(); + (*(__a1_input_reports_array[data[0] - 0x20]))(chan, data); + OSRestoreInterrupts(enable); + WPADiExcludeButton(chan); + WPADiCopyOut(chan); + } else { + ret = -1; + } + + return ret; +} + +void __a1_20_status_report(u8 chan, u8* data) { + WPADControlBlock* p_wpd; + BOOL enable; + BOOL attach; + WPADStatus* p_status; + WPADExtensionCallback extcb; + u8* p_clear; + int i; + WPADCmdQueue* cmdQueue; + + DEBUGPrint("Received report 20\n"); + + enable = OSDisableInterrupts(); + p_wpd = _wpdcb[chan]; + + if (!p_wpd->handshakeFinished) { + OSRestoreInterrupts(enable); + return; + } + + p_status = (WPADStatus*)&p_wpd->rxBufs[p_wpd->rxBufIndex]; + p_clear = (u8*)p_status; + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + attach = p_wpd->info.attach; + + p_status->button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & + HID_WPAD_BUTTON_MASK); + p_wpd->info.nearempty = (u8)((data[HID_IDX_BYTE7] & HID_NEAREMPTY_MASK) >> 7); + p_wpd->info.dpd = (data[HID_IDX_BYTE9] & HID_DPD_MASK) >> 3; + p_wpd->info.speaker = (data[HID_IDX_BYTE9] & HID_SPEAKER_MASK) >> 2; + + p_wpd->info.attach = (data[HID_IDX_BYTE9] & HID_ATTACH_MASK) >> 1; + p_wpd->info.lowBat = data[HID_IDX_BYTE9] & HID_LOWBAT_MASK; + p_wpd->info.led = (u8)((data[HID_IDX_BYTE9] & HID_LED_MASK) >> 4); + p_wpd->info.protocol = (u8)((data[HID_IDX_BYTE11] & HID_PRT_MASK) >> 4); + p_wpd->info.firmware = (u8)(data[HID_IDX_BYTE11] & HID_FW_MASK); + + if (data[HID_IDX_BYTE12] >= 0x55) { + p_wpd->info.battery = WPAD_BATTERY_LEVEL_MAX; + } else if (data[HID_IDX_BYTE12] >= 0x44) { + p_wpd->info.battery = WPAD_BATTERY_LEVEL_HIGH; + } else if (data[HID_IDX_BYTE12] >= 0x33) { + p_wpd->info.battery = WPAD_BATTERY_LEVEL_MEDIUM; + } else if (data[HID_IDX_BYTE12] >= 0x3) { + p_wpd->info.battery = WPAD_BATTERY_LEVEL_LOW; + } else { + p_wpd->info.battery = WPAD_BATTERY_LEVEL_CRITICAL; + } + + if (p_wpd->info.attach) { + if (!attach) { + DEBUGPrint("initialize attachment\n"); + + extcb = initExtension(chan, p_wpd); + + cmdQueue = &p_wpd->extCmdQueue; + + p_wpd->calibrated = 0; + p_wpd->devType = WPAD_DEV_INITIALIZING; + p_wpd->devMode = 0; + + if (extcb) { + extcb(chan, WPAD_DEV_INITIALIZING); + } + } else { + DEBUGPrint("already initialized\n"); + } + } else { + p_wpd->devType = WPAD_DEV_CORE; + p_wpd->devMode = 0; + + if (attach) { + WPADiClearQueue(&p_wpd->extCmdQueue); + WPADiSendSetReportType(&p_wpd->stdCmdQueue, p_wpd->dataFormat, NULL); + + if (p_wpd->extensionCallback) { + p_wpd->extensionCallback(chan, WPAD_DEV_CORE); + } + } else { + DEBUGPrint("already disconnected\n"); + } + } + + if (p_wpd->infoOut) { + memcpy(p_wpd->infoOut, &p_wpd->info, sizeof(WPADInfo)); + p_wpd->infoOut = NULL; + } + + if (p_wpd->cmdBlkCallback && p_wpd->statusReqBusy) { + p_wpd->cmdBlkCallback(chan, WPAD_ERR_OK); + p_wpd->cmdBlkCallback = NULL; + } + + p_status->err = WPAD_ERR_BUSY; + p_status->dev = p_wpd->devType; + p_wpd->statusReqBusy = 0; + p_wpd->rxBufIndex = (u8)((p_wpd->rxBufIndex) ? 0 : 1); + + OSRestoreInterrupts(enable); +} + +void __a1_21_user_data(u8 chan, u8* data) { + WPADControlBlock* p_wpd; + BOOL enable; + WPADStatus* p_status; + u8* p_clear; + u16 addr; + u16 base; + u16 i2c; + u8 err; + u8 len; + s16 offset; + int i; + s32 status; + + enable = OSDisableInterrupts(); + p_wpd = _wpdcb[chan]; + p_status = (WPADStatus*)(p_wpd->rxBufs + p_wpd->rxBufIndex); + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & + HID_WPAD_BUTTON_MASK); + + err = (u8)(data[HID_IDX_BYTE9] & 0x0f); + len = (u8)(((u8)(data[HID_IDX_BYTE9] >> 4) & 0x0f) + 1); + addr = (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE10]) << 8) & (u16)0xFF00) | (u16)((u16)(data[HID_IDX_BYTE11]) & (u16)0xFF)); + + if (err != 0) { + DEBUGPrint("read error happens!\n"); + p_wpd->wmReadErr = -1; + + if (p_wpd->cmdBlkCallback) { + p_wpd->cmdBlkCallback(chan, WPAD_ERR_TRANSFER); + p_wpd->cmdBlkCallback = NULL; + } + p_wpd->status = WPAD_ERR_OK; + } + + base = (u16)(p_wpd->wmReadAddr & 0xFFFF); + i2c = (u16)((p_wpd->wmReadAddr & 0xFFFF0000) >> 16); + offset = (s16)(addr - base); + + if (addr >= base && addr <= base + p_wpd->wmReadLength) { + memcpy((u8*)p_wpd->wmReadDataPtr + offset, data + HID_IDX_BYTE12, len); + + if (base + p_wpd->wmReadLength == addr + len) { + DEBUGPrint("base addr: %08x\n", p_wpd->wmReadAddr); + DEBUGPrint("length : %d\n", p_wpd->wmReadLength); + status = p_wpd->wmReadErr < 0 ? WPAD_CETRANSFER : WPAD_CESUCCESS; + + if ((p_wpd->wmReadAddr == 0 && p_wpd->oldFw == FALSE) || + (p_wpd->wmReadAddr == WM_ADDR_MEM_176C && p_wpd->oldFw == TRUE)) { + getDevConfig(chan, status, p_status, data); + } + if (p_wpd->wmReadAddr == WM_REG_EXTENSION_CONFIG) { + getExtConfig(chan, status); + } + if (p_wpd->wmReadAddr == WM_REG_EXTENSION_DEV_MODE) { + getExtType(chan, status); + } + if (p_wpd->wmReadAddr == 0x2A) { + getGameInfo(chan, status, 0); + } + if (p_wpd->wmReadAddr == 0x2A + sizeof(WPADMEMGameInfo)) { + getGameInfo(chan, status, 1); + } + + if (p_wpd->cmdBlkCallback) { + p_wpd->cmdBlkCallback(chan, status); + p_wpd->cmdBlkCallback = NULL; + } + p_wpd->status = WPAD_ERR_OK; + } + } else { + DEBUGPrint("received data is out of range!\n"); + } + + p_status->err = WPAD_ERR_BUSY; + p_status->dev = p_wpd->devType; + + p_wpd->rxBufIndex = (u8)((p_wpd->rxBufIndex) ? 0 : 1); + + OSRestoreInterrupts(enable); +} + +void __a1_22_ack(u8 chan, u8* data) { + WPADControlBlock* p_wpd = _wpdcb[chan]; + u8 type; + u8 err; + BOOL enable; + WPADStatus* p_status; + u8* p_clear; + s32 status; + int i; + + enable = OSDisableInterrupts(); + + DEBUGPrint("Received ack!\n"); + + p_wpd = _wpdcb[chan]; + p_status = (WPADStatus*)(p_wpd->rxBufs + p_wpd->rxBufIndex); + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & (u16)HID_WPAD_BUTTON_MASK); + + type = data[HID_IDX_BYTE9]; + err = data[HID_IDX_BYTE10]; + + DEBUGPrint("ack --> report ID = %02x, error code = %d\n", type, err); + + status = err == 0 ? WPAD_CESUCCESS : WPAD_CETRANSFER; + p_status->err = WPAD_ERR_BUSY; + p_status->dev = p_wpd->devType; + + if (err != 0) { + DEBUGPrint("ack error --> report ID = %d, error code = %d\n", type, err); + } + + if (p_wpd->lastReportId == type) { + if (p_wpd->cmdBlkCallback) { + p_wpd->cmdBlkCallback(chan, status); + p_wpd->cmdBlkCallback = NULL; + } + p_wpd->status = WPAD_ERR_OK; + } else { + DEBUGPrint("invalid ack!\n"); + } + p_wpd->rxBufIndex = (u8)((p_wpd->rxBufIndex) ? 0 : 1); + + OSRestoreInterrupts(enable); +} + +void __a1_30_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatus* p_status; + u8* p_clear; + + int old; + int i; + + old = OSDisableInterrupts(); + p_cb = _wpdcb[chan]; + p_status = (WPADStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)data[HID_IDX_BYTE7] & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & + HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN) { + p_status->err = p_cb->status; + } else if (p_cb->status == 0) { + p_status->err = WPAD_ERR_INVALID; + } + + p_status->dev = p_cb->devType; + p_cb->info.nearempty = (u8)((data[HID_IDX_BYTE7] & HID_NEAREMPTY_MASK) >> 7); + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + OSRestoreInterrupts(old); +} + +void __a1_31_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatus* p_status; + u8* p_clear; + int old, i; + + p_cb = _wpdcb[chan]; + p_status = (WPADStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)data[HID_IDX_BYTE7] & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & + HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN || p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC) { + p_status->err = p_cb->status; + } else if (p_cb->status == 0) { + p_status->err = WPAD_ERR_INVALID; + } + + p_status->dev = p_cb->devType; + p_cb->info.nearempty = (u8)((data[HID_IDX_BYTE7] & HID_NEAREMPTY_MASK) >> 7); + p_status->accX = (s16)((s16)((s16)((s16)((s16)data[HID_IDX_BYTE9] << 2) & (s16)0xFFFC) | + (s16)((s16)(u16)(data[HID_IDX_BYTE7] >> 5) & (s16)0x0003)) - + p_cb->devConf.acc_0g.x); + p_status->accY = (s16)((s16)((s16)((s16)((s16)data[HID_IDX_BYTE10] << 2) & (s16)0xFFFC) | + (s16)((s16)(u16)(data[HID_IDX_BYTE8] >> 4) & (s16)0x0002)) - + p_cb->devConf.acc_0g.y); + p_status->accZ = (s16)((s16)((s16)((s16)((s16)data[HID_IDX_BYTE11] << 2) & (s16)0xFFFC) | + (s16)((s16)(u16)(data[HID_IDX_BYTE8] >> 5) & (s16)0x0002)) - + p_cb->devConf.acc_0g.z); + old = OSDisableInterrupts(); + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + OSRestoreInterrupts(old); +} + +void __a1_32_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatus* p_status; + WPADFSStatus* p_fsStat; + WPADCLStatus* p_clStat; + u8* p_clear; + int old, i; + s16 x, y; + old = OSDisableInterrupts(); + p_cb = _wpdcb[chan]; + p_status = (WPADStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & (u16)HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN || p_cb->dataFormat == WPAD_FMT_FS_BTN || p_cb->dataFormat == WPAD_FMT_CLASSIC_BTN) { + p_status->err = p_cb->status; + } else if (p_cb->status == 0) { + p_status->err = WPAD_ERR_INVALID; + } + + p_status->dev = p_cb->devType; + p_cb->info.nearempty = (u8)((data[HID_IDX_BYTE7] & HID_NEAREMPTY_MASK) >> 7); + + memcpy(checkBuffer, data + HID_IDX_BYTE9, 8); + WPADiDecode(chan, data + HID_IDX_BYTE9, 8, 0); + + if (p_cb->info.attach) { + if (p_cb->devType == WPAD_DEV_FS) { + p_fsStat = (WPADFSStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_fsStat->fsStickX = (s8)(data[HID_IDX_BYTE9]); + p_fsStat->fsStickY = (s8)(data[HID_IDX_BYTE10]); + p_fsStat->fsAccX = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE11]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE14] >> 2) & (s16)(0x0003))) - + p_cb->extConf.fs.acc_0g.x); + p_fsStat->fsAccY = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE12]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE14] >> 4) & (s16)(0x0003))) - + p_cb->extConf.fs.acc_0g.y); + p_fsStat->fsAccZ = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE13]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE14] >> 6) & (s16)(0x0003))) - + p_cb->extConf.fs.acc_0g.z); + + p_fsStat->base.button |= (u16)(((u16)(~data[HID_IDX_BYTE14]) << 13) & (u16)0x6000); + + if (!p_cb->calibrated) { + p_cb->calibrated = 1; + p_cb->extConf.fs.stick.x = p_fsStat->fsStickX; + p_cb->extConf.fs.stick.y = p_fsStat->fsStickY; + } + + x = (s16)((u8)p_fsStat->fsStickX - (u8)p_cb->extConf.fs.stick.x); + y = (s16)((u8)p_fsStat->fsStickY - (u8)p_cb->extConf.fs.stick.y); + + if (x < -128) { + p_fsStat->fsStickX = -128; + } else if (x > 127) { + p_fsStat->fsStickX = 127; + } else { + p_fsStat->fsStickX = (s8)x; + } + + if (y < -128) { + p_fsStat->fsStickY = -128; + } else if (y > 127) { + p_fsStat->fsStickY = 127; + } else { + p_fsStat->fsStickY = (s8)y; + } + } else if (p_cb->devType == WPAD_DEV_CLASSIC) { + switch (p_cb->devMode) { + case 1: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_clStat->clLStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE9]) & (s16)0x003F) << 4)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE10]) & (s16)0x003F) << 4)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE9]) >> 3) & (s16)0x0018) | + (s16)((s16)((s16)(data[HID_IDX_BYTE10]) >> 5) & (s16)0x0006) | + (s16)((s16)((s16)(data[HID_IDX_BYTE11]) >> 7) & (s16)0x0001)) + << 5) - + (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE11]) & (s16)0x001F) << 5) - (s16)(1024 / 2)); + p_clStat->clTriggerL = + (u8)((u8)((u8)((u8)(data[HID_IDX_BYTE11] >> 2) & (u8)0x18) | (u8)((u8)(data[HID_IDX_BYTE12] >> 5) & (u8)0x07)) << 3); + p_clStat->clTriggerR = (u8)((u8)(data[HID_IDX_BYTE12] & (u8)0x1F) << 3); + + p_clStat->clButton = + (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE13]) << 8) & (u16)0xFF00 | (u16)(data[HID_IDX_BYTE14]) & (u16)0xFF) ^ 0xFFFF); + break; + + case 2: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clStat->clLStickX = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE9]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE13])) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE10]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE13]) >> 2) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE11]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE13]) >> 4) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE12]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE13]) >> 6) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clTriggerL = (u8)(data[HID_IDX_BYTE14]); + p_clStat->clTriggerR = (u8)(data[HID_IDX_BYTE15]); + + p_clStat->clButton = + (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE16]) << 8) & (u16)0xFF00 | (u16)(data[HID_IDX_BYTE17]) & (u16)0xFF) ^ 0xFFFF); + break; + + case 3: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_clStat->clLStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE9]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE10]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE11]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE12]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clTriggerL = (u8)(data[HID_IDX_BYTE13]); + p_clStat->clTriggerR = (u8)(data[HID_IDX_BYTE14]); + + p_clStat->clButton = + (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE15]) << 8) & (u16)0xFF00 | (u16)(data[HID_IDX_BYTE16]) & (u16)0xFF) ^ 0xFFFF); + break; + } + + if (!p_cb->calibrated) { + p_cb->calibrated = 1; + p_cb->extConf.cl.lstk.x = p_clStat->clLStickX; + p_cb->extConf.cl.lstk.y = p_clStat->clLStickY; + p_cb->extConf.cl.rstk.x = p_clStat->clRStickX; + p_cb->extConf.cl.rstk.y = p_clStat->clRStickY; + p_cb->extConf.cl.triggerL = p_clStat->clTriggerL; + p_cb->extConf.cl.triggerR = p_clStat->clTriggerR; + } + + x = (s16)(p_clStat->clLStickX - p_cb->extConf.cl.lstk.x); + y = (s16)(p_clStat->clLStickY - p_cb->extConf.cl.lstk.y); + + if (x < -0x400) { + p_clStat->clLStickX = -0x400; + } else if (x > 0x3FF) { + p_clStat->clLStickX = 0x3FF; + } else { + p_clStat->clLStickX = x; + } + + if (y < -0x400) { + p_clStat->clLStickY = -0x400; + } else if (y > 0x3FF) { + p_clStat->clLStickY = 0x3FF; + } else { + p_clStat->clLStickY = y; + } + + x = (s16)(p_clStat->clRStickX - p_cb->extConf.cl.rstk.x); + y = (s16)(p_clStat->clRStickY - p_cb->extConf.cl.rstk.y); + + if (x < -0x400) { + p_clStat->clRStickX = -0x400; + } else if (x > 0x3FF) { + p_clStat->clRStickX = 0x3FF; + } else { + p_clStat->clRStickX = x; + } + + if (y < -0x400) { + p_clStat->clRStickY = -0x400; + } else if (y > 0x3FF) { + p_clStat->clRStickY = 0x3FF; + } else { + p_clStat->clRStickY = y; + } + + x = (s16)((u8)p_clStat->clTriggerL - (u8)p_cb->extConf.cl.triggerL); + y = (s16)((u8)p_clStat->clTriggerR - (u8)p_cb->extConf.cl.triggerR); + + if (x < 0) { + p_clStat->clTriggerL = 0; + } else { + p_clStat->clTriggerL = p_clStat->clTriggerL = (u8)x; + } + + if (y < 0) { + p_clStat->clTriggerR = 0; + } else { + p_clStat->clTriggerR = p_clStat->clTriggerR = (u8)y; + } + } + + if (!memcmp(checkBuffer, checkInvalidData, 7)) { + if (p_status->err == WPAD_ERR_OK) { + p_status->err = WPAD_ERR_CORRUPTED; + } + } + } + + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + OSRestoreInterrupts(old); +} + +void __a1_33_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatus* p_status; + u8* p_clear; + int old, i; + + p_cb = _wpdcb[chan]; + p_status = (WPADStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clear = (u8*)(p_status); + + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & (u16)HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN || p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC || p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC_DPD) { + p_status->err = WPAD_ERR_OK; + } else { + p_status->err = WPAD_ERR_INVALID; + } + + p_status->dev = p_cb->devType; + p_cb->info.nearempty = (u8)((data[HID_IDX_BYTE7] & HID_NEAREMPTY_MASK) >> 7); + p_status->accX = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE9]) << 2) & (s16)0xFFFC) | + (s16)((s16)((u16)(data[HID_IDX_BYTE7] >> 5)) & (s16)0x0003))) - + (s16)(p_cb->devConf.acc_0g.x)); + p_status->accY = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE10]) << 2) & (s16)0xFFFC) | + (s16)((s16)((u16)(data[HID_IDX_BYTE8] >> 4)) & (s16)0x0002))) - + (s16)(p_cb->devConf.acc_0g.y)); + p_status->accZ = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE11]) << 2) & (s16)0xFFFC) | + (s16)((s16)((u16)(data[HID_IDX_BYTE8] >> 5)) & (s16)0x0002))) - + (s16)(p_cb->devConf.acc_0g.z)); + + __parse_dpd_data(chan, &p_status, WPAD_DPD_STANDARD, data, 0); + + old = OSDisableInterrupts(); + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + OSRestoreInterrupts(old); +} + +void __a1_34_data_type(u8 chan, u8* data) { + // empty function +} + +void __a1_35_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatus* p_status; + WPADFSStatus* p_fsStat; + WPADCLStatus* p_clStat; + u8* p_clear; + int old, i; + s16 x, y; + p_cb = _wpdcb[chan]; + p_status = (WPADStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & (u16)HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN || p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC || p_cb->dataFormat == WPAD_FMT_FS_BTN || + p_cb->dataFormat == WPAD_FMT_FS_BTN_ACC || p_cb->dataFormat == WPAD_FMT_CLASSIC_BTN || p_cb->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC) { + p_status->err = p_cb->status; + } else if (p_cb->status != 0) { + p_status->err = WPAD_ERR_INVALID; + } + + p_status->dev = p_cb->devType; + p_cb->info.nearempty = (u8)((data[HID_IDX_BYTE7] & HID_NEAREMPTY_MASK) >> 7); + p_status->accX = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE9]) << 2) & (s16)0xFFFC) | + (s16)((s16)((u16)(data[HID_IDX_BYTE7] >> 5)) & (s16)0x0003))) - + (s16)(p_cb->devConf.acc_0g.x)); + p_status->accY = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE10]) << 2) & (s16)0xFFFC) | + (s16)((s16)((u16)(data[HID_IDX_BYTE8] >> 4)) & (s16)0x0002))) - + (s16)(p_cb->devConf.acc_0g.y)); + p_status->accZ = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE11]) << 2) & (s16)0xFFFC) | + (s16)((s16)((u16)(data[HID_IDX_BYTE8] >> 5)) & (s16)0x0002))) - + (s16)(p_cb->devConf.acc_0g.z)); + + memcpy(checkBuffer, data + HID_IDX_BYTE12, 16); + WPADiDecode(chan, data + HID_IDX_BYTE12, 16, 0); + + if (p_cb->info.attach) { + if (p_cb->devType == WPAD_DEV_FS) { + p_fsStat = (WPADFSStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_fsStat->fsStickX = (s8)(data[HID_IDX_BYTE12]); + p_fsStat->fsStickY = (s8)(data[HID_IDX_BYTE13]); + p_fsStat->fsAccX = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE14]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE17] >> 2) & (s16)(0x0003))) - + (s16)(p_cb->extConf.fs.acc_0g.x)); + p_fsStat->fsAccY = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE15]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE17] >> 4) & (s16)(0x0003))) - + (s16)(p_cb->extConf.fs.acc_0g.y)); + p_fsStat->fsAccZ = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE16]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE17] >> 6) & (s16)(0x0003))) - + (s16)(p_cb->extConf.fs.acc_0g.z)); + + p_fsStat->base.button |= (u16)(((u16)(~data[HID_IDX_BYTE17]) << 13) & (u16)0x6000); + + if (!p_cb->calibrated) { + p_cb->calibrated = 1; + p_cb->extConf.fs.stick.x = p_fsStat->fsStickX; + p_cb->extConf.fs.stick.y = p_fsStat->fsStickY; + } + + x = (s16)((u8)p_fsStat->fsStickX - (u8)p_cb->extConf.fs.stick.x); + y = (s16)((u8)p_fsStat->fsStickY - (u8)p_cb->extConf.fs.stick.y); + + if (x < -128) { + p_fsStat->fsStickX = -128; + } else if (x > 127) { + p_fsStat->fsStickX = 127; + } else { + p_fsStat->fsStickX = (s8)x; + } + + if (y < -128) { + p_fsStat->fsStickY = -128; + } else if (y > 127) { + p_fsStat->fsStickY = 127; + } else { + p_fsStat->fsStickY = (s8)y; + } + } else if (p_cb->devType == WPAD_DEV_CLASSIC) { + switch (p_cb->devMode) { + case 1: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clStat->clLStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE12]) & (s16)0x003F) << 4) - (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE13]) & (s16)0x003F) << 4) - (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE12]) >> 3) & (s16)0x0018) | + (s16)((s16)((s16)(data[HID_IDX_BYTE13]) >> 5) & (s16)0x0006) | + (s16)((s16)((s16)(data[HID_IDX_BYTE14]) >> 7) & (s16)0x0001)) + << 5) - + (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE14]) & (s16)0x001F) << 5) - (s16)(1024 / 2)); + p_clStat->clTriggerL = + (u8)((u8)((u8)((u8)(data[HID_IDX_BYTE14] >> 2) & (u8)0x18) | (u8)((u8)(data[HID_IDX_BYTE15] >> 5) & (u8)0x07)) << 3); + p_clStat->clTriggerR = (u8)((u8)((u8)(data[HID_IDX_BYTE15]) & (u8)0x1F) << 3); + + p_clStat->clButton = + (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE16]) << 8) & (u16)0xFF00 | (u16)(data[HID_IDX_BYTE17]) & (u16)0xFF) ^ 0xFFFF); + break; + + case 2: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clStat->clLStickX = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE12]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE16])) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE13]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE16]) >> 2) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE14]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE16]) >> 4) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE15]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE16]) >> 6) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clTriggerL = (u8)(data[HID_IDX_BYTE17]); + p_clStat->clTriggerR = (u8)(data[HID_IDX_BYTE18]); + + p_clStat->clButton = + (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE19]) << 8) & (u16)0xFF00 | (u16)(data[HID_IDX_BYTE20]) & (u16)0xFF) ^ 0xFFFF); + break; + + case 3: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_clStat->clLStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE12]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE13]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE14]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE15]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clTriggerL = (u8)(data[HID_IDX_BYTE16]); + p_clStat->clTriggerR = (u8)(data[HID_IDX_BYTE17]); + + p_clStat->clButton = + (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE18]) << 8) & (u16)0xFF00 | (u16)(data[HID_IDX_BYTE19]) & (u16)0xFF) ^ 0xFFFF); + break; + } + + if (!p_cb->calibrated) { + p_cb->calibrated = 1; + p_cb->extConf.cl.lstk.x = p_clStat->clLStickX; + p_cb->extConf.cl.lstk.y = p_clStat->clLStickY; + p_cb->extConf.cl.rstk.x = p_clStat->clRStickX; + p_cb->extConf.cl.rstk.y = p_clStat->clRStickY; + p_cb->extConf.cl.triggerL = p_clStat->clTriggerL; + p_cb->extConf.cl.triggerR = p_clStat->clTriggerR; + } + + x = (s16)(p_clStat->clLStickX - p_cb->extConf.cl.lstk.x); + y = (s16)(p_clStat->clLStickY - p_cb->extConf.cl.lstk.y); + + if (x < -0x400) { + p_clStat->clLStickX = -0x400; + } else if (x > 0x3FF) { + p_clStat->clLStickX = 0x3FF; + } else { + p_clStat->clLStickX = x; + } + + if (y < -0x400) { + p_clStat->clLStickY = -0x400; + } else if (y > 0x3FF) { + p_clStat->clLStickY = 0x3FF; + } else { + p_clStat->clLStickY = y; + } + + x = (s16)(p_clStat->clRStickX - p_cb->extConf.cl.rstk.x); + y = (s16)(p_clStat->clRStickY - p_cb->extConf.cl.rstk.y); + + if (x < -0x400) { + p_clStat->clRStickX = -0x400; + } else if (x > 0x3FF) { + p_clStat->clRStickX = 0x3FF; + } else { + p_clStat->clRStickX = x; + } + + if (y < -0x400) { + p_clStat->clRStickY = -0x400; + } else if (y > 0x3FF) { + p_clStat->clRStickY = 0x3FF; + } else { + p_clStat->clRStickY = y; + } + + x = (s16)(p_clStat->clTriggerL - p_cb->extConf.cl.triggerL); + y = (s16)(p_clStat->clTriggerR - p_cb->extConf.cl.triggerR); + + if (x < 0) { + p_clStat->clTriggerL = 0; + } else { + p_clStat->clTriggerL = p_clStat->clTriggerL = (u8)x; + } + + if (y < 0) { + p_clStat->clTriggerR = 0; + } else { + p_clStat->clTriggerR = p_clStat->clTriggerR = (u8)y; + } + } + + if (!memcmp(checkBuffer, checkInvalidData, 16)) { + if (p_status->err == WPAD_ERR_OK) { + p_status->err = WPAD_ERR_CORRUPTED; + } + } + } + + old = OSDisableInterrupts(); + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + OSRestoreInterrupts(old); +} + +void __a1_36_data_type(u8 chan, u8* data) { + // empty function +} + +void __a1_37_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatus* p_status; + WPADFSStatus* p_fsStat; + WPADCLStatus* p_clStat; + u8* p_clear; + int old, i; + s16 x, y; + s16 temp_r0; + p_cb = _wpdcb[chan]; + p_status = (WPADStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clear = (u8*)(p_status); + + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + + p_status->button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & (u16)HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN || p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC || p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC_DPD || + p_cb->dataFormat == WPAD_FMT_FS_BTN || p_cb->dataFormat == WPAD_FMT_FS_BTN_ACC || p_cb->dataFormat == WPAD_FMT_FS_BTN_ACC_DPD || + p_cb->dataFormat == WPAD_FMT_CLASSIC_BTN || p_cb->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC || p_cb->dataFormat == WPAD_FMT_CLASSIC_BTN_ACC_DPD) { + p_status->err = p_cb->status; + } else if (p_cb->status == 0) { + p_status->err = WPAD_ERR_INVALID; + } + + p_status->dev = p_cb->devType; + p_cb->info.nearempty = (u8)((data[HID_IDX_BYTE7] & HID_NEAREMPTY_MASK) >> 7); + p_status->accX = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE9]) << 2) & (s16)0xFFFC) | + (s16)((s16)((u16)(data[HID_IDX_BYTE7] >> 5)) & (s16)0x0003))) - + p_cb->devConf.acc_0g.x); + p_status->accY = (s16)((s16)((s16)((s16)((s16)data[HID_IDX_BYTE10] << 2) & (s16)0xFFFC) | + (s16)((s16)(u16)(data[HID_IDX_BYTE8] >> 4) & (s16)0x0002)) - + p_cb->devConf.acc_0g.y); + p_status->accZ = (s16)((s16)((s16)((s16)((s16)data[HID_IDX_BYTE11] << 2) & (s16)0xFFFC) | + (s16)((s16)(u16)(data[HID_IDX_BYTE8] >> 5) & (s16)0x0002)) - + p_cb->devConf.acc_0g.z); + + __parse_dpd_data(chan, &p_status, WPAD_DPD_STANDARD, data, 0); + + memcpy(checkBuffer, data + HID_IDX_BYTE22, 6); + WPADiDecode(chan, data + HID_IDX_BYTE22, 6, 0); + + if (p_cb->info.attach) { + if (p_cb->devType == WPAD_DEV_FS) { + p_fsStat = (WPADFSStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_fsStat->fsStickX = (s8)(data[HID_IDX_BYTE22]); + p_fsStat->fsStickY = (s8)(data[HID_IDX_BYTE23]); + p_fsStat->fsAccX = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE24]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE27] >> 2) & (s16)(0x0003))) - + p_cb->extConf.fs.acc_0g.x); + p_fsStat->fsAccY = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE25]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE27] >> 4) & (s16)(0x0003))) - + p_cb->extConf.fs.acc_0g.y); + p_fsStat->fsAccZ = + (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE26]) << 2) & (s16)0xFFFC) | (s16)((s16)(data[HID_IDX_BYTE27] >> 6) & (s16)(0x0003))) - + p_cb->extConf.fs.acc_0g.z); + + p_fsStat->base.button |= (u16)(((u16)(~data[HID_IDX_BYTE27]) << 13) & (u16)0x6000); + + if (!p_cb->calibrated) { + p_cb->calibrated = 1; + p_cb->extConf.fs.stick.x = p_fsStat->fsStickX; + p_cb->extConf.fs.stick.y = p_fsStat->fsStickY; + } + + x = (s16)((u8)p_fsStat->fsStickX - (u8)p_cb->extConf.fs.stick.x); + y = (s16)((u8)p_fsStat->fsStickY - (u8)p_cb->extConf.fs.stick.y); + + if (x < -128) { + p_fsStat->fsStickX = -128; + } else if (x > 127) { + p_fsStat->fsStickX = 127; + } else { + p_fsStat->fsStickX = (s8)x; + } + + if (y < -128) { + p_fsStat->fsStickY = -128; + } else if (y > 127) { + p_fsStat->fsStickY = 127; + } else { + p_fsStat->fsStickY = (s8)y; + } + } else if (p_cb->devType == WPAD_DEV_CLASSIC) { + switch (p_cb->devMode) { + case 1: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clStat->clLStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE22]) & (s16)0x003F) << 4) - (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE23]) & (s16)0x003F) << 4) - (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE22]) >> 3) & (s16)0x0018) | + (s16)((s16)((s16)(data[HID_IDX_BYTE23]) >> 5) & (s16)0x0006) | + (s16)((s16)((s16)(data[HID_IDX_BYTE24]) >> 7) & (s16)0x0001)) + << 5) - + (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE24]) & (s16)0x001F) << 5) - (s16)(1024 / 2)); + p_clStat->clTriggerL = + (u8)((u8)((u8)((u8)(data[HID_IDX_BYTE24] >> 2) & (u8)0x18) | (u8)((u8)(data[HID_IDX_BYTE25] >> 5) & (u8)0x07)) << 3); + p_clStat->clTriggerR = (u8)((u8)((u8)(data[HID_IDX_BYTE25]) & (u8)0x1F) << 3); + + p_clStat->clButton = + (u16)((u16)((u16)((u16)(data[HID_IDX_BYTE26]) << 8) & (u16)0xFF00 | (u16)(data[HID_IDX_BYTE27]) & (u16)0xFF) ^ 0xFFFF); + break; + + case 2: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + p_clStat->clLStickX = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE22]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE26])) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE23]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE26]) >> 2) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE24]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE26]) >> 4) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)((s16)(data[HID_IDX_BYTE25]) << 2) & (s16)0xFFFC) | + (s16)((s16)((s16)(data[HID_IDX_BYTE26]) >> 6) & (s16)0x0003)) - + (s16)(1024 / 2)); + p_clStat->clTriggerL = (u8)(data[HID_IDX_BYTE27]); + p_clStat->clTriggerR = (u8)0; + + p_clStat->clButton = (u16)0; + break; + + case 3: + p_clStat = (WPADCLStatus*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + p_clStat->clLStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE22]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clRStickX = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE23]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clLStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE24]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clRStickY = (s16)((s16)((s16)((s16)(data[HID_IDX_BYTE25]) & (s16)0xFF) << 2) - (s16)(1024 / 2)); + p_clStat->clTriggerL = (u8)(data[HID_IDX_BYTE26]); + p_clStat->clTriggerR = (u8)(data[HID_IDX_BYTE27]); + + p_clStat->clButton = (u16)0; + break; + } + + if (!p_cb->calibrated) { + p_cb->calibrated = 1; + p_cb->extConf.cl.lstk.x = p_clStat->clLStickX; + p_cb->extConf.cl.lstk.y = p_clStat->clLStickY; + p_cb->extConf.cl.rstk.x = p_clStat->clRStickX; + p_cb->extConf.cl.rstk.y = p_clStat->clRStickY; + p_cb->extConf.cl.triggerL = p_clStat->clTriggerL; + p_cb->extConf.cl.triggerR = p_clStat->clTriggerR; + } + + x = (s16)(p_clStat->clLStickX - p_cb->extConf.cl.lstk.x); + y = (s16)(p_clStat->clLStickY - p_cb->extConf.cl.lstk.y); + + if (x < -0x400) { + p_clStat->clLStickX = -0x400; + } else if (x > 0x3FF) { + p_clStat->clLStickX = 0x3FF; + } else { + p_clStat->clLStickX = x; + } + + if (y < -0x400) { + p_clStat->clLStickY = -0x400; + } else if (y > 0x3FF) { + p_clStat->clLStickY = 0x3FF; + } else { + p_clStat->clLStickY = y; + } + + x = (s16)(p_clStat->clRStickX - p_cb->extConf.cl.rstk.x); + y = (s16)(p_clStat->clRStickY - p_cb->extConf.cl.rstk.y); + + if (x < -0x400) { + p_clStat->clRStickX = -0x400; + } else if (x > 0x3FF) { + p_clStat->clRStickX = 0x3FF; + } else { + p_clStat->clRStickX = x; + } + + if (y < -0x400) { + p_clStat->clRStickY = -0x400; + } else if (y > 0x3FF) { + p_clStat->clRStickY = 0x3FF; + } else { + p_clStat->clRStickY = y; + } + + x = (s16)(p_clStat->clTriggerL - p_cb->extConf.cl.triggerL); + y = (s16)(p_clStat->clTriggerR - p_cb->extConf.cl.triggerR); + + if (x < 0) { + p_clStat->clTriggerL = 0; + } else { + p_clStat->clTriggerL = p_clStat->clTriggerL = (u8)x; + } + + if (y < 0) { + p_clStat->clTriggerR = 0; + } else { + p_clStat->clTriggerR = p_clStat->clTriggerR = (u8)y; + } + } + + if (!memcmp(checkBuffer, checkInvalidData, 6)) { + if (p_status->err == WPAD_ERR_OK) { + p_status->err = WPAD_ERR_CORRUPTED; + } + } + } + + old = OSDisableInterrupts(); + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + OSRestoreInterrupts(old); +} +void __a1_3d_data_type(u8 chan, u8* data) {} + +u8 _recv_3e[WPAD_MAX_CONTROLLERS] = {0, 0, 0, 0}; +u8 _recv_3f[WPAD_MAX_CONTROLLERS] = {0, 0, 0, 0}; + +void __a1_3e_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatusEx* p_status; + u8* p_clear; + int old, i; + p_cb = _wpdcb[chan]; + p_status = (WPADStatusEx*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + if (_recv_3e[chan] == 0 && _recv_3f[chan] == 0) { + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + } + + p_status->base.button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & (u16)HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN || + p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC || + p_cb->dataFormat == WPAD_FMT_BTN_ACC_DPD_EXTENDED) { + p_status->base.err = p_cb->status; + } else if (p_cb->status == 0) { + p_status->base.err = WPAD_ERR_INVALID; + } + p_status->base.dev = p_cb->devType; + p_cb->info.nearempty = 0; + p_status->base.accX = (s16)((s16)((s16)((s16)((s16)data[HID_IDX_BYTE9] << 2) & (s16)0xFFFC) | + (s16)((s16)(u16)(data[HID_IDX_BYTE7] >> 6) & (s16)0x0002)) - + p_cb->devConf.acc_0g.x); + p_status->base.accZ |= (s16)((s16)((s16)((s16)data[HID_IDX_BYTE8] << 3) & (s16)0xFF00) | + (s16)((s16)(u16)(data[HID_IDX_BYTE7] << 1) & (s16)0x00C0)); + + p_status->base.obj[0].x = (s16)((s16)((u16)data[HID_IDX_BYTE10] & 0xFF) | + (u16)((u16)(data[HID_IDX_BYTE12] & 0x30) << 4)); + p_status->base.obj[0].y = + (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)(data[HID_IDX_BYTE11])) & 0xFF) | (u16)(((u16)(data[HID_IDX_BYTE12] & 0xC0)) << 2))); + p_status->exp[0].pixel = (u16)(((s16)((s16)(((u16)(data[HID_IDX_BYTE17]) << 8) & 0xFF00) | (u16)(data[HID_IDX_BYTE18] & 0xFF))) * 64); + p_status->exp[0].radius = (s8)((data[HID_IDX_BYTE12] & 0x0f)); + p_status->exp[0].range_x1 = (s16)(((s8)(data[HID_IDX_BYTE13]) == -1) ? 0 : data[HID_IDX_BYTE13]); + p_status->exp[0].range_y1 = (s16)(((s8)(data[HID_IDX_BYTE14]) == -1) ? 0 : data[HID_IDX_BYTE14]); + p_status->exp[0].range_x2 = (s16)(((s8)(data[HID_IDX_BYTE15]) == -1) ? 0 : data[HID_IDX_BYTE15]); + p_status->exp[0].range_y2 = (s16)(((s8)(data[HID_IDX_BYTE16]) == -1) ? 0 : data[HID_IDX_BYTE16]); + p_status->exp[0].range_x1 = (s16)(p_status->exp[0].range_x1 * 8); + p_status->exp[0].range_y1 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[0].range_y1 * 8)); + p_status->exp[0].range_x2 = (s16)(p_status->exp[0].range_x2 * 8); + p_status->exp[0].range_y2 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[0].range_y2 * 8)); + p_status->base.obj[0].size = (u16)((f32)p_status->exp[0].radius * (f32)p_status->exp[0].radius * PI); + if (p_status->base.obj[0].size == 0 || p_status->base.obj[0].x == (s16)(WPAD_DPD_IMG_RESO_WX - 1) || + p_status->base.obj[0].y == (s16)(WPAD_DPD_IMG_RESO_WY - 1) || p_status->exp[0].radius == 0xf) { + p_status->base.obj[0].x = (s16)0; + p_status->base.obj[0].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1); + p_status->base.obj[0].size = 0; + p_status->exp[0].pixel = 0; + p_status->exp[0].radius = 0; + } + p_status->base.obj[0].traceId = 0; + + p_status->base.obj[1].x = (s16)((s16)((u16)data[HID_IDX_BYTE19] & 0xFF) | + (u16)((u16)(data[HID_IDX_BYTE21] & 0x30) << 4)); + p_status->base.obj[1].y = + (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)(data[HID_IDX_BYTE20])) & 0xFF) | (u16)(((u16)(data[HID_IDX_BYTE21] & 0xC0)) << 2))); + p_status->exp[1].pixel = (u16)(((s16)((s16)(((u16)(data[HID_IDX_BYTE26]) << 8) & 0xFF00) | (u16)(data[HID_IDX_BYTE27] & 0xFF))) * 64); + p_status->exp[1].radius = (s8)((data[HID_IDX_BYTE21] & 0x0f)); + p_status->exp[1].range_x1 = (s16)(((s8)(data[HID_IDX_BYTE22]) == -1) ? 0 : data[HID_IDX_BYTE22]); + p_status->exp[1].range_y1 = (s16)(((s8)(data[HID_IDX_BYTE23]) == -1) ? 0 : data[HID_IDX_BYTE23]); + p_status->exp[1].range_x2 = (s16)(((s8)(data[HID_IDX_BYTE24]) == -1) ? 0 : data[HID_IDX_BYTE24]); + p_status->exp[1].range_y2 = (s16)(((s8)(data[HID_IDX_BYTE25]) == -1) ? 0 : data[HID_IDX_BYTE25]); + p_status->exp[1].range_x1 = (s16)(p_status->exp[1].range_x1 * 8); + p_status->exp[1].range_y1 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[1].range_y1 * 8)); + p_status->exp[1].range_x2 = (s16)(p_status->exp[1].range_x2 * 8); + p_status->exp[1].range_y2 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[1].range_y2 * 8)); + p_status->base.obj[1].size = (u16)((f32)p_status->exp[1].radius * (f32)p_status->exp[1].radius * PI); + if (p_status->base.obj[1].size == 0 || p_status->base.obj[1].x == (s16)(WPAD_DPD_IMG_RESO_WX - 1) || + p_status->base.obj[1].y == (s16)(WPAD_DPD_IMG_RESO_WY - 1) || p_status->exp[1].radius == 0xf) { + p_status->base.obj[1].x = (s16)0; + p_status->base.obj[1].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1); + p_status->base.obj[1].size = 0; + p_status->exp[1].pixel = 0; + p_status->exp[1].radius = 0; + } + p_status->base.obj[1].traceId = 1; + + old = OSDisableInterrupts(); + _recv_3e[chan] = 1; + if (_recv_3e[chan] && _recv_3f[chan]) { + p_status->base.accZ -= (s16)(p_cb->devConf.acc_0g.z); + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + _recv_3e[chan] = _recv_3f[chan] = 0; + } + OSRestoreInterrupts(old); +} + +void __a1_3f_data_type(u8 chan, u8* data) { + WPADControlBlock* p_cb; + WPADStatusEx* p_status; + u8* p_clear; + int old, i; + p_cb = _wpdcb[chan]; + p_status = (WPADStatusEx*)&p_cb->rxBufs[p_cb->rxBufIndex]; + + if (_recv_3e[chan] == 0 && _recv_3f[chan] == 0) { + p_clear = (u8*)(p_status); + for (i = 0; i < WPAD_RX_DATASIZE; i++) { + p_clear[i] = 0; + } + } + + p_status->base.button = + (u16)((u16)(((u16)((u16)(data[HID_IDX_BYTE7]) & 0xFF) | (u16)((u16)(data[HID_IDX_BYTE8] << 8) & 0xFF00))) & + HID_WPAD_BUTTON_MASK); + + if (p_cb->dataFormat == WPAD_FMT_CORE_BTN || p_cb->dataFormat == WPAD_FMT_CORE_BTN_ACC || p_cb->dataFormat == WPAD_FMT_BTN_ACC_DPD_EXTENDED) { + p_status->base.err = p_cb->status; + } else if (p_cb->status == 0) { + p_status->base.err = WPAD_ERR_INVALID; + } + p_status->base.dev = p_cb->devType; + p_cb->info.nearempty = 0; + p_status->base.accY = (s16)((s16)((s16)((s16)((s16)data[HID_IDX_BYTE9] << 2) & (s16)0xFFFC) | + (s16)((s16)(u16)(data[HID_IDX_BYTE7] >> 6) & (s16)0x0002)) - + p_cb->devConf.acc_0g.y); + p_status->base.accZ |= (s16)((s16)((s16)((s16)data[HID_IDX_BYTE8] >> 1) & (s16)0x0030) | + (s16)((s16)(u16)(data[HID_IDX_BYTE7] >> 3) & (s16)0x000C)); + + p_status->base.obj[2].x = (s16)((s16)((u16)data[HID_IDX_BYTE10] & 0xFF) | + (u16)((u16)(data[HID_IDX_BYTE12] & 0x30) << 4)); + p_status->base.obj[2].y = + (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)(data[HID_IDX_BYTE11])) & 0xFF) | (u16)(((u16)(data[HID_IDX_BYTE12] & 0xC0)) << 2))); + p_status->exp[2].pixel = (u16)(((s16)((s16)(((u16)(data[HID_IDX_BYTE17]) << 8) & 0xFF00) | (u16)(data[HID_IDX_BYTE18] & 0xFF))) * 64); + p_status->exp[2].radius = (s8)((data[HID_IDX_BYTE12] & 0x0f)); + p_status->exp[2].range_x1 = (s16)(((s8)(data[HID_IDX_BYTE13]) == -1) ? 0 : data[HID_IDX_BYTE13]); + p_status->exp[2].range_y1 = (s16)(((s8)(data[HID_IDX_BYTE14]) == -1) ? 0 : data[HID_IDX_BYTE14]); + p_status->exp[2].range_x2 = (s16)(((s8)(data[HID_IDX_BYTE15]) == -1) ? 0 : data[HID_IDX_BYTE15]); + p_status->exp[2].range_y2 = (s16)(((s8)(data[HID_IDX_BYTE16]) == -1) ? 0 : data[HID_IDX_BYTE16]); + p_status->exp[2].range_x1 = (s16)(p_status->exp[2].range_x1 * 8); + p_status->exp[2].range_y1 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[2].range_y1 * 8)); + p_status->exp[2].range_x2 = (s16)(p_status->exp[2].range_x2 * 8); + p_status->exp[2].range_y2 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[2].range_y2 * 8)); + p_status->base.obj[2].size = (u16)((f32)p_status->exp[2].radius * (f32)p_status->exp[2].radius * PI); + if (p_status->base.obj[2].size == 0 || p_status->base.obj[2].x == (s16)(WPAD_DPD_IMG_RESO_WX - 1) || + p_status->base.obj[2].y == (s16)(WPAD_DPD_IMG_RESO_WY - 1) || p_status->exp[2].radius == 0xf) { + p_status->base.obj[2].x = (s16)0; + p_status->base.obj[2].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1); + p_status->base.obj[2].size = 0; + p_status->exp[2].pixel = 0; + p_status->exp[2].radius = 0; + } + p_status->base.obj[2].traceId = 2; + + p_status->base.obj[3].x = (s16)((s16)((u16)data[HID_IDX_BYTE19] & 0xFF) | + (u16)((u16)(data[HID_IDX_BYTE21] & 0x30) << 4)); + p_status->base.obj[3].y = + (s16)(WPAD_DPD_IMG_RESO_WY - 1 - (s16)((s16)(((u16)(data[HID_IDX_BYTE20])) & 0xFF) | (u16)(((u16)(data[HID_IDX_BYTE21] & 0xC0)) << 2))); + p_status->exp[3].pixel = (u16)(((s16)((s16)(((u16)(data[HID_IDX_BYTE26]) << 8) & 0xFF00) | (u16)(data[HID_IDX_BYTE27] & 0xFF))) * 64); + p_status->exp[3].radius = (s8)((data[HID_IDX_BYTE21] & 0x0f)); + p_status->exp[3].range_x1 = (s16)(((s8)(data[HID_IDX_BYTE22]) == -1) ? 0 : data[HID_IDX_BYTE22]); + p_status->exp[3].range_y1 = (s16)(((s8)(data[HID_IDX_BYTE23]) == -1) ? 0 : data[HID_IDX_BYTE23]); + p_status->exp[3].range_x2 = (s16)(((s8)(data[HID_IDX_BYTE24]) == -1) ? 0 : data[HID_IDX_BYTE24]); + p_status->exp[3].range_y2 = (s16)(((s8)(data[HID_IDX_BYTE25]) == -1) ? 0 : data[HID_IDX_BYTE25]); + p_status->exp[3].range_x1 = (s16)(p_status->exp[3].range_x1 * 8); + p_status->exp[3].range_y1 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[3].range_y1 * 8)); + p_status->exp[3].range_x2 = (s16)(p_status->exp[3].range_x2 * 8); + p_status->exp[3].range_y2 = (s16)((s16)(WPAD_DPD_IMG_RESO_WY - 1) - (s16)(p_status->exp[3].range_y2 * 8)); + p_status->base.obj[3].size = (u16)((f32)p_status->exp[3].radius * (f32)p_status->exp[3].radius * PI); + if (p_status->base.obj[3].size == 0 || p_status->base.obj[3].x == (s16)(WPAD_DPD_IMG_RESO_WX - 1) || + p_status->base.obj[3].y == (s16)(WPAD_DPD_IMG_RESO_WY - 1) || p_status->exp[3].radius == 0xf) { + p_status->base.obj[3].x = (s16)0; + p_status->base.obj[3].y = (s16)(WPAD_DPD_IMG_RESO_WY - 1); + p_status->base.obj[3].size = 0; + p_status->exp[3].pixel = 0; + p_status->exp[3].radius = 0; + } + + p_status->base.obj[3].traceId = 3; + old = OSDisableInterrupts(); + _recv_3f[chan] = 1; + if (_recv_3e[chan] && _recv_3f[chan]) { + p_status->base.accZ -= p_cb->devConf.acc_0g.z; + p_cb->rxBufIndex = (u8)((p_cb->rxBufIndex) ? 0 : 1); + _recv_3e[chan] = _recv_3f[chan] = 0; + } + OSRestoreInterrupts(old); +} + +void __a1_unused_report(u8 chan, u8* data) {} diff --git a/src/revolution/wpad/WPADMem.c b/src/revolution/wpad/WPADMem.c new file mode 100644 index 0000000000..efbcc8b9e5 --- /dev/null +++ b/src/revolution/wpad/WPADMem.c @@ -0,0 +1,3 @@ +#include + +WPADMEMControlBlock _wmb[WPAD_MAX_CONTROLLERS]; diff --git a/src/revolution/wpad/__wpad.h b/src/revolution/wpad/__wpad.h index 1bfb13099c..2c5329a221 100644 --- a/src/revolution/wpad/__wpad.h +++ b/src/revolution/wpad/__wpad.h @@ -190,7 +190,7 @@ extern "C" { #define RPT3E_DPD1 1 #define RPT3E_DPD1_OFFSET 13 -/* Report 0x3e: Buttons, Accelerometer (Interleaved 2), IR Camera (Full 2, +/* Report 0x3f: Buttons, Accelerometer (Interleaved 2), IR Camera (Full 2, * 18 bytes) */ #define RPTID_DATA_BTN_ACC_DPD18_2 0x3f @@ -226,13 +226,15 @@ extern "C" { */ // 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) +#define SPK_RST_REG WM_EXT_REG_ADDR(SPEAKER, 0x01) +#define SPK_CTRL_REG WM_EXT_REG_ADDR(SPEAKER, 0x08) +#define SPK_CLK_REG 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_46 WM_EXT_REG_ADDR(EXTENSION, 0x46) +#define WM_REG_EXTENSION_4C WM_EXT_REG_ADDR(EXTENSION, 0x4c) #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) @@ -266,39 +268,129 @@ extern "C" { #define WPAD_NZFILTER_MPLS 3 #define WPAD_MAX_NZFILTERS 4 +#define WPAD_DPD_IMG_RESO_WX 1024 +#define WPAD_DPD_IMG_RESO_WY 768 + +#define WPAD_STATE_DISABLED 0 +#define WPAD_STATE_ENABLING 1 +#define WPAD_STATE_ENABLED 2 +#define WPAD_STATE_SETUP 3 +#define WPAD_STATE_DISABLING 4 + +#define WPAD_BATTERY_LEVEL_CRITICAL 0 +#define WPAD_BATTERY_LEVEL_LOW 1 +#define WPAD_BATTERY_LEVEL_MEDIUM 2 +#define WPAD_BATTERY_LEVEL_HIGH 3 +#define WPAD_BATTERY_LEVEL_MAX 4 #define WPAD_RADIO_QUALITY_GOOD 0 // 80+ #define WPAD_RADIO_QUALITY_BAD 1 // 80- -struct WPADCmd { - /* 0x00 */ u32 reportID; - /* 0x04 */ u8 dataBuf[RPT_MAX_SIZE]; - /* 0x1a */ u16 dataLength; - /* 0x1c */ void* dstBuf; - /* 0x20 */ u16 readLength; - /* 0x24 */ u32 readAddress; - /* 0x28 */ WPADInfo* statusReportOut; - /* 0x2c */ WPADCallback cmdCB; -}; // size 0x30 -struct WPADCmdQueue { - /* 0x00 */ s8 indexOut; - /* 0x01 */ s8 indexIn; - /* 0x04 */ struct WPADCmd* queue; - /* 0x08 */ u32 length; -}; // size 0x0c +#define WPAD_SENSOR_BAR_POS_BOTTOM 0 +#define WPAD_SENSOR_BAR_POS_TOP 1 -struct WPADDevConfig { - /* 0x00 */ DPDObject dpd[WPAD_MAX_DPD_OBJECTS]; - /* 0x20 */ s16 accX0g; - /* 0x22 */ s16 accY0g; - /* 0x24 */ s16 accZ0g; - /* 0x26 */ s16 accX1g; - /* 0x28 */ s16 accY1g; - /* 0x2a */ s16 accZ1g; - /* 0x2c */ u8 motor; - /* 0x2d */ u8 volume; - /* 0x30 */ u8 pad0_[2]; -}; +#define WPAD_RX_DATASIZE 96 +#define WPAD_COMMAND_CMD_MAX_LEN 24 +#if PLATFORM_SHIELD +#define WPAD_COMMAND_EXT_MAX_LEN 12 +#else +#define WPAD_COMMAND_EXT_MAX_LEN 8 +#endif +#define WPAD_COMMAND_BUF_LEN 22 + +#define WPAD_I2CDEV_SEL_MASK (u32)(0xFF000000) +#define WPAD_I2CDEV_DADR_MASK (u32)(0x00FF0000) +#define WPAD_I2CDEV_UADR_MASK (u32)(0x0000FF00) +#define WPAD_I2CDEV_LADR_MASK (u32)(0x000000FF) +#define WPAD_WRITE_LEN_MASK (u16)(0x001F) +#define WPAD_READ_ULEN_MASK (u16)(0xFF00) +#define WPAD_READ_LLEN_MASK (u16)(0x00FF) + +#define SPK_CLK_OFF 0x00 +#define SPK_CLK_ON 0x01 +#define SPK_DERESET 0x01 +#if SDK_AUG2010 +#define SPK_RESET 0x80 +#else +#define SPK_RESET 0x08 +#endif +#define SPK_CTRL_PLAY 0x01 + +// Utility macros to help with SDK version differences + +#if SDK_AUG2010 +#define DIFF_COUNT_DPD(p_wpd) (p_wpd->filterDiff[WPAD_NZFILTER_DPD]) +#define HYST_COUNT_DPD(p_wpd) (p_wpd->filterSame[WPAD_NZFILTER_DPD]) +#define DIFF_COUNT_ACC(p_wpd) (p_wpd->filterDiff[WPAD_NZFILTER_ACC]) +#define HYST_COUNT_ACC(p_wpd) (p_wpd->filterSame[WPAD_NZFILTER_ACC]) +#define DIFF_COUNT_FS_ACC(p_wpd) (p_wpd->filterDiff[WPAD_NZFILTER_EXT]) +#define HYST_COUNT_FS_ACC(p_wpd) (p_wpd->filterSame[WPAD_NZFILTER_EXT]) +#else +#define DIFF_COUNT_DPD(p_wpd) (p_wpd->diffCountDpd) +#define HYST_COUNT_DPD(p_wpd) (p_wpd->hystCountDpd) +#define DIFF_COUNT_ACC(p_wpd) (p_wpd->diffCountAcc) +#define HYST_COUNT_ACC(p_wpd) (p_wpd->hystCountAcc) +#define DIFF_COUNT_FS_ACC(p_wpd) (p_wpd->diffCountfsAcc) +#define HYST_COUNT_FS_ACC(p_wpd) (p_wpd->hystCountfsAcc) +#endif + +typedef struct WPADUnkStatus { + /* 0x00 */ WPADStatus base; + /* 0x2A */ u8 field_0x2a[0x60 - 0x2a]; +} WPADUnkStatus; + +typedef struct WPADMEMGameInfo { + /* 0x00 */ OSTime calendarTimeTick; + /* 0x08 */ u16 gameTitle[17]; + /* 0x2A */ char gameId[4]; + /* 0x2E */ u8 gameType; + /* 0x2F */ u8 checkSum; + /* 0x30 */ u8 reserved[8]; +} WPADMEMGameInfo; + +typedef struct WPADMemBlock { + /* 0x00 */ BOOL busy; + /* 0x04 */ const u8* data; + /* 0x08 */ BOOL len; + /* 0x0C */ BOOL addr; + /* 0x10 */ WPADCallback* cb; +} WPADMemBlock; + +typedef struct WPADCommand { + /* 0x00 */ u32 command; + /* 0x04 */ u8 data[22]; + /* 0x1A */ u16 len; + /* 0x1C */ void* readBuf; + /* 0x20 */ u16 readLen; + /* 0x24 */ u32 readAddr; + /* 0x28 */ WPADInfo* info; + /* 0x2C */ WPADCallback callback; +} WPADCommand; + +typedef struct WPADCmdQueue { + /* 0x00 */ s8 head; + /* 0x01 */ s8 tail; + /* 0x04 */ WPADCommand* cmd; + /* 0x08 */ u32 cmdlen; +} WPADCmdQueue; + +typedef struct WPADDevConfig { + /* 0x00 */ DPDObject obj[WPAD_DPD_MAX_OBJECTS]; + /* 0x20 */ WPADAcc acc_0g; + /* 0x26 */ WPADAcc acc_1g; + /* 0x2C */ u8 motor; + /* 0x2D */ u8 volume; + /* 0x2E */ u8 unk_0x2e[0x30 - 0x2e]; +} WPADDevConfig; + +typedef struct WPADStick { + /* 0x00 */ s16 x; + /* 0x02 */ s16 x_min; + /* 0x04 */ s16 x_max; + /* 0x06 */ s16 y; + /* 0x08 */ s16 y_min; + /* 0x0A */ s16 y_max; +} WPADStick; typedef struct WPADMplsCalibration { /* 0x00 */ f32 pitchZero; @@ -310,109 +402,84 @@ typedef struct WPADMplsCalibration { /* 0x18 */ s32 degrees; } WPADMplsCalibration; -struct WPADExtConfig { - union { - struct WPADFSConfig { - /* 0x00 */ s16 stickXCenter; - /* 0x02 */ s16 at_0x02; - /* 0x04 */ s16 at_0x04; - /* 0x06 */ s16 stickYCenter; - /* 0x08 */ s16 at_0x08; - /* 0x0a */ s16 at_0x0a; - /* 0x0c */ s16 accX0g; - /* 0x0e */ s16 accY0g; - /* 0x10 */ s16 accZ0g; - /* 0x12 */ s16 accX1g; - /* 0x14 */ s16 accY1g; - /* 0x16 */ s16 accZ1g; - } fs; // size 0x1a +typedef struct WPADFsConfig { + /* 0x00 */ WPADStick stick; + /* 0x0C */ WPADAcc acc_0g; + /* 0x12 */ WPADAcc acc_1g; +} WPADFsConfig; - struct WPADCLConfig { - /* 0x00 */ s16 lStickXCenter; - /* 0x02 */ s16 at_0x02; - /* 0x04 */ s16 at_0x04; - /* 0x06 */ s16 lStickYCenter; - /* 0x08 */ s16 at_0x08; - /* 0x0a */ s16 at_0x0a; - /* 0x0c */ s16 rStickXCenter; - /* 0x0e */ s16 at_0x0e; - /* 0x10 */ s16 at_0x10; - /* 0x12 */ s16 rStickYCenter; - /* 0x14 */ s16 at_0x14; - /* 0x16 */ s16 at_0x16; - /* 0x18 */ u8 triggerLZero; - /* 0x19 */ u8 triggerRZero; - } cl; // size 0x1a - - u8 forceUnionSize_[0x1c]; // alignment? - }; // size 0x1c +typedef struct WPADClConfig { + /* 0x00 */ WPADStick lstk; + /* 0x0C */ WPADStick rstk; + /* 0x18 */ u8 triggerL; + /* 0x19 */ u8 triggerR; +} WPADClConfig; +typedef struct WPADExtConfig { + /* 0x00 */ union { + WPADFsConfig fs; + WPADClConfig cl; + u8 bytes[0x1c]; + }; +#if SDK_AUG2010 struct WPADMplsConfig { /* 0x00 */ WPADMplsCalibration high; /* 0x1c */ WPADMplsCalibration low; /* 0x38 */ u32 calibCRC; /* 0x3c */ u16 calibID; } /* 0x1a */ mpls; -}; // size 0x5c +#endif +} WPADExtConfig; -typedef struct WPADGameInfo { - /* 0x00 */ OSTime timestamp; - /* 0x08 */ u16 gameTitle[16 + 1]; - /* 0x2a */ char gameCode[4]; - /* 0x2e */ u8 gameType; - /* 0x2f */ u8 checksum; - u8 _pad0[8]; -} WPADGameInfo; // size 0x38 - -struct WPADMemBlock { - /* 0x00 */ BOOL busy; - /* 0x04 */ u8 const* data; - /* 0x08 */ u16 len; - /* 0x0c */ u32 addr; - /* 0x10 */ WPADCallback* cb; -}; // size 0x14 - -typedef struct /* possibly untagged, like kpad */ { - /* 0x000 */ WPADGameInfo gameInfo; - /* 0x038 */ s32 at_0x038[2]; /* unknown */ // WPADResult[2]? see __wpadGetGameInfo - /* 0x040 */ u8 rxBufMain[RX_BUFFER_SIZE]; - /* 0x0a0 */ u8 rxBufs[2][RX_BUFFER_SIZE]; - /* 0x160 */ struct WPADCmdQueue stdCmdQueue; - /* 0x16c */ struct WPADCmd stdCmdQueueList[24]; - /* 0x5ec */ struct WPADCmdQueue extCmdQueue; - /* 0x16c */ struct WPADCmd extCmdQueueList[12]; - /* 0x838 */ WPADInfo info; - /* 0x850 */ WPADInfo* infoOut; - /* 0x854 */ struct WPADDevConfig devConfig; - /* 0x884 */ struct WPADExtConfig extConfig; - /* 0x8e0 */ WPADCallback cmdBlkCB; - /* 0x8e4 */ WPADExtensionCallback extensionCB; - /* 0x8e8 */ WPADConnectCallback connectCB; - /* 0x8ec */ WPADSamplingCallback samplingCB; - /* 0x8f0 */ void* samplingBuf; - /* 0x8f4 */ u32 samplingBufIndex; - /* 0x8f8 */ u32 samplingBufSize; - /* 0x8fc */ u32 dataFormat; - /* 0x900 */ s32 status; - /* 0x904 */ u8 statusReqBusy; - /* 0x905 */ u8 devType; - /* 0x906 */ u8 devMode; - /* 0x907 */ s8 devHandle; +typedef struct WPADControlBlock { + /* 0x000 */ WPADMEMGameInfo gameInfo; + /* 0x038 */ s32 gameInfoErr[2]; + /* 0x040 */ WPADUnkStatus prBuf[1]; + /* 0x0A0 */ WPADUnkStatus rxBufs[2]; + /* 0x160 */ WPADCmdQueue stdCmdQueue; + /* 0x16C */ WPADCommand stdCmdQueueList[WPAD_COMMAND_CMD_MAX_LEN]; + /* 0x5EC */ WPADCmdQueue extCmdQueue; + /* 0x5F8 */ WPADCommand extCmdQueueList[WPAD_COMMAND_EXT_MAX_LEN]; + /* 0x778 */ WPADInfo info; + /* 0x790 */ WPADInfo* infoOut; + /* 0x794 */ WPADDevConfig devConf; + /* 0x7C4 */ WPADExtConfig extConf; + /* 0x7DC */ WPADCallback cmdBlkCallback; + /* 0x7E0 */ WPADExtensionCallback extensionCallback; + /* 0x7E4 */ WPADConnectCallback connectCallback; + /* 0x7E8 */ WPADSamplingCallback samplingCallback; + /* 0x7EC */ void* samplingBufs_ptr; + /* 0x7F0 */ u32 samplingBufIndex; + /* 0x7F4 */ u32 samplingBufLength; + /* 0x7F8 */ u32 dataFormat; + /* 0x7FC */ s32 status; + /* 0x800 */ u8 statusReqBusy; + /* 0x801 */ u8 devType; + /* 0x802 */ u8 devMode; + /* 0x803 */ s8 devHandle; +#if SDK_AUG2010 /* 0x908 */ int at_0x908; /* unknown */ /* 0x90c */ u8 rxBufIndex; /* 0x90d */ s8 at_0x90d; /* unknown */ - /* 0x90e */ u8 defaultDpdSize; // maybe? + /* 0x90e */ u8 dpdDummyObjSize; // maybe? /* 0x90f */ u8 currentDpdCommand; /* 0x910 */ u8 pendingDpdCommand; - /* 0x911 */ u8 radioQuality; - /* 0x912 */ u8 radioQualityOkMs; // see __wpadCalcRadioQuality - /* 0x913 */ u8 audioFrames; - /* 0x914 */ u32 motorBusy; - /* 0x918 */ BOOL motorRunning; - /* 0x91c */ BOOL used; - /* 0x920 */ BOOL handshakeFinished; - /* 0x924 */ int configIndex; - /* 0x928 */ OSThreadQueue threadQueue; /* purpose unknown */ +#else + /* 0x804 */ u16 dpdDummyObjSize; + /* 0x806 */ u8 rxBufIndex; + /* 0x807 */ u8 reqVolume; + /* 0x808 */ WPADCallback reqVolCb; +#endif + /* 0x80C */ u8 radioQuality; + /* 0x80D */ u8 radioQualityOkMs; // see __wpadCalcRadioQuality + /* 0x80E */ u8 audioFrames; + /* 0x810 */ BOOL motorBusy; + /* 0x814 */ BOOL motorRunning; + /* 0x818 */ BOOL used; + /* 0x81C */ BOOL handshakeFinished; + /* 0x820 */ BOOL oldFw; + /* 0x824 */ OSThreadQueue threadQueue; +#if SDK_AUG2010 /* 0x930 */ WPADCallback vsmCallback; /* 0x934 */ u8 controlMplsBusy; /* 0x935 */ u8 mplsCBReadBuf[2]; @@ -436,26 +503,36 @@ typedef struct /* possibly untagged, like kpad */ { /* 0x994 */ u32 certLintY[1 + 16 + 1]; /* 0x994 */ u32 certLintBig[LINT_NUM_MAX_BUFSIZ]; /* 0xae4 */ int at_0xae4; /* unknown */ - /* 0xae8 */ OSTime lastControllerDataUpdate; +#endif + /* 0x830 */ OSTime lastUpdateTime; +#if SDK_AUG2010 /* 0xaf0 */ u16 filterDiff[WPAD_MAX_NZFILTERS]; /* 0xaf8 */ u16 filterSame[WPAD_MAX_NZFILTERS]; - /* 0xb00 */ OSTime lastReportSendTime; - /* 0xb08 */ u8 at_0xb08; /* unknown */ - /* 0xb09 */ u8 calibrated; - /* 0xb0a */ u16 recalibHoldMs; - /* 0xb0c */ u8 encryptionKey[16]; - /* 0xb1c */ u8 decryptAddTable[8]; - /* 0xb24 */ u8 decryptXorTable[8]; - /* 0xb2c */ u8 wmReadDataBuf[64]; - /* 0xb6c */ u8* wmReadDataPtr; - /* 0xb70 */ u32 wmReadAddress; - /* 0xb74 */ int wmReadHadError; - /* 0xb78 */ u16 wmReadLength; - /* 0xb7a */ s8 at_0xb7a; /* unknown */ - /* 0xb7b */ u8 radioSensitivity; - /* 0xb7c */ u16 copyOutCount; - /* 0xb7e */ u8 sleeping; - /* 0xb7f */ u8 lastReportID; +#else + /* 0x838 */ u16 diffCountDpd; + /* 0x83A */ u16 hystCountDpd; + /* 0x83C */ u16 diffCountAcc; + /* 0x83E */ u16 hystCountAcc; + /* 0x840 */ u16 diffCountfsAcc; + /* 0x842 */ u16 hystCountfsAcc; +#endif + /* 0x844 */ OSTime lastReportSendTime; + /* 0x850 */ u8 cmdTimeoutAction; + /* 0x851 */ u8 calibrated; + /* 0x852 */ u16 recalibrateCount; + /* 0x854 */ u8 key[16]; + /* 0x864 */ u8 ft[8]; + /* 0x86C */ u8 sb[8]; + /* 0x874 */ u8 wmReadDataBuf[64]; + /* 0x8B4 */ void* wmReadDataPtr; + /* 0x8B8 */ u32 wmReadAddr; + /* 0x8BC */ s32 wmReadErr; + /* 0x8C0 */ u16 wmReadLength; + /* 0x8C2 */ u8 keyIdx; + /* 0x8C3 */ u8 radioSensitivity; + /* 0x8C4 */ u16 packetCnt; + /* 0x8C6 */ u8 disconnect; + /* 0x8C7 */ u8 lastReportId; /* 0xb80 */ WPADCallback getInfoCB; /* 0xb84 */ u8 getInfoBusy; /* 0xb85 */ u8 extState; @@ -464,7 +541,7 @@ typedef struct /* possibly untagged, like kpad */ { /* 0xb88 */ u8 savedDevType; // maybe? /* 0xb89 */ u8 extWasDisconnected; /* 0xb8a */ s16 reconnectExtMs; - /* 0xb8c */ struct WPADMemBlock memBlock; + /* 0xb8c */ WPADMemBlock memBlock; /* 0xba0 */ WPADCallback controlMplsCB; /* 0xba4 */ u8 parseMPBuf; /* 0xba5 */ u8 certProbeByte; @@ -474,7 +551,7 @@ typedef struct /* possibly untagged, like kpad */ { /* 0xbac */ u8 mplsCBState; /* 0xbad */ u8 mplsUptimeMs; /* 0xbae */ s8 certMayVerifyByCalibBlock; - u8 pad0_[2]; /* unknown (can't be alignment) */ + /* 0xbaf */ u8 unk_0xbaf[0xbb1 - 0xbaf]; /* unknown (can't be alignment) */ /* 0xbb1 */ u8 certProbeStartingValue; /* 0xbb2 */ u16 lastMplsCalibID; /* 0xbb4 */ u32 lastMplsCalibCRC; @@ -484,17 +561,90 @@ typedef struct /* possibly untagged, like kpad */ { /* 0xbbb */ u8 extDevType; /* 0xbbc */ u8 currPwmDuty; /* 0xbbd */ u8 pendingPwmDuty; - u8 pad1_[2]; /* unknown (can't be alignment) */ + /* 0xbbe */ u8 unk_0xbbe[0xbc0 - 0xbbe]; /* unknown (can't be alignment) */ /* 0xbc0 */ u8 extDataBuf[32]; -} ATTRIBUTE_ALIGN(32) wpad_cb_st; // size 0xbe0 +} WPADControlBlock; -BOOL WPADiIsAvailableCmdQueue(struct WPADCmdQueue* cmdQueue, s8 num); -BOOL WPADiSendWriteDataCmd(struct WPADCmdQueue* cmdQueue, u8 cmd, u32 address, WPADCallback cb); -BOOL WPADiSendWriteData(struct WPADCmdQueue* cmdQueue, void const* p_buf, u16 len, u32 address, WPADCallback cb); -BOOL WPADiSendStreamData(struct WPADCmdQueue* cmdQueue, void const* p_buf, u16 len); -BOOL WPADiSendMuteSpeaker(struct WPADCmdQueue* cmdQueue, BOOL muted, WPADCallback cb); -BOOL WPADiSendEnableSpeaker(struct WPADCmdQueue* cmdQueue, BOOL enabled, WPADCallback cb); -BOOL WPADiSendGetContStat(struct WPADCmdQueue* cmdQueue, WPADInfo* infoOut, WPADCallback cb); +typedef struct WPADMEMControlBlock { + /* 0x00 */ BOOL used; + /* 0x04 */ u8* p_buf; + /* 0x08 */ u16 len; + /* 0x0C */ u32 addr; + /* 0x10 */ WPADCallback callback; +} WPADMEMControlBlock; + +struct WPADCmd { + /* 0x00 */ u32 reportID; + /* 0x04 */ u8 dataBuf[RPT_MAX_SIZE]; + /* 0x1a */ u16 dataLength; + /* 0x1c */ void* dstBuf; + /* 0x20 */ u16 readLength; + /* 0x24 */ u32 readAddress; + /* 0x28 */ WPADInfo* statusReportOut; + /* 0x2c */ WPADCallback cmdCB; +}; // size 0x30 + +extern WPADMEMControlBlock _wmb[WPAD_MAX_CONTROLLERS]; +#if SDK_AUG2010 +extern WPADControlBlock* __rvl_p_wpadcb[WPAD_MAX_CONTROLLERS]; +#define _wpdcb __rvl_p_wpadcb +#else +extern WPADControlBlock* _wpdcb[WPAD_MAX_CONTROLLERS]; +#endif + +/* WPAD.c */ + +void WPADiCreateKey(s32); +void WPADiCreateKeyFor3rd(s32); +s32 WPADiHIDParser(u8 chan, u8* p_rpt); + +void WPADiClearQueue(WPADCmdQueue* queue); +BOOL WPADiSendSetReportType(WPADCmdQueue* queue, u32 fmt, WPADCallback callback); +BOOL WPADiSendWriteDataCmd(WPADCmdQueue* queue, u8 cmd, u32 addr, WPADCallback callback); +BOOL WPADiSendReadData(WPADCmdQueue* queue, void* p_buf, u16 len, u32 addr, WPADCallback callback); +BOOL WPADiSendWriteData(WPADCmdQueue* queue, void* p_buf, u16 len, u32 addr, WPADCallback callback); + +void WPADiCopyOut(s32 chan); +u32 WPADGetLatestIndexInBuf(s32 chan, void* buf); +void WPADiExcludeButton(s32 chan); +s32 WPADiGetStatus(s32 chan); + +void WPADiShutdown(BOOL exec); +void WPADiDisconnect(s32 chan, BOOL polite); + +BOOL WPADiSendSetPort(WPADCmdQueue* queue, u8 pattern, WPADCallback callback); +BOOL WPADiSendDPDCSB(WPADCmdQueue* queue, BOOL enable, WPADCallback callback); +#if SDK_AUG2010 +BOOL WPADiSendGetContStat(WPADCmdQueue* queue, WPADInfo* info, WPADCallback callback); +#else +BOOL WPADiSendGetContStat(WPADCmdQueue* queue, WPADInfo* info, u32 addr, WPADCallback callback); +#endif +void WPADiCheckContInputs(s32 chan); + +s32 WPADiRetrieveChannel(u8 dev_handle); +s32 WPADiSendData(s32 chan, WPADCommand cmd); + +BOOL WPADiGetCommand(WPADCmdQueue* queue, WPADCommand* cmd); +BOOL WPADiPopCommand(WPADCmdQueue* queue); +BOOL __wpadPushCommand(WPADCmdQueue* queue, WPADCommand cmd); +BOOL WPADiProcessCommand(s32 chan); +BOOL WPADiProcessExtCommand(s32 chan); +void WPADiRumbleMotor(s32 chan, BOOL sendCmd); +void WPADiRadioSensitivity(s32 chan); + +void WPADiContMapTableUpdate(void); +void WPADiAfh(void); +void WPADiGetScSettings(void); + +void WPADiConnCallback(u8 dev_handle, u8 open); +void WPADiRecvCallback(u8 dev_handle, u8* p_rpt, u16); + +/* WPADEncrypt.c */ +void WPADiCreateKey(s32 chan); +void WPADiDecode(s32 chan, void* p_buf, u16 len, u16 offset); + +/* wpad_debug_msg.c */ +void DEBUGPrint(const char* fmt, ...); #ifdef __cplusplus } diff --git a/src/revolution/wpad/wpad_debug_msg.c b/src/revolution/wpad/wpad_debug_msg.c new file mode 100644 index 0000000000..2713ba81c9 --- /dev/null +++ b/src/revolution/wpad/wpad_debug_msg.c @@ -0,0 +1,5 @@ +#include + +void DEBUGPrint(const char* fmt, ...) { + // NONMATCHING +} diff --git a/src/revolution/wpad/WUD.c b/src/revolution/wud/WUD.c similarity index 88% rename from src/revolution/wpad/WUD.c rename to src/revolution/wud/WUD.c index 54685342a8..9c38c36731 100644 --- a/src/revolution/wpad/WUD.c +++ b/src/revolution/wud/WUD.c @@ -1,7 +1,9 @@ -#include -#include +#include +#include +#include #include "__wud.h" +#include "types.h" wud_cb_st __rvl_wudcb; @@ -61,3 +63,11 @@ u16 WUDiGetQueueSizeForHandle(u8 dev_handle) { u16 WUDiGetNotAckNumForHandle(u8 dev_handle) { return _dev_handle_notack_num[dev_handle]; } + +BOOL WUDStartSyncSimple(void) { + // NONMATCHING +} + +BOOL WUDStartFastSyncSimple(void) { + // NONMATCHING +} diff --git a/src/revolution/wpad/__wud.h b/src/revolution/wud/__wud.h similarity index 98% rename from src/revolution/wpad/__wud.h rename to src/revolution/wud/__wud.h index 0f3c2499b0..dace1a2f71 100644 --- a/src/revolution/wpad/__wud.h +++ b/src/revolution/wud/__wud.h @@ -3,7 +3,6 @@ #include #include -#include #ifdef __cplusplus extern "C" { diff --git a/src/revolution/wud/debug_msg.c b/src/revolution/wud/debug_msg.c new file mode 100644 index 0000000000..43ab011cb5 --- /dev/null +++ b/src/revolution/wud/debug_msg.c @@ -0,0 +1,6 @@ +#include + +void WUD_DEBUGPrint(const char* msg, ...) { + // NONMATCHING +} +