Advertisement
Tarferi

Starcraft Emulator Trigger Core

Aug 23rd, 2019
581
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.83 KB | None | 0 0
  1. #include "TriggerCore.h"
  2.  
  3.  
  4.  
  5. TriggerCore::TriggerCore(EUDStarcraft* sc, char* data, unsigned int length) {
  6.     this->data = data;
  7.     this->length = length;
  8.     this->sc = sc;
  9.  
  10.     this->sc->PlayersTriggerList[0].first = nullptr;
  11.     this->sc->PlayersTriggerList[1].first = nullptr;
  12.     this->sc->PlayersTriggerList[2].first = nullptr;
  13.     this->sc->PlayersTriggerList[3].first = nullptr;
  14.     this->sc->PlayersTriggerList[4].first = nullptr;
  15.     this->sc->PlayersTriggerList[5].first = nullptr;
  16.     this->sc->PlayersTriggerList[6].first = nullptr;
  17.     this->sc->PlayersTriggerList[7].first = nullptr;
  18.  
  19. }
  20.  
  21. #define NODE_NEEDED EnabledFor(t, player) || EnabledFor(t, Players::AllPlayers) || EnabledFor(t, Players::Force1 + playerForces[player])
  22.  
  23. void createNodeIfNeeded(TriggerNode* nodes, unsigned int* freeNodeIndex, Trigger* t, unsigned int player, unsigned char* playerForces, TriggerList* PlayersTriggerList) {
  24.     if (NODE_NEEDED) {
  25.         TriggerList* lst = &(PlayersTriggerList[player]);
  26.         TriggerNode* node = &(nodes[*freeNodeIndex]);
  27.         *freeNodeIndex = (*freeNodeIndex) + 1;
  28.         node->prev = nullptr;
  29.         node->next = nullptr;
  30.         memcpy(&(node->data), t->data, sizeof(TriggerData));
  31.         if (lst->first == nullptr) { // First
  32.             lst->first = node;
  33.         } else { // Has prev
  34.             node->prev = lst->last;
  35.             node->prev->next = node;
  36.         }
  37.         lst->last = node;
  38.     }
  39. }
  40.  
  41. bool TriggerCore::construct() {
  42.     char* localData = this->data;
  43.  
  44.     // Construct trigger array
  45.     for (unsigned int i = 0; i < length / sizeof(TriggerData); i++) {
  46.         Trigger* t = new Trigger(localData, i);
  47.         localData += sizeof(TriggerData);
  48.         if (!triggers.append(t)) {
  49.             delete t;
  50.             return false;
  51.         }
  52.     }
  53.  
  54.     // Calculate how many nodes it takes
  55.     totalNodes = 0;
  56.     unsigned char* playerForces = sc->playerForces;
  57.     for (unsigned int i = 0; i < triggers.getSize(); i++) {
  58.         Trigger* t = triggers.get(i);
  59.         for (unsigned int player = 0; player < 8; player++) {
  60.             if (NODE_NEEDED) {
  61.                 totalNodes++;
  62.             }
  63.         }
  64.     }
  65.  
  66.     sc->firstNode = nullptr;
  67.     sc->lastNode = nullptr;
  68.  
  69.     if (totalNodes > 0) { // Create nodes
  70.  
  71.         memset(sc->PlayersTriggerList, 0, sizeof(TriggerList) * 8);
  72.         MALLOC_N(newNodes, TriggerNode, totalNodes, { return false; });
  73.         nodes = newNodes;
  74.  
  75.         sc->firstNode = nodes;
  76.         sc->lastNode = nodes + (sizeof(TriggerNode)*totalNodes);
  77.  
  78.         // Create trigger lists
  79.         unsigned int currentNodeIndex = 0;
  80.         for (unsigned int i = 0; i < triggers.getSize(); i++) {
  81.             Trigger* t = triggers.get(i);
  82.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player1, sc->playerForces, sc->PlayersTriggerList);
  83.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player2, sc->playerForces, sc->PlayersTriggerList);
  84.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player3, sc->playerForces, sc->PlayersTriggerList);
  85.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player4, sc->playerForces, sc->PlayersTriggerList);
  86.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player5, sc->playerForces, sc->PlayersTriggerList);
  87.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player6, sc->playerForces, sc->PlayersTriggerList);
  88.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player7, sc->playerForces, sc->PlayersTriggerList);
  89.             createNodeIfNeeded(nodes, &currentNodeIndex, t, Players::Player8, sc->playerForces, sc->PlayersTriggerList);
  90.         }
  91.     }
  92.     return true;
  93. }
  94.  
  95. inline bool TriggerCore::isNativeTrigger(TriggerNode* node) {
  96.     return node >= nodes && node < nodes + ((sizeof(TriggerNode)*totalNodes));
  97. }
  98.  
  99. TriggerCore::~TriggerCore() {
  100.     for (unsigned int i = 0; i < triggers.getSize(); i++) {
  101.         Trigger* trig = triggers.get(i);
  102.         delete trig;
  103.     }
  104.     FREE_NOT_NULL(nodes);
  105.     FREE_NOT_NULL(data);
  106. }
  107.  
  108. TriggerCore * TriggerCore::get(char * file, EUDStarcraft* sc) {
  109.     bool error = false;
  110.     FILE* f;
  111.     if (!fopen_s(&f, file, "rb")) {
  112.         ReadBuffer rb(f, &error);
  113.         fclose(f);
  114.         if (error) {
  115.             return nullptr;
  116.         }
  117.         unsigned int length = rb.getDataSize();
  118.         char* data = (char*) rb.readArray(length, &error);
  119.         if (error) {
  120.             return nullptr;
  121.         }
  122.         TriggerCore* tc = new TriggerCore(sc, data, length);
  123.         if (!tc->construct()) {
  124.             delete tc;
  125.             return nullptr;
  126.         }
  127.         return tc;
  128.     }
  129.     return nullptr;
  130. }
  131.  
  132. void TriggerCore::run() {
  133.  
  134.     sc->load();
  135.  
  136.     bool _segFault = false;
  137.     bool* segFault = &_segFault;
  138.  
  139.     FILE* f;
  140.     if (fopen_s(&f, "..\\EUDEmulator\\exec.txt", "wb")) {
  141.         return;
  142.     }
  143.  
  144.     // Execute triggers in loops
  145.     while(true) {
  146.  
  147.         TriggerNode* prev = nullptr;
  148.  
  149.         for (unsigned int playerTriggerIndex = 0; playerTriggerIndex < 8; playerTriggerIndex++) {
  150.             sc->currentPlayerIndexForTriggers = playerTriggerIndex;
  151.             if (sc->executePlayerLoop[playerTriggerIndex]) {
  152.                 TriggerList* triggers = &(sc->PlayersTriggerList[playerTriggerIndex]);
  153.                 TriggerNode* node = triggers->first;
  154.  
  155.                 unsigned int triggersExecutedCounter = 0;
  156.  
  157.                 while (node != nullptr) {
  158.  
  159.                     bool outputCurrentTrigger = false;
  160.                     int triggerIndex = -1;
  161.                     int triggerFlags = -1;
  162.                     WriteBuffer conditionBuffer;
  163.                     WriteBuffer actionBuffer;
  164.  
  165.                     if (!sc->isAllocated((unsigned int) node, sizeof(TriggerNode))) {
  166.                         *segFault = true;
  167. #ifdef TRIG_PRINT
  168.                         OutputDebugStringA("\r\n\r\n =================== End of execution because of segfault of node =================== \r\n\r\n");
  169. #endif
  170.                     }
  171.  
  172.                     if (!(*segFault)) { // Node is valid
  173.                         // Update current trigger
  174.                         sc->currentTriggerNode = node;
  175.                         triggersExecutedCounter++;
  176.  
  177.                         TriggerData* trigger = (TriggerData*)(&node->data);
  178.                         triggerIndex = trigger->flags >> 16;
  179.                         triggerFlags = trigger->flags & 0xffff;
  180.  
  181.                         if (Trigger::canBeExecutedNow(sc, trigger, &conditionBuffer, segFault)) { // Can be executed
  182.                             SET_EXECUTE(trigger);
  183.                         }
  184.  
  185.  
  186.                         if (!(*segFault)) { // Conditions didn't cause segfault
  187.                             if (HAS_EXECUTE(trigger)) { // Can be executed
  188.                                 outputCurrentTrigger = true;
  189.                                 CLEAR_EXECUTE(trigger); // Clear execution flag
  190.                                 bool stopTriggersForCurrentPlayer = false;
  191.                                 bool stopTriggersForAllPlayers = false;
  192.                                 Trigger::executeNow(sc, trigger, &actionBuffer, &stopTriggersForCurrentPlayer, &stopTriggersForAllPlayers, segFault);
  193.  
  194.                                 if (!HAS_PRESERVE(trigger)) {
  195.                                     SET_IGNORE_EXECUTION(trigger);
  196.                                 }
  197.  
  198.                                 if (stopTriggersForCurrentPlayer) {
  199.                                     sc->executePlayerLoop[playerTriggerIndex] = false;
  200.                                 }
  201.                                 if (stopTriggersForAllPlayers) {
  202.                                     for (unsigned int playerIndex = 0; playerIndex < 8; playerIndex++) {
  203.                                         sc->executePlayerLoop[playerIndex] = false;
  204.                                     }
  205.                                     break;
  206.                                 }
  207.                             }
  208.                         }
  209.                     }
  210.                        
  211. #ifdef TRIG_PRINT
  212.                     if (outputCurrentTrigger || (*segFault)) { // Output incomplete trigger causing segfault or any executed trigged
  213.                         bool error = false;
  214.                         conditionBuffer.writeByte(0, &error);
  215.                         actionBuffer.writeByte(0, &error);
  216.                         unsigned char* actData;
  217.                         unsigned char* condData;
  218.                         unsigned int actDataLen;
  219.                         unsigned int condDataLen;
  220.                         conditionBuffer.getWrittenData(&condData, &condDataLen);
  221.                         actionBuffer.getWrittenData(&actData, &actDataLen);
  222.                         char trigID[128];
  223.                         if (isNativeTrigger(node)) {
  224.                             sprintf_s(trigID, "%d (flags: %d), for player %d", triggerIndex, triggerFlags, playerTriggerIndex + 1);
  225.                         } else { // Trigger outside of TRIG section
  226.                             unsigned int offPtr = 0;
  227.                             char* fmt = sc->getTriggerOrigin(node, &offPtr, segFault);
  228.                             sprintf_s(trigID, "%s[%d] 0x%X (flags: %d), for player %d", fmt, offPtr, (unsigned int)node, triggerFlags, playerTriggerIndex + 1);
  229.                         }
  230.  
  231.                         if (!outputCurrentTrigger) {
  232.                             OutputDebugStringA("Following trigger was NOT executed\r\n");
  233.                         }
  234.                         if (*segFault) {
  235.                             OutputDebugStringA("Following trigger caused segfault\r\n");
  236.                         }
  237.                         OutputDebugStringA("///////////////////// Conditions[");
  238.                         OutputDebugStringA(trigID);
  239.                         OutputDebugStringA("] ////////////////////\r\n");
  240.                         OutputDebugStringA((char*)condData);
  241.                         OutputDebugStringA("////////////////////// Actions[");
  242.                         OutputDebugStringA(trigID);
  243.                         OutputDebugStringA("] //////////////////////\r\n");
  244.                         OutputDebugStringA((char*)actData);
  245.                         OutputDebugStringA("///////////////////////////////////////////////////////////////////////////////////\r\n\r\n");
  246.                     }
  247. #endif
  248.                        
  249.                     if (*segFault) { // Break trigger loop for current player
  250.                         break;
  251.                     }
  252.                     prev = node;
  253.                     node = node->next;
  254.                 }
  255.             }
  256.             if (*segFault) { // Break trigger loop for all players
  257.                 break;
  258.             }
  259.         }
  260.         if (*segFault) { // Stop triggers
  261.             break;
  262.         }
  263.         OutputDebugStringA("\r\n\r\n ================== End of trigger loop =================\r\n\r\n");
  264.         Sleep(500);
  265.     }
  266.  
  267.     if (*segFault) {
  268.         OutputDebugStringA("\r\n\r\n =================== End of execution because of segfault =================== \r\n\r\n");
  269.     }
  270.  
  271.     fclose(f);
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement