void NewRoom(int nrnum) { if (nrnum < 0) quitprintf("!NewRoom: room change requested to invalid room number %d.", nrnum); if (displayed_room < 0) { // called from game_start; change the room where the game will start playerchar->room = nrnum; return; } DEBUG_CONSOLE("Room change requested to room %d", nrnum); EndSkippingUntilCharStops(); can_run_delayed_command(); if (play.stop_dialog_at_end != DIALOG_NONE) { if (play.stop_dialog_at_end == DIALOG_RUNNING) play.stop_dialog_at_end = DIALOG_NEWROOM + nrnum; else { quitprintf("!NewRoom: two NewRoom/RunDialog/StopDialog requests within dialog; last was called in \"%s\", line %d", last_in_dialog_request_script_pos.Section.GetCStr(), last_in_dialog_request_script_pos.Line); } return; } get_script_position(last_in_dialog_request_script_pos); if (in_leaves_screen >= 0) { // NewRoom called from the Player Leaves Screen event -- just // change which room it will go to in_leaves_screen = nrnum; } else if (in_enters_screen) { setevent(EV_NEWROOM,nrnum); return; } else if (in_inv_screen) { inv_screen_newroom = nrnum; return; } else if ((inside_script==0) & (in_graph_script==0)) { new_room(nrnum,playerchar); return; } else if (inside_script) { curscript->queue_action(ePSANewRoom, nrnum, "NewRoom"); // we might be within a MoveCharacterBlocking -- the room // change should abort it if ((playerchar->walking > 0) && (playerchar->walking < TURNING_AROUND)) { // nasty hack - make sure it doesn't move the character // to a walkable area mls[playerchar->walking].direct = 1; StopMoving(game.playercharacter); } } else if (in_graph_script) gs_to_newroom = nrnum; }
int32_t FTDIListener(ftdi_context ftdihandle) { int32_t returnvalue,i; unsigned char * bufferptr; #ifdef DEBUGMODE printf("FTDIListener\n"); #endif do { do { returnvalue=p_ftdi_read_data(ftdihandle, RXBUFFER, 2); }while(returnvalue==0); if(returnvalue>0) { for(i=0;i<returnvalue;i++) { rx_fifo.BUFFER[(rx_fifo.ptr_in)&(BUFFERSIZE-1)]=RXBUFFER[i]; rx_fifo.ptr_in=(rx_fifo.ptr_in+1)&(BUFFERSIZE-1); } #ifdef DEBUGMODE printf("rx : %d %d \n",rx_fifo.ptr_in,returnvalue); #endif if(READ_THREAD_EVENT)setevent(READ_THREAD_EVENT); } else { #ifdef DEBUGMODE printf("FTDIListener : ftdi_read_data=%d\n",returnvalue); #endif stop_thread=1; if(READ_THREAD_EVENT)setevent(READ_THREAD_EVENT); } }while(!stop_thread); setevent(STOP_THREAD_EVENT); return 0; }
// Function name : ShmemLockedQueue::RemoveNextInsert // Description : // Return type : bool // Argument : MessageQueue *pMsgQueue bool ShmemLockedQueue::RemoveNextInsert(MessageQueue *pMsgQueue, bool bBlocking) { ShmemLockedQueueHeader *pTail, *pHead, *pMessage; if (bBlocking) { // Get the next available entry in the queue while(true) { // Get the queue mutex lock(m_plQMutex); // Wait for the queue to not be empty while (SHMEM_Q_HEAD_OFFSET == 0) { unlock(m_plQMutex); if (m_bUseEvent) { if (WaitForSingleObject(m_hMsgAvailableEvent, INFINITE) != WAIT_OBJECT_0) { printf("ShmemLockedQueue:RemoveNextInsert:Wait for MsgAvailableEvent on an empty queue failed, error %d\n", GetLastError());fflush(stdout); return false; } } else wait(m_plMsgAvailableTrigger); lock(m_plQMutex); } // Search the queue for the next available entry pMessage = SHMEM_Q_HEAD_PTR; pTail = SHMEM_Q_TAIL_PTR; while ((pMessage->state == SHMEM_Q_BEING_READ) && (pMessage < pTail)) pMessage = (ShmemLockedQueueHeader*) ((LPBYTE)pMessage + pMessage->next_offset); // If we haven't reached the tail and the element we are on is not // currently being written, then successfully break out of this loop if ( (pMessage < pTail) && (pMessage->state != SHMEM_Q_BEING_WRITTEN) ) break; // All messages are being read or the next message in order is not // ready. I need to reset MsgAvailableEvent, wait for it to be // signalled and then start over if (m_bUseEvent) { ResetEvent(m_hMsgAvailableEvent); unlock(m_plQMutex); if (WaitForSingleObject(m_hMsgAvailableEvent, INFINITE) != WAIT_OBJECT_0) { printf("ShmemLockedQueue:RemoveNextInsert:Wait for MsgAvailableEvent failed, error %d\n", GetLastError());fflush(stdout); return false; } } else { resetevent(m_plMsgAvailableTrigger); unlock(m_plQMutex); wait(m_plMsgAvailableTrigger); } } } else { // Try to get the next available entry in the queue // Get the queue mutex lock(m_plQMutex); // Wait for the queue to not be empty if (SHMEM_Q_HEAD_OFFSET == 0) { unlock(m_plQMutex); return false; } // Search the queue for the next available entry pMessage = SHMEM_Q_HEAD_PTR; pTail = SHMEM_Q_TAIL_PTR; while ((pMessage->state == SHMEM_Q_BEING_READ) && (pMessage < pTail)) pMessage = (ShmemLockedQueueHeader*) ((LPBYTE)pMessage + pMessage->next_offset); // If we haven't reached the tail and the element we are on is not // currently being written, then successfully break out of this loop if ( (pMessage >= pTail) || (pMessage->state == SHMEM_Q_BEING_WRITTEN) ) { // All messages are being read or the next message in order is not // ready. I need to reset MsgAvailableEvent, wait for it to be // signalled and then start over if (m_bUseEvent) { ResetEvent(m_hMsgAvailableEvent); unlock(m_plQMutex); return false; } else { resetevent(m_plMsgAvailableTrigger); unlock(m_plQMutex); return false; } } } MessageQueue::MsgQueueElement *pElement; if (pMessage->from == -1) { unlock(m_plQMutex); return false; } if (pMessage->state == SHMEM_Q_SHP_AVAIL_FOR_READ) { shpData data; memcpy(&data, (LPBYTE)pMessage + sizeof(ShmemLockedQueueHeader), sizeof(shpData)); void *pLocal = g_MsgQueue.GetBufferToFill(pMessage->tag, data.length, pMessage->from, &pElement); if (!ReadProcessMemory( g_hProcesses[pMessage->from], data.address, pLocal, data.length , NULL)) //nt_error("Unable to read remote memory", pMessage->from); MakeErrMsg(GetLastError(), "Unable to read remote memory in process %d", pMessage->from); SetEvent(g_hShpSendCompleteEvent[g_nIproc]); g_MsgQueue.SetElementEvent(pElement); } else { void *pBuffer = pMsgQueue->GetBufferToFill( pMessage->tag, pMessage->length, pMessage->from, &pElement); // Mark the message as being read pMessage->state = SHMEM_Q_BEING_READ; unlock(m_plQMutex); // Read the data from the message memcpy(pBuffer, (LPBYTE)pMessage + sizeof(ShmemLockedQueueHeader), pMessage->length); pMsgQueue->SetElementEvent(pElement); lock(m_plQMutex); } // Mark the message as having been read pMessage->state = SHMEM_Q_READ; // Update the head and tail pointers of the queue pHead = SHMEM_Q_HEAD_PTR; pTail = SHMEM_Q_TAIL_PTR; // Advance the head pointer over all the read messages while ( (pHead < pTail) && (pHead->state == SHMEM_Q_READ) ) pHead = (ShmemLockedQueueHeader*)((LPBYTE)pHead + pHead->next_offset); if (pHead >= pTail) { // When the head catches up to the tail, the queue is empty so reset // the pointers and signal the queue empty SHMEM_Q_HEAD_OFFSET = 0; SHMEM_Q_TAIL_OFFSET = 2*sizeof(unsigned long); if (m_bUseEvent) ResetEvent(m_hMsgAvailableEvent); else resetevent(m_plMsgAvailableTrigger); setevent(m_plQEmptyTrigger); } else SHMEM_Q_HEAD_OFFSET = (unsigned long)((LPBYTE)pHead - (LPBYTE)m_pBase); unlock(m_plQMutex); return true; }
// Function name : ShmemLockedQueue::RemoveNext // Description : // Return type : bool // Argument : unsigned char *buffer // Argument : unsigned int *length // Argument : int *tag // Argument : int *from bool ShmemLockedQueue::RemoveNext( unsigned char *buffer, unsigned int *length, int *tag, int *from) { ShmemLockedQueueHeader *pTail, *pHead, *pMessage; // Get the next available entry in the queue while(true) { // Get the queue mutex lock(m_plQMutex); // Wait for the queue to not be empty while (SHMEM_Q_HEAD_OFFSET == 0) { unlock(m_plQMutex); if (m_bUseEvent) { if (WaitForSingleObject(m_hMsgAvailableEvent, INFINITE) != WAIT_OBJECT_0) { printf("ShmemLockedQueue:RemoveNext:Wait for MsgAvailableEvent on an empty queue failed, error %d\n", GetLastError());fflush(stdout); return false; } } else wait(m_plMsgAvailableTrigger); lock(m_plQMutex); } // Search the queue for the next entry not being read by another thread pMessage = SHMEM_Q_HEAD_PTR; pTail = SHMEM_Q_TAIL_PTR; while ((pMessage->state == SHMEM_Q_BEING_READ) && (pMessage < pTail)) pMessage = (ShmemLockedQueueHeader*) ((LPBYTE)pMessage + pMessage->next_offset); // If we haven't reached the tail and the element we are on is not // currently being written, then successfully break out of this loop if ( (pMessage < pTail) && (pMessage->state != SHMEM_Q_BEING_WRITTEN) ) break; // All messages are being read or the next message in order is // not ready. I need to reset MsgAvailableEvent, wait for it to be // signalled and then start over if (m_bUseEvent) { ResetEvent(m_hMsgAvailableEvent); unlock(m_plQMutex); if (WaitForSingleObject(m_hMsgAvailableEvent, INFINITE) != WAIT_OBJECT_0) { printf("ShmemLockedQueue:RemoveNext:Wait for MsgAvailableEvent failed, error %d\n", GetLastError());fflush(stdout); return false; } } else { resetevent(m_plMsgAvailableTrigger); unlock(m_plQMutex); wait(m_plMsgAvailableTrigger); } } // Check that the buffer provided is large enough to hold the data if (pMessage->length > *length) { printf("ShmemLockedQueue:RemoveNext:shmem message length %d > %d user buffer length\n", pMessage->length, *length); unlock(m_plQMutex); return false; } // Mark the message as being read pMessage->state = SHMEM_Q_BEING_READ; unlock(m_plQMutex); // Read the data from the message *tag = pMessage->tag; *from = pMessage->from; *length = pMessage->length; memcpy(buffer, (LPBYTE)pMessage + sizeof(ShmemLockedQueueHeader), pMessage->length); lock(m_plQMutex); // Mark the message as having been read pMessage->state = SHMEM_Q_READ; // Update the head and tail pointers of the queue pHead = SHMEM_Q_HEAD_PTR; pTail = SHMEM_Q_TAIL_PTR; // Advance the head pointer over all the read messages while ( (pHead < pTail) && (pHead->state == SHMEM_Q_READ) ) pHead = (ShmemLockedQueueHeader*)((LPBYTE)pHead + pHead->next_offset); if (pHead >= pTail) { // When the head catches up to the tail, // the queue is empty so reset the pointers and signal the queue empty SHMEM_Q_HEAD_OFFSET = 0; SHMEM_Q_TAIL_OFFSET = 2*sizeof(unsigned long); if (m_bUseEvent) ResetEvent(m_hMsgAvailableEvent); else resetevent(m_plMsgAvailableTrigger); setevent(m_plQEmptyTrigger); } else SHMEM_Q_HEAD_OFFSET = (unsigned long)((LPBYTE)pHead - (LPBYTE)m_pBase); unlock(m_plQMutex); return true; }
bool ShmemLockedQueue::InsertSHP( unsigned char *buffer, unsigned int length, int tag, int from, HANDLE hRemoteMutex, HANDLE hRemoteEvent, ShmemLockedQueue *pOtherQueue) { ShmemLockedQueueHeader *pMessage; shpData data; data.address = buffer; data.length = length; WaitForSingleObject(hRemoteMutex, INFINITE); lock(m_plQMutex); // Wait for a contiguous block large enough to hold the data while ( ( SHMEM_Q_TAIL_PTR >= m_pEnd ) || ( (unsigned long)m_pEnd - (unsigned long)SHMEM_Q_TAIL_PTR - sizeof(ShmemLockedQueueHeader) < sizeof(shpData) ) ) { unlock(m_plQMutex); if (m_pProgressPollFunction) { while (!test(m_plQEmptyTrigger)) m_pProgressPollFunction(); } else wait(m_plQEmptyTrigger); lock(m_plQMutex); } // Read the tail pointer pMessage = SHMEM_Q_TAIL_PTR; // If the head offset is 0, set it to the tail if ( SHMEM_Q_HEAD_OFFSET == 0 ) SHMEM_Q_HEAD_OFFSET = SHMEM_Q_TAIL_OFFSET; // Set the state and advance the tail offset pMessage->state = SHMEM_Q_BEING_WRITTEN; // Advance the tail offset SHMEM_Q_TAIL_OFFSET = (unsigned long)( (unsigned long)pMessage + sizeof(ShmemLockedQueueHeader) + sizeof(shpData) - (unsigned long)m_pBase); unlock(m_plQMutex); // Write the header pMessage->tag = tag; pMessage->from = from; pMessage->length = sizeof(shpData); pMessage->next_offset = (sizeof(ShmemLockedQueueHeader) + sizeof(shpData)); // Copy the data memcpy((LPBYTE)pMessage + sizeof(ShmemLockedQueueHeader), &data, sizeof(shpData)); lock(m_plQMutex); // Signal data has arrived and release the mutex pMessage->state = SHMEM_Q_SHP_AVAIL_FOR_READ; if (m_bUseEvent) SetEvent(m_hMsgAvailableEvent); else setevent(m_plMsgAvailableTrigger); resetevent(m_plQEmptyTrigger); unlock(m_plQMutex); if (g_MsgQueue.m_pProgressPollFunction) { while (WaitForSingleObject(hRemoteEvent, 0) != WAIT_OBJECT_0) g_MsgQueue.m_pProgressPollFunction(); } else if (pOtherQueue->m_pProgressPollFunction) { while (WaitForSingleObject(hRemoteEvent, 0) != WAIT_OBJECT_0) pOtherQueue->m_pProgressPollFunction(); //pOtherQueue->RemoveNextInsert(&g_MsgQueue, false); } else WaitForSingleObject(hRemoteEvent, INFINITE); ResetEvent(hRemoteEvent); ReleaseMutex(hRemoteMutex); return true; }
// Function name : ShmemLockedQueue::Insert // Description : // Return type : bool // Argument : unsigned char *buffer // Argument : unsigned int length // Argument : int tag // Argument : int from bool ShmemLockedQueue::Insert( unsigned char *buffer, unsigned int length, int tag, int from) { ShmemLockedQueueHeader *pMessage; lock(m_plQMutex); if (length > m_dwMaxMsgSize) { unlock(m_plQMutex); return false; } // Wait for a contiguous block large enough to hold the data while ( ( SHMEM_Q_TAIL_PTR >= m_pEnd ) || ( (unsigned long)m_pEnd - (unsigned long)SHMEM_Q_TAIL_PTR - sizeof(ShmemLockedQueueHeader) < length) ) { unlock(m_plQMutex); if (m_pProgressPollFunction) { while (!test(m_plQEmptyTrigger)) m_pProgressPollFunction(); } else wait(m_plQEmptyTrigger); lock(m_plQMutex); } // Read the tail pointer pMessage = SHMEM_Q_TAIL_PTR; // If the head offset is 0, set it to the tail if ( SHMEM_Q_HEAD_OFFSET == 0 ) SHMEM_Q_HEAD_OFFSET = SHMEM_Q_TAIL_OFFSET; // Set the state and advance the tail offset pMessage->state = SHMEM_Q_BEING_WRITTEN; // Advance the tail offset SHMEM_Q_TAIL_OFFSET = (unsigned long)( (unsigned long)pMessage + sizeof(ShmemLockedQueueHeader) + length - (unsigned long)m_pBase); unlock(m_plQMutex); // Write the header pMessage->tag = tag; pMessage->from = from; pMessage->length = length; pMessage->next_offset = (sizeof(ShmemLockedQueueHeader) + length); // Copy the data memcpy((LPBYTE)pMessage + sizeof(ShmemLockedQueueHeader), buffer, length); lock(m_plQMutex); // Signal data has arrived and release the mutex pMessage->state = SHMEM_Q_AVAIL_FOR_READ; if (m_bUseEvent) SetEvent(m_hMsgAvailableEvent); else setevent(m_plMsgAvailableTrigger); resetevent(m_plQEmptyTrigger); unlock(m_plQMutex); return true; }