// 处理所有按键 void HandleKeys(unsigned char Id, unsigned short Key) { char Pos; struct stUserInfo *pUser = GetUserInfo(Id); int OldTotalScore = GetIntValue(UD_TOTALSCORE+Id); int OldTotalBet = pUser->TotalBetScore; // 有押分 if (Key & 0x1F) { if (IsBetting() && !IsPollingCoin(Id)) { OnBetAll(Id, Key&0x1F); } } Key &= ~0x1F; // 其它按键 while (Key) { Pos = bsr32(Key); Key &= ~(1<<Pos); if (KeyDownHandler[Pos]) { KeyDownHandler[Pos](Id); // 处理 } } // 设置标志 if ( (OldTotalBet != pUser->TotalBetScore) || (OldTotalScore != GetIntValue(UD_TOTALSCORE+Id)) ) { Set_Score(Id); Set_Sound(Id); } }
// 接收按键处理 void Process_BetPadKey(unsigned char Id, unsigned char *Data) { unsigned short Key = (Data[0]|(Data[1]<<8)); unsigned short Release; // 已释放掉的键 unsigned char BitIdx; int Tick; Key &= 0x0EFF; if (!RecvTick[Id]) { // 发送ID if (Id < COM_PLAYER_COUNT) { Send_ID(Id); } Set_Odds(Id); Set_LED(Id); Set_Score(Id); } RecvTick[Id] = GetTick() + 3000; // 如果1.5秒内没有信息发过来就当掉线 DownKey[Id] = Key & (Key ^ ConstDownKey[Id]); // 长按开始计数 Release = DownKey[Id]&(~ConstDownKey[Id]); Tick = GetTick(); while (Release & KeyPressFlag) { BitIdx = bsr32(Release); Release &= ~(1<<BitIdx); KeyCount[Id][BitIdx] = Tick + 200; } Release = (Key ^ DownKey[Id] ^ ConstDownKey[Id]); ConstDownKey[Id] = Key & (~Release); }
unsigned bitdelta32(unsigned *in, unsigned n, unsigned *out, unsigned start, unsigned inc) { #ifdef __SSE2__ unsigned *ip,b,*op = out; __m128i bv = _mm_setzero_si128(), sv = _mm_set1_epi32(start), cv = _mm_set1_epi32(inc), dv; for(ip = in; ip != in+(n&~(4-1)); ip += 4) { __m128i iv = _mm_loadu_si128((__m128i *)ip); bv = _mm_or_si128(bv, dv = _mm_sub_epi32(DELTA128_32(iv,sv),cv)); sv = iv; _mm_storeu_si128((__m128i *)op, dv); op += 4; } start = (unsigned)_mm_cvtsi128_si32(_mm_srli_si128(sv,12)); HOR128_32(bv, b); while(ip < in+n) { unsigned x = *ip-start-inc; start = *ip++; b |= x; *op++ = x; } #else typeof(in[0]) b = 0,*op = out; BITDELTA(in, n, inc, start, b |= _x;*op++ = _x); #endif return bsr32(b); }
unsigned bitd32(unsigned *in, unsigned n, unsigned start) { #ifdef __SSE2__ unsigned *ip,b; __m128i bv = _mm_setzero_si128(), sv = _mm_set1_epi32(start); for(ip = in; ip != in+(n&~(4-1)); ip += 4) { __m128i iv = _mm_loadu_si128((__m128i *)ip); bv = _mm_or_si128(bv, DELTA128_32(iv,sv)); sv = iv; } start = (unsigned)_mm_cvtsi128_si32(_mm_srli_si128(sv,12)); HOR128_32(bv, b); while(ip < in+n) { unsigned x = *ip-start; start = *ip++; b |= x; } #else typeof(in[0]) b = 0; BITDELTA(in,n, 0, start, b |= _x); #endif return bsr32(b); }
void Process_PressKey() { static int HeartBeatTick = 0; char Id; char Idx; unsigned short ValidConstKey = 0; unsigned short Flag; // 一次 for (Id = 0; Id < PLAYER_COUNT; Id++) { if (DownKey[Id] & KeyDownFlag) { HandleKeys(Id, DownKey[Id] & KeyDownFlag); DownKey[Id] = 0; } } // 心跳 if (GetTick() > HeartBeatTick) { HeartBeatTick = GetTick() + 1000; ScoreFlag = ALLBITS; } // 常押 for (Id = 0; Id < PLAYER_COUNT; Id++) { if (GetTick() > RecvTick[Id]) { RecvTick[Id] = 0; continue; } // 处理按键 if (ConstDownKey[Id] & KeyPressFlag) { ValidConstKey = 0; Flag = ConstDownKey[Id] & KeyPressFlag; while (Flag) { Idx = bsr32(Flag); Flag &= ~(1<<Idx); if (GetTick() > KeyCount[Id][Idx]) { KeyCount[Id][Idx] = GetTick() + 100; ValidConstKey |= (1<<Idx); } } HandleKeys(Id, ValidConstKey); } } // 填充串口消息 for (Id = 0; Id < COM_PLAYER_COUNT; Id++) { for (Idx = 0; Idx < sizeof(pMsgFlags)/sizeof(pMsgFlags[0]); Idx++) { if (ReturnWriteCount(Id) < 32) { break; } if (*pMsgFlags[Idx] & (1<<Id)) { *pMsgFlags[Idx] &= ~(1<<Id); CallBack_SendCom[Idx](Id); } } } // 填充USB消息 for (Id = COM_PLAYER_COUNT; Id < PLAYER_COUNT; Id++) { if (!RecvTick[Id]) { continue; } for (Idx = 0; Idx < sizeof(usb_bits)/sizeof(*usb_bits); Idx++) { if (*pMsgFlags[Idx] & (1<<Id)) { *pMsgFlags[Idx] &= ~(1<<Id); SetUSBFlag(usb_bits[Idx], Id); } } // for (Idx = 0; Idx < sizeof(pMsgFlags)/sizeof(pMsgFlags[0]); Idx++) { // if (CallBack_SendUSB[Idx] && (*pMsgFlags[Idx] & (1<<Id))) { // *pMsgFlags[Idx] &= ~(1<<Id); // CallBack_SendUSB[Idx](Id); // } // } } }
// 注册键位 void RegisterKeyDown(unsigned long Key, void (*CallBack)(char)) { KeyDownFlag |= Key; KeyDownHandler[bsr32(Key)] = CallBack; }
void OnBetAll(char Id, unsigned long Key) { char BetIdx; char BetSwitch = GetCharValue(UD_BETSCORE_SWITCH + Id) + GetShortValue(UD_SWITCH_MIN); int BetScore = SwitchScore[BetSwitch]; static short NewBetscores[EXTRA_COUNT]; struct stUserInfo *pUser = GetUserInfo(Id); int Left,Right; int LeftTotalScore,CanBetScore; // 押分限制 for (BetIdx = 0; BetIdx < EXTRA_COUNT; BetIdx++) { NewBetscores[BetIdx] = pUser->BetScore[BetIdx]; } Key &= GetCanBetFlag(); while (Key) { BetIdx = bsr32(Key); Key &= ~(1<<BetIdx); if (BetIdx == 4) { LeftTotalScore = GetIntValue(UD_TOTALSCORE + Id) - pUser->TotalBetScore; // 剩余总分 CanBetScore = MIN(LeftTotalScore, GetShortValue(UD_EXTRABET_MAX) - NewBetscores[BetIdx]); } else { Left = GetExtraSumBetScore(Id) + NewBetscores[4] - pUser->TotalBetScore; // 总押分限制(不包含第4门) Right = GetShortValue(UD_EXTRABET_MAX) - NewBetscores[BetIdx]; // 单门押分限制 LeftTotalScore = GetIntValue(UD_TOTALSCORE + Id) - pUser->TotalBetScore; // 还剩余总分 CanBetScore = MIN(MIN(Left, Right), LeftTotalScore); } // 分数不够 if (CanBetScore <= 0) { continue; } // 第一次押分要取最小押注和押分板押注间的最大者 if (!NewBetscores[BetIdx]) { if (GetShortValue(UD_EXTRABET_MIN) > BetScore) { BetScore = GetShortValue(UD_EXTRABET_MIN); } } // 可押分 if (BetScore > CanBetScore) { BetScore = CanBetScore; } pUser->TotalBetScore -= pUser->BetScore[BetIdx]; NewBetscores[BetIdx] += BetScore; // 是否可押成功 for (char k = 0; k < BetIdx; k++) { pUser->BetScore[k] = NewBetscores[k]; } CalculateLimit(Id+1, NewBetscores); NewBetscores[BetIdx] = pUser->BetScore[BetIdx]; // 如果为负,则为0 if (pUser->BetScore[BetIdx] < 0) { // SendUSB_Debug("ID(%d)->%d:%d", Id, BetIdx, pUser->BetScore[BetIdx]); pUser->BetScore[BetIdx] = 0; } pUser->TotalBetScore += pUser->BetScore[BetIdx]; } // 重新计算押分和 pUser->TotalBetScore = 0; for (BetIdx = 0; BetIdx < EXTRA_COUNT; BetIdx++) { pUser->TotalBetScore += pUser->BetScore[BetIdx]; } // 总押分不能超过总分 if (pUser->TotalBetScore > GetIntValue(UD_TOTALSCORE+Id)) { // SendUSB_Debug("ID(%d) bet>total %d:%d", Id, pUser->TotalBetScore, GetIntValue(UD_TOTALSCORE+Id)); for (BetIdx = 0; BetIdx < EXTRA_COUNT; BetIdx++) { pUser->BetScore[BetIdx] = 0; } pUser->TotalBetScore = 0; } }
/// Add a new node to the tree. node->uncompressed_base and /// node->compressed_base must have been set by the caller already. static void index_tree_append(index_tree *tree, index_tree_node *node) { node->parent = tree->rightmost; node->left = NULL; node->right = NULL; ++tree->count; // Handle the special case of adding the first node. if (tree->root == NULL) { tree->root = node; tree->leftmost = node; tree->rightmost = node; return; } // The tree is always filled sequentially. assert(tree->rightmost->uncompressed_base <= node->uncompressed_base); assert(tree->rightmost->compressed_base < node->compressed_base); // Add the new node after the rightmost node. It's the correct // place due to the reason above. tree->rightmost->right = node; tree->rightmost = node; // Balance the AVL-tree if needed. We don't need to keep the balance // factors in nodes, because we always fill the tree sequentially, // and thus know the state of the tree just by looking at the node // count. From the node count we can calculate how many steps to go // up in the tree to find the rotation root. uint32_t up = tree->count ^ (UINT32_C(1) << bsr32(tree->count)); if (up != 0) { // Locate the root node for the rotation. up = ctz32(tree->count) + 2; do { node = node->parent; } while (--up > 0); // Rotate left using node as the rotation root. index_tree_node *pivot = node->right; if (node->parent == NULL) { tree->root = pivot; } else { assert(node->parent->right == node); node->parent->right = pivot; } pivot->parent = node->parent; node->right = pivot->left; if (node->right != NULL) node->right->parent = node; pivot->left = node; node->parent = pivot; } return; }