Ejemplo n.º 1
0
        private void ReadFromMemory(object state)
        {
            lock (_memoryTimerLock)
            {
                var timer = state as Timer;
                if (timer != _memoryTimer || _memoryTimer == null)
                {
                    return;
                }

                var spideyData = MemoryScanner.ReadSpideyData();
                var levelData  = MemoryScanner.ReadLevelData();

                var message = SpideyUdpMessage.CreateSpidermanMessage(_myInfo.Number, spideyData, levelData);

                foreach (var udpClient in udpWebSwing)
                {
                    udpClient.Send(message, message.Length);
                }

                var spideyLevel = SpideyLevels.GetSpideyLevel(levelData);
                var location    = spideyLevel.Name.TrimEnd();
                _onLocationUpdate.Report(new ConnectedPlayerInformation(_myInfo.Number, location));

                _udpBase.MyLastLocation = location;
            }
        }
Ejemplo n.º 2
0
        // TODO - looks like 0xC0 is not so straightforward - not just an array count
        // e.g. MJ = FF 04, Rat = C0 81??
        public static void WriteSpideyData(byte[] spideyData, SpideyLevel playerSpideyLevel, int playerOffset, int playerCount)
        {
            var dosBoxProcess     = Interlocked.Read(ref _dosBoxProcess);
            var enemyCountAddress = Interlocked.Read(ref _enemyCountAddress);
            var spideyAddress     = Interlocked.Read(ref _spideyAddress);
            int bytesWritten;

            var mySpideyLevel = SpideyLevels.GetSpideyLevel(ReadLevelData(dosBoxProcess));

            // TODO - fix teleporting enemy issue - prolly to do with how they get stored in array
            if (enemyCountAddress != 0 && spideyAddress != 0)
            {
                var desiredEnemyCount = Convert.ToByte(_highestEnemyCount + playerCount);
                var enemyCountBuffer  = new byte[ENEMY_COUNT_DATA_SIZE];
                ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(enemyCountAddress), enemyCountBuffer, ENEMY_COUNT_DATA_SIZE, out int bytesRead);
                var enemyCountNeedsUpdate = false;
                if (enemyCountBuffer[0] < desiredEnemyCount)
                {
                    enemyCountNeedsUpdate = true;

                    // Null out any extra enemy data that shouldn't be there
                    var invalidEnemies = _highestEnemyCount - mySpideyLevel.EnemyCount;
                    var enemyData      = new byte[ENEMY_HEADER_SIZE + SPIDEY_DATA_SIZE];
                    //enemyData[0] = 0xC0;
                    Buffer.BlockCopy(DEAD_ENEMY_PLACEHOLDER, 0, enemyData, ENEMY_HEADER_SIZE, SPIDEY_DATA_SIZE);
                    while (invalidEnemies > 0)
                    {
                        // TODO - Try copy the first enemy to other spots as well so it loads the right values?

                        var enemyIndex        = _highestEnemyCount - invalidEnemies - 1;
                        var enemyMemoryOffset = (ENEMY_HEADER_SIZE + SPIDEY_DATA_SIZE) * enemyIndex;
                        //WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset), new byte[] { 0xC0 }, 1, out bytesWritten);
                        //WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 1), new byte[] { 0x01 }, 1, out bytesWritten);

                        var singleByteBuffer = new byte[1];
                        // Just the essential enemy bits
                        // Blank sprite
                        var lSpriteAddress = spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 8;
                        ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lSpriteAddress), singleByteBuffer, 1, out bytesRead);
                        if (singleByteBuffer[0] < 0x50 || singleByteBuffer[0] > 0x5F)
                        {
                            WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lSpriteAddress), new byte[] { 0x5F }, 1, out bytesWritten);
                        }

                        // To avoid corruption
                        var lCorruptionOneAddress = spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 31;
                        ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionOneAddress), singleByteBuffer, 1, out bytesRead);
                        if (singleByteBuffer[0] == 0x00)
                        {
                            WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionOneAddress), new byte[] { 0x01 }, 1, out bytesWritten);
                        }

                        // To avoid corruption
                        var lCorruptionTwoAddress = spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 34;
                        ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionTwoAddress), singleByteBuffer, 1, out bytesRead);
                        if (singleByteBuffer[0] == 0x00)
                        {
                            WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionTwoAddress), new byte[] { 0x01 }, 1, out bytesWritten);
                        }

                        // Enemy health
                        var lEnemyHealthAddress = spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 41;
                        ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lEnemyHealthAddress), singleByteBuffer, 1, out bytesRead);
                        if (singleByteBuffer[0] != 0x00)
                        {
                            WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lEnemyHealthAddress), new byte[] { 0x00 }, 1, out bytesWritten);
                        }

                        /*
                         * //enemyData[1] = Convert.ToByte(enemyIndex);
                         * if (enemyIndex == 3)
                         * {
                         *  // TODO - tidy up, need to skip bytes 3 and 4 as they contain web swing data
                         *  // TODO - also seems to cause instant win when going to end screen, maybe just need to send bare minimum?
                         *  //WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset), enemyData, 3, out bytesWritten);
                         *  //WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 5), enemyData.Skip(5).ToArray(), 45, out bytesWritten);
                         *  WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 8), new byte[] { 0x5F }, 1, out bytesWritten);
                         *  WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 31), new byte[] { 0x01 }, 1, out bytesWritten);
                         *  WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset + 34), new byte[] { 0x01 }, 1, out bytesWritten);
                         * }
                         * else
                         * {
                         *  WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + enemyMemoryOffset), enemyData, ENEMY_HEADER_SIZE + SPIDEY_DATA_SIZE, out bytesWritten);
                         * }*/
                        --invalidEnemies;
                    }
                }
                var playerIndex        = _highestEnemyCount + playerOffset - 1;
                var playerMemoryOffset = (ENEMY_HEADER_SIZE + SPIDEY_DATA_SIZE) * playerIndex;
                var playerData         = new byte[ENEMY_HEADER_SIZE + SPIDEY_DATA_SIZE];
                //playerData[0] = 0xC0;
                //playerData[1] = Convert.ToByte(playerIndex);

                if (playerSpideyLevel.Number == mySpideyLevel.Number)
                {
                    Buffer.BlockCopy(spideyData, 0, playerData, ENEMY_HEADER_SIZE, SPIDEY_DATA_SIZE);
                    //WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + playerMemoryOffset), playerData, ENEMY_HEADER_SIZE + SPIDEY_DATA_SIZE, out bytesWritten);

                    // Cutting out half the data seems to fix graphical glitching issues and disables interaction with other player's game
                    WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(spideyAddress + SPIDEY_DATA_SIZE + playerMemoryOffset), playerData, ENEMY_HEADER_SIZE + (SPIDEY_DATA_SIZE / 2), out bytesWritten);
                }
                else
                {
                    var singleByteBuffer = new byte[1];
                    // Just the essential enemy bits
                    // Blank sprite
                    var lSpriteAddress = spideyAddress + SPIDEY_DATA_SIZE + playerMemoryOffset + 8;
                    ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lSpriteAddress), singleByteBuffer, 1, out bytesRead);
                    if (singleByteBuffer[0] < 0x50 || singleByteBuffer[0] > 0x5F)
                    {
                        WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lSpriteAddress), new byte[] { 0x5F }, 1, out bytesWritten);
                    }

                    // To avoid corruption
                    var lCorruptionOneAddress = spideyAddress + SPIDEY_DATA_SIZE + playerMemoryOffset + 31;
                    ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionOneAddress), singleByteBuffer, 1, out bytesRead);
                    if (singleByteBuffer[0] == 0x00)
                    {
                        WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionOneAddress), new byte[] { 0x01 }, 1, out bytesWritten);
                    }

                    // To avoid corruption
                    var lCorruptionTwoAddress = spideyAddress + SPIDEY_DATA_SIZE + playerMemoryOffset + 34;
                    ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionTwoAddress), singleByteBuffer, 1, out bytesRead);
                    if (singleByteBuffer[0] == 0x00)
                    {
                        WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lCorruptionTwoAddress), new byte[] { 0x01 }, 1, out bytesWritten);
                    }

                    // Enemy health
                    var lEnemyHealthAddress = spideyAddress + SPIDEY_DATA_SIZE + playerMemoryOffset + 41;
                    ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lEnemyHealthAddress), singleByteBuffer, 1, out bytesRead);
                    if (singleByteBuffer[0] != 0x00)
                    {
                        WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(lEnemyHealthAddress), new byte[] { 0x00 }, 1, out bytesWritten);
                    }
                }

                if (enemyCountNeedsUpdate)
                {
                    WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(enemyCountAddress), new byte[] { desiredEnemyCount }, ENEMY_COUNT_DATA_SIZE, out bytesWritten);
                }
            }

            /*
             * // If first time doing this, needs to be done slowly (one by one + write enemy data first)
             * if (enemyCountAddress != 0)
             * {
             *  var desiredEnemyCount = Convert.ToByte(_highestEnemyCount + playerCount);
             *  var enemyCountBuffer = new byte[ENEMY_COUNT_DATA_SIZE];
             *  ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(enemyCountAddress), enemyCountBuffer, ENEMY_COUNT_DATA_SIZE, out int bytesRead);
             *  while((enemyCountBuffer[0] < desiredEnemyCount) && (bytesRead == ENEMY_COUNT_DATA_SIZE))
             *  {
             *      // TODO - detect level change while doing this?
             *      WriteProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(enemyCountAddress), new byte[] { Convert.ToByte(enemyCountBuffer[0] + 1) }, ENEMY_COUNT_DATA_SIZE, out bytesWritten);
             *      ReadProcessMemory(new IntPtr(dosBoxProcess), new IntPtr(enemyCountAddress), enemyCountBuffer, ENEMY_COUNT_DATA_SIZE, out bytesRead);
             *      Thread.Sleep(5000);
             *  }
             * }*/
        }