diff --git a/headers/addons/wiiext.h b/headers/addons/wiiext.h index 6fb6a088f0..efce5e9792 100644 --- a/headers/addons/wiiext.h +++ b/headers/addons/wiiext.h @@ -382,6 +382,7 @@ class WiiExtensionInput : public GPAddon { void setControllerAnalog(uint16_t controllerID, uint16_t analogID, uint32_t axisType); void setControllerStickMode(uint16_t controllerID, uint16_t analogID, uint32_t axisType); void setButtonState(bool buttonState, uint16_t buttonMask); + bool getButtonState(uint16_t buttonMask); void queueAnalogChange(uint16_t analogInput, uint16_t analogValue, uint16_t lastAnalogValue); void updateAnalogState(); void updateMotionState(); diff --git a/lib/WiiExtension/CMakeLists.txt b/lib/WiiExtension/CMakeLists.txt index 6387dc5262..d16fc1944f 100644 --- a/lib/WiiExtension/CMakeLists.txt +++ b/lib/WiiExtension/CMakeLists.txt @@ -7,9 +7,10 @@ add_library(WiiExtension extensions/MotionPlusExtension.cpp extensions/NunchuckExtension.cpp extensions/TaikoExtension.cpp + extensions/TrainExtension.cpp extensions/TurntableExtension.cpp extensions/UDrawExtension.cpp ) -target_link_libraries(WiiExtension PUBLIC pico_stdlib PicoPeripherals CRC32) +target_link_libraries(WiiExtension PUBLIC pico_stdlib pico_i2c_slave PicoPeripherals CRC32) target_include_directories(WiiExtension INTERFACE .) -target_include_directories(WiiExtension PUBLIC . PicoPeripherals CRC32) +target_include_directories(WiiExtension PUBLIC . pico_i2c_slave PicoPeripherals CRC32) diff --git a/lib/WiiExtension/README.md b/lib/WiiExtension/README.md index f375f90eb8..c0b5765c81 100644 --- a/lib/WiiExtension/README.md +++ b/lib/WiiExtension/README.md @@ -1,5 +1,8 @@ # WiiExtension -# -# Written by: -# Mike Parks -# \ No newline at end of file + +Wii extension controller input/output handling for pico-sdk based projects via I2C. + +Written by: + Mike Parks @mikepparks + +Output encryption functionality based on work by @Santroller, @RobertDaleSmith, and marcan. \ No newline at end of file diff --git a/lib/WiiExtension/WiiExtension.cpp b/lib/WiiExtension/WiiExtension.cpp index 5da384d297..66b44bc062 100644 --- a/lib/WiiExtension/WiiExtension.cpp +++ b/lib/WiiExtension/WiiExtension.cpp @@ -3,282 +3,682 @@ #include #include +typedef struct { + uint8_t kind; // 'A'=addr seek, 'W'=write, 'R'=first read of transaction + uint8_t reg; + uint8_t val; +} wii_log_event_t; + +static const uint8_t ans_tbl[7][6] = { + {0xA8,0x77,0xA6,0xE0,0xF7,0x43}, + {0x5A,0x35,0x85,0xE2,0x72,0x97}, + {0x8F,0xB7,0x1A,0x62,0x87,0x38}, + { 0xD,0x67,0xC7,0xBE,0x4F,0x3E}, + {0x20,0x76,0x37,0x8F,0x68,0xB7}, + {0xA9,0x26,0x3F,0x2B,0x10,0xE3}, + {0x30,0x7E,0x90, 0xE,0x85, 0xA} +}; + +static const uint8_t sboxes[10][256] = { + { + 0x70,0x51, 3,0x86,0x40, 0xD,0x4F,0xEB,0x3E,0xCC,0xD1,0x87,0x35,0xBD,0xF5, 0xB, + 0x5E,0xD0,0xF8,0xF2,0xD5,0xE2,0x6C,0x31, 0xC,0xAD,0xFC,0x21,0xC3,0x78,0xC1, 6, + 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, 7,0x8F,0x54, + 0xEA,0x91,0xCA,0x3F,0xF9,0x19,0xF0,0xD7,0x46,0xBC,0x28,0x1B,0x61,0xE8,0x2F,0x6A, + 0xAE,0x9D,0xF6,0x4E, 9,0x14,0x77,0x4D,0xDB,0x1F,0x2E,0x7B,0x7C,0xF1,0x43,0xA3, + 0,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, 1,0x8A,0x9A,0x80,0x1D, 0xE,0xB0,0x5C,0xD4,0x38,0x62,0xF4,0x30,0xE0,0x8E, + 0x53,0xB7, 2,0x57,0xAC,0xA6,0x52, 0xA,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, 5,0x3A,0x8D,0x6E,0xFB,0x3D,0xA9,0x69,0x36,0xF3,0x94,0xDE,0xEF,0x15,0x6F, + 0x8B,0x9B, 8, 0xF,0xDC,0x81,0x18,0x20, 4,0xE4,0x71,0xCF,0xE9,0x2B,0x42,0x58, + }, + { + 1,0xA0,0xA9,0x62,0xD6,0x3F,0x85,0xA7,0xB6,0xD4,0xFA,0x15,0x66,0x17, 9,0xBD, + 0x5D,0x14,0x34,0x26,0x59,0x72,0x91,0x54, 6,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, 2,0xCC, 8,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, 3,0x18,0x2B,0x3E,0xBF,0x68,0x61,0xFC,0x52,0xC0, + 0xDE,0xE0, 0xA,0x58,0x13,0x5A, 0,0xBE,0x1C,0x90, 0xE,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, 4,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, 0xD, 7, + 0x76,0x8A,0x2C, 0xB,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, 5,0x6B, 0xF, + 0x1D,0xFB,0x82,0x98,0x57,0x8D,0xF3,0x6A,0xBC,0xAC,0xC9,0xA6,0xFF,0xB8,0x69, 0xC, + }, + { + 0x4C,0x4D,0x72, 7,0x5A,0x49,0x33,0x8D,0xA2,0xAB,0x46,0x3D,0x63, 0xD,0xA0,0x97, + 0xFF,0xF0,0xF5,0xFA,0xC0,0xE9,0xDB,0x62,0xE4,0xE1,0x74,0x43,0xDC,0x86,0x18,0x29, + 0x37,0xF4, 6,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, 9,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, 1, 0xE,0x9C,0x41,0x56,0x5F,0xB3,0x26, 3,0x83,0xBA,0x13,0x4B, + 0xCA,0xC5, 0xA,0xF8,0x60,0xA5,0xB9,0xC7,0xC3,0x98,0x32,0xFB,0x12,0xF9,0xA7,0x92, + 0xAA,0x68,0xF3,0x78,0x7E, 5,0x20,0x21, 2,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, 0xC,0x91,0x93,0x6A,0x5E, 0xB,0x79, + 0xE3,0xDD, 0,0x4F,0x3C,0x89,0x6E,0x71,0x69,0xA9,0xAC,0x40,0xE5,0x99,0x28,0xC6, + 0x31,0x4E,0x7A,0xCD, 8,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, 4,0xC4, + 0xB6,0xC1,0xC2,0x7F,0x9A,0xDA,0xD5,0x39,0x42,0x14,0x9D,0xB1, 0xF,0x35,0xD6,0xCC, + }, + { + 0xB9,0xDA,0x38, 0xC,0xA2,0x9C, 9,0x1F, 6,0xB1,0xB6,0xFD,0x1A,0x69,0x23,0x30, + 0xC4,0xDE, 1,0xD1,0xF4,0x58,0x29,0x37,0x1C,0x7D,0xD5,0xBF,0xFF,0xBD,0xC8,0xC9, + 0xCF,0x65,0xBE,0x7B,0x78,0x97,0x98,0x67, 8,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, + 0xB,0x35,0x95,0x31,0x59,0x9A,0x4D, 4, 7,0x1E,0x5A,0x76,0x13,0xF3,0x71,0x83, + 0xD0,0x86, 3,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, 0,0x46,0xED,0xC6,0x6C,0x43,0x60,0x92,0x2D,0xA9,0x22, + 0x45,0x8F,0x34,0x55,0xAE,0xA4, 0xA,0x66,0x32,0xE0,0xDC, 2,0xAC,0xE8,0x20,0x8C, + 0x89,0x62,0x4A,0xFE,0xEE,0xC3,0xE3,0x3C,0xF1,0x79, 5,0xE9,0xF6,0x27,0x33,0xCC, + 0xF2,0x9E,0x11,0x81,0x7E,0x80,0x10,0x8A,0x82,0x9F,0x48, 0xD,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, 0xE,0x52,0x61,0x25,0x3E,0xF8, 0xF,0x4B,0xEC, + }, + { + 0xC0, 0,0x30,0xF6, 2,0x49,0x3D,0x10,0x6E,0x20,0xC9,0xA6,0x2F,0xFE,0x2C,0x2B, + 0x75,0x2E,0x45,0x26,0xAB,0x48,0xA9,0x80,0xFC, 4,0xCC,0xD3,0xB5,0xBA,0xA3,0x38, + 0x31,0x7D, 1,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, 0xE,0x12,0x87,0x8D, + 0xE9,0x34,0xED,0x73,0xC4,0xF8,0x61,0x5B, 5,0xDF,0x59,0x4C,0x97,0x79,0x83,0x18, + 0xA4,0x55,0x95,0xEB,0xBD,0x53,0xF5,0xF1,0x57,0x66,0x46,0x9F,0xB2,0x81, 9,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, 0xD,0x92,0x9C,0xB0,0xEF, + 0x58,0x6C,0x9D,0x77,0x2D,0x70,0xFA,0xF3,0xB3, 0xB,0xE2,0x40,0x7E,0xF4,0x8A,0xE5, + 0x8C,0x3C,0x56,0x71,0xD1,0x64,0xE1,0x82, 0xA,0xCB,0x13,0x15,0x90,0xEC, 3,0x99, + 0xAF,0x14,0x5D, 0xF,0x33,0x4A,0x94,0xA5,0xA8,0x35,0x1B,0xE3,0x6A,0xC6,0x28,0xFF, + 0x4D,0xE7,0x25,0x84,0xAC, 8,0xAE,0xC5,0xA2,0x2A,0xB8,0x37, 0xC,0x7A,0xA0,0xC3, + 0xCE,0xAD, 6,0x1A,0x9E,0x8B,0xFB,0xD5,0xD0,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, 7,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, 9,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, 7,0x6B,0x1B,0x47, + 0x15, 0xF,0xE4, 0xA,0xEA,0xD1,0x32,0x78,0x36,0x49,0x8D,0x4B,0xD2,0xBC,0xA5,0xDC, + 0x1D, 0xD,0x4D,0xCD,0x9A,0x82,0x5F,0xFC,0x94,0x65,0xBE,0xE2,0xF4,0xC9,0x1E,0x44, + 0xCB,0x9E, 0xC,0x64,0x71,0x26,0x63,0xB3,0x14,0xE8,0x40,0x70,0x8A, 0xE,0x19,0x42, + 0x6D,0xAC,0x88,0x10,0x5C,0xDF,0x41,0xA9,0xAD,0xE5,0xFB,0x74,0xCC,0xD5, 6,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, 5,0x93, + 0xCA,0x4E,0xF1,0x7D,0x30,0xFD,0xC4,0x69,0x66,0x2F, 8,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, 4,0xF5,0x90,0xEE,0x7E,0x83,0x1C, 3,0x56,0xB6,0xAA, + 0,0x17, 1,0x35,0x55,0x79, 0xB,0x12,0xBB,0x1A,0x31,0xE7, 2,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, 9,0x19,0xC0,0x67,0xD6, 0,0x3C,0x7E,0xE7, + 0xE9,0xF4, 8,0x5A,0xF8,0xB8,0x2E, 5,0xA6,0x25,0x9E,0x5C,0xD8,0x15, 0xD,0xE1, + 0xF6,0x11,0x54,0x6B,0xCD,0x21,0x46,0x66,0x5E,0x84,0xAD, 6,0x38,0x29,0x44,0xC5, + 0xA2,0xCE,0xF1,0xAA,0xC1,0x40,0x71,0x86,0xB5,0xEF,0xFC,0x36,0xA8,0xCB, 0xA,0x48, + 0x27,0x45,0x64,0xA3,0xAF,0x8C,0xB2,0xC6,0x9F, 7,0x89,0xDC,0x17,0xD3,0x49,0x79, + 0xFB,0xFE,0x1D,0xD0,0xB9,0x88,0x43,0x52,0xBC, 1,0x78,0x2B,0x7D,0x94,0xC7, 0xE, + 0xDE,0xA5,0xD5,0x9B,0xCC,0xF7,0x61,0x7A,0xC2,0x74,0x81,0x39, 3,0xAB,0x96,0xA0, + 0x37,0xBD,0x2D,0x72,0x75,0x3F,0xC9,0xD4,0x8E,0x6F,0xF9,0x8D,0xED,0x62,0xDB,0x1C, + 0xDF, 4,0xAC,0x1B,0x6C,0x14,0x4B,0x63,0xD0,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, 0xB,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, 0xF,0x24,0xFF,0x23,0x18,0x85,0x4E,0x7F, 0xC,0xE0,0xA1,0xD2,0xD1,0x2C,0x2A, + 0x4A, 2,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, 3,0xB2,0x4C,0x87,0xA9,0xD4,0x4D, 0xF,0xD8,0x15,0x6C,0xAA, + 0x18,0xF6,0x49,0x57,0x5D,0xFB,0x7A,0x14,0x94,0x63,0xA0,0x11,0xB0,0x9E,0xDE, 5, + 0x46,0xC8,0xEE,0x47,0xDB,0xDC,0x24,0x89,0x9C,0x91,0x97,0x29,0xE9,0x7B,0xC1, 7, + 0x1E,0xB8,0xFD,0xFE,0xAC,0xC6,0x62,0x98,0x4F,0xF1,0x79,0xE0,0xE8,0x6B,0x78,0x56, + 0xB6,0x8D, 4,0x50,0x86,0xCA,0x6F,0x20,0xE6,0xEA,0xE5,0x76,0x17,0x1C,0x74,0x7F, + 0xBC, 0xD,0x2C,0x85,0xF7,0x66,0x96,0xE4,0x8B,0x75,0x3F,0x4B,0xD9,0x38,0xAF,0x7C, + 0xDA, 0xB,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, 1,0xA6,0xD7,0xB5, + 0xC0,0x7D,0xFF,0x58, 0xE,0x3A,0x92,0xD1,0x55,0xE3, 8,0x9F,0xD6,0x3E,0x52,0x8E, + 0xFA,0xA3,0xC7, 2,0xCD,0xDF,0x8F,0x64,0x19,0x8C,0xF3,0xA7, 0xC,0x5E, 0xA,0x6A, + 9,0xF0,0x93,0x5B,0x42,0xC2, 6,0x23,0xEC,0x71,0xAD,0xB4,0xCB,0xBB,0x70,0x28, + 0xD5,0x1A,0x5C,0x33,0x68,0x5A, 0,0x44,0x90,0xA5,0xC4,0x26,0x3D,0x2B,0xF2,0x54, + }, + { + 0x96,0xAD,0xDA,0x1F,0xED,0x33,0xE1,0x81,0x69, 8, 0xD, 0xA,0xDB,0x35,0x77,0x9A, + 0x64,0xD1,0xFC,0x78,0xAA,0x1B,0xD0,0x67,0xA0,0xDD,0xFA,0x6C,0x63,0x71, 5,0x84, + 0x17,0x6A,0x89,0x4F,0x66,0x7F,0xC6,0x50,0x55,0x92,0x6F,0xBD,0xE7,0xD2,0x40,0x72, + 0x8D,0xBB,0xEC, 6,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, 0xF,0xF2,0x3B,0x51,0xC1,0xDE,0x5F,0xE5,0x2A,0x2F,0x99, 0xB,0x5D,0xA3,0x2B, + 0x4A,0xAB,0x95,0xA5,0xD3,0x58,0x56,0xEE,0x28,0x31, 0,0xCC,0x15,0x46,0xCA,0xE6, + 0x86,0x38,0x3C,0x65,0xF5,0xE3,0x9F,0xD6,0x5B, 9,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, 0xE,0x1E,0xBE,0xD5,0x22,0x23,0xB1,0xC9, + 0x18,0x62,0x16,0x2E,0x91,0x3E, 7,0x8F,0xD8,0x3F,0x93,0x3D,0xD4,0x9B,0xDF,0x85, + 0x21,0xFB,0x11,0x74,0x97,0xC7,0xD7,0xDC,0x4C,0x19,0x45,0x98,0xE9,0x43, 2,0x4B, + 0xBC,0xC3, 4,0x9C,0x6B,0xF0,0x75,0x52,0xA7,0x26,0xF6,0xC5,0xBA,0xCF,0xB0,0xB7, + 0xAE,0x5A,0xA1,0xBF, 3,0x8B,0x80,0x12,0x6E, 0xC,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, 1,0x1D,0xB6,0xFD,0x37,0x48,0x4D,0x39,0xCB,0xE0,0x32, + } +}; + +#define WII_LOG_BUF_SIZE 256 +static wii_log_event_t wii_log_buf[WII_LOG_BUF_SIZE]; +static uint16_t wii_log_head = 0; +static uint16_t wii_log_tail = 0; +static uint16_t wii_log_dropped = 0; +static bool tx_first_read = true; + +static inline void wii_log_push(uint8_t kind, uint8_t reg, uint8_t val) { +#if WII_EXTENSION_DEBUG==true + uint16_t next = (uint16_t)((wii_log_head + 1) % WII_LOG_BUF_SIZE); + if (next == wii_log_tail) { + wii_log_dropped++; + return; + } + wii_log_buf[wii_log_head].kind = kind; + wii_log_buf[wii_log_head].reg = reg; + wii_log_buf[wii_log_head].val = val; + wii_log_head = next; +#endif +} + +static void wii_log_drain(void) { +#if WII_EXTENSION_DEBUG==true +// while (wii_log_tail != wii_log_head) { +// wii_log_event_t e = wii_log_buf[wii_log_tail]; +// wii_log_tail = (uint16_t)((wii_log_tail + 1) % WII_LOG_BUF_SIZE); +// switch (e.kind) { +// case 'A': printf("[wii_ext] seek 0x%02X\n", e.reg); break; +// case 'W': printf("[wii_ext] W 0x%02X = 0x%02X\n", e.reg, e.val); break; +// case 'R': printf("[wii_ext] R 0x%02X = 0x%02X\n", e.reg, e.val); break; +// case 'M': printf("[wii_ext] format mode changed: 0x%02X -> 0x%02X\n", e.reg, e.val); break; +// } +// } +// if (wii_log_dropped) { +// printf("[wii_ext] dropped %u log events\n", (unsigned)wii_log_dropped); +// wii_log_dropped = 0; +// } +#endif +} + + WiiExtension::WiiExtension(PeripheralI2C *i2cController, uint8_t addr) { i2c = i2cController; address = addr; } void WiiExtension::begin() { - doI2CInit(); + if (this->extensionMode) { + i2c_slave_init(i2c->getController(), address, &this->i2cHandler); + } else { + doI2CInit(); #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::begin\n"); + printf("WiiExtension::begin\n"); #endif + } isReady = false; } void WiiExtension::start() { - uint8_t idRead[32]; - uint8_t regWrite[16]; - bool canContinue = true; - int8_t result, retryCtr; - - // we need to determine which address gets used - if (isMotionPlus && !isExtension) { - // Motion Plus only + if (this->extensionMode) { + memset((void *)WiiExtension_extensionMemory, 0, sizeof WiiExtension_extensionMemory); + WiiExtension_memoryCursor = 0; + WiiExtension_hasAddress = false; + WiiExtension_firstRead = true; + WiiExtension_isCryptoEnabled = false; + + // reset extension type + WiiExtension_extensionMemory[0xFA+0] = 0x00; + WiiExtension_extensionMemory[0xFA+1] = 0x00; + WiiExtension_extensionMemory[0xFA+2] = 0xA4; + WiiExtension_extensionMemory[0xFA+3] = 0x20; + WiiExtension_extensionMemory[0xFA+4] = 0x01; + WiiExtension_extensionMemory[0xFA+5] = 0x00; + + // change to extension ID + switch (extensionType) { + case WII_EXTENSION_NUNCHUCK: + { + WiiExtension_extensionMemory[0xFA+0] = 0x00; + WiiExtension_extensionMemory[0xFA+4] = 0x00; + WiiExtension_extensionMemory[0xFA+5] = 0x00; + extensionController = new NunchuckExtension(); + + // set neutral position + WiiExtension_extensionMemory[0x00] = 0xA0; // RX<4:3>=10, LX=0x20 + WiiExtension_extensionMemory[0x01] = 0x20; // RX<2:1>=00, LY=0x20 + WiiExtension_extensionMemory[0x02] = 0x10; // RX<0>=0, LT<4:3>=0, RY=0x10 + WiiExtension_extensionMemory[0x03] = 0x00; // LT<2:0>=0, RT=0 + WiiExtension_extensionMemory[0x04] = 0xFF; // buttons unpressed + WiiExtension_extensionMemory[0x05] = 0xFF; + + // set default calibration + uint8_t cal[16] = { + 0x00, 0x00, 0x00, // 0GX<9:2>, 0GY<9:2>, 0GZ<9:2> + 0x00, // LSB of 0G X, Y, Z + 0x00, 0x00, 0x00, // 1GX<9:2>, 1GY<9:2>, 1GZ<9:2> + 0x00, // LSB of 1G X, Y, Z + 0x00, 0x00, 0x00, // X max, min, center + 0x00, 0x00, 0x00, // Y + 0x00, 0x00, // checksum (filled below) + }; + uint8_t checksum = 0x55; + for (int i = 0; i < 14; i++) checksum += cal[i]; + cal[14] = checksum; + cal[15] = (uint8_t)(checksum + 0x55); + + memcpy((void *)&WiiExtension_extensionMemory[0x20], cal, 16); + memcpy((void *)&WiiExtension_extensionMemory[0x30], cal, 16); // mirror + break; + } + case WII_EXTENSION_CLASSIC: + case WII_EXTENSION_CLASSIC_PRO: + { + WiiExtension_extensionMemory[0xFA+0] = 0x00; + if (extensionType == WII_EXTENSION_CLASSIC) { + WiiExtension_extensionMemory[0xFA+4] = 0x01; + } + WiiExtension_extensionMemory[0xFA+5] = 0x01; + extensionController = new ClassicExtension(); + + // set neutral position + WiiExtension_extensionMemory[0x00] = 0xA0; // RX<4:3>=10, LX=0x20 + WiiExtension_extensionMemory[0x01] = 0x20; // RX<2:1>=00, LY=0x20 + WiiExtension_extensionMemory[0x02] = 0x10; // RX<0>=0, LT<4:3>=0, RY=0x10 + WiiExtension_extensionMemory[0x03] = 0x00; // LT<2:0>=0, RT=0 + WiiExtension_extensionMemory[0x04] = 0xFF; // buttons unpressed + WiiExtension_extensionMemory[0x05] = 0xFF; + + // set default calibration + uint8_t cal[16] = { + 0x00, 0x00, 0x00, // LX max, min, center + 0x00, 0x00, 0x00, // LY + 0x00, 0x00, 0x00, // RX + 0x00, 0x00, 0x00, // RY + 0x00, 0x00, // LT, RT neutral + 0x00, 0x00, // checksum (filled below) + }; + uint8_t checksum = 0x55; + for (int i = 0; i < 14; i++) checksum += cal[i]; + cal[14] = checksum; + cal[15] = (uint8_t)(checksum + 0x55); + + memcpy((void *)&WiiExtension_extensionMemory[0x20], cal, 16); + memcpy((void *)&WiiExtension_extensionMemory[0x30], cal, 16); // mirror + break; + } + case WII_EXTENSION_GUITAR: + case WII_EXTENSION_DRUMS: + case WII_EXTENSION_TURNTABLE: + { + WiiExtension_extensionMemory[0xFA+4] = 0x01; + WiiExtension_extensionMemory[0xFA+5] = 0x03; + if (extensionType == WII_EXTENSION_GUITAR) { + WiiExtension_extensionMemory[0xFA+0] = 0x00; + extensionController = new GuitarExtension(); + } else if (extensionType == WII_EXTENSION_DRUMS) { + WiiExtension_extensionMemory[0xFA+0] = 0x01; + extensionController = new DrumExtension(); + } else if (extensionType == WII_EXTENSION_TURNTABLE) { + WiiExtension_extensionMemory[0xFA+0] = 0x03; + extensionController = new TurntableExtension(); + } + break; + } + case WII_EXTENSION_TAIKO: + WiiExtension_extensionMemory[0xFA+0] = 0x00; + WiiExtension_extensionMemory[0xFA+4] = 0x01; + WiiExtension_extensionMemory[0xFA+5] = 0x11; + extensionController = new TaikoExtension(); + break; + case WII_EXTENSION_TRAIN: + WiiExtension_extensionMemory[0xFA+0] = 0x00; + WiiExtension_extensionMemory[0xFA+4] = 0x03; + WiiExtension_extensionMemory[0xFA+5] = 0x10; + extensionController = new TrainExtension(); + break; + case WII_EXTENSION_DRAWSOME: + WiiExtension_extensionMemory[0xFA+0] = 0xFF; + WiiExtension_extensionMemory[0xFA+4] = 0x00; + WiiExtension_extensionMemory[0xFA+5] = 0x13; + //extensionController = new DrawsomeExtension(); + break; + case WII_EXTENSION_UDRAW: + WiiExtension_extensionMemory[0xFA+0] = 0x00; + WiiExtension_extensionMemory[0xFA+4] = 0x01; + WiiExtension_extensionMemory[0xFA+5] = 0x12; + extensionController = new UDrawExtension(); + break; + case WII_EXTENSION_MOTION_PLUS: + WiiExtension_extensionMemory[0xFA+0] = 0x00; + WiiExtension_extensionMemory[0xFA+4] = 0x04; + WiiExtension_extensionMemory[0xFA+5] = 0x05; + extensionController = new MotionPlusExtension(); + break; + } + #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start Motion Plus detected\n"); + //printf("%02x%02x %02x%02x %02x%02x = %d (%d)\n", WiiExtension_extensionMemory[0xFA+0], WiiExtension_extensionMemory[0xFA+1], WiiExtension_extensionMemory[0xFA+2], WiiExtension_extensionMemory[0xFA+3], WiiExtension_extensionMemory[0xFA+4], WiiExtension_extensionMemory[0xFA+5], extensionType, (extensionController == NULL)); #endif - address = WII_MOTIONPLUS_I2C_ADDR; - } else if (!isMotionPlus && isExtension) { - // Extension only + + isReady = true; + } else { + uint8_t idRead[32]; + uint8_t regWrite[16]; + bool canContinue = true; + int8_t result, retryCtr; + + // we need to determine which address gets used + if (isMotionPlus && !isExtension) { + // Motion Plus only #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start Extension detected\n"); + printf("WiiExtension::start Motion Plus detected\n"); #endif - address = WII_EXTENSION_I2C_ADDR; - } else if (isMotionPlus && isExtension) { - // Both attached + address = WII_MOTIONPLUS_I2C_ADDR; + } else if (!isMotionPlus && isExtension) { + // Extension only #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start Motion Plus & Extension detected\n"); + printf("WiiExtension::start Extension detected\n"); #endif - address = WII_MOTIONPLUS_I2C_ADDR; - } else { - // Nothing attached + address = WII_EXTENSION_I2C_ADDR; + } else if (isMotionPlus && isExtension) { + // Both attached #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start No Extension devices detected\n"); + printf("WiiExtension::start Motion Plus & Extension detected\n"); #endif - canContinue = false; - isReady = false; - return; - } - - if (!isReady) { -#if WII_EXTENSION_ENCRYPTION==false - if (canContinue) { - regWrite[0] = 0xF0; - regWrite[1] = 0x55; - result = doI2CWrite(regWrite, 2); - canContinue = (result > -1); - + address = WII_MOTIONPLUS_I2C_ADDR; + } else { + // Nothing attached #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start 0xF0? %1d\n", result); + printf("WiiExtension::start No Extension devices detected\n"); #endif - } else { canContinue = false; + isReady = false; + return; } - result = doI2CRead(regWrite, 1); - if (canContinue) { - regWrite[0] = 0xFB; - regWrite[1] = 0x00; - result = doI2CWrite(regWrite, 2); - canContinue = (result > -1); + if (!isReady) { +#if WII_EXTENSION_ENCRYPTION==false + if (canContinue) { + regWrite[0] = 0xF0; + regWrite[1] = 0x55; + result = doI2CWrite(regWrite, 2); + canContinue = (result > -1); #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start 0xFB? %1d\n", result); -#endif - } else { - canContinue = false; - } + printf("WiiExtension::start 0xF0? %1d\n", result); #endif + } else { + canContinue = false; + } + result = doI2CRead(regWrite, 1); - result = doI2CRead(regWrite, 1); - - if (canContinue) { - for (retryCtr = 0; retryCtr < 3; retryCtr++) { - // set data format - regWrite[0] = 0xFE; - if (isMotionPlus) { - //regWrite[1] = 0x04; - regWrite[1] = 0x05; - } else { - regWrite[1] = 0x03; - } + if (canContinue) { + regWrite[0] = 0xFB; + regWrite[1] = 0x00; result = doI2CWrite(regWrite, 2); + canContinue = (result > -1); #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start 0xFE? %1d\n", result); + printf("WiiExtension::start 0xFB? %1d\n", result); #endif + } else { + canContinue = false; + } +#endif + + result = doI2CRead(regWrite, 1); - // no error returned, check the device ID - if (result > -1) { + if (canContinue) { + for (retryCtr = 0; retryCtr < 3; retryCtr++) { + // set data format + regWrite[0] = 0xFE; if (isMotionPlus) { - // switch address back - address = WII_EXTENSION_I2C_ADDR; + //regWrite[1] = 0x04; + regWrite[1] = 0x05; + } else { + regWrite[1] = 0x03; } - - result = doI2CRead(idRead, 2); - isReady = true; + result = doI2CWrite(regWrite, 2); #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start 0xFE Check %02x %02x\n", idRead[0], idRead[1]); + printf("WiiExtension::start 0xFE? %1d\n", result); #endif - break; - } - } - } - result = doI2CRead(regWrite, 1); - } + // no error returned, check the device ID + if (result > -1) { + if (isMotionPlus) { + // switch address back + address = WII_EXTENSION_I2C_ADDR; + } + + result = doI2CRead(idRead, 2); + isReady = true; #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start Is Ready? %01d\n", isReady); + printf("WiiExtension::start 0xFE Check %02x %02x\n", idRead[0], idRead[1]); #endif + break; + } + } + } - if (isReady) { - // fetch the extension ID - regWrite[0] = 0xFA; - result = doI2CWrite(®Write[0], 1); + result = doI2CRead(regWrite, 1); + } #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::start Extension Check? %1d\n", result); + printf("WiiExtension::start Is Ready? %01d\n", isReady); #endif - extensionType = WII_EXTENSION_NONE; + if (isReady) { + // fetch the extension ID + regWrite[0] = 0xFA; + result = doI2CWrite(®Write[0], 1); - // continue if the write was successful - if (result > -1) { - result = doI2CRead(idRead, 6); +#if WII_EXTENSION_DEBUG==true + printf("WiiExtension::start Extension Check? %1d\n", result); +#endif - if (idRead[2] != 0xA4 || idRead[3] != 0x20) return; + extensionType = WII_EXTENSION_NONE; - if (idRead[5] == 0x00) { - extensionType = WII_EXTENSION_NUNCHUCK; - extensionController = new NunchuckExtension(); - } else if (idRead[5] == 0x01) { - extensionType = WII_EXTENSION_CLASSIC; - //if (idRead[0] == 0x01) { - // extensionType = WII_EXTENSION_CLASSIC_PRO; - //} - extensionController = new ClassicExtension(); - } else if (idRead[5] == 0x03) { - extensionType = WII_EXTENSION_GUITAR; - if (idRead[0] == 0x01) { - extensionType = WII_EXTENSION_DRUMS; - extensionController = new DrumExtension(); - } else if (idRead[0] == 0x03) { - extensionType = WII_EXTENSION_TURNTABLE; - extensionController = new TurntableExtension(); - } else { - extensionController = new GuitarExtension(); + // continue if the write was successful + if (result > -1) { + result = doI2CRead(idRead, 6); + + if (idRead[2] != 0xA4 || idRead[3] != 0x20) return; + + if (idRead[5] == 0x00) { + extensionType = WII_EXTENSION_NUNCHUCK; + extensionController = new NunchuckExtension(); + } else if (idRead[5] == 0x01) { + extensionType = WII_EXTENSION_CLASSIC; + //if (idRead[0] == 0x01) { + // extensionType = WII_EXTENSION_CLASSIC_PRO; + //} + extensionController = new ClassicExtension(); + } else if (idRead[5] == 0x03) { + extensionType = WII_EXTENSION_GUITAR; + if (idRead[0] == 0x01) { + extensionType = WII_EXTENSION_DRUMS; + extensionController = new DrumExtension(); + } else if (idRead[0] == 0x03) { + extensionType = WII_EXTENSION_TURNTABLE; + extensionController = new TurntableExtension(); + } else { + extensionController = new GuitarExtension(); + } + } else if (idRead[5] == 0x05) { + extensionType = WII_EXTENSION_MOTION_PLUS; + extensionController = new MotionPlusExtension(); + } else if (idRead[5] == 0x11) { + extensionType = WII_EXTENSION_TAIKO; + extensionController = new TaikoExtension(); + } else if (idRead[5] == 0x12) { + extensionType = WII_EXTENSION_UDRAW; + extensionController = new UDrawExtension(); } - } else if (idRead[5] == 0x05) { - extensionType = WII_EXTENSION_MOTION_PLUS; - extensionController = new MotionPlusExtension(); - } else if (idRead[5] == 0x11) { - extensionType = WII_EXTENSION_TAIKO; - extensionController = new TaikoExtension(); - } else if (idRead[5] == 0x12) { - extensionType = WII_EXTENSION_UDRAW; - extensionController = new UDrawExtension(); - } - // in certain situations (eg. Nunchuck), setting the data type in reset() does not affect what this value will be - dataType = idRead[4]; - if (dataType == WII_DATA_TYPE_0) dataType = WII_DATA_TYPE_1; - extensionController->init(dataType); - extensionController->setExtensionType(extensionType); + // in certain situations (eg. Nunchuck), setting the data type in reset() does not affect what this value will be + dataType = idRead[4]; + if (dataType == WII_DATA_TYPE_0) dataType = WII_DATA_TYPE_1; + extensionController->init(dataType); + extensionController->setExtensionType(extensionType); #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::Extension ID: %02x%02x %02x%02x %02x%02x\n", idRead[0], idRead[1], idRead[2], idRead[3], idRead[4], idRead[5]); - printf("WiiExtension::Data Format: %02x\n",idRead[4]); + printf("WiiExtension::Extension ID: %02x%02x %02x%02x %02x%02x\n", idRead[0], idRead[1], idRead[2], idRead[3], idRead[4], idRead[5]); + printf("WiiExtension::Data Format: %02x\n",idRead[4]); #endif - if (extensionType != WII_EXTENSION_NONE) { + if (extensionType != WII_EXTENSION_NONE) { #if WII_EXTENSION_CALIBRATION==true #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::Calibration Data\n"); + printf("WiiExtension::Calibration Data\n"); #endif - regWrite[0] = 0x20; - doI2CWrite(regWrite, 1); + regWrite[0] = 0x20; + doI2CWrite(regWrite, 1); - doI2CRead(idRead, 32); - extensionController->calibrate(idRead); + doI2CRead(idRead, 32); + extensionController->calibrate(idRead); #endif - } else { + } else { #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::Unknown Extension: %02x%02x %02x%02x %02x%02x\n", idRead[0], idRead[1], idRead[2], idRead[3], idRead[4], idRead[5]); + printf("WiiExtension::Unknown Extension: %02x%02x %02x%02x %02x%02x\n", idRead[0], idRead[1], idRead[2], idRead[3], idRead[4], idRead[5]); #endif - } + } - regWrite[0] = 0x00; - result = doI2CWrite(regWrite, 1); + regWrite[0] = 0x00; + result = doI2CWrite(regWrite, 1); + } } } } void WiiExtension::poll() { - uint8_t regWrite[16]; - uint8_t regRead[16]; - int8_t result; + //printf("Polling\n"); + if (this->extensionMode) { + //printf("Controller Type: %d\n", extensionType); + uint8_t outputSize = extensionController->prepareOutput(); + //printf("Output Size: %d\n", outputSize); + + if (outputSize > 0) { + memcpy((void *)&WiiExtension_extensionMemory[0x00], extensionController->controllerData, outputSize); + + //WiiExtension_extensionMemory[0x00] = 0xA0; // RX<4:3>=10, LX=0x20 + //WiiExtension_extensionMemory[0x01] = 0x20; // RX<2:1>=00, LY=0x20 + //WiiExtension_extensionMemory[0x02] = 0x10; // RX<0>=0, LT<4:3>=0, RY=0x10 + //WiiExtension_extensionMemory[0x03] = 0x00; // LT<2:0>=0, RT=0 + //WiiExtension_extensionMemory[0x04] = 0xFF; // buttons unpressed + //WiiExtension_extensionMemory[0x05] = ((!(extensionController->buttons[WiiButtons::WII_BUTTON_C] & 0x01)) << 1) | ((!(extensionController->buttons[WiiButtons::WII_BUTTON_Z] & 0x01)) << 0); + + //printf("%d\n", WiiExtension_extensionMemory[0x05]); + } + + wii_log_drain(); + } else { + uint8_t regWrite[16]; + uint8_t regRead[16]; + int8_t result; + + std::memset(regRead,0,sizeof(regRead)); #if WII_EXTENSION_DEBUG==true - //printf("WiiExtension::poll\n"); - //printf("WiiExtension::poll isReady? %1d\n", isReady); + //printf("WiiExtension::poll\n"); + //printf("WiiExtension::poll isReady? %1d\n", isReady); #endif - if (!isReady) return; + if (!isReady) return; - if (extensionType != WII_EXTENSION_NONE) { - switch (dataType) { - case WII_DATA_TYPE_1: - result = doI2CRead(regRead, 6); - break; - case WII_DATA_TYPE_2: - result = doI2CRead(regRead, 9); - break; - case WII_DATA_TYPE_3: - result = doI2CRead(regRead, 8); - break; - // Motion Plus data types - case WII_DATA_TYPE_4: - case WII_DATA_TYPE_5: - case WII_DATA_TYPE_6: - case WII_DATA_TYPE_7: - result = doI2CRead(regRead, 16); - break; - default: - // unknown. TBD - result = -1; + if (extensionType != WII_EXTENSION_NONE) { + switch (dataType) { + case WII_DATA_TYPE_1: + result = doI2CRead(regRead, 6); + break; + case WII_DATA_TYPE_2: + result = doI2CRead(regRead, 9); + break; + case WII_DATA_TYPE_3: + result = doI2CRead(regRead, 8); + break; + // Motion Plus data types + case WII_DATA_TYPE_4: + case WII_DATA_TYPE_5: + case WII_DATA_TYPE_6: + case WII_DATA_TYPE_7: + result = doI2CRead(regRead, 16); + break; + default: + // unknown. TBD + result = -1; #if WII_EXTENSION_DEBUG==true - printf("WiiExtension::poll Unknown data type: %1d\n", dataType); + printf("WiiExtension::poll Unknown data type: %1d\n", dataType); #endif - break; - } + break; + } - if (result > 0) { - extensionController->process(regRead); - if (!extensionController->skipPostProcess) extensionController->postProcess(); + if (result > 0) { + extensionController->process(regRead); + std::memset(extensionController->controllerData,0,sizeof(extensionController->controllerData)); + std::memcpy(extensionController->controllerData,regRead,sizeof(extensionController->controllerData)); + if (!extensionController->skipPostProcess) extensionController->postProcess(); #if WII_EXTENSION_DEBUG==true - for (int i = 0; i < result; ++i) { - _lastRead[i] = regRead[i]; - } + for (int i = 0; i < result; ++i) { + _lastRead[i] = regRead[i]; + } #endif - if (extensionType == WII_EXTENSION_TURNTABLE) { - regWrite[0] = 0xFB; - regWrite[1] = ((TurntableExtension*)extensionController)->getLED(); - result = doI2CWrite(regWrite, 2); - } + if (extensionType == WII_EXTENSION_TURNTABLE) { + regWrite[0] = 0xFB; + regWrite[1] = ((TurntableExtension*)extensionController)->getLED(); + result = doI2CWrite(regWrite, 2); + } - // continue poll - regWrite[0] = 0x00; - result = doI2CWrite(regWrite, 1); + // continue poll + regWrite[0] = 0x00; + result = doI2CWrite(regWrite, 1); + } else { + // device disconnected or invalid read + extensionType = WII_EXTENSION_NONE; + reset(); + start(); + } } else { - // device disconnected or invalid read - extensionType = WII_EXTENSION_NONE; reset(); start(); } - } else { - reset(); - start(); } } void WiiExtension::reset() { - isReady = false; + if (this->extensionMode) { + + } else { + isReady = false; + } } int WiiExtension::doI2CWrite(uint8_t *pData, int iLen) { @@ -353,3 +753,167 @@ void WiiExtension::alarmIRQ() { // Assume alarm 0 has fired WiiExtension_alarmFired = true; } + +void WiiExtension::i2cHandler(i2c_inst_t *i2c, i2c_slave_event_t event) { + switch (event) { + case I2C_SLAVE_RECEIVE: { + // Master sent us a byte. If this is the first byte of the + // transaction, it's the register address to seek to. + // Subsequent bytes are writes to that address with + // auto-increment. + uint8_t b = (uint8_t)i2c_read_byte_raw(i2c); + if (!WiiExtension_hasAddress) { + WiiExtension_memoryCursor = b; + WiiExtension_hasAddress = true; + // Suppress the very common 0x00 data-poll seek so init reads + // (0x20, 0x30, 0xFA, 0xFE, ...) are visible in the log. + if (b != 0x00) wii_log_push('A', b, 0); + } else { + // Decrypt incoming write IF encryption is on � but skip + // the decrypt for control registers (0xF0, 0xFB, 0xFE), + // which the Wii always sends in plaintext for protocol + // negotiation. This lets a new session reset stale + // encryption state from a previous session: when 0x55 + // arrives at 0xF0, we recognize it raw and disable. + bool is_control_reg = ((WiiExtension_memoryCursor == 0xF0) || (WiiExtension_memoryCursor == 0xFB)); + uint8_t store_b = b; + if (WiiExtension_isCryptoEnabled && !is_control_reg) { + decrypt(&store_b, (uint8_t)WiiExtension_memoryCursor, 1); + } + if (WiiExtension_memoryCursor < WII_EXT_MEMORY_SIZE) { + WiiExtension_extensionMemory[WiiExtension_memoryCursor] = store_b; + } + wii_log_push('W', (uint8_t)WiiExtension_memoryCursor, store_b); + // Encryption negotiation. Both 0x55 and 0xAA writes to 0xF0 + // disable encryption � the Wiimote then sends a fresh + // 16-byte key in plaintext to 0x40-0x4F, and we re-init + // the cipher when the last key byte (0x4F) lands. + if (WiiExtension_memoryCursor == 0xF0) { + if (store_b == 0x55 || store_b == 0xAA) { + WiiExtension_isCryptoEnabled = false; + } + } else if (WiiExtension_memoryCursor == 0x4F && WiiExtension_extensionMemory[0xF0] == 0xAA) { + initCrypt(&WiiExtension_extensionMemory[0x40]); + } else if (WiiExtension_memoryCursor == 0xFE) { + // Format-mode switch — mirror into id[4] (the ID byte + // and the 0xFE format register must agree per real-CC + // behavior). Also seed sensible neutral data bytes + // for the new format so a host read between the mode + // switch and the next BT input event sees centred + // sticks instead of stale bytes from the old format. + uint8_t prev = WiiExtension_extensionMemory[0xFE]; + if (prev != store_b) { + wii_log_push('M', prev, store_b); // 'M' = mode change + } + WiiExtension_extensionMemory[0xFE] = store_b; + WiiExtension_extensionMemory[0xFA + 4] = store_b; + } + WiiExtension_memoryCursor = (uint16_t)(WiiExtension_memoryCursor + 1) % WII_EXT_MEMORY_SIZE; + } + } + break; + case I2C_SLAVE_REQUEST: { + // Master wants to read. Encrypt if encryption is active. + uint8_t out_byte; + if (WiiExtension_memoryCursor < WII_EXT_MEMORY_SIZE) { + out_byte = WiiExtension_extensionMemory[WiiExtension_memoryCursor]; + if (WiiExtension_isCryptoEnabled) { + encrypt(&out_byte, (uint8_t)WiiExtension_memoryCursor, 1); + } + } else { + out_byte = 0xFF; + } + // Log the first byte of each read transaction (skip 0x00 polls). + if (WiiExtension_firstRead && WiiExtension_memoryCursor != 0x00) { + wii_log_push('R', (uint8_t)WiiExtension_memoryCursor, out_byte); + } + WiiExtension_firstRead = false; + i2c_write_byte_raw(i2c, out_byte); + WiiExtension_memoryCursor = (uint16_t)(WiiExtension_memoryCursor + 1) % WII_EXT_MEMORY_SIZE; + } + break; + case I2C_SLAVE_FINISH: { + // STOP or RESTART: end of this transaction. Reset the + // "next-byte-is-address" flag so the next RECEIVE starts a + // fresh seek. Keep `memoryCursor` pointing where the last read + // left off � real Wii extensions auto-increment across + // back-to-back reads, and some games depend on it. + WiiExtension_hasAddress = false; + WiiExtension_firstRead = true; + } + break; + default: { + break; + } + } +} + +static inline uint8_t ror8(uint8_t a, uint8_t b) +{ + return (a>>b) | ((a<<(8-b))&0xff); +} + +void WiiExtension::initCrypt(const uint8_t key[16]) { + int idx, i; + const uint8_t * ans; + uint8_t t0[10]; + + //determine idx with simple brute force + for (idx = 0; idx < 7; idx++) + { + ans = ans_tbl[idx]; + + for(i = 0; i < 10; i++) + { + t0[i] = sboxes[0][key[9 - i]]; + } + + //todo: clean up this nasty mess + if ((key[0xf] == (uint8_t)((ror8(ans[0]^t0[5],t0[2]%8) - t0[9]) ^ t0[4])) && + (key[0xe] == (uint8_t)((ror8(ans[1]^t0[1],t0[0]%8) - t0[5]) ^ t0[7])) && + (key[0xd] == (uint8_t)((ror8(ans[2]^t0[6],t0[8]%8) - t0[2]) ^ t0[0])) && + (key[0xc] == (uint8_t)((ror8(ans[3]^t0[4],t0[7]%8) - t0[3]) ^ t0[2])) && + (key[0xb] == (uint8_t)((ror8(ans[4]^t0[1],t0[6]%8) - t0[3]) ^ t0[4])) && + (key[0xa] == (uint8_t)((ror8(ans[5]^t0[7],t0[8]%8) - t0[5]) ^ t0[9]))) + { + break; + } + } + + WiiExtension_ft[0] = sboxes[idx+1][key[0xb]] ^ sboxes[idx+2][key[0x6]]; + WiiExtension_ft[1] = sboxes[idx+1][key[0xd]] ^ sboxes[idx+2][key[0x4]]; + WiiExtension_ft[2] = sboxes[idx+1][key[0xa]] ^ sboxes[idx+2][key[0x2]]; + WiiExtension_ft[3] = sboxes[idx+1][key[0xf]] ^ sboxes[idx+2][key[0x7]]; + WiiExtension_ft[4] = sboxes[idx+1][key[0xe]] ^ sboxes[idx+2][key[0x5]]; + WiiExtension_ft[5] = sboxes[idx+1][key[0xc]] ^ sboxes[idx+2][key[0x0]]; + WiiExtension_ft[6] = sboxes[idx+1][key[0x9]] ^ sboxes[idx+2][key[0x3]]; + WiiExtension_ft[7] = sboxes[idx+1][key[0x8]] ^ sboxes[idx+2][key[0x1]]; + + WiiExtension_sb[0] = sboxes[idx+1][key[0xf]] ^ sboxes[idx+2][key[0x8]]; + WiiExtension_sb[1] = sboxes[idx+1][key[0xa]] ^ sboxes[idx+2][key[0x5]]; + WiiExtension_sb[2] = sboxes[idx+1][key[0xc]] ^ sboxes[idx+2][key[0x9]]; + WiiExtension_sb[3] = sboxes[idx+1][key[0xd]] ^ sboxes[idx+2][key[0x0]]; + WiiExtension_sb[4] = sboxes[idx+1][key[0xb]] ^ sboxes[idx+2][key[0x2]]; + WiiExtension_sb[5] = sboxes[idx+1][key[0xe]] ^ sboxes[idx+2][key[0x1]]; + WiiExtension_sb[6] = sboxes[idx+1][key[0x6]] ^ sboxes[idx+2][key[0x4]]; + WiiExtension_sb[7] = sboxes[idx+1][key[0x7]] ^ sboxes[idx+2][key[0x3]]; + + WiiExtension_isCryptoEnabled = true; +#if WII_EXTENSION_DEBUG==true + //printf("[wii_ext_crypto] Encryption enabled (ft=%02X%02X%02X%02X sb=%02X%02X%02X%02X)\n", WiiExtension_ft[0], WiiExtension_ft[1], WiiExtension_ft[2], WiiExtension_ft[3], WiiExtension_sb[0], WiiExtension_sb[1], WiiExtension_sb[2], WiiExtension_sb[3]); +#endif +} + +void WiiExtension::encrypt(uint8_t* data, uint8_t addr, uint8_t len) { + for (int i = 0; i < len; i++) + { + data[i] = (data[i] - WiiExtension_ft[(i + addr) % 8]) ^ WiiExtension_sb[(i + addr) % 8]; + } +} + +void WiiExtension::decrypt(uint8_t* data, uint8_t addr, uint8_t len) { + for (int i = 0; i < len; i++) + { + data[i] = (data[i] ^ WiiExtension_sb[(i + addr) % 8]) + WiiExtension_ft[(i + addr) % 8]; + } +} \ No newline at end of file diff --git a/lib/WiiExtension/WiiExtension.h b/lib/WiiExtension/WiiExtension.h index 520c6f0907..1fd2153244 100644 --- a/lib/WiiExtension/WiiExtension.h +++ b/lib/WiiExtension/WiiExtension.h @@ -6,6 +6,7 @@ #include "pico/stdlib.h" #include "hardware/i2c.h" +#include "pico/i2c_slave.h" #include "peripheral_i2c.h" #include "extensions/Extensions.h" @@ -99,6 +100,7 @@ typedef enum { #define WII_CHECKSUM_MAGIC 0x55 #define WII_CALIBRATION_SIZE 0x10 #define WII_CALIBRATION_CHECKSUM_SIZE 0x02 +#define WII_EXT_MEMORY_SIZE 256 static volatile bool WiiExtension_alarmFired; @@ -116,47 +118,65 @@ static volatile bool WiiExtension_alarmFired; #define TOUCH_BETWEEN_RANGE(val,beg,end) (((val) >= ((beg)-WII_GUITAR_TOUCHPAD_OVERLAP)) && ((val) < (end))) #define WII_DECRYPT_BYTE(x) (((x) ^ 0x17) + 0x17) -class WiiExtension { - protected: - uint8_t address; - PeripheralI2C* i2c; - public: - int8_t extensionType = WII_EXTENSION_NONE; - int8_t dataType = WII_DATA_TYPE_0; - - bool isReady = false; - - // Constructor - WiiExtension() {} - WiiExtension(PeripheralI2C *i2cController, uint8_t addr); - - // Methods - void begin(); - void reset(); - void start(); - void poll(); +static bool WiiExtension_isCryptoEnabled; +static uint8_t WiiExtension_extensionMemory[WII_EXT_MEMORY_SIZE]; +static uint16_t WiiExtension_memoryCursor; +static bool WiiExtension_hasAddress; +static bool WiiExtension_firstRead; +static uint8_t WiiExtension_ft[8]; +static uint8_t WiiExtension_sb[8]; - void setI2C(PeripheralI2C *i2cController) { this->i2c = i2cController; } - void setAddress(uint8_t addr) { this->address = addr; } - - ExtensionBase* getController() { return extensionController; }; - private: - ExtensionBase *extensionController = NULL; +class WiiExtension { + protected: + uint8_t address; + PeripheralI2C* i2c; + public: + int8_t extensionType = WII_EXTENSION_NONE; + int8_t dataType = WII_DATA_TYPE_0; + + // false = read input from connected device (default) + // true = output as extension + bool extensionMode = false; + + bool isReady = false; + + // Constructor + WiiExtension() {} + WiiExtension(PeripheralI2C *i2cController, uint8_t addr); + + // Methods + void begin(); + void reset(); + void start(); + void poll(); + + void setI2C(PeripheralI2C *i2cController) { this->i2c = i2cController; } + void setAddress(uint8_t addr) { this->address = addr; } + void setExtensionMode(bool extMode) { this->extensionMode = extMode; } + + ExtensionBase* getController() { return extensionController; }; + private: + ExtensionBase *extensionController = NULL; #if WII_EXTENSION_DEBUG==true - uint8_t _lastRead[16] = {0xFF}; + uint8_t _lastRead[16] = {0xFF}; #endif - int doI2CWrite(uint8_t *pData, int iLen); - int doI2CRead(uint8_t *pData, int iLen); - uint8_t doI2CTest(); - void doI2CInit(); + int doI2CWrite(uint8_t *pData, int iLen); + int doI2CRead(uint8_t *pData, int iLen); + uint8_t doI2CTest(); + void doI2CInit(); + + void waitUntil_us(uint64_t us); + static void alarmIRQ(); - void waitUntil_us(uint64_t us); - static void alarmIRQ(); + bool isMotionPlus = false; + bool isExtension = false; - bool isMotionPlus = false; - bool isExtension = false; + static void i2cHandler(i2c_inst_t *i2c, i2c_slave_event_t event); + static void initCrypt(const uint8_t key[16]); + static void decrypt(uint8_t* data, uint8_t addr, uint8_t len); + static void encrypt(uint8_t* data, uint8_t addr, uint8_t len); }; #endif diff --git a/lib/WiiExtension/extensions/ClassicExtension.cpp b/lib/WiiExtension/extensions/ClassicExtension.cpp index c12a46507a..875efb5b8f 100644 --- a/lib/WiiExtension/extensions/ClassicExtension.cpp +++ b/lib/WiiExtension/extensions/ClassicExtension.cpp @@ -207,4 +207,113 @@ void ClassicExtension::process(uint8_t *inputData) { //printf("Joy1 X=%5d Y=%5d Joy2 X=%5d Y=%5d U=%1d D=%1d L=%1d R=%1d TL=%5d TR=%5d\n", analogState[WiiAnalogs::ANALOG_LEFT_X], analogState[WiiAnalogs::ANALOG_LEFT_Y], analogState[WiiAnalogs::ANALOG_RIGHT_X], analogState[WiiAnalogs::ANALOG_RIGHT_Y], directionalPad[WiiDirectionalPad::DIRECTION_UP], directionalPad[WiiDirectionalPad::DIRECTION_DOWN], directionalPad[WiiDirectionalPad::DIRECTION_LEFT], directionalPad[WiiDirectionalPad::DIRECTION_RIGHT], analogState[WiiAnalogs::ANALOG_TRIGGER_LEFT], analogState[WiiAnalogs::ANALOG_TRIGGER_RIGHT]); //printf("A=%1d B=%1d X=%1d Y=%1d ZL=%1d ZR=%1d LT=%1d RT=%1d -=%1d H=%1d +=%1d\n", buttonA, buttonB, buttonX, buttonY, buttonZL, buttonZR, buttonLT, buttonRT, buttonMinus, buttonHome, buttonPlus); #endif -} \ No newline at end of file +} + +uint8_t ClassicExtension::prepareOutput() { + uint16_t lx = 0; + uint16_t ly = 0; + uint16_t rx = 0; + uint16_t ry = 0; + uint16_t lt = 0; + uint16_t rt = 0; + // expect all source analog sticks at 16 bit and scale down + // expect all source analog triggers at 8 bit and scale down + if (getDataType() == WII_DATA_TYPE_1) { + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3F) / 0xFFFF); + ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3F) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x1F) / 0xFFFF); + ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x1F) / 0xFFFF)); + lt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] * 0x1F) / 0xFF); + rt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] * 0x1F) / 0xFF); + + controllerData[0x00] = ((rx & 0x18) << 3) | (lx & 0x3F); + controllerData[0x01] = ((rx & 0x06) << 5) | (ly & 0x3F); + controllerData[0x02] = ((rx & 0x01) << 7) | ((lt & 0x0C) << 5) | (ry & 0x1F); + controllerData[0x03] = ((lt & 0x07) << 5) | (rt & 0x0F); + controllerData[0x04] = (1 | + ((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7)) + ); + controllerData[0x05] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) | + ((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) | + ((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) | + ((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) | + ((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) | + ((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) | + ((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) | + ((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7) + ); + return 6; + } else if (getDataType() == WII_DATA_TYPE_2) { + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3FF) / 0xFFFF); + ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3FF) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x3FF) / 0xFFFF); + ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x3FF) / 0xFFFF)); + lt = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER]; + rt = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER]; + + controllerData[0x00] = ((lx & 0x03FC) >> 2); + controllerData[0x01] = ((rx & 0x03FC) >> 2); + controllerData[0x02] = ((ly & 0x03FC) >> 2); + controllerData[0x03] = ((ry & 0x03FC) >> 2); + controllerData[0x04] = ((lx & 0x03) << 0) | ((rx & 0x03) << 2) | ((ly & 0x03) << 4) | ((ry & 0x03) << 6); + controllerData[0x05] = lt; + controllerData[0x06] = rt; + controllerData[0x07] = (1 | + ((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7)) + ); + controllerData[0x08] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) | + ((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) | + ((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) | + ((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) | + ((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) | + ((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) | + ((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) | + ((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7) + ); + return 9; + } else if (getDataType() == WII_DATA_TYPE_3) { + controllerData[0x00] = analogState[WiiAnalogs::WII_ANALOG_LEFT_X]; + controllerData[0x01] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_X]; + controllerData[0x02] = analogState[WiiAnalogs::WII_ANALOG_LEFT_Y]; + controllerData[0x03] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y]; + controllerData[0x04] = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER]; + controllerData[0x05] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER]; + controllerData[0x06] = (1 | + ((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7)) + ); + controllerData[0x07] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) | + ((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) | + ((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) | + ((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) | + ((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) | + ((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) | + ((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) | + ((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7) + ); + return 8; + } else { + } + + return 0; +} diff --git a/lib/WiiExtension/extensions/ClassicExtension.h b/lib/WiiExtension/extensions/ClassicExtension.h index c2b33f3759..a61bdaf648 100644 --- a/lib/WiiExtension/extensions/ClassicExtension.h +++ b/lib/WiiExtension/extensions/ClassicExtension.h @@ -13,6 +13,7 @@ class ClassicExtension : public ExtensionBase { void init(uint8_t dataType) override; bool calibrate(uint8_t *calibrationData) override; void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; }; #endif \ No newline at end of file diff --git a/lib/WiiExtension/extensions/DrumExtension.cpp b/lib/WiiExtension/extensions/DrumExtension.cpp index 481100325f..34389f4da4 100644 --- a/lib/WiiExtension/extensions/DrumExtension.cpp +++ b/lib/WiiExtension/extensions/DrumExtension.cpp @@ -29,4 +29,114 @@ void DrumExtension::process(uint8_t *inputData) { // _lastRead[i] = inputData[i]; //} #endif -} \ No newline at end of file +} + +uint8_t DrumExtension::prepareOutput() { + uint16_t lx = 0; + uint16_t ly = 0; + uint16_t rx = 0; + uint16_t ry = 0; + uint16_t lt = 0; + uint16_t rt = 0; + // expect all source analog sticks at 16 bit and scale down + // expect all source analog triggers at 8 bit and scale down + if (getDataType() == WII_DATA_TYPE_1) { + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3F) / 0xFFFF); + ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3F) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x1F) / 0xFFFF); + ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x1F) / 0xFFFF)); + lt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] * 0x1F) / 0xFF); + rt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] * 0x1F) / 0xFF); + + controllerData[0x00] = 0xC0 | ((lx+1) & 0x3F); + controllerData[0x01] = 0xC0 | (ly & 0x3F); + controllerData[0x02] = 0xFF; + controllerData[0x03] = 0xFF; + controllerData[0x04] = ( + ((1 << 0)) | + ((1 << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((1 << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((1 << 5)) | + ((1 << 6)) | + ((1 << 7)) + ); + controllerData[0x05] = ( + ((1 << 0)) | + ((1 << 1)) | + ((!(buttons[GuitarButtons::GUITAR_PEDAL] & 0x01) << 2)) | + ((!(buttons[GuitarButtons::GUITAR_YELLOW] & 0x01) << 3)) | + ((!(buttons[GuitarButtons::GUITAR_GREEN] & 0x01) << 4)) | + ((!(buttons[GuitarButtons::GUITAR_BLUE] & 0x01) << 5)) | + ((!(buttons[GuitarButtons::GUITAR_RED] & 0x01) << 6)) | + ((!(buttons[GuitarButtons::GUITAR_ORANGE] & 0x01) << 7)) + ); + return 6; + } else if (getDataType() == WII_DATA_TYPE_2) { + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3FF) / 0xFFFF); + ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3FF) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x3FF) / 0xFFFF); + ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x3FF) / 0xFFFF)); + lt = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER]; + rt = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER]; + + controllerData[0x00] = ((lx & 0x03FC) >> 2); + controllerData[0x01] = ((rx & 0x03FC) >> 2); + controllerData[0x02] = ((ly & 0x03FC) >> 2); + controllerData[0x03] = ((ry & 0x03FC) >> 2); + controllerData[0x04] = ((lx & 0x03) << 0) | ((rx & 0x03) << 2) | ((ly & 0x03) << 4) | ((ry & 0x03) << 6); + controllerData[0x05] = lt; + controllerData[0x06] = rt; + controllerData[0x07] = (1 | + ((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7)) + ); + controllerData[0x08] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) | + ((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) | + ((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) | + ((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) | + ((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) | + ((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) | + ((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) | + ((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7) + ); + return 9; + } else if (getDataType() == WII_DATA_TYPE_3) { + controllerData[0x00] = analogState[WiiAnalogs::WII_ANALOG_LEFT_X]; + controllerData[0x01] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_X]; + controllerData[0x02] = analogState[WiiAnalogs::WII_ANALOG_LEFT_Y]; + controllerData[0x03] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y]; + controllerData[0x04] = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER]; + controllerData[0x05] = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER]; + controllerData[0x06] = (1 | + ((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7)) + ); + controllerData[0x07] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) | + ((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) | + ((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) | + ((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) | + ((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) | + ((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) | + ((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) | + ((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7) + ); + return 8; + } else { + } + + return 0; +} diff --git a/lib/WiiExtension/extensions/DrumExtension.h b/lib/WiiExtension/extensions/DrumExtension.h index 3227159d5c..5f4fceeddf 100644 --- a/lib/WiiExtension/extensions/DrumExtension.h +++ b/lib/WiiExtension/extensions/DrumExtension.h @@ -15,6 +15,7 @@ enum DrumButtons { class DrumExtension : public ExtensionBase { public: void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; }; #endif \ No newline at end of file diff --git a/lib/WiiExtension/extensions/ExtensionBase.h b/lib/WiiExtension/extensions/ExtensionBase.h index 6e0f9103c1..1bd363f226 100644 --- a/lib/WiiExtension/extensions/ExtensionBase.h +++ b/lib/WiiExtension/extensions/ExtensionBase.h @@ -87,6 +87,8 @@ class ExtensionBase { uint16_t analogState[WiiAnalogs::WII_MAX_ANALOGS]; int16_t motionState[WiiMotions::WII_MAX_MOTIONS]; + uint8_t controllerData[16]; + uint16_t initialAnalogState[WiiAnalogs::WII_MAX_ANALOGS]; bool isFirstRead = true; bool skipPostProcess = false; @@ -95,6 +97,8 @@ class ExtensionBase { virtual bool calibrate(uint8_t *calibrationData); virtual void process(uint8_t *inputData) = 0; virtual void postProcess(); + + virtual uint8_t prepareOutput(); #if WII_EXTENSION_DEBUG==true uint8_t _lastRead[16] = {0xFF}; diff --git a/lib/WiiExtension/extensions/Extensions.h b/lib/WiiExtension/extensions/Extensions.h index a175381741..9d03fd346a 100644 --- a/lib/WiiExtension/extensions/Extensions.h +++ b/lib/WiiExtension/extensions/Extensions.h @@ -8,6 +8,7 @@ #include "MotionPlusExtension.h" #include "NunchuckExtension.h" #include "TaikoExtension.h" +#include "TrainExtension.h" #include "TurntableExtension.h" #include "UDrawExtension.h" diff --git a/lib/WiiExtension/extensions/GuitarExtension.cpp b/lib/WiiExtension/extensions/GuitarExtension.cpp index 741217aba2..5b5e000aff 100644 --- a/lib/WiiExtension/extensions/GuitarExtension.cpp +++ b/lib/WiiExtension/extensions/GuitarExtension.cpp @@ -218,4 +218,122 @@ void GuitarExtension::process(uint8_t *inputData) { // printf("U=%1d D=%1d -=%1d +=%1d\n", buttons[WiiButtons::WII_BUTTON_UP], buttons[WiiButtons::WII_BUTTON_DOWN], buttons[WiiButtons::WII_BUTTON_MINUS], buttons[WiiButtons::WII_BUTTON_PLUS]); // printf("O=%1d B=%1d Y=%1d R=%1d G=%1d\n", buttons[GuitarButtons::GUITAR_ORANGE], buttons[GuitarButtons::GUITAR_BLUE], buttons[GuitarButtons::GUITAR_YELLOW], buttons[GuitarButtons::GUITAR_RED], buttons[GuitarButtons::GUITAR_GREEN]); #endif -} \ No newline at end of file +} + +uint8_t GuitarExtension::prepareOutput() { + uint16_t lx = 0; + uint16_t ly = 0; + uint16_t rx = 0; + uint16_t ry = 0; + uint16_t lt = 0; + uint16_t rt = 0; + // expect all source analog sticks at 16 bit and scale down + // expect all source analog triggers at 8 bit and scale down + if (getDataType() == WII_DATA_TYPE_1) { + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3F) / 0xFFFF); + ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3F) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x1F) / 0xFFFF); + ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x1F) / 0xFFFF)); + lt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] * 0x1F) / 0xFF); + rt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] * 0x1F) / 0xFF); + + controllerData[0x00] = 0xC0 | (lx & 0x01); + controllerData[0x01] = 0xC0 | (ly & 0x01); + controllerData[0x02] = 0 | (0x1F); + controllerData[0x03] = (rt & 0x1F); + controllerData[0x04] = ( + ((1 << 0)) | + ((1 << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((1 << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((1 << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((1 << 7)) + ); + controllerData[0x05] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01) << 0)) | + ((1 << 1)) | + ((!(buttons[GuitarButtons::GUITAR_PEDAL] & 0x01) << 2)) | + ((!(buttons[GuitarButtons::GUITAR_YELLOW] & 0x01) << 3)) | + ((!(buttons[GuitarButtons::GUITAR_GREEN] & 0x01) << 4)) | + ((!(buttons[GuitarButtons::GUITAR_BLUE] & 0x01) << 5)) | + ((!(buttons[GuitarButtons::GUITAR_RED] & 0x01) << 6)) | + ((!(buttons[GuitarButtons::GUITAR_ORANGE] & 0x01) << 7)) + ); + return 6; + } else if (getDataType() == WII_DATA_TYPE_2) { + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3FF) / 0xFFFF); + ly = (uint8_t)(0x3FF - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3FF) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x3FF) / 0xFFFF); + ry = (uint8_t)(0x3FF - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x3FF) / 0xFFFF)); + lt = analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER]; + rt = analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER]; + + controllerData[0x00] = ((lx & 0x03FC) >> 2); + controllerData[0x01] = ((rx & 0x03FC) >> 2); + controllerData[0x02] = ((ly & 0x03FC) >> 2); + controllerData[0x03] = ((ry & 0x03FC) >> 2); + controllerData[0x04] = ((lx & 0x03) << 0) | ((rx & 0x03) << 2) | ((ly & 0x03) << 4) | ((ry & 0x03) << 6); + controllerData[0x05] = lt; + controllerData[0x06] = rt; + controllerData[0x07] = (1 | + ((!(buttons[WiiButtons::WII_BUTTON_R] & 0x01) << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((!(buttons[WiiButtons::WII_BUTTON_HOME] & 0x01) << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((!(buttons[WiiButtons::WII_BUTTON_L] & 0x01) << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((!(buttons[WiiButtons::WII_BUTTON_RIGHT] & 0x01) << 7)) + ); + controllerData[0x08] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01)) << 0) | + ((!(buttons[WiiButtons::WII_BUTTON_LEFT] & 0x01)) << 1) | + ((!(buttons[WiiButtons::WII_BUTTON_ZR] & 0x01)) << 2) | + ((!(buttons[WiiButtons::WII_BUTTON_X] & 0x01)) << 3) | + ((!(buttons[WiiButtons::WII_BUTTON_A] & 0x01)) << 4) | + ((!(buttons[WiiButtons::WII_BUTTON_Y] & 0x01)) << 5) | + ((!(buttons[WiiButtons::WII_BUTTON_B] & 0x01)) << 6) | + ((!(buttons[WiiButtons::WII_BUTTON_ZL] & 0x01)) << 7) + ); + return 9; + } else if (getDataType() == WII_DATA_TYPE_3) { + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0xFF) / 0xFFFF); + ly = (uint8_t)(0xFF - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0xFF) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0xFF) / 0xFFFF); + ry = (uint8_t)(0xFF - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0xFF) / 0xFFFF)); + lt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] * 0xFF) / 0xFF); + rt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] * 0xFF) / 0xFF); + + controllerData[0x00] = (lx & 0xFF); + controllerData[0x01] = 0xFF; + controllerData[0x02] = (ly & 0xFF); + controllerData[0x03] = 0xFF; + controllerData[0x04] = 0xFF; + controllerData[0x05] = (rx & 0xFF); + controllerData[0x06] = ( + ((1 << 0)) | + ((1 << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((1 << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((1 << 5)) | + ((!(buttons[WiiButtons::WII_BUTTON_DOWN] & 0x01) << 6)) | + ((1 << 7)) + ); + controllerData[0x07] = ( + ((!(buttons[WiiButtons::WII_BUTTON_UP] & 0x01) << 0)) | + ((1 << 1)) | + ((!(buttons[GuitarButtons::GUITAR_PEDAL] & 0x01) << 2)) | + ((!(buttons[GuitarButtons::GUITAR_YELLOW] & 0x01) << 3)) | + ((!(buttons[GuitarButtons::GUITAR_GREEN] & 0x01) << 4)) | + ((!(buttons[GuitarButtons::GUITAR_BLUE] & 0x01) << 5)) | + ((!(buttons[GuitarButtons::GUITAR_RED] & 0x01) << 6)) | + ((!(buttons[GuitarButtons::GUITAR_ORANGE] & 0x01) << 7)) + ); + return 8; + } else { + } + + return 0; +} diff --git a/lib/WiiExtension/extensions/GuitarExtension.h b/lib/WiiExtension/extensions/GuitarExtension.h index db8cc9dc97..66d9d4d023 100644 --- a/lib/WiiExtension/extensions/GuitarExtension.h +++ b/lib/WiiExtension/extensions/GuitarExtension.h @@ -21,6 +21,7 @@ class GuitarExtension : public ExtensionBase { public: void init(uint8_t dataType) override; void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; private: uint8_t _guitarType = 0; uint16_t whammyBar = 0; diff --git a/lib/WiiExtension/extensions/MotionPlusExtension.cpp b/lib/WiiExtension/extensions/MotionPlusExtension.cpp index eda082ccf3..8459cd79ce 100644 --- a/lib/WiiExtension/extensions/MotionPlusExtension.cpp +++ b/lib/WiiExtension/extensions/MotionPlusExtension.cpp @@ -163,4 +163,16 @@ void MotionPlusExtension::process(uint8_t *inputData) { #if WII_EXTENSION_DEBUG==true // printf("Roll: %5d Pitch: %5d Yaw: %5d\n", motionState[WiiMotions::WII_GYROSCOPE_ROLL], motionState[WiiMotions::WII_GYROSCOPE_PITCH], motionState[WiiMotions::WII_GYROSCOPE_YAW]); #endif -} \ No newline at end of file +} + +uint8_t MotionPlusExtension::prepareOutput() { + controllerData[0x00] = analogState[WiiAnalogs::WII_ANALOG_LEFT_X]; + controllerData[0x01] = analogState[WiiAnalogs::WII_ANALOG_LEFT_Y]; + controllerData[0x02] = 0x00; + controllerData[0x03] = 0x00; + controllerData[0x04] = 0x00; + controllerData[0x05] = ((!(buttons[WiiButtons::WII_BUTTON_C] & 0x01)) << 1) | ((!(buttons[WiiButtons::WII_BUTTON_Z] & 0x01)) << 0); + + return 6; +} + diff --git a/lib/WiiExtension/extensions/MotionPlusExtension.h b/lib/WiiExtension/extensions/MotionPlusExtension.h index d3db8d697f..e7ec8b4955 100644 --- a/lib/WiiExtension/extensions/MotionPlusExtension.h +++ b/lib/WiiExtension/extensions/MotionPlusExtension.h @@ -8,6 +8,7 @@ class MotionPlusExtension : public ExtensionBase { void init(uint8_t dataType) override; bool calibrate(uint8_t *calibrationData) override; void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; private: struct CalibrationBlock { diff --git a/lib/WiiExtension/extensions/NunchuckExtension.cpp b/lib/WiiExtension/extensions/NunchuckExtension.cpp index 49aa26a479..28f075c589 100644 --- a/lib/WiiExtension/extensions/NunchuckExtension.cpp +++ b/lib/WiiExtension/extensions/NunchuckExtension.cpp @@ -78,4 +78,22 @@ void NunchuckExtension::process(uint8_t *inputData) { #if WII_EXTENSION_DEBUG==true //printf("Joy X=%4d Y=%4d Acc X=%4d Y=%4d Z=%4d Btn Z=%1d C=%1d\n", analogState[WiiAnalogs::ANALOG_LEFT_X], analogState[WiiAnalogs::ANALOG_LEFT_Y], motionState[WiiMotions::MOTION_X], motionState[WiiMotions::MOTION_Y], motionState[WiiMotions::MOTION_Z], buttons[WiiButtons::BUTTON_Z], buttons[WiiButtons::BUTTON_C]); #endif +} + +uint8_t NunchuckExtension::prepareOutput() { + uint16_t lx = 0; + uint16_t ly = 0; + + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0xFF) / 0xFFFF); + ly = (uint8_t)(0xFF - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0xFF) / 0xFFFF)); + + // expect all source analogs at 16 bit and scale down + controllerData[0x00] = lx; + controllerData[0x01] = ly; + controllerData[0x02] = 0x00; + controllerData[0x03] = 0x00; + controllerData[0x04] = 0x00; + controllerData[0x05] = ((!(buttons[WiiButtons::WII_BUTTON_C] & 0x01)) << 1) | ((!(buttons[WiiButtons::WII_BUTTON_Z] & 0x01)) << 0); + + return 6; } \ No newline at end of file diff --git a/lib/WiiExtension/extensions/NunchuckExtension.h b/lib/WiiExtension/extensions/NunchuckExtension.h index 78939e7a0f..0be85fd31d 100644 --- a/lib/WiiExtension/extensions/NunchuckExtension.h +++ b/lib/WiiExtension/extensions/NunchuckExtension.h @@ -11,6 +11,7 @@ class NunchuckExtension : public ExtensionBase { void init(uint8_t dataType) override; bool calibrate(uint8_t *calibrationData) override; void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; }; #endif \ No newline at end of file diff --git a/lib/WiiExtension/extensions/TaikoExtension.cpp b/lib/WiiExtension/extensions/TaikoExtension.cpp index 2d2cea55d9..52cc20bc54 100644 --- a/lib/WiiExtension/extensions/TaikoExtension.cpp +++ b/lib/WiiExtension/extensions/TaikoExtension.cpp @@ -34,4 +34,24 @@ void TaikoExtension::process(uint8_t *inputData) { // } printf("DL=%1d RL=%1d DR=%1d RR=%1d\n", buttons[TaikoButtons::TATA_DON_LEFT], buttons[TaikoButtons::TATA_KAT_LEFT], buttons[TaikoButtons::TATA_DON_RIGHT], buttons[TaikoButtons::TATA_KAT_RIGHT]); #endif -} \ No newline at end of file +} + +uint8_t TaikoExtension::prepareOutput() { + controllerData[0x00] = 0xFF; + controllerData[0x01] = 0xFF; + controllerData[0x02] = 0xFF; + controllerData[0x03] = 0xFF; + controllerData[0x04] = 0xFF; + controllerData[0x05] = ( + ((1 << 0)) | + ((1 << 1)) | + ((1 << 2)) | + ((!(buttons[TaikoButtons::TATA_KAT_RIGHT] & 0x01) << 3)) | + ((!(buttons[TaikoButtons::TATA_DON_RIGHT] & 0x01) << 4)) | + ((!(buttons[TaikoButtons::TATA_KAT_LEFT] & 0x01) << 5)) | + ((!(buttons[TaikoButtons::TATA_DON_LEFT] & 0x01) << 6)) | + ((1 << 7)) + ); + return 6; +} + diff --git a/lib/WiiExtension/extensions/TaikoExtension.h b/lib/WiiExtension/extensions/TaikoExtension.h index 743ba659b1..566e679852 100644 --- a/lib/WiiExtension/extensions/TaikoExtension.h +++ b/lib/WiiExtension/extensions/TaikoExtension.h @@ -13,6 +13,7 @@ enum TaikoButtons { class TaikoExtension : public ExtensionBase { public: void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; }; #endif \ No newline at end of file diff --git a/lib/WiiExtension/extensions/TrainExtension.cpp b/lib/WiiExtension/extensions/TrainExtension.cpp new file mode 100644 index 0000000000..1f5de46803 --- /dev/null +++ b/lib/WiiExtension/extensions/TrainExtension.cpp @@ -0,0 +1,28 @@ +#include "ExtensionBase.h" +#include "TrainExtension.h" + +#include "WiiExtension.h" + +void TrainExtension::process(uint8_t *inputData) { +#if WII_EXTENSION_DEBUG==true +// //if (_lastRead[0] != regRead[0]) printf("Byte0 " BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(regRead[0])); +// //if (_lastRead[1] != regRead[1]) printf("Byte1 " BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(regRead[1])); +// //if (_lastRead[2] != regRead[2]) printf("Byte2 " BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(regRead[2])); +// //if (_lastRead[3] != regRead[3]) printf("Byte3 " BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(regRead[3])); +// //if (_lastRead[4] != regRead[4]) printf("Byte4 " BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(regRead[4])); +// //if (_lastRead[5] != regRead[5]) printf("Byte5 " BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(regRead[5])); +#endif +} + +uint8_t TrainExtension::prepareOutput() { + controllerData[0x00] = 0xFF; + controllerData[0x01] = 0xFF; + controllerData[0x02] = 0xFF; + controllerData[0x03] = 0xFF; + controllerData[0x04] = 0xFF; + controllerData[0x05] = 0xFF; + controllerData[0x06] = 0xFF; + controllerData[0x07] = 0xFF; + return 8; +} + diff --git a/lib/WiiExtension/extensions/TrainExtension.h b/lib/WiiExtension/extensions/TrainExtension.h new file mode 100644 index 0000000000..9cb3807b48 --- /dev/null +++ b/lib/WiiExtension/extensions/TrainExtension.h @@ -0,0 +1,19 @@ +#ifndef _TRAINEXTENSION_H_ +#define _TRAINEXTENSION_H_ + +#include "ExtensionBase.h" + +enum TrainButtons { + TRAIN_BUTTON_C = WiiButtons::WII_BUTTON_A, + TRAIN_BUTTON_B = WiiButtons::WII_BUTTON_B, + TRAIN_BUTTON_D = WiiButtons::WII_BUTTON_X, + TRAIN_BUTTON_A = WiiButtons::WII_BUTTON_Y +}; + +class TrainExtension : public ExtensionBase { + public: + void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; +}; + +#endif \ No newline at end of file diff --git a/lib/WiiExtension/extensions/TurntableExtension.cpp b/lib/WiiExtension/extensions/TurntableExtension.cpp index 79ecde5165..849ae8a296 100644 --- a/lib/WiiExtension/extensions/TurntableExtension.cpp +++ b/lib/WiiExtension/extensions/TurntableExtension.cpp @@ -89,4 +89,46 @@ void TurntableExtension::process(uint8_t *inputData) { // if (_lastRead[i] != inputData[i]) printf("Byte%2d " BYTE_TO_BINARY_PATTERN "\n", i, BYTE_TO_BINARY(inputData[i])); //} #endif -} \ No newline at end of file +} + +uint8_t TurntableExtension::prepareOutput() { + uint16_t lx = 0; + uint16_t ly = 0; + uint16_t rx = 0; + uint16_t ry = 0; + uint16_t lt = 0; + uint16_t rt = 0; + + lx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_X] * 0x3F) / 0xFFFF); + ly = (uint8_t)(0x3F - ((analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] * 0x3F) / 0xFFFF)); + rx = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] * 0x1F) / 0xFFFF); + ry = (uint8_t)(0x1F - ((analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] * 0x1F) / 0xFFFF)); + lt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] * 0x1F) / 0xFF); + rt = (uint8_t)((analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] * 0x1F) / 0xFF); + + controllerData[0x00] = /*((rx & 0x18) << 6) | */(lx & 0x3F); + controllerData[0x01] = /*((rx & 0x06) << 6) | */(ly & 0x3F); + controllerData[0x02] = /*((rx & 0x01) << 7) | ((lt & 0x0C) << 5) | ((rx & 0x1F) >> 4)*/0xFF; + controllerData[0x03] = /*((lt & 0x07) << 5) | (rt & 0x1F)*/0xFF; + controllerData[0x04] = ( + ((1 << 0)) | + ((!(buttons[TurntableButtons::TURNTABLE_RIGHT_RED] & 0x01) << 1)) | + ((!(buttons[WiiButtons::WII_BUTTON_PLUS] & 0x01) << 2)) | + ((0 << 3)) | + ((!(buttons[WiiButtons::WII_BUTTON_MINUS] & 0x01) << 4)) | + ((!(buttons[TurntableButtons::TURNTABLE_LEFT_RED] & 0x01) << 5)) | + ((0 << 6)) | + ((0 << 7)) + ); + controllerData[0x05] = ( + ((0 << 0)) | + ((0 << 1)) | + ((!(buttons[TurntableButtons::TURNTABLE_RIGHT_BLUE] & 0x01) << 2)) | + ((!(buttons[TurntableButtons::TURNTABLE_LEFT_GREEN] & 0x01) << 3)) | + ((!(buttons[TurntableButtons::TURNTABLE_EUPHORIA] & 0x01) << 4)) | + ((!(buttons[TurntableButtons::TURNTABLE_RIGHT_GREEN] & 0x01) << 5)) | + ((0 << 6)) | + ((!(buttons[TurntableButtons::TURNTABLE_LEFT_BLUE] & 0x01) << 7)) + ); + return 6; +} diff --git a/lib/WiiExtension/extensions/TurntableExtension.h b/lib/WiiExtension/extensions/TurntableExtension.h index 87d3fa883b..7958719a85 100644 --- a/lib/WiiExtension/extensions/TurntableExtension.h +++ b/lib/WiiExtension/extensions/TurntableExtension.h @@ -32,6 +32,7 @@ class TurntableExtension : public ExtensionBase { public: void init(uint8_t dataType) override; void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; void setLED(bool ledOn) {_ledState = ledOn;}; bool getLED() {return _ledState;}; diff --git a/lib/WiiExtension/extensions/UDrawExtension.cpp b/lib/WiiExtension/extensions/UDrawExtension.cpp index 785da92e7d..efbf3af1c4 100644 --- a/lib/WiiExtension/extensions/UDrawExtension.cpp +++ b/lib/WiiExtension/extensions/UDrawExtension.cpp @@ -29,4 +29,15 @@ void UDrawExtension::process(uint8_t *inputData) { printf("\x1B[20;0H" BYTE_TO_BINARY_PATTERN "\n", BYTE_TO_BINARY(inputData[5])); printf("\x1B[21;0HX=%5d Y=%5d B0=%1d B1=%1d B2=%1d\n", motionState[WiiMotions::WII_TOUCH_X], motionState[WiiMotions::WII_TOUCH_Y], buttons[WiiButtons::WII_BUTTON_A], buttons[WiiButtons::WII_BUTTON_L], buttons[WiiButtons::WII_BUTTON_R]); #endif -} \ No newline at end of file +} + +uint8_t UDrawExtension::prepareOutput() { + controllerData[0x00] = analogState[WiiAnalogs::WII_ANALOG_LEFT_X]; + controllerData[0x01] = analogState[WiiAnalogs::WII_ANALOG_LEFT_Y]; + controllerData[0x02] = 0x00; + controllerData[0x03] = 0x00; + controllerData[0x04] = 0x00; + controllerData[0x05] = ((!(buttons[WiiButtons::WII_BUTTON_C] & 0x01)) << 1) | ((!(buttons[WiiButtons::WII_BUTTON_Z] & 0x01)) << 0); + + return 6; +} diff --git a/lib/WiiExtension/extensions/UDrawExtension.h b/lib/WiiExtension/extensions/UDrawExtension.h index a1504d9b4c..c1a18683d8 100644 --- a/lib/WiiExtension/extensions/UDrawExtension.h +++ b/lib/WiiExtension/extensions/UDrawExtension.h @@ -6,6 +6,7 @@ class UDrawExtension : public ExtensionBase { public: void process(uint8_t *inputData) override; + uint8_t prepareOutput() override; private: const uint16_t UDRAW_MIN_X = 80; const uint16_t UDRAW_MAX_X = 1955; diff --git a/src/addons/wiiext.cpp b/src/addons/wiiext.cpp index 63b2d6285a..373750e978 100644 --- a/src/addons/wiiext.cpp +++ b/src/addons/wiiext.cpp @@ -5,7 +5,20 @@ #include "helper.h" #include "config.pb.h" +#define WII_RUN_AS_EXTENSION true + bool WiiExtensionInput::available() { +#if WII_RUN_AS_EXTENSION + const WiiOptions& options = Storage::getInstance().getAddonOptions().wiiOptions; + if (options.enabled) { + // addon is enabled. let's scan available blocks. + wii = new WiiExtensionDevice(); + wii->setAddress(WII_EXTENSION_I2C_ADDR); + wii->setI2C(PeripheralManager::getInstance().getI2C(1)); + return true; + } + return false; +#else const WiiOptions& options = Storage::getInstance().getAddonOptions().wiiOptions; if (options.enabled) { // addon is enabled. let's scan available blocks. @@ -20,6 +33,7 @@ bool WiiExtensionInput::available() { } } return false; +#endif } void WiiExtensionInput::setup() { @@ -34,66 +48,188 @@ void WiiExtensionInput::setup() { currentConfig = NULL; - //wii = new WiiExtensionDevice( - // i2c, - // WII_EXTENSION_I2C_ADDR); + wii->extensionType = WII_EXTENSION_GUITAR; + wii->setExtensionMode(WII_RUN_AS_EXTENSION); wii->begin(); wii->start(); + wii->getController()->setDataType(WII_DATA_TYPE_1); reloadConfig(); - // Run during setup to catch boot selection mode - wii->poll(); + if (wii->extensionMode) { + currentConfig = &extensionConfigs[wii->extensionType]; + } else { + // Run during setup to catch boot selection mode + wii->poll(); - update(); + update(); + } } void WiiExtensionInput::process() { - if (nextTimer < getMillis()) { - wii->poll(); + if (wii->extensionMode) { + if (currentConfig != NULL) { + Gamepad * gamepad = Storage::getInstance().GetGamepad(); + + if (wii->extensionType == WII_EXTENSION_NUNCHUCK) { + wii->getController()->buttons[WiiButtons::WII_BUTTON_C] = getButtonState(WiiButtons::WII_BUTTON_C); + wii->getController()->buttons[WiiButtons::WII_BUTTON_Z] = getButtonState(WiiButtons::WII_BUTTON_Z); + + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X] = gamepad->state.lx; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] = gamepad->state.ly; + } else if ((wii->extensionType == WII_EXTENSION_CLASSIC) || (wii->extensionType == WII_EXTENSION_CLASSIC_PRO)) { + wii->getController()->buttons[WiiButtons::WII_BUTTON_A] = getButtonState(WiiButtons::WII_BUTTON_A); + wii->getController()->buttons[WiiButtons::WII_BUTTON_B] = getButtonState(WiiButtons::WII_BUTTON_B); + wii->getController()->buttons[WiiButtons::WII_BUTTON_X] = getButtonState(WiiButtons::WII_BUTTON_X); + wii->getController()->buttons[WiiButtons::WII_BUTTON_Y] = getButtonState(WiiButtons::WII_BUTTON_Y); + wii->getController()->buttons[WiiButtons::WII_BUTTON_L] = getButtonState(WiiButtons::WII_BUTTON_L); + wii->getController()->buttons[WiiButtons::WII_BUTTON_ZL] = getButtonState(WiiButtons::WII_BUTTON_ZL); + wii->getController()->buttons[WiiButtons::WII_BUTTON_R] = getButtonState(WiiButtons::WII_BUTTON_R); + wii->getController()->buttons[WiiButtons::WII_BUTTON_ZR] = getButtonState(WiiButtons::WII_BUTTON_ZR); + wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS] = getButtonState(WiiButtons::WII_BUTTON_MINUS); + wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS] = getButtonState(WiiButtons::WII_BUTTON_PLUS); + wii->getController()->buttons[WiiButtons::WII_BUTTON_HOME] = getButtonState(WiiButtons::WII_BUTTON_HOME); + + wii->getController()->buttons[WiiButtons::WII_BUTTON_UP] = getButtonState(WiiButtons::WII_BUTTON_UP); + wii->getController()->buttons[WiiButtons::WII_BUTTON_DOWN] = getButtonState(WiiButtons::WII_BUTTON_DOWN); + wii->getController()->buttons[WiiButtons::WII_BUTTON_LEFT] = getButtonState(WiiButtons::WII_BUTTON_LEFT); + wii->getController()->buttons[WiiButtons::WII_BUTTON_RIGHT] = getButtonState(WiiButtons::WII_BUTTON_RIGHT); + + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X] = gamepad->state.lx; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] = gamepad->state.ly; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] = gamepad->state.rx; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] = gamepad->state.ry; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] = gamepad->state.lt; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] = gamepad->state.rt; + } else if (wii->extensionType == WII_EXTENSION_GUITAR) { + wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS] = getButtonState(WiiButtons::WII_BUTTON_MINUS); + wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS] = getButtonState(WiiButtons::WII_BUTTON_PLUS); + + wii->getController()->buttons[WiiButtons::WII_BUTTON_UP] = getButtonState(WiiButtons::WII_BUTTON_UP); + wii->getController()->buttons[WiiButtons::WII_BUTTON_DOWN] = getButtonState(WiiButtons::WII_BUTTON_DOWN); + + wii->getController()->buttons[GuitarButtons::GUITAR_GREEN] = getButtonState(GuitarButtons::GUITAR_GREEN); + wii->getController()->buttons[GuitarButtons::GUITAR_RED] = getButtonState(GuitarButtons::GUITAR_RED); + wii->getController()->buttons[GuitarButtons::GUITAR_YELLOW] = getButtonState(GuitarButtons::GUITAR_YELLOW); + wii->getController()->buttons[GuitarButtons::GUITAR_BLUE] = getButtonState(GuitarButtons::GUITAR_BLUE); + wii->getController()->buttons[GuitarButtons::GUITAR_ORANGE] = getButtonState(GuitarButtons::GUITAR_ORANGE); + wii->getController()->buttons[GuitarButtons::GUITAR_PEDAL] = getButtonState(GuitarButtons::GUITAR_PEDAL); + + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X] = gamepad->state.lx; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] = gamepad->state.ly; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X] = gamepad->state.rx; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y] = gamepad->state.ry; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER] = gamepad->state.lt; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER] = gamepad->state.rt; + } else if (wii->extensionType == WII_EXTENSION_TRAIN) { + wii->getController()->buttons[WiiButtons::WII_BUTTON_UP] = getButtonState(WiiButtons::WII_BUTTON_UP); + wii->getController()->buttons[WiiButtons::WII_BUTTON_DOWN] = getButtonState(WiiButtons::WII_BUTTON_DOWN); + wii->getController()->buttons[WiiButtons::WII_BUTTON_LEFT] = getButtonState(WiiButtons::WII_BUTTON_LEFT); + wii->getController()->buttons[WiiButtons::WII_BUTTON_RIGHT] = getButtonState(WiiButtons::WII_BUTTON_RIGHT); + + wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS] = getButtonState(WiiButtons::WII_BUTTON_MINUS); + wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS] = getButtonState(WiiButtons::WII_BUTTON_PLUS); + + wii->getController()->buttons[TrainButtons::TRAIN_BUTTON_A] = getButtonState(TrainButtons::TRAIN_BUTTON_A); + wii->getController()->buttons[TrainButtons::TRAIN_BUTTON_B] = getButtonState(TrainButtons::TRAIN_BUTTON_B); + wii->getController()->buttons[TrainButtons::TRAIN_BUTTON_C] = getButtonState(TrainButtons::TRAIN_BUTTON_C); + wii->getController()->buttons[TrainButtons::TRAIN_BUTTON_D] = getButtonState(TrainButtons::TRAIN_BUTTON_D); + } else if (wii->extensionType == WII_EXTENSION_TAIKO) { + wii->getController()->buttons[TaikoButtons::TATA_KAT_LEFT] = getButtonState(TaikoButtons::TATA_KAT_LEFT); + wii->getController()->buttons[TaikoButtons::TATA_KAT_RIGHT] = getButtonState(TaikoButtons::TATA_KAT_RIGHT); + wii->getController()->buttons[TaikoButtons::TATA_DON_LEFT] = getButtonState(TaikoButtons::TATA_DON_LEFT); + wii->getController()->buttons[TaikoButtons::TATA_DON_RIGHT] = getButtonState(TaikoButtons::TATA_DON_RIGHT); + } else if (wii->extensionType == WII_EXTENSION_DRUMS) { + wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS] = getButtonState(WiiButtons::WII_BUTTON_MINUS); + wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS] = getButtonState(WiiButtons::WII_BUTTON_PLUS); + + wii->getController()->buttons[DrumButtons::DRUM_RED] = getButtonState(DrumButtons::DRUM_RED); + wii->getController()->buttons[DrumButtons::DRUM_GREEN] = getButtonState(DrumButtons::DRUM_GREEN); + wii->getController()->buttons[DrumButtons::DRUM_YELLOW] = getButtonState(DrumButtons::DRUM_YELLOW); + wii->getController()->buttons[DrumButtons::DRUM_BLUE] = getButtonState(DrumButtons::DRUM_BLUE); + wii->getController()->buttons[DrumButtons::DRUM_ORANGE] = getButtonState(DrumButtons::DRUM_ORANGE); + wii->getController()->buttons[DrumButtons::DRUM_PEDAL] = getButtonState(DrumButtons::DRUM_PEDAL); + + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X] = gamepad->state.lx; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] = gamepad->state.ly; + } else if (wii->extensionType == WII_EXTENSION_TURNTABLE) { + wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS] = getButtonState(WiiButtons::WII_BUTTON_MINUS); + wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS] = getButtonState(WiiButtons::WII_BUTTON_PLUS); + + wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_GREEN] = getButtonState(TurntableButtons::TURNTABLE_LEFT_GREEN); + wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_RED] = getButtonState(TurntableButtons::TURNTABLE_LEFT_RED); + wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_BLUE] = getButtonState(TurntableButtons::TURNTABLE_LEFT_BLUE); + + wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_GREEN] = getButtonState(TurntableButtons::TURNTABLE_RIGHT_GREEN); + wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_RED] = getButtonState(TurntableButtons::TURNTABLE_RIGHT_RED); + wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_BLUE] = getButtonState(TurntableButtons::TURNTABLE_RIGHT_BLUE); + + wii->getController()->buttons[TurntableButtons::TURNTABLE_EUPHORIA] = getButtonState(TurntableButtons::TURNTABLE_EUPHORIA); + + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X] = gamepad->state.lx; + wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y] = gamepad->state.ly; + wii->getController()->analogState[TurntableAnalogs::TURNTABLE_RIGHT] = gamepad->state.rx; + wii->getController()->analogState[TurntableAnalogs::TURNTABLE_LEFT] = gamepad->state.ry; + wii->getController()->analogState[TurntableAnalogs::TURNTABLE_EFFECTS] = gamepad->state.lt; + wii->getController()->analogState[TurntableAnalogs::TURNTABLE_CROSSFADE] = gamepad->state.rt; + } else if ((wii->extensionType == WII_EXTENSION_DRAWSOME) || (wii->extensionType == WII_EXTENSION_UDRAW)) { + // not yet implemented for output + } else if (wii->extensionType == WII_EXTENSION_MOTION_PLUS) { + // not yet implemented for output + } + if (nextTimer < getMillis()) { + wii->poll(); + + nextTimer = getMillis() + uIntervalMS; + } + } + } else { + if (nextTimer < getMillis()) { + wii->poll(); - update(); - - nextTimer = getMillis() + uIntervalMS; - } + update(); + + nextTimer = getMillis() + uIntervalMS; + } - if (currentConfig != NULL) { - queueAnalogChange(WiiAnalogs::WII_ANALOG_LEFT_X, leftX, lastLeftX); - queueAnalogChange(WiiAnalogs::WII_ANALOG_LEFT_Y, leftY, lastLeftY); - queueAnalogChange(WiiAnalogs::WII_ANALOG_RIGHT_X, rightX, lastRightX); - queueAnalogChange(WiiAnalogs::WII_ANALOG_RIGHT_Y, rightY, lastRightY); - queueAnalogChange(WiiAnalogs::WII_ANALOG_LEFT_TRIGGER, triggerLeft, lastTriggerLeft); - queueAnalogChange(WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER, triggerRight, lastTriggerRight); - updateAnalogState(); - - setButtonState(buttonC, WiiButtons::WII_BUTTON_C); - setButtonState(buttonZ, WiiButtons::WII_BUTTON_Z); - - setButtonState(buttonA, WiiButtons::WII_BUTTON_A); - setButtonState(buttonB, WiiButtons::WII_BUTTON_B); - setButtonState(buttonX, WiiButtons::WII_BUTTON_X); - setButtonState(buttonY, WiiButtons::WII_BUTTON_Y); - setButtonState(buttonL, WiiButtons::WII_BUTTON_L); - setButtonState(buttonZL, WiiButtons::WII_BUTTON_ZL); - setButtonState(buttonR, WiiButtons::WII_BUTTON_R); - setButtonState(buttonZR, WiiButtons::WII_BUTTON_ZR); - setButtonState(buttonSelect, WiiButtons::WII_BUTTON_MINUS); - setButtonState(buttonStart, WiiButtons::WII_BUTTON_PLUS); - setButtonState(buttonHome, WiiButtons::WII_BUTTON_HOME); - - setButtonState(dpadUp, WiiButtons::WII_BUTTON_UP); - setButtonState(dpadDown, WiiButtons::WII_BUTTON_DOWN); - setButtonState(dpadLeft, WiiButtons::WII_BUTTON_LEFT); - setButtonState(dpadRight, WiiButtons::WII_BUTTON_RIGHT); - - updateMotionState(); - - if (lastLeftX != leftX) lastLeftX = leftX; - if (lastLeftY != leftY) lastLeftY = leftY; - if (lastRightX != rightX) lastRightX = rightX; - if (lastRightY != rightY) lastRightY = rightY; - if (lastTriggerLeft != triggerLeft) lastTriggerLeft = triggerLeft; - if (lastTriggerRight != triggerRight) lastTriggerRight = triggerRight; + if (currentConfig != NULL) { + queueAnalogChange(WiiAnalogs::WII_ANALOG_LEFT_X, leftX, lastLeftX); + queueAnalogChange(WiiAnalogs::WII_ANALOG_LEFT_Y, leftY, lastLeftY); + queueAnalogChange(WiiAnalogs::WII_ANALOG_RIGHT_X, rightX, lastRightX); + queueAnalogChange(WiiAnalogs::WII_ANALOG_RIGHT_Y, rightY, lastRightY); + queueAnalogChange(WiiAnalogs::WII_ANALOG_LEFT_TRIGGER, triggerLeft, lastTriggerLeft); + queueAnalogChange(WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER, triggerRight, lastTriggerRight); + updateAnalogState(); + + setButtonState(buttonC, WiiButtons::WII_BUTTON_C); + setButtonState(buttonZ, WiiButtons::WII_BUTTON_Z); + + setButtonState(buttonA, WiiButtons::WII_BUTTON_A); + setButtonState(buttonB, WiiButtons::WII_BUTTON_B); + setButtonState(buttonX, WiiButtons::WII_BUTTON_X); + setButtonState(buttonY, WiiButtons::WII_BUTTON_Y); + setButtonState(buttonL, WiiButtons::WII_BUTTON_L); + setButtonState(buttonZL, WiiButtons::WII_BUTTON_ZL); + setButtonState(buttonR, WiiButtons::WII_BUTTON_R); + setButtonState(buttonZR, WiiButtons::WII_BUTTON_ZR); + setButtonState(buttonSelect, WiiButtons::WII_BUTTON_MINUS); + setButtonState(buttonStart, WiiButtons::WII_BUTTON_PLUS); + setButtonState(buttonHome, WiiButtons::WII_BUTTON_HOME); + + setButtonState(dpadUp, WiiButtons::WII_BUTTON_UP); + setButtonState(dpadDown, WiiButtons::WII_BUTTON_DOWN); + setButtonState(dpadLeft, WiiButtons::WII_BUTTON_LEFT); + setButtonState(dpadRight, WiiButtons::WII_BUTTON_RIGHT); + + updateMotionState(); + + if (lastLeftX != leftX) lastLeftX = leftX; + if (lastLeftY != leftY) lastLeftY = leftY; + if (lastRightX != rightX) lastRightX = rightX; + if (lastRightY != rightY) lastRightY = rightY; + if (lastTriggerLeft != triggerLeft) lastTriggerLeft = triggerLeft; + if (lastTriggerRight != triggerRight) lastTriggerRight = triggerRight; + } } } @@ -108,174 +244,177 @@ uint16_t WiiExtensionInput::bounds(uint16_t x, uint16_t out_min, uint16_t out_ma } void WiiExtensionInput::update() { - if (wii->extensionType != WII_EXTENSION_NONE) { - uint16_t joystickMid = GAMEPAD_JOYSTICK_MID; - if ( DriverManager::getInstance().getDriver() != nullptr ) { - joystickMid = DriverManager::getInstance().getDriver()->GetJoystickMidValue(); - } - currentConfig = &extensionConfigs[wii->extensionType]; + if (wii->extensionMode) { + } else { + if (wii->extensionType != WII_EXTENSION_NONE) { + uint16_t joystickMid = GAMEPAD_JOYSTICK_MID; + if ( DriverManager::getInstance().getDriver() != nullptr ) { + joystickMid = DriverManager::getInstance().getDriver()->GetJoystickMidValue(); + } + currentConfig = &extensionConfigs[wii->extensionType]; + + //for (const auto& [extensionButton, value] : currentConfig->buttonMap) { + // WII_SET_MASK(buttonState, wii->getController()->buttons[extensionButton], value); + //} + + isAnalogTriggers = false; + isAccelerometer = false; + isGyroscope = false; + + if (wii->extensionType == WII_EXTENSION_NUNCHUCK) { + buttonZ = wii->getController()->buttons[WiiButtons::WII_BUTTON_Z]; + buttonC = wii->getController()->buttons[WiiButtons::WII_BUTTON_C]; + + leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightX = joystickMid; + rightY = joystickMid; + + accelerometerX = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_X]; + accelerometerY = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Y]; + accelerometerZ = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Z]; + isAccelerometer = true; + + triggerLeft = 0; + triggerRight = 0; + } else if ((wii->extensionType == WII_EXTENSION_CLASSIC) || (wii->extensionType == WII_EXTENSION_CLASSIC_PRO)) { + buttonA = wii->getController()->buttons[WiiButtons::WII_BUTTON_A]; + buttonB = wii->getController()->buttons[WiiButtons::WII_BUTTON_B]; + buttonX = wii->getController()->buttons[WiiButtons::WII_BUTTON_X]; + buttonY = wii->getController()->buttons[WiiButtons::WII_BUTTON_Y]; + buttonL = wii->getController()->buttons[WiiButtons::WII_BUTTON_L]; + buttonZL = wii->getController()->buttons[WiiButtons::WII_BUTTON_ZL]; + buttonR = wii->getController()->buttons[WiiButtons::WII_BUTTON_R]; + buttonZR = wii->getController()->buttons[WiiButtons::WII_BUTTON_ZR]; + buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; + buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; + buttonHome = wii->getController()->buttons[WiiButtons::WII_BUTTON_HOME]; + dpadUp = wii->getController()->buttons[WiiButtons::WII_BUTTON_UP]; + dpadDown = wii->getController()->buttons[WiiButtons::WII_BUTTON_DOWN]; + dpadLeft = wii->getController()->buttons[WiiButtons::WII_BUTTON_LEFT]; + dpadRight = wii->getController()->buttons[WiiButtons::WII_BUTTON_RIGHT]; + + if (wii->extensionType == WII_EXTENSION_CLASSIC) { + triggerLeft = wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER]; + triggerRight = wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER]; + isAnalogTriggers = true; + } + + leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + } else if (wii->extensionType == WII_EXTENSION_GUITAR) { + buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; + buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; + + dpadUp = wii->getController()->buttons[WiiButtons::WII_BUTTON_UP]; + dpadDown = wii->getController()->buttons[WiiButtons::WII_BUTTON_DOWN]; + + buttonB = wii->getController()->buttons[GuitarButtons::GUITAR_GREEN]; + buttonA = wii->getController()->buttons[GuitarButtons::GUITAR_RED]; + buttonX = wii->getController()->buttons[GuitarButtons::GUITAR_YELLOW]; + buttonY = wii->getController()->buttons[GuitarButtons::GUITAR_BLUE]; + buttonZL = wii->getController()->buttons[GuitarButtons::GUITAR_ORANGE]; + + // whammy currently maps to Joy2X in addition to the raw whammy value + whammyBar = wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X]; + buttonR = wii->getController()->buttons[GuitarButtons::GUITAR_PEDAL]; + + leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightY = joystickMid; + + triggerLeft = 0; + triggerRight = 0; - //for (const auto& [extensionButton, value] : currentConfig->buttonMap) { - // WII_SET_MASK(buttonState, wii->getController()->buttons[extensionButton], value); - //} - - isAnalogTriggers = false; - isAccelerometer = false; - isGyroscope = false; - - if (wii->extensionType == WII_EXTENSION_NUNCHUCK) { - buttonZ = wii->getController()->buttons[WiiButtons::WII_BUTTON_Z]; - buttonC = wii->getController()->buttons[WiiButtons::WII_BUTTON_C]; - - leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightX = joystickMid; - rightY = joystickMid; - - accelerometerX = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_X]; - accelerometerY = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Y]; - accelerometerZ = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Z]; - isAccelerometer = true; - - triggerLeft = 0; - triggerRight = 0; - } else if ((wii->extensionType == WII_EXTENSION_CLASSIC) || (wii->extensionType == WII_EXTENSION_CLASSIC_PRO)) { - buttonA = wii->getController()->buttons[WiiButtons::WII_BUTTON_A]; - buttonB = wii->getController()->buttons[WiiButtons::WII_BUTTON_B]; - buttonX = wii->getController()->buttons[WiiButtons::WII_BUTTON_X]; - buttonY = wii->getController()->buttons[WiiButtons::WII_BUTTON_Y]; - buttonL = wii->getController()->buttons[WiiButtons::WII_BUTTON_L]; - buttonZL = wii->getController()->buttons[WiiButtons::WII_BUTTON_ZL]; - buttonR = wii->getController()->buttons[WiiButtons::WII_BUTTON_R]; - buttonZR = wii->getController()->buttons[WiiButtons::WII_BUTTON_ZR]; - buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; - buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; - buttonHome = wii->getController()->buttons[WiiButtons::WII_BUTTON_HOME]; - dpadUp = wii->getController()->buttons[WiiButtons::WII_BUTTON_UP]; - dpadDown = wii->getController()->buttons[WiiButtons::WII_BUTTON_DOWN]; - dpadLeft = wii->getController()->buttons[WiiButtons::WII_BUTTON_LEFT]; - dpadRight = wii->getController()->buttons[WiiButtons::WII_BUTTON_RIGHT]; - - if (wii->extensionType == WII_EXTENSION_CLASSIC) { - triggerLeft = wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_TRIGGER]; - triggerRight = wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER]; isAnalogTriggers = true; - } + } else if (wii->extensionType == WII_EXTENSION_TAIKO) { + buttonL = wii->getController()->buttons[TaikoButtons::TATA_KAT_LEFT]; + buttonR = wii->getController()->buttons[TaikoButtons::TATA_KAT_RIGHT]; + + dpadLeft = wii->getController()->buttons[TaikoButtons::TATA_DON_LEFT]; + buttonA = wii->getController()->buttons[TaikoButtons::TATA_DON_RIGHT]; + } else if (wii->extensionType == WII_EXTENSION_DRUMS) { + buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; + buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; + + buttonB = wii->getController()->buttons[DrumButtons::DRUM_RED]; + buttonA = wii->getController()->buttons[DrumButtons::DRUM_GREEN]; + buttonX = wii->getController()->buttons[DrumButtons::DRUM_YELLOW]; + buttonY = wii->getController()->buttons[DrumButtons::DRUM_BLUE]; + buttonL = wii->getController()->buttons[DrumButtons::DRUM_ORANGE]; + buttonZR = wii->getController()->buttons[DrumButtons::DRUM_PEDAL]; + + leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightX = joystickMid; + rightY = joystickMid; + + triggerLeft = 0; + triggerRight = 0; + + isAnalogTriggers = true; + } else if (wii->extensionType == WII_EXTENSION_TURNTABLE) { + buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; + buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; + + dpadLeft = wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_GREEN]; + dpadUp = wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_RED]; + dpadRight = wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_BLUE]; + + buttonY = wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_GREEN]; + buttonX = wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_RED]; + buttonA = wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_BLUE]; + + buttonZR = wii->getController()->buttons[TurntableButtons::TURNTABLE_EUPHORIA]; + + leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightX = map(wii->getController()->analogState[TurntableAnalogs::TURNTABLE_RIGHT],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightY = map(wii->getController()->analogState[TurntableAnalogs::TURNTABLE_LEFT],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - } else if (wii->extensionType == WII_EXTENSION_GUITAR) { - buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; - buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; - - dpadUp = wii->getController()->buttons[WiiButtons::WII_BUTTON_UP]; - dpadDown = wii->getController()->buttons[WiiButtons::WII_BUTTON_DOWN]; - - buttonB = wii->getController()->buttons[GuitarButtons::GUITAR_GREEN]; - buttonA = wii->getController()->buttons[GuitarButtons::GUITAR_RED]; - buttonX = wii->getController()->buttons[GuitarButtons::GUITAR_YELLOW]; - buttonY = wii->getController()->buttons[GuitarButtons::GUITAR_BLUE]; - buttonZL = wii->getController()->buttons[GuitarButtons::GUITAR_ORANGE]; - - // whammy currently maps to Joy2X in addition to the raw whammy value - whammyBar = wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X]; - buttonR = wii->getController()->buttons[GuitarButtons::GUITAR_PEDAL]; - - leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_RIGHT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightY = joystickMid; - - triggerLeft = 0; - triggerRight = 0; - - isAnalogTriggers = true; - } else if (wii->extensionType == WII_EXTENSION_TAIKO) { - buttonL = wii->getController()->buttons[TaikoButtons::TATA_KAT_LEFT]; - buttonR = wii->getController()->buttons[TaikoButtons::TATA_KAT_RIGHT]; - - dpadLeft = wii->getController()->buttons[TaikoButtons::TATA_DON_LEFT]; - buttonA = wii->getController()->buttons[TaikoButtons::TATA_DON_RIGHT]; - } else if (wii->extensionType == WII_EXTENSION_DRUMS) { - buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; - buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; - - buttonB = wii->getController()->buttons[DrumButtons::DRUM_RED]; - buttonA = wii->getController()->buttons[DrumButtons::DRUM_GREEN]; - buttonX = wii->getController()->buttons[DrumButtons::DRUM_YELLOW]; - buttonY = wii->getController()->buttons[DrumButtons::DRUM_BLUE]; - buttonL = wii->getController()->buttons[DrumButtons::DRUM_ORANGE]; - buttonZR = wii->getController()->buttons[DrumButtons::DRUM_PEDAL]; - - leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightX = joystickMid; - rightY = joystickMid; - - triggerLeft = 0; - triggerRight = 0; - - isAnalogTriggers = true; - } else if (wii->extensionType == WII_EXTENSION_TURNTABLE) { - buttonSelect = wii->getController()->buttons[WiiButtons::WII_BUTTON_MINUS]; - buttonStart = wii->getController()->buttons[WiiButtons::WII_BUTTON_PLUS]; - - dpadLeft = wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_GREEN]; - dpadUp = wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_RED]; - dpadRight = wii->getController()->buttons[TurntableButtons::TURNTABLE_LEFT_BLUE]; - - buttonY = wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_GREEN]; - buttonX = wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_RED]; - buttonA = wii->getController()->buttons[TurntableButtons::TURNTABLE_RIGHT_BLUE]; - - buttonZR = wii->getController()->buttons[TurntableButtons::TURNTABLE_EUPHORIA]; - - leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightX = map(wii->getController()->analogState[TurntableAnalogs::TURNTABLE_RIGHT],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightY = map(wii->getController()->analogState[TurntableAnalogs::TURNTABLE_LEFT],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - - triggerLeft = wii->getController()->analogState[TurntableAnalogs::TURNTABLE_EFFECTS]; - triggerRight = wii->getController()->analogState[TurntableAnalogs::TURNTABLE_CROSSFADE]; - - isAnalogTriggers = true; - } else if ((wii->extensionType == WII_EXTENSION_DRAWSOME) || (wii->extensionType == WII_EXTENSION_UDRAW)) { - buttonA = wii->getController()->buttons[WiiButtons::WII_BUTTON_A]; - buttonL = wii->getController()->buttons[WiiButtons::WII_BUTTON_L]; - buttonR = wii->getController()->buttons[WiiButtons::WII_BUTTON_R]; - - touchX = wii->getController()->motionState[WiiMotions::WII_TOUCH_X]; - touchY = wii->getController()->motionState[WiiMotions::WII_TOUCH_Y]; - touchZ = wii->getController()->motionState[WiiMotions::WII_TOUCH_Z]; - touchPressed = wii->getController()->motionState[WiiMotions::WII_TOUCH_PRESSED]; - - isTouch = true; - } else if (wii->extensionType == WII_EXTENSION_MOTION_PLUS) { - currentConfig = &extensionConfigs[WII_EXTENSION_NUNCHUCK]; - - gyroscopeX = wii->getController()->motionState[WiiMotions::WII_GYROSCOPE_YAW]; - gyroscopeY = wii->getController()->motionState[WiiMotions::WII_GYROSCOPE_ROLL]; - gyroscopeZ = wii->getController()->motionState[WiiMotions::WII_GYROSCOPE_PITCH]; - isGyroscope = true; - - // add logic to know if an attachment is detected. for now, just stream it. - buttonZ = wii->getController()->buttons[WiiButtons::WII_BUTTON_Z]; - buttonC = wii->getController()->buttons[WiiButtons::WII_BUTTON_C]; - - leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); - rightX = joystickMid; - rightY = joystickMid; - - accelerometerX = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_X]; - accelerometerY = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Y]; - accelerometerZ = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Z]; - isAccelerometer = true; + triggerLeft = wii->getController()->analogState[TurntableAnalogs::TURNTABLE_EFFECTS]; + triggerRight = wii->getController()->analogState[TurntableAnalogs::TURNTABLE_CROSSFADE]; + + isAnalogTriggers = true; + } else if ((wii->extensionType == WII_EXTENSION_DRAWSOME) || (wii->extensionType == WII_EXTENSION_UDRAW)) { + buttonA = wii->getController()->buttons[WiiButtons::WII_BUTTON_A]; + buttonL = wii->getController()->buttons[WiiButtons::WII_BUTTON_L]; + buttonR = wii->getController()->buttons[WiiButtons::WII_BUTTON_R]; + + touchX = wii->getController()->motionState[WiiMotions::WII_TOUCH_X]; + touchY = wii->getController()->motionState[WiiMotions::WII_TOUCH_Y]; + touchZ = wii->getController()->motionState[WiiMotions::WII_TOUCH_Z]; + touchPressed = wii->getController()->motionState[WiiMotions::WII_TOUCH_PRESSED]; + + isTouch = true; + } else if (wii->extensionType == WII_EXTENSION_MOTION_PLUS) { + currentConfig = &extensionConfigs[WII_EXTENSION_NUNCHUCK]; + + gyroscopeX = wii->getController()->motionState[WiiMotions::WII_GYROSCOPE_YAW]; + gyroscopeY = wii->getController()->motionState[WiiMotions::WII_GYROSCOPE_ROLL]; + gyroscopeZ = wii->getController()->motionState[WiiMotions::WII_GYROSCOPE_PITCH]; + isGyroscope = true; + + // add logic to know if an attachment is detected. for now, just stream it. + buttonZ = wii->getController()->buttons[WiiButtons::WII_BUTTON_Z]; + buttonC = wii->getController()->buttons[WiiButtons::WII_BUTTON_C]; + + leftX = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_X],0,WII_ANALOG_PRECISION_3,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + leftY = map(wii->getController()->analogState[WiiAnalogs::WII_ANALOG_LEFT_Y],WII_ANALOG_PRECISION_3,0,GAMEPAD_JOYSTICK_MIN,GAMEPAD_JOYSTICK_MAX); + rightX = joystickMid; + rightY = joystickMid; + + accelerometerX = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_X]; + accelerometerY = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Y]; + accelerometerZ = wii->getController()->motionState[WiiMotions::WII_ACCELEROMETER_Z]; + isAccelerometer = true; + } + } else { + currentConfig = NULL; } - } else { - currentConfig = NULL; } } @@ -371,6 +510,16 @@ void WiiExtensionInput::reloadConfig() { setControllerAnalog(WII_EXTENSION_TURNTABLE, WiiAnalogs::WII_ANALOG_RIGHT_TRIGGER, wiiOptions.controllers.turntable.fader.axisType); } +bool WiiExtensionInput::getButtonState(uint16_t buttonMask) { + Gamepad * gamepad = Storage::getInstance().GetGamepad(); + + if (currentConfig->buttonMap[buttonMask] > GAMEPAD_MASK_A2) { + return gamepad->pressedDpad(buttonMask >> 16); + } else { + return gamepad->pressedButton(buttonMask); + } +} + void WiiExtensionInput::setButtonState(bool buttonState, uint16_t buttonMask) { Gamepad * gamepad = Storage::getInstance().GetGamepad();