From 879153d478c8153e5b6ce87bd08ca0369f11ec8f Mon Sep 17 00:00:00 2001 From: Tam D Date: Wed, 30 Aug 2023 03:57:45 +0000 Subject: [PATCH] Coolermaster keyboard device view --- .../CoolerMasterController/CMMKController.cpp | 150 +++++++++++++-- .../CoolerMasterController/CMMKController.h | 47 ++++- .../RGBController_CMMKController.cpp | 171 +++++++++--------- .../RGBController_CMMKController.h | 88 ++++----- OpenRGB.pro | 11 ++ .../libcmmk/src/mappings/ansi/sk630.h | 33 +++- 6 files changed, 345 insertions(+), 155 deletions(-) diff --git a/Controllers/CoolerMasterController/CMMKController.cpp b/Controllers/CoolerMasterController/CMMKController.cpp index e50d2308..efd6cbac 100644 --- a/Controllers/CoolerMasterController/CMMKController.cpp +++ b/Controllers/CoolerMasterController/CMMKController.cpp @@ -1,10 +1,8 @@ /*-------------------------------------------------------------------*\ | CMMKController.cpp | | | -| Driver for Coolermaster MasterKeys Keyboards | -| | -| Lukas N (chmod222) 28th Jun 2020 | -| Tam D (too.manyhobbies) 25th Apr 2021 | +| Lukas N (chmod222) 28th Jun 2020 | +| Tam D (too.manyhobbies) 25th Apr 2021 | | | \*-------------------------------------------------------------------*/ @@ -29,28 +27,128 @@ CMMKController::CMMKController(hid_device* dev, hid_device_info* dev_info) char buf[32] = {0}; cmmk_get_firmware_version(&cmmk_handle, buf, 32); + firmware_version = std::string(buf); - /*--------------------------------------------------------------*\ - | Adjust the row count for keyboards without the front light bar | - | Adjust the column count for TKL keyboards (i.e. x30 vs x50) | - \*--------------------------------------------------------------*/ enum cmmk_product_type kb_type = cmmk_get_device_model(&cmmk_handle); - row_count = (kb_type == CMMK_PRODUCT_MASTERKEYS_MK750) ? CMMK_ROWS_MAX : CMMK_ROWS_MAX - 1; + switch(kb_type) { case CMMK_PRODUCT_MASTERKEYS_PRO_S: case CMMK_PRODUCT_MASTERKEYS_SK630: + kb_size = KEYBOARD_SIZE_TKL; + row_count = CMMK_ROWS_MAX - 1; column_count = CMMK_COLS_MAX - 4; break; case CMMK_PRODUCT_MASTERKEYS_PRO_L: - case CMMK_PRODUCT_MASTERKEYS_MK750: case CMMK_PRODUCT_MASTERKEYS_SK650: + kb_size = KEYBOARD_SIZE_FULL; + row_count = CMMK_ROWS_MAX - 1; + column_count = CMMK_COLS_MAX; + break; + + case CMMK_PRODUCT_MASTERKEYS_MK750: default: + kb_size = KEYBOARD_SIZE_FULL; + row_count = CMMK_ROWS_MAX; column_count = CMMK_COLS_MAX; } - firmware_version = buf; + /*--------------------------------------------------------------*\ + | Detect the keyboard version and set the appropriate layout. | + \*--------------------------------------------------------------*/ + + switch(firmware_version[0]) + { + case '1': + kb_layout_type = KEYBOARD_LAYOUT_ANSI_QWERTY; + break; + + /*--------------------------------------------------------------*\ + | In case we need to handle different versions in the future. | + \*--------------------------------------------------------------*/ + default: + kb_layout_type = KEYBOARD_LAYOUT_ISO_QWERTY; + break; + } + + /*--------------------------------------------------------------*\ + | Populate key offsets. | + \*--------------------------------------------------------------*/ + keyboard_layout* kb_layout; + if(KEYBOARD_LAYOUT_ANSI_QWERTY == kb_layout_type) + { + switch (kb_type) + { + case CMMK_PRODUCT_MASTERKEYS_PRO_L: + kb_layout = &layout_ansi_pro_l; + break; + case CMMK_PRODUCT_MASTERKEYS_PRO_S: + kb_layout = &layout_ansi_pro_s; + break; + case CMMK_PRODUCT_MASTERKEYS_MK750: + kb_layout = &layout_ansi_mk750; + break; + case CMMK_PRODUCT_MASTERKEYS_SK630: + kb_layout = &layout_ansi_sk630; + break; + case CMMK_PRODUCT_MASTERKEYS_SK650: + kb_layout = &layout_ansi_sk650; + break; + + default: + kb_layout = 0; + break; + } + } + else + { + switch (kb_type) + { + case CMMK_PRODUCT_MASTERKEYS_PRO_L: + kb_layout = &layout_iso_pro_l; + break; + case CMMK_PRODUCT_MASTERKEYS_PRO_S: + kb_layout = &layout_iso_pro_s; + break; + case CMMK_PRODUCT_MASTERKEYS_MK750: + kb_layout = &layout_iso_mk750; + break; + case CMMK_PRODUCT_MASTERKEYS_SK630: + kb_layout = &layout_iso_sk630; + break; + case CMMK_PRODUCT_MASTERKEYS_SK650: + kb_layout = &layout_iso_sk650; + break; + + default: + kb_layout = 0; + break; + } + } + + std::vector keys_fn, keys_main, keys_num, keys_extra; + + memset(&kb_transform, -1, row_count*column_count); + + int key_idx = 0; + if(kb_layout) + { + for(int row = 0; row < row_count; row++) + { + for(int col = 0; col < column_count; col++) + { + int val = (*kb_layout)[row][col]; + + if (-1 != val) + { + kb_offsets.ansi.push_back(val); + kb_transform[row][col] = key_idx; + key_idx++; + } + } + } + } } CMMKController::~CMMKController() @@ -88,6 +186,26 @@ uint8_t CMMKController::GetColumnCount() return column_count; } +KEYBOARD_LAYOUT CMMKController::GetLayout() +{ + return kb_layout_type; +} + +keyboard_layout * CMMKController::GetTransform() +{ + return &kb_transform; +} + +KEYBOARD_SIZE CMMKController::GetSize() +{ + return kb_size; +} + +layout_values CMMKController::GetLayoutValues() +{ + return kb_offsets; +} + void CMMKController::SetFirmwareControl() { ActivateMode(CMMK_FIRMWARE); @@ -146,31 +264,31 @@ void CMMKController::SetMode(cmmk_effect_wave eff) void CMMKController::SetMode(cmmk_effect_ripple eff) { ActivateEffect(CMMK_EFFECT_RIPPLE); - cmmk_set_effect_ripple(&cmmk_handle, &eff); + cmmk_set_effect_ripple(&cmmk_handle, &eff); } void CMMKController::SetMode(cmmk_effect_cross eff) { ActivateEffect(CMMK_EFFECT_CROSS); - cmmk_set_effect_cross(&cmmk_handle, &eff); + cmmk_set_effect_cross(&cmmk_handle, &eff); } void CMMKController::SetMode(cmmk_effect_raindrops eff) { ActivateEffect(CMMK_EFFECT_RAINDROPS); - cmmk_set_effect_raindrops(&cmmk_handle, &eff); + cmmk_set_effect_raindrops(&cmmk_handle, &eff); } void CMMKController::SetMode(cmmk_effect_stars eff) { ActivateEffect(CMMK_EFFECT_STARS); - cmmk_set_effect_stars(&cmmk_handle, &eff); + cmmk_set_effect_stars(&cmmk_handle, &eff); } void CMMKController::SetMode(cmmk_effect_snake eff) { ActivateEffect(CMMK_EFFECT_SNAKE); - cmmk_set_effect_snake(&cmmk_handle, &eff); + cmmk_set_effect_snake(&cmmk_handle, &eff); } bool CMMKController::PositionValid(int y, int x) diff --git a/Controllers/CoolerMasterController/CMMKController.h b/Controllers/CoolerMasterController/CMMKController.h index 641a0de1..2f132862 100644 --- a/Controllers/CoolerMasterController/CMMKController.h +++ b/Controllers/CoolerMasterController/CMMKController.h @@ -7,10 +7,31 @@ | | \*-------------------------------------------------------------------*/ -#include +#include +#include #include #include +typedef int16_t keyboard_layout[CMMK_ROWS_MAX][CMMK_COLS_MAX]; + +/*---------------------------------------------------------*\ +| i'm not thrilled with the include path, but this will | +| work for now. fixing this would need to happen in libcmmk | +\*---------------------------------------------------------*/ +#pragma GCC push +#pragma GCC diagnostic ignored "-Wunused-variable" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#pragma GCC pop + #pragma once class CMMKController @@ -19,12 +40,17 @@ public: CMMKController(hid_device* dev_handle, hid_device_info* dev_info); ~CMMKController(); - std::string GetDeviceName(); - std::string GetDeviceVendor(); - std::string GetLocation(); - std::string GetFirmwareVersion(); - uint8_t GetRowCount(); - uint8_t GetColumnCount(); + std::string GetDeviceName(); + std::string GetDeviceVendor(); + std::string GetLocation(); + std::string GetFirmwareVersion(); + uint8_t GetRowCount(); + uint8_t GetColumnCount(); + + KEYBOARD_LAYOUT GetLayout(); + KEYBOARD_SIZE GetSize(); + layout_values GetLayoutValues(); + keyboard_layout* GetTransform(); void SetFirmwareControl(); void SetManualControl(); @@ -57,6 +83,13 @@ private: std::string vendor_name; std::string location; std::string firmware_version; + + KEYBOARD_SIZE kb_size; + KEYBOARD_LAYOUT kb_layout_type; + layout_values kb_offsets; + keyboard_layout kb_transform; + keyboard_layout* kb_layout; + uint8_t row_count; uint8_t column_count; diff --git a/Controllers/CoolerMasterController/RGBController_CMMKController.cpp b/Controllers/CoolerMasterController/RGBController_CMMKController.cpp index dce60a1f..4e26d1ba 100644 --- a/Controllers/CoolerMasterController/RGBController_CMMKController.cpp +++ b/Controllers/CoolerMasterController/RGBController_CMMKController.cpp @@ -34,7 +34,6 @@ using namespace std::chrono_literals; RGBController_CMMKController::RGBController_CMMKController(CMMKController* controller_ptr) { controller = controller_ptr; - name = controller->GetDeviceName(); vendor = controller->GetDeviceVendor(); type = DEVICE_TYPE_KEYBOARD; @@ -187,68 +186,48 @@ RGBController_CMMKController::~RGBController_CMMKController() delete controller; } -void RGBController_CMMKController::SetupMatrixMap() -{ - for(int y = 0; y < CMMK_ROWS_MAX; y++) - { - for(int x = 0; x < CMMK_COLS_MAX; x++) - { - matrix_map[y][x] = 0xFFFFFFFF; - } - } - - for(size_t i = 0; i < leds.size(); i++) - { - led& l = leds[i]; - - int y = (l.value & 0xFF00) >> 8; - int x = (l.value & 0xFF); - - matrix_map[y][x] = i; - } -} - void RGBController_CMMKController::SetupZones() { - uint8_t row_count = controller->GetRowCount(); - uint8_t column_count = controller->GetColumnCount(); + /*---------------------------------------------------------*\ + | Create the keyboard zone usiung Keyboard Layout Manager | + \*---------------------------------------------------------*/ + zone new_zone; + new_zone.name = ZONE_EN_KEYBOARD; + new_zone.type = ZONE_TYPE_MATRIX; - for(int y = 0; y < row_count; y++) + layoutManager = new KeyboardLayoutManager(controller->GetLayout(), controller->GetSize(), controller->GetLayoutValues()); + + matrix_map_type * new_map = new matrix_map_type; + new_zone.matrix_map = new_map; + new_zone.matrix_map->height = layoutManager->GetRowCount(); + new_zone.matrix_map->width = layoutManager->GetColumnCount(); + + new_zone.matrix_map->map = new unsigned int[new_map->height * new_map->width]; + new_zone.leds_count = layoutManager->GetKeyCount(); + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + + /*---------------------------------------------------------*\ + | Matrix map still uses declared zone rows and columns | + | as the packet structure depends on the matrix map | + \*---------------------------------------------------------*/ + layoutManager->GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT, new_map->height, new_map->width); + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + for(size_t led_idx = 0; led_idx < new_zone.leds_count; led_idx++) { - for(int x = 0; x < column_count; x++) - { - if(!controller->PositionValid(y, x)) - { - continue; - } + led new_led; - std::stringstream namestrm; - - led key; - - namestrm << "Key @ Row " << (y + 1) << ", Column" << (x + 1); - - key.name = namestrm.str(); - key.value = (y & 0xFF) << 8 | (x & 0xFF); - - leds.push_back(key); - } + new_led.name = layoutManager->GetKeyNameAt(led_idx); + new_led.value = layoutManager->GetKeyValueAt(led_idx); + leds.push_back(new_led); } - zone KeyboardZone; - KeyboardZone.name = "Keyboard"; - KeyboardZone.type = ZONE_TYPE_MATRIX; - KeyboardZone.leds_min = leds.size(); - KeyboardZone.leds_max = leds.size(); - KeyboardZone.leds_count = leds.size(); - KeyboardZone.matrix_map = new matrix_map_type; - KeyboardZone.matrix_map->height = row_count; - KeyboardZone.matrix_map->width = column_count; - KeyboardZone.matrix_map->map = (unsigned int *)&matrix_map; + zones.push_back(new_zone); - zones.push_back(KeyboardZone); - - SetupMatrixMap(); SetupColors(); } @@ -290,32 +269,40 @@ enum cmmk_wave_direction map_to_cmmk_dir(int input) } } -void copy_buffers(led* buf, RGBColor* colbuf, size_t n, struct cmmk_color_matrix& mat, std::atomic& dirty) + +void RGBController_CMMKController::copy_buffers(std::vector &in_colors, struct cmmk_color_matrix& mat, std::atomic& dirty) { dirty.store(false); - for(size_t i = 0; i < n; i++) + keyboard_layout * transform = controller->GetTransform(); + + if(0 == transform) { - led const& selected_led = buf[i]; + return; + } - int y = (selected_led.value & 0xFF00) >> 8; - int x = selected_led.value & 0xFF; - - struct rgb col = map_to_cmmk_rgb(colbuf[i]); - struct rgb ecol = mat.data[y][x]; - - if(ecol.R != col.R || ecol.G != col.G || ecol.B != col.B) + for(int row = 0; row < controller->GetRowCount(); row++) + { + for(int col = 0; col < controller->GetColumnCount(); col++) { - dirty.store(true); + int key_idx = (*transform)[row][col]; - mat.data[y][x] = col; + if(-1 == key_idx) + { + continue; + } + + struct rgb color = map_to_cmmk_rgb(in_colors[key_idx]); + + dirty.store(true); + mat.data[row][col] = color; } } } void RGBController_CMMKController::DeviceUpdateLEDs() { - copy_buffers(leds.data(), colors.data(), leds.size(), current_matrix, dirty); + copy_buffers(colors, current_matrix, dirty); if(force_update.load() || dirty.load()) { @@ -327,29 +314,47 @@ void RGBController_CMMKController::DeviceUpdateLEDs() void RGBController_CMMKController::UpdateZoneLEDs(int zone_idx) { - zone& z = zones[zone_idx]; + /*---------------------------------------------------------*\ + | This device only supports a single zone, as a result we | + | update all LEDs. | + \*---------------------------------------------------------*/ + DeviceUpdateLEDs(); +} - copy_buffers(z.leds, z.colors, z.leds_count, current_matrix, dirty); +void RGBController_CMMKController::UpdateSingleLED(int led_idx, RGBColor color) +{ + keyboard_layout * transform = controller->GetTransform(); + led selected_led = leds[led_idx]; - if(force_update.load() || dirty.load()) + if(0 == transform) { - controller->SetAll(current_matrix); - - force_update.store(false); + return; } + + // this is really expensive + for(int row = 0; row < controller->GetRowCount(); row++) + { + for(int col = 0; col < controller->GetColumnCount(); col++) + { + int val = (*transform)[row][col]; + + if(val != (int)selected_led.value) + { + continue; + } + + controller->SetSingle(row, col, map_to_cmmk_rgb(color)); + dirty.store(false); + + return; + } + } + } void RGBController_CMMKController::UpdateSingleLED(int led_idx) { - led& selected_led = leds[led_idx]; - - int y = (selected_led.value & 0xFF00) >> 8; - int x = selected_led.value & 0xFF; - - current_matrix.data[y][x] = map_to_cmmk_rgb(colors[led_idx]); - - controller->SetSingle(y, x, map_to_cmmk_rgb(colors[led_idx])); - dirty.store(false); + UpdateSingleLED(led_idx, colors[led_idx]); } void RGBController_CMMKController::SetCustomMode() diff --git a/Controllers/CoolerMasterController/RGBController_CMMKController.h b/Controllers/CoolerMasterController/RGBController_CMMKController.h index 39c87ab3..55b99c84 100644 --- a/Controllers/CoolerMasterController/RGBController_CMMKController.h +++ b/Controllers/CoolerMasterController/RGBController_CMMKController.h @@ -1,42 +1,46 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMKController.h | -| | -| Driver for Coolermaster MasterKeys keyboards | -| | -| Lukas N (chmod222) 28th Jun 2020 | -| Tam D (too.manyhobbies) 25th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "CMMKController.h" - -class RGBController_CMMKController : public RGBController -{ -public: - RGBController_CMMKController(CMMKController* controller_ptr); - ~RGBController_CMMKController(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - -private: - void SetupMatrixMap(); - - CMMKController* controller; - - int matrix_map[CMMK_ROWS_MAX][CMMK_COLS_MAX]; - struct cmmk_color_matrix current_matrix; - - std::atomic dirty; - std::atomic force_update; -}; +/*-------------------------------------------------------------------*\ +| RGBController_CMMKController.h | +| | +| Driver for Coolermaster MasterKeys keyboards | +| | +| Lukas N (chmod222) 28th Jun 2020 | +| Tam D (too.manyhobbies) 25th Apr 2021 | +| | +\*-------------------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "CMMKController.h" +#include "RGBControllerKeyNames.h" +#include "KeyboardLayoutManager.h" + +class RGBController_CMMKController : public RGBController +{ +public: + RGBController_CMMKController(CMMKController* controller_ptr); + ~RGBController_CMMKController(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateSingleLED(int led, RGBColor color); + void UpdateSingleLED(int led); + void UpdateZoneLEDs(int zone_idx); + + void SetCustomMode(); + void DeviceUpdateMode(); + +private: + void copy_buffers(std::vector &in_colors, struct cmmk_color_matrix& mat, std::atomic& dirty); + + CMMKController* controller; + KeyboardLayoutManager* layoutManager; + + struct cmmk_color_matrix current_matrix; + + std::atomic dirty; + std::atomic force_update; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index d108093f..db92f311 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -71,6 +71,7 @@ INCLUDEPATH += dependencies/json/ \ dependencies/libe131/src/ \ dependencies/libcmmk/include/ \ + dependencies/libcmmk/src/mappings/ \ dependencies/libusb-1.0.22/include/ \ dependencies/mdns \ dependencies/mbedtls-2.24.0/include/ \ @@ -240,6 +241,16 @@ HEADERS += dependencies/hidapi/hidapi/hidapi.h \ dependencies/json/json.hpp \ dependencies/libcmmk/include/libcmmk/libcmmk.h \ + dependencies/libcmmk/src/mappings/ansi/pro_s.h \ + dependencies/libcmmk/src/mappings/ansi/pro_l.h \ + dependencies/libcmmk/src/mappings/ansi/mk750.h \ + dependencies/libcmmk/src/mappings/ansi/sk630.h \ + dependencies/libcmmk/src/mappings/ansi/sk650.h \ + dependencies/libcmmk/src/mappings/iso/pro_s.h \ + dependencies/libcmmk/src/mappings/iso/pro_l.h \ + dependencies/libcmmk/src/mappings/iso/mk750.h \ + dependencies/libcmmk/src/mappings/iso/sk630.h \ + dependencies/libcmmk/src/mappings/iso/sk650.h \ LogManager.h \ NetworkClient.h \ NetworkProtocol.h \ diff --git a/dependencies/libcmmk/src/mappings/ansi/sk630.h b/dependencies/libcmmk/src/mappings/ansi/sk630.h index 02454df0..54de4c9f 100644 --- a/dependencies/libcmmk/src/mappings/ansi/sk630.h +++ b/dependencies/libcmmk/src/mappings/ansi/sk630.h @@ -15,11 +15,30 @@ * License along with libcmmk. If not, see . */ static keyboard_layout layout_ansi_sk630 = { + /* + ESC F1 F2 F3 F4 XXX F5 F6 F7 F8 XXX F9 F10 F11 F12 PRN SCL PAU XXX XXX XXX XXX */ + { 9, 33, 41, 49, 57, -1, 73, 81, 89, 97, -1, 105, 113, 121, 129, 137, 145, 153, -1, -1, -1, -1}, + + /* + ^ 1 2 3 4 5 6 7 8 9 0 ß ´ XXX BCK INS HOM PUP XXX XXX XXX` XXX */ + {10, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 114, -1, 130, 138, 146, 154, -1, -1, -1, -1}, + + /* + TAB Q W E R T Z/Y U I O P { } XXX | DEL END PGDN XXX XXX XXX XXX */ + {11, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, -1, 131, 139, 147, 155, -1, -1, -1, -1}, + + /* + CAP A S D F G H J K L ; " XXX XXX ENT XXX XXX XXX XXX XXX XXX XXX */ + {12, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, -1, -1, 132, -1, -1, -1, -1, -1, -1, -1}, + + /* + LSHFT Z X C V B N M < > ? XXX XXX XXX RSHFT XXX UP XXX XXX XXX XXX XXX */ + {13, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, -1, -1, -1, 133, -1, 149, -1, -1, -1, -1, -1}, + + /* + LCTRL LWIN LALT XXX XXX XXX SPACE XXX XXX XXX RALT RWIN FN XXX RCTRL LEFT DOWN RIGHT XXX XXX XXX XXX */ + {14, 22, 30, -1, -1, -1, 62, -1, -1, -1, 94, 102, 110, -1, 134, 142, 150, 158, -1, -1, -1, -1}, + + /* Bottom row does not exist */ {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, -}; \ No newline at end of file +};