all repos — gemini-redirect @ c36fb3ddc7e25d5d28171196c9cc6bdc4dd2ec7e

blog/atom.xml (view raw)

   1<?xml version="1.0" encoding="UTF-8"?>
   2<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
   3	<title>Lonami&#x27;s Site - My Blog</title>
   4	<link href="https://lonami.dev/blog/atom.xml" rel="self" type="application/atom+xml"/>
   5  <link href="https://lonami.dev/blog/"/>
   6	<generator uri="https://www.getzola.org/">Zola</generator>
   7	<updated>2021-03-06T00:00:00+00:00</updated>
   8	<id>https://lonami.dev/blog/atom.xml</id>
   9	<entry xml:lang="en">
  10		<title>Writing our own Cheat Engine: Code finder</title>
  11		<published>2021-03-06T00:00:00+00:00</published>
  12		<updated>2021-03-06T00:00:00+00:00</updated>
  13		<link href="https://lonami.dev/blog/woce-5/" type="text/html"/>
  14		<id>https://lonami.dev/blog/woce-5/</id>
  15		<content type="html">&lt;p&gt;This is part 5 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt;
  16&lt;ul&gt;
  17&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-1&quot;&gt;Part 1: Introduction&lt;&#x2F;a&gt; (start here if you&#x27;re new to the series!)&lt;&#x2F;li&gt;
  18&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-2&quot;&gt;Part 2: Exact Value scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  19&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-3&quot;&gt;Part 3: Unknown initial value&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  20&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-4&quot;&gt;Part 4: Floating points&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  21&lt;li&gt;Part 5: Code finder&lt;&#x2F;li&gt;
  22&lt;&#x2F;ul&gt;
  23&lt;p&gt;In part 4 we spent a good deal of time trying to make our scans generic, and now we have something that works&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;! Now that the scanning is fairly powerful and all covered, the Cheat Engine tutorial shifts focus into slightly more advanced techniques that you will most certainly need in anything bigger than a toy program.&lt;&#x2F;p&gt;
  24&lt;p&gt;It&#x27;s time to write our very own &lt;strong&gt;debugger&lt;&#x2F;strong&gt; in Rust!&lt;&#x2F;p&gt;
  25&lt;h2 id=&quot;code-finder&quot;&gt;Code finder&lt;&#x2F;h2&gt;
  26&lt;details open&gt;&lt;summary&gt;Cheat Engine Tutorial: Step 5&lt;&#x2F;summary&gt;
  27&lt;blockquote&gt;
  28&lt;p&gt;Sometimes the location something is stored at changes when you restart the game, or even while you&#x27;re playing… In that case you can use 2 things to still make a table that works. In this step I&#x27;ll try to describe how to use the Code Finder function.&lt;&#x2F;p&gt;
  29&lt;p&gt;The value down here will be at a different location each time you start the tutorial, so a normal entry in the address list wouldn&#x27;t work. First try to find the address. (You&#x27;ve got to this point so I assume you know how to.)&lt;&#x2F;p&gt;
  30&lt;p&gt;When you&#x27;ve found the address, right-click the address in Cheat Engine and choose &amp;quot;Find out what writes to this address&amp;quot;. A window will pop up with an empty list.&lt;&#x2F;p&gt;
  31&lt;p&gt;Then click on the Change value button in this tutorial, and go back to Cheat Engine. If everything went right there should be an address with assembler code there now.&lt;&#x2F;p&gt;
  32&lt;p&gt;Click it and choose the replace option to replace it with code that does nothing. That will also add the code address to the code list in the advanced options window. (Which gets saved if you save your table.)&lt;&#x2F;p&gt;
  33&lt;p&gt;Click on stop, so the game will start running normal again, and close to close the window. Now, click on Change value, and if everything went right the Next button should become enabled.&lt;&#x2F;p&gt;
  34&lt;p&gt;Note: When you&#x27;re freezing the address with a high enough speed it may happen that next becomes visible anyhow&lt;&#x2F;p&gt;
  35&lt;&#x2F;blockquote&gt;
  36&lt;&#x2F;details&gt;
  37&lt;h2 id=&quot;baby-steps-to-debugging&quot;&gt;Baby steps to debugging&lt;&#x2F;h2&gt;
  38&lt;p&gt;Although I have used debuggers before, I have never had a need to write one myself so it&#x27;s time for some research.&lt;&#x2F;p&gt;
  39&lt;p&gt;Searching on DuckDuckGo, I can find entire series to &lt;a href=&quot;http:&#x2F;&#x2F;system.joekain.com&#x2F;debugger&#x2F;&quot;&gt;Writing a Debugger&lt;&#x2F;a&gt;. We would be done by now if only that series wasn&#x27;t written for Linux. The Windows documentation contains a section called &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;debug&#x2F;creating-a-basic-debugger&quot;&gt;Creating a Basic Debugger&lt;&#x2F;a&gt;, but as far as I can tell, it only teaches you the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;debug&#x2F;debugging-functions&quot;&gt;functions&lt;&#x2F;a&gt; needed to configure the debugging loop. Which mind you, we will need, but in due time.&lt;&#x2F;p&gt;
  40&lt;p&gt;According to &lt;a href=&quot;https:&#x2F;&#x2F;www.gironsec.com&#x2F;blog&#x2F;2013&#x2F;12&#x2F;writing-your-own-debugger-windows-in-c&#x2F;&quot;&gt;Writing your own windows debugger in C&lt;&#x2F;a&gt;, the steps needed to write a debugger are:&lt;&#x2F;p&gt;
  41&lt;ul&gt;
  42&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;processthreadsapi&#x2F;nf-processthreadsapi-suspendthread&quot;&gt;&lt;code&gt;SuspendThread(proc)&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. It makes sense that we need to pause all the threads&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; before messing around with the code the program is executing, or things are very prone to go wrong.&lt;&#x2F;li&gt;
  43&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;processthreadsapi&#x2F;nf-processthreadsapi-getthreadcontext&quot;&gt;&lt;code&gt;GetThreadContext(proc)&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This function retrieves the appropriate context of the specified thread and is highly processor specific. It basically takes a snapshot of all the registers. Think of registers like extremely fast, but also extremely limited, memory the processor uses.&lt;&#x2F;li&gt;
  44&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winbase&#x2F;nf-winbase-debugbreakprocess&quot;&gt;&lt;code&gt;DebugBreakProcess&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Essentially &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;drivers&#x2F;debugger&#x2F;x86-instructions#miscellaneous&quot;&gt;writes out the 0xCC opcode&lt;&#x2F;a&gt;, &lt;code&gt;int 3&lt;&#x2F;code&gt; in assembly, also known as software breakpoint. It&#x27;s written wherever the Register Instruction Pointer (RIP&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;) currently points to, so in essence, when the thread resumes, it will immediately &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;3915511&#x2F;&quot;&gt;trigger the breakpoint&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
  45&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;debugapi&#x2F;nf-debugapi-continuedebugevent&quot;&gt;&lt;code&gt;ContinueDebugEvent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Presumably continues debugging.&lt;&#x2F;li&gt;
  46&lt;&#x2F;ul&gt;
  47&lt;p&gt;There are pages documenting &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;debug&#x2F;debugging-events&quot;&gt;all of the debug events&lt;&#x2F;a&gt; that our debugger will be able to handle.&lt;&#x2F;p&gt;
  48&lt;p&gt;Okay, nice! Software breakpoints seem to be done by writing out memory to the region where the program is reading instructions from. We know how to write memory, as that&#x27;s what all the previous posts have been doing to complete the corresponding tutorial steps. After the breakpoint is executed, all we need to do is &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;3747852&#x2F;&quot;&gt;restore the original memory back&lt;&#x2F;a&gt; so that the next time the program executes the code it sees no difference.&lt;&#x2F;p&gt;
  49&lt;p&gt;But a software breakpoint will halt execution when the code executes the interrupt instruction. This step of the tutorial wants us to find &lt;em&gt;what writes to a memory location&lt;&#x2F;em&gt;. Where should we place the breakpoint to detect such location? Writing out the instruction to the memory we want to break in won&#x27;t do; it&#x27;s not an instruction, it&#x27;s just data.&lt;&#x2F;p&gt;
  50&lt;p&gt;The name may have given it away. If we&#x27;re talking about software breakpoints, it makes sense that there would exist such a thing as &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Breakpoint#Hardware&quot;&gt;&lt;em&gt;hardware&lt;&#x2F;em&gt; breakpoints&lt;&#x2F;a&gt;. Because they&#x27;re tied to the hardware, they&#x27;re highly processor-specific, but luckily for us, the processor on your usual desktop computer probably has them! Even the &lt;a href=&quot;https:&#x2F;&#x2F;interrupt.memfault.com&#x2F;blog&#x2F;cortex-m-breakpoints&quot;&gt;cortex-m&lt;&#x2F;a&gt; does. The wikipedia page also tells us the name of the thing we&#x27;re looking for, watchpoints:&lt;&#x2F;p&gt;
  51&lt;blockquote&gt;
  52&lt;p&gt;Other kinds of conditions can also be used, such as the reading, writing, or modification of a specific location in an area of memory. This is often referred to as a conditional breakpoint, a data breakpoint, or a watchpoint.&lt;&#x2F;p&gt;
  53&lt;&#x2F;blockquote&gt;
  54&lt;p&gt;A breakpoint that triggers when a specific memory location is written to is exactly what we need, and &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;19109153&#x2F;&quot;&gt;x86 has debug registers D0 to D3 to track memory addresses&lt;&#x2F;a&gt;. As far as I can tell, there is no API in specific to mess with the registers. But we don&#x27;t need any of that! We can just go ahead and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;unstable-book&#x2F;library-features&#x2F;asm.html&quot;&gt;write some assembly by hand&lt;&#x2F;a&gt; to access these registers. At the time of writing, inline assembly is unstable, so we need a nightly compiler. Run &lt;code&gt;rustup toolchain install nightly&lt;&#x2F;code&gt; if you haven&#x27;t yet, and execute the following code with &lt;code&gt;cargo +nightly run&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
  55&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;#![feature(asm)] &#x2F;&#x2F; top of the file
  56
  57fn main() {
  58    let x: u64 = 123;
  59    unsafe {
  60        asm!(&amp;quot;mov dr7, {}&amp;quot;, in(reg) x);
  61    }
  62}
  63
  64&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  65&lt;p&gt;&lt;code&gt;dr7&lt;&#x2F;code&gt; stands is the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;X86_debug_register&quot;&gt;debug control register&lt;&#x2F;a&gt;, and running this we get…&lt;&#x2F;p&gt;
  66&lt;pre&gt;&lt;code&gt;&amp;gt;cargo +nightly run
  67   Compiling memo v0.1.0
  68    Finished dev [unoptimized + debuginfo] target(s) in 0.74s
  69     Running `target\debug\memo.exe`
  70error: process didn&#x27;t exit successfully: `target\debug\memo.exe` (exit code: 0xc0000096, STATUS_PRIVILEGED_INSTRUCTION)
  71&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  72&lt;p&gt;…an exception! In all fairness, I have no idea what that code would have done. So maybe the &lt;code&gt;STATUS_PRIVILEGED_INSTRUCTION&lt;&#x2F;code&gt; is just trying to protect us. Can we read from the register instead, and see it&#x27;s default value?&lt;&#x2F;p&gt;
  73&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let x: u64;
  74unsafe {
  75    asm!(&amp;quot;mov {}, dr7&amp;quot;, out(reg) x);
  76}
  77assert_eq!(x, 5);
  78&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  79&lt;pre&gt;&lt;code&gt;&amp;gt;cargo +nightly run
  80...
  81error: process didn&#x27;t exit successfully: `target\debug\memo.exe` (exit code: 0xc0000096, STATUS_PRIVILEGED_INSTRUCTION)
  82&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  83&lt;p&gt;Nope. Okay, it seems directly reading from or writing to the debug register is a ring-0 thing. Surely there&#x27;s a way around this. But first we should figure out how to enumerate and pause all the threads.&lt;&#x2F;p&gt;
  84&lt;h2 id=&quot;pausing-all-the-threads&quot;&gt;Pausing all the threads&lt;&#x2F;h2&gt;
  85&lt;p&gt;It seems there is no straightforward way to enumerate the threads. One has to &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;1206915&#x2F;&quot;&gt;create a &amp;quot;toolhelp&amp;quot;&lt;&#x2F;a&gt; and poll the entries. I won&#x27;t bore you with the details. Let&#x27;s add &lt;code&gt;tlhelp32&lt;&#x2F;code&gt; to the crate features of &lt;code&gt;winapi&lt;&#x2F;code&gt; and try it out:&lt;&#x2F;p&gt;
  86&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;
  87#[derive(Debug)]
  88pub struct Toolhelp {
  89    handle: winapi::um::winnt::HANDLE,
  90}
  91
  92impl Drop for Toolhelp {
  93    fn drop(&amp;amp;mut self) {
  94        unsafe { winapi::um::handleapi::CloseHandle(self.handle) };
  95    }
  96}
  97
  98pub fn enum_threads(pid: u32) -&amp;gt; io::Result&amp;lt;Vec&amp;lt;u32&amp;gt;&amp;gt; {
  99    const ENTRY_SIZE: u32 = mem::size_of::&amp;lt;winapi::um::tlhelp32::THREADENTRY32&amp;gt;() as u32;
 100
 101    &#x2F;&#x2F; size_of(dwSize + cntUsage + th32ThreadID + th32OwnerProcessID)
 102    const NEEDED_ENTRY_SIZE: u32 = 4 * mem::size_of::&amp;lt;DWORD&amp;gt;() as u32;
 103
 104    &#x2F;&#x2F; SAFETY: it is always safe to attempt to call this function.
 105    let handle = unsafe {
 106        winapi::um::tlhelp32::CreateToolhelp32Snapshot(winapi::um::tlhelp32::TH32CS_SNAPTHREAD, 0)
 107    };
 108    if handle == winapi::um::handleapi::INVALID_HANDLE_VALUE {
 109        return Err(io::Error::last_os_error());
 110    }
 111    let toolhelp = Toolhelp { handle };
 112
 113    let mut result = Vec::new();
 114    let mut entry = winapi::um::tlhelp32::THREADENTRY32 {
 115        dwSize: ENTRY_SIZE,
 116        cntUsage: 0,
 117        th32ThreadID: 0,
 118        th32OwnerProcessID: 0,
 119        tpBasePri: 0,
 120        tpDeltaPri: 0,
 121        dwFlags: 0,
 122    };
 123
 124    &#x2F;&#x2F; SAFETY: we have a valid handle, and point to memory we own with the right size.
 125    if unsafe { winapi::um::tlhelp32::Thread32First(toolhelp.handle, &amp;amp;mut entry) } != FALSE {
 126        loop {
 127            if entry.dwSize &amp;gt;= NEEDED_ENTRY_SIZE &amp;amp;&amp;amp; entry.th32OwnerProcessID == pid {
 128                result.push(entry.th32ThreadID);
 129            }
 130
 131            entry.dwSize = ENTRY_SIZE;
 132            &#x2F;&#x2F; SAFETY: we have a valid handle, and point to memory we own with the right size.
 133            if unsafe { winapi::um::tlhelp32::Thread32Next(toolhelp.handle, &amp;amp;mut entry) } == FALSE {
 134                break;
 135            }
 136        }
 137    }
 138
 139    Ok(result)
 140}
 141&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 142&lt;p&gt;Annoyingly, invalid handles returned by &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;tlhelp32&#x2F;nf-tlhelp32-createtoolhelp32snapshot&quot;&gt;&lt;code&gt;CreateToolhelp32Snapshot&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, are &lt;code&gt;INVALID_HANDLE_VALUE&lt;&#x2F;code&gt; (which is -1), not null. But that&#x27;s not a big deal, we simply can&#x27;t use &lt;code&gt;NonNull&lt;&#x2F;code&gt; here. The function ignores the process identifier when using &lt;code&gt;TH32CS_SNAPTHREAD&lt;&#x2F;code&gt;, used to include all threads, and we need to compare the process identifier ourselves.&lt;&#x2F;p&gt;
 143&lt;p&gt;In summary, we create a &amp;quot;toolhelp&amp;quot; (wrapped in a helper &lt;code&gt;struct&lt;&#x2F;code&gt; so that whatever happens, &lt;code&gt;Drop&lt;&#x2F;code&gt; will clean it up), initialize a thread enntry (with everything but the structure size to zero) and call &lt;code&gt;Thread32First&lt;&#x2F;code&gt; the first time, &lt;code&gt;Thread32Next&lt;&#x2F;code&gt; subsequent times. It seems to work all fine!&lt;&#x2F;p&gt;
 144&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;dbg!(process::enum_threads(pid));
 145&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 146&lt;pre&gt;&lt;code&gt;[src\main.rs:46] process::enum_threads(pid) = Ok(
 147    [
 148        10560,
 149    ],
 150)
 151&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 152&lt;p&gt;According to this, the Cheat Engine tutorial is only using one thread. Good to know. Much like processes, threads need to be opened before we can use them, with &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;processthreadsapi&#x2F;nf-processthreadsapi-openthread&quot;&gt;&lt;code&gt;OpenThread&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
 153&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub struct Thread {
 154    tid: u32,
 155    handle: NonNull&amp;lt;c_void&amp;gt;,
 156}
 157
 158impl Thread {
 159    pub fn open(tid: u32) -&amp;gt; io::Result&amp;lt;Self&amp;gt; {
 160        &#x2F;&#x2F; SAFETY: the call doesn&#x27;t have dangerous side-effects
 161        NonNull::new(unsafe {
 162            winapi::um::processthreadsapi::OpenThread(
 163                winapi::um::winnt::THREAD_SUSPEND_RESUME,
 164                FALSE,
 165                tid,
 166            )
 167        })
 168        .map(|handle| Self { tid, handle })
 169        .ok_or_else(io::Error::last_os_error)
 170    }
 171
 172    pub fn tid(&amp;amp;self) -&amp;gt; u32 {
 173        self.tid
 174    }
 175}
 176
 177impl Drop for Thread {
 178    fn drop(&amp;amp;mut self) {
 179        unsafe { winapi::um::handleapi::CloseHandle(self.handle.as_mut()) };
 180    }
 181}
 182&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 183&lt;p&gt;Just your usual RAII pattern. The thread is opened with permission to suspend and resume it. Let&#x27;s try to pause the handles with &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;processthreadsapi&#x2F;nf-processthreadsapi-suspendthread&quot;&gt;&lt;code&gt;SuspendThread&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to make sure that this thread is actually the one we&#x27;re looking for:&lt;&#x2F;p&gt;
 184&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn suspend(&amp;amp;mut self) -&amp;gt; io::Result&amp;lt;usize&amp;gt; {
 185    &#x2F;&#x2F; SAFETY: the handle is valid.
 186    let ret = unsafe {
 187        winapi::um::processthreadsapi::SuspendThread(self.handle.as_ptr())
 188    };
 189    if ret == -1i32 as u32 {
 190        Err(io::Error::last_os_error())
 191    } else {
 192        Ok(ret as usize)
 193    }
 194}
 195
 196pub fn resume(&amp;amp;mut self) -&amp;gt; io::Result&amp;lt;usize&amp;gt; {
 197    &#x2F;&#x2F; SAFETY: the handle is valid.
 198    let ret = unsafe {
 199        winapi::um::processthreadsapi::ResumeThread(self.handle.as_ptr())
 200    };
 201    if ret == -1i32 as u32 {
 202        Err(io::Error::last_os_error())
 203    } else {
 204        Ok(ret as usize)
 205    }
 206}
 207&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 208&lt;p&gt;Both suspend and resume return the previous &amp;quot;suspend count&amp;quot;. It&#x27;s kind of like a barrier or semaphore where the thread only runs if the suspend count is zero. Trying it out:&lt;&#x2F;p&gt;
 209&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let mut threads = thread::enum_threads(pid)
 210    .unwrap()
 211    .into_iter()
 212    .map(Thread::open)
 213    .collect::&amp;lt;Result&amp;lt;Vec&amp;lt;_&amp;gt;, _&amp;gt;&amp;gt;()
 214    .unwrap();
 215
 216threads
 217    .iter_mut()
 218    .for_each(|thread| {
 219        println!(&amp;quot;Pausing thread {} for 10 seconds…&amp;quot;, thread.tid());
 220        thread.suspend().unwrap();
 221
 222        std::thread::sleep(std::time::Duration::from_secs(10));
 223
 224        println!(&amp;quot;Wake up, {}!&amp;quot;, thread.tid());
 225        thread.resume().unwrap();
 226    });
 227&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 228&lt;p&gt;If you run this code with the process ID of the Cheat Engine tutorial, you will see that the tutorial window freezes for ten seconds! Because the main and only thread is paused, it cannot process any window events, so it becomes unresponsive. It is now &amp;quot;safe&amp;quot; to mess around with the thread context.&lt;&#x2F;p&gt;
 229&lt;h2 id=&quot;setting-hardware-breakpoints&quot;&gt;Setting hardware breakpoints&lt;&#x2F;h2&gt;
 230&lt;p&gt;I&#x27;m definitely not the first person to wonder &lt;a href=&quot;https:&#x2F;&#x2F;social.msdn.microsoft.com&#x2F;Forums&#x2F;en-US&#x2F;0cb3360d-3747-42a7-bc0e-668c5d9ee1ee&#x2F;how-to-set-a-hardware-breakpoint&quot;&gt;How to set a hardware breakpoint?&lt;&#x2F;a&gt;. This is great, because it means I don&#x27;t need to ask that question myself. It appears we need to change the debug register &lt;em&gt;via the thread context&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
 231&lt;p&gt;One has to be careful to use the right context structure. Confusingly enough, &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;17504174&#x2F;&quot;&gt;&lt;code&gt;WOW64_CONTEXT&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is 32 bits, not 64. &lt;code&gt;CONTEXT&lt;&#x2F;code&gt; alone seems to be the right one:&lt;&#x2F;p&gt;
 232&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn get_context(&amp;amp;self) -&amp;gt; io::Result&amp;lt;winapi::um::winnt::CONTEXT&amp;gt; {
 233    let context = MaybeUninit::&amp;lt;winapi::um::winnt::CONTEXT&amp;gt;::zeroed();
 234    &#x2F;&#x2F; SAFETY: it&#x27;s a C struct, and all-zero is a valid bit-pattern for the type.
 235    let mut context = unsafe { context.assume_init() };
 236    context.ContextFlags = winapi::um::winnt::CONTEXT_ALL;
 237
 238    &#x2F;&#x2F; SAFETY: the handle is valid and structure points to valid memory.
 239    if unsafe {
 240        winapi::um::processthreadsapi::GetThreadContext(self.handle.as_ptr(), &amp;amp;mut context)
 241    } == FALSE
 242    {
 243        Err(io::Error::last_os_error())
 244    } else {
 245        Ok(context)
 246    }
 247}
 248&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 249&lt;p&gt;Trying it out:&lt;&#x2F;p&gt;
 250&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;thread.suspend().unwrap();
 251
 252let context = thread.get_context().unwrap();
 253println!(&amp;quot;Dr0: {:016x}&amp;quot;, context.Dr0);
 254println!(&amp;quot;Dr7: {:016x}&amp;quot;, context.Dr7);
 255println!(&amp;quot;Dr6: {:016x}&amp;quot;, context.Dr6);
 256println!(&amp;quot;Rax: {:016x}&amp;quot;, context.Rax);
 257println!(&amp;quot;Rbx: {:016x}&amp;quot;, context.Rbx);
 258println!(&amp;quot;Rcx: {:016x}&amp;quot;, context.Rcx);
 259println!(&amp;quot;Rip: {:016x}&amp;quot;, context.Rip);
 260&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 261&lt;pre&gt;&lt;code&gt;Dr0: 0000000000000000
 262Dr7: 0000000000000000
 263Dr6: 0000000000000000
 264Rax: 0000000000001446
 265Rbx: 0000000000000000
 266Rcx: 0000000000000000
 267Rip: 00007ffda4259904
 268&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 269&lt;p&gt;Looks about right! Hm, I wonder what happens if I use Cheat Engine to add the watchpoint on the memory location we care about?&lt;&#x2F;p&gt;
 270&lt;pre&gt;&lt;code&gt;Dr0: 000000000157e650
 271Dr7: 00000000000d0001
 272&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 273&lt;p&gt;Look at that! The debug registers changed! DR0 contains the location we want to watch for writes, and the debug control register DR7 changed. Cheat Engine sets the same values on all threads (for some reason I now see more than one thread printed for the tutorial, not sure what&#x27;s up with that; maybe the single-thread is the weird one out).&lt;&#x2F;p&gt;
 274&lt;p&gt;Hmm, what happens if I watch for access instead of write?&lt;&#x2F;p&gt;
 275&lt;pre&gt;&lt;code&gt;Dr0: 000000000157e650
 276Dr7: 00000000000f0001
 277&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 278&lt;p&gt;What if I set both?&lt;&#x2F;p&gt;
 279&lt;pre&gt;&lt;code&gt;Dr0: 000000000157e650
 280Dr7: 0000000000fd0005
 281&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 282&lt;p&gt;Most intriguing! This was done by telling Cheat Engine to find &amp;quot;what writes&amp;quot; to the address, then &amp;quot;what accesses&amp;quot; the address. I wonder if the order matters?&lt;&#x2F;p&gt;
 283&lt;pre&gt;&lt;code&gt;Dr0: 000000000157e650
 284Dr7: 0000000000df0005
 285&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 286&lt;p&gt;&amp;quot;What accesses&amp;quot; and then &amp;quot;what writes&amp;quot; does change it. Very well! We&#x27;re only concerned in a single breakpoint, so we won&#x27;t worry about this, but it&#x27;s good to know that we can inspect what Cheat Engine is doing. It&#x27;s also interesting to see how Cheat Engine is using hardware breakpoints and not software breakpoints.&lt;&#x2F;p&gt;
 287&lt;p&gt;For simplicity, our code is going to assume that we&#x27;re the only ones messing around with the debug registers, and that there will only be a single debug register in use. Make sure to add &lt;code&gt;THREAD_SET_CONTEXT&lt;&#x2F;code&gt; to the permissions when opening the thread handle:&lt;&#x2F;p&gt;
 288&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn set_context(&amp;amp;self, context: &amp;amp;winapi::um::winnt::CONTEXT) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
 289    &#x2F;&#x2F; SAFETY: the handle is valid and structure points to valid memory.
 290    if unsafe {
 291        winapi::um::processthreadsapi::SetThreadContext(self.handle.as_ptr(), context)
 292    } == FALSE
 293    {
 294        Err(io::Error::last_os_error())
 295    } else {
 296        Ok(())
 297    }
 298}
 299
 300pub fn watch_memory_write(&amp;amp;self, addr: usize) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
 301    let mut context = self.get_context()?;
 302    context.Dr0 = addr as u64;
 303    context.Dr7 = 0x00000000000d0001;
 304    self.set_context(&amp;amp;context)?;
 305    todo!()
 306}
 307&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 308&lt;p&gt;If we do this (and temporarily get rid of the &lt;code&gt;todo!()&lt;&#x2F;code&gt;), trying to change the value in the Cheat Engine tutorial will greet us with a warm message:&lt;&#x2F;p&gt;
 309&lt;blockquote&gt;
 310&lt;p&gt;&lt;strong&gt;Tutorial-x86_64&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
 311&lt;p&gt;External exception 80000004.&lt;&#x2F;p&gt;
 312&lt;p&gt;Press OK to ignore and risk data corruption.&lt;br &#x2F;&gt;
 313Press Abort to kill the program.&lt;&#x2F;p&gt;
 314&lt;p&gt;&lt;kbd&gt;OK&lt;&#x2F;kbd&gt; &lt;kbd&gt;Abort&lt;&#x2F;kbd&gt;&lt;&#x2F;p&gt;
 315&lt;&#x2F;blockquote&gt;
 316&lt;p&gt;There is no debugger attached yet that could possibly handle this exception, so the exception just propagates. Let&#x27;s fix that.&lt;&#x2F;p&gt;
 317&lt;h2 id=&quot;handling-debug-events&quot;&gt;Handling debug events&lt;&#x2F;h2&gt;
 318&lt;p&gt;Now that we&#x27;ve succeeded on setting breakpoints, we can actually follow the steps described in &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;debug&#x2F;creating-a-basic-debugger&quot;&gt;Creating a Basic Debugger&lt;&#x2F;a&gt;. It starts by saying that we should use &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;debugapi&#x2F;nf-debugapi-debugactiveprocess&quot;&gt;&lt;code&gt;DebugActiveProcess&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to attach our processor, the debugger, to the process we want to debug, the debuggee. This function lives under the &lt;code&gt;debugapi&lt;&#x2F;code&gt; header, so add it to &lt;code&gt;winapi&lt;&#x2F;code&gt; features:&lt;&#x2F;p&gt;
 319&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub struct DebugToken {
 320    pid: u32,
 321}
 322
 323pub fn debug(pid: u32) -&amp;gt; io::Result&amp;lt;DebugToken&amp;gt; {
 324    if unsafe { winapi::um::debugapi::DebugActiveProcess(pid) } == FALSE {
 325        return Err(io::Error::last_os_error());
 326    };
 327    let token = DebugToken { pid };
 328    if unsafe { winapi::um::winbase::DebugSetProcessKillOnExit(FALSE) } == FALSE {
 329        return Err(io::Error::last_os_error());
 330    };
 331    Ok(token)
 332}
 333
 334impl Drop for DebugToken {
 335    fn drop(&amp;amp;mut self) {
 336        unsafe { winapi::um::debugapi::DebugActiveProcessStop(self.pid) };
 337    }
 338}
 339&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 340&lt;p&gt;Once again, we create a wrapper &lt;code&gt;struct&lt;&#x2F;code&gt; with &lt;code&gt;Drop&lt;&#x2F;code&gt; to stop debugging the process once the token is dropped. The call to &lt;code&gt;DebugSetProcessKillOnExit&lt;&#x2F;code&gt; in our &lt;code&gt;debug&lt;&#x2F;code&gt; method ensures that, if our process (the debugger) dies, the process we&#x27;re debugging (the debuggee) stays alive. We don&#x27;t want to be restarting the entire Cheat Engine tutorial every time our Rust code crashes!&lt;&#x2F;p&gt;
 341&lt;p&gt;With the debugger attached, we can wait for debug events. We will put this method inside of &lt;code&gt;impl DebugToken&lt;&#x2F;code&gt;, so that the only way you can call it is if you successfully attached to another process:&lt;&#x2F;p&gt;
 342&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;impl DebugToken {
 343    pub fn wait_event(
 344        &amp;amp;self,
 345        timeout: Option&amp;lt;Duration&amp;gt;,
 346    ) -&amp;gt; io::Result&amp;lt;winapi::um::minwinbase::DEBUG_EVENT&amp;gt; {
 347        let mut result = MaybeUninit::uninit();
 348        let timeout = timeout
 349            .map(|d| d.as_millis().try_into().ok())
 350            .flatten()
 351            .unwrap_or(winapi::um::winbase::INFINITE);
 352
 353        &#x2F;&#x2F; SAFETY: can only wait for events with a token, so the debugger is active.
 354        if unsafe { winapi::um::debugapi::WaitForDebugEvent(result.as_mut_ptr(), timeout) } == FALSE
 355        {
 356            Err(io::Error::last_os_error())
 357        } else {
 358            &#x2F;&#x2F; SAFETY: the call returned non-zero, so the structure is initialized.
 359            Ok(unsafe { result.assume_init() })
 360        }
 361    }
 362}
 363&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 364&lt;p&gt;&lt;code&gt;WaitForDebugEvent&lt;&#x2F;code&gt; wants a timeout in milliseconds, so our function lets the user pass the more Rusty &lt;code&gt;Duration&lt;&#x2F;code&gt; type. &lt;code&gt;None&lt;&#x2F;code&gt; will indicate &amp;quot;there is no timeout&amp;quot;, i.e., it&#x27;s infinite. If the duration is too large to fit in the &lt;code&gt;u32&lt;&#x2F;code&gt; (&lt;code&gt;try_into&lt;&#x2F;code&gt; fails), it will also be infinite.&lt;&#x2F;p&gt;
 365&lt;p&gt;If we attach the debugger, set the hardware watchpoint, and modify the memory location from the tutorial, an event with &lt;code&gt;dwDebugEventCode = 3&lt;&#x2F;code&gt; will be returned! Now, back to the page with the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;debug&#x2F;debugging-events&quot;&gt;Debugging Events&lt;&#x2F;a&gt;… Gah! It only has the name of the constants, not the values. Well, good thing &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;&quot;&gt;docs.rs&lt;&#x2F;a&gt; has a source view! We can just check the values in the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;winapi&#x2F;0.3.9&#x2F;src&#x2F;winapi&#x2F;um&#x2F;minwinbase.rs.html#203-211&quot;&gt;source code for &lt;code&gt;winapi&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
 366&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub const EXCEPTION_DEBUG_EVENT: DWORD = 1;
 367pub const CREATE_THREAD_DEBUG_EVENT: DWORD = 2;
 368pub const CREATE_PROCESS_DEBUG_EVENT: DWORD = 3;
 369pub const EXIT_THREAD_DEBUG_EVENT: DWORD = 4;
 370pub const EXIT_PROCESS_DEBUG_EVENT: DWORD = 5;
 371pub const LOAD_DLL_DEBUG_EVENT: DWORD = 6;
 372pub const UNLOAD_DLL_DEBUG_EVENT: DWORD = 7;
 373pub const OUTPUT_DEBUG_STRING_EVENT: DWORD = 8;
 374pub const RIP_EVENT: DWORD = 9;
 375&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 376&lt;p&gt;So, we&#x27;ve got a &lt;code&gt;CREATE_PROCESS_DEBUG_EVENT&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
 377&lt;blockquote&gt;
 378&lt;p&gt;Generated whenever a new process is created in a process being debugged or whenever the debugger begins debugging an already active process. The system generates this debugging event before the process begins to execute in user mode and before the system generates any other debugging events for the new process.&lt;&#x2F;p&gt;
 379&lt;&#x2F;blockquote&gt;
 380&lt;p&gt;It makes sense that this is our first event. By the way, if you were trying this out with a &lt;code&gt;sleep&lt;&#x2F;code&gt; lying around in your code, you may have noticed that the window froze until the debugger terminated. That&#x27;s because:&lt;&#x2F;p&gt;
 381&lt;blockquote&gt;
 382&lt;p&gt;When the system notifies the debugger of a debugging event, it also suspends all threads in the affected process. The threads do not resume execution until the debugger continues the debugging event by using &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;debugapi&#x2F;nf-debugapi-continuedebugevent&quot;&gt;&lt;code&gt;ContinueDebugEvent&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
 383&lt;&#x2F;blockquote&gt;
 384&lt;p&gt;Let&#x27;s call &lt;code&gt;ContinueDebugMethod&lt;&#x2F;code&gt; but also wait on more than one event and see what happens:&lt;&#x2F;p&gt;
 385&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;for _ in 0..10 {
 386    let event = debugger.wait_event(None).unwrap();
 387    println!(&amp;quot;Got {}&amp;quot;, event.dwDebugEventCode);
 388    debugger.cont(event, true).unwrap();
 389}
 390&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 391&lt;pre&gt;&lt;code&gt;Got 3
 392Got 6
 393Got 6
 394Got 6
 395Got 6
 396Got 6
 397Got 6
 398Got 6
 399Got 6
 400Got 6
 401&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 402&lt;p&gt;That&#x27;s a lot of &lt;code&gt;LOAD_DLL_DEBUG_EVENT&lt;&#x2F;code&gt;. Pumping it up to one hundred and also showing the index we get the following:&lt;&#x2F;p&gt;
 403&lt;pre&gt;&lt;code&gt;0. Got 3
 4041. Got 6
 405...
 40640. Got 6
 40741. Got 2
 40842. Got 1
 40943. Got 4
 410&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 411&lt;p&gt;In order, we got:&lt;&#x2F;p&gt;
 412&lt;ul&gt;
 413&lt;li&gt;One &lt;code&gt;CREATE_PROCESS_DEBUG_EVENT&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
 414&lt;li&gt;Forty &lt;code&gt;LOAD_DLL_DEBUG_EVENT&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
 415&lt;li&gt;One &lt;code&gt;CREATE_THREAD_DEBUG_EVENT&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
 416&lt;li&gt;One &lt;code&gt;EXCEPTION_DEBUG_EVENT&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
 417&lt;li&gt;One &lt;code&gt;EXIT_THREAD_DEBUG_EVENT&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
 418&lt;&#x2F;ul&gt;
 419&lt;p&gt;And, if after all this, you change the value in the Cheat Engine tutorial (thus triggering our watch point), we get &lt;code&gt;EXCEPTION_DEBUG_EVENT&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
 420&lt;blockquote&gt;
 421&lt;p&gt;Generated whenever an exception occurs in the process being debugged. Possible exceptions include attempting to access inaccessible memory, executing breakpoint instructions, attempting to divide by zero, or any other exception noted in Structured Exception Handling.&lt;&#x2F;p&gt;
 422&lt;&#x2F;blockquote&gt;
 423&lt;p&gt;If we print out all the fields in the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;minwinbase&#x2F;ns-minwinbase-exception_debug_info&quot;&gt;&lt;code&gt;EXCEPTION_DEBUG_INFO&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; structure:&lt;&#x2F;p&gt;
 424&lt;pre&gt;&lt;code&gt;Watching writes to 10e3a0 for 10s
 425First chance: 1
 426ExceptionCode: 2147483652
 427ExceptionFlags: 0
 428ExceptionRecord: 0x0
 429ExceptionAddress: 0x10002c5ba
 430NumberParameters: 0
 431ExceptionInformation: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 432&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 433&lt;p&gt;The &lt;code&gt;ExceptionCode&lt;&#x2F;code&gt;, which is &lt;code&gt;0x80000004&lt;&#x2F;code&gt;, corresponds with &lt;code&gt;EXCEPTION_SINGLE_STEP&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
 434&lt;blockquote&gt;
 435&lt;p&gt;A trace trap or other single-instruction mechanism signaled that one instruction has been executed.&lt;&#x2F;p&gt;
 436&lt;&#x2F;blockquote&gt;
 437&lt;p&gt;The &lt;code&gt;ExceptionAddress&lt;&#x2F;code&gt; is supposed to be &amp;quot;the address where the exception occurred&amp;quot;. Very well! I have already completed this step of the tutorial, and I know the instruction is &lt;code&gt;mov [rax],edx&lt;&#x2F;code&gt; (or, as Cheat Engine shows, the bytes &lt;code&gt;89 10&lt;&#x2F;code&gt; in hexadecimal). The opcode for the &lt;code&gt;nop&lt;&#x2F;code&gt; instruction is &lt;code&gt;90&lt;&#x2F;code&gt; in hexadecimal, so if we replace two bytes at this address, we should be able to complete the tutorial.&lt;&#x2F;p&gt;
 438&lt;p&gt;Note that we also need to flush the instruction cache, as noted in the Windows documentation:&lt;&#x2F;p&gt;
 439&lt;blockquote&gt;
 440&lt;p&gt;Debuggers frequently read the memory of the process being debugged and write the memory that contains instructions to the instruction cache. After the instructions are written, the debugger calls the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;processthreadsapi&#x2F;nf-processthreadsapi-flushinstructioncache&quot;&gt;&lt;code&gt;FlushInstructionCache&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function to execute the cached instructions.&lt;&#x2F;p&gt;
 441&lt;&#x2F;blockquote&gt;
 442&lt;p&gt;So we add a new method to &lt;code&gt;impl Process&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
 443&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&#x2F;&#x2F;&#x2F; Flushes the instruction cache.
 444&#x2F;&#x2F;&#x2F;
 445&#x2F;&#x2F;&#x2F; Should be called when writing to memory regions that contain code.
 446pub fn flush_instruction_cache(&amp;amp;self) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
 447    &#x2F;&#x2F; SAFETY: the call doesn&#x27;t have dangerous side-effects.
 448    if unsafe {
 449        winapi::um::processthreadsapi::FlushInstructionCache(
 450            self.handle.as_ptr(),
 451            ptr::null(),
 452            0,
 453        )
 454    } == FALSE
 455    {
 456        Err(io::Error::last_os_error())
 457    } else {
 458        Ok(())
 459    }
 460}
 461&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 462&lt;p&gt;And write some quick and dirty code to get this done:&lt;&#x2F;p&gt;
 463&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let addr = ...;
 464println!(&amp;quot;Watching writes to {:x} for 10s&amp;quot;, addr);
 465threads.iter_mut().for_each(|thread| {
 466    thread.watch_memory_write(addr).unwrap();
 467});
 468loop {
 469    let event = debugger.wait_event(None).unwrap();
 470    if event.dwDebugEventCode == 1 {
 471        let exc = unsafe { event.u.Exception() };
 472        if exc.ExceptionRecord.ExceptionCode == 2147483652 {
 473            let addr = exc.ExceptionRecord.ExceptionAddress as usize;
 474            match process.write_memory(addr, &amp;amp;[0x90, 0x90]) {
 475                Ok(_) =&amp;gt; eprintln!(&amp;quot;Patched [{:x}] with NOP&amp;quot;, addr),
 476                Err(e) =&amp;gt; eprintln!(&amp;quot;Failed to patch [{:x}] with NOP: {}&amp;quot;, addr, e),
 477            };
 478            process.flush_instruction_cache().unwrap();
 479            debugger.cont(event, true).unwrap();
 480            break;
 481        }
 482    }
 483    debugger.cont(event, true).unwrap();
 484}
 485&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 486&lt;p&gt;Although it seems to work:&lt;&#x2F;p&gt;
 487&lt;pre&gt;&lt;code&gt;Watching writes to 15103f0 for 10s
 488Patched [10002c5ba] with NOP
 489&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 490&lt;p&gt;It really doesn&#x27;t:&lt;&#x2F;p&gt;
 491&lt;blockquote&gt;
 492&lt;p&gt;&lt;strong&gt;Tutorial-x86_64&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
 493&lt;p&gt;Access violation.&lt;&#x2F;p&gt;
 494&lt;p&gt;Press OK to ignore and risk data corruption.&lt;br &#x2F;&gt;
 495Press Abort to kill the program.&lt;&#x2F;p&gt;
 496&lt;p&gt;&lt;kbd&gt;OK&lt;&#x2F;kbd&gt; &lt;kbd&gt;Abort&lt;&#x2F;kbd&gt;&lt;&#x2F;p&gt;
 497&lt;&#x2F;blockquote&gt;
 498&lt;p&gt;Did we write memory somewhere we shouldn&#x27;t? The documentation does mention &amp;quot;segment-relative&amp;quot; and &amp;quot;linear virtual addresses&amp;quot;:&lt;&#x2F;p&gt;
 499&lt;blockquote&gt;
 500&lt;p&gt;&lt;code&gt;GetThreadSelectorEntry&lt;&#x2F;code&gt; returns the descriptor table entry for a specified selector and thread. Debuggers use the descriptor table entry to convert a segment-relative address to a linear virtual address. The &lt;code&gt;ReadProcessMemory&lt;&#x2F;code&gt; and &lt;code&gt;WriteProcessMemory&lt;&#x2F;code&gt; functions require linear virtual addresses.&lt;&#x2F;p&gt;
 501&lt;&#x2F;blockquote&gt;
 502&lt;p&gt;But nope! This isn&#x27;t the problem. The problem is that the &lt;code&gt;ExceptionRecord.ExceptionAddress&lt;&#x2F;code&gt; is &lt;em&gt;after&lt;&#x2F;em&gt; the execution happened, so it&#x27;s already 2 bytes beyond where it should be. We were accidentally writing out the first half of the next instruction, which, yeah, could not end good.&lt;&#x2F;p&gt;
 503&lt;p&gt;So does it work if I do this instead?:&lt;&#x2F;p&gt;
 504&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;process.write_memory(addr - 2, &amp;amp;[0x90, 0x90])
 505&#x2F;&#x2F;                        ^^^ new
 506&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 507&lt;p&gt;This totally does work. Step 5: complete 🎉&lt;&#x2F;p&gt;
 508&lt;h2 id=&quot;properly-patching-instructions&quot;&gt;Properly patching instructions&lt;&#x2F;h2&gt;
 509&lt;p&gt;You may not be satisfied at all with our solution. Not only are we hardcoding some magic constants to set hardware watchpoints, we&#x27;re also relying on knowledge specific to the Cheat Engine tutorial (insofar that we&#x27;re replacing two bytes worth of instruction with NOPs).&lt;&#x2F;p&gt;
 510&lt;p&gt;Properly supporting more than one hardware breakpoint, along with supporting different types of breakpoints, is definitely doable. The meaning of the bits for the debug registers is well defined, and you can definitely study that to come up with &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mmorearty&#x2F;hardware-breakpoints&quot;&gt;something more sophisticated&lt;&#x2F;a&gt; and support multiple different breakpoints. But for now, that&#x27;s out of the scope of this series. The tutorial only wants us to use an on-write watchpoint, and our solution is fine and portable for that use case.&lt;&#x2F;p&gt;
 511&lt;p&gt;However, relying on the size of the instructions is pretty bad. The instructions x86 executes are of variable length, so we can&#x27;t possibly just look back until we find the previous instruction, or even naively determine its length. A lot of unrelated sequences of bytes are very likely instructions themselves. We need a disassembler. No, we&#x27;re not writing our own&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
 512&lt;p&gt;Searching on &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&quot;&gt;crates.io&lt;&#x2F;a&gt; for &amp;quot;disassembler&amp;quot; yields a few results, and the first one I&#x27;ve found is &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;iced-x86&quot;&gt;iced-x86&lt;&#x2F;a&gt;. I like the name, it has a decent amount of GitHub stars, and it was last updated less than a month ago. I don&#x27;t know about you, but I think we&#x27;ve just hit a jackpot!&lt;&#x2F;p&gt;
 513&lt;p&gt;It&#x27;s quite heavy though, so I will add it behind a feature gate, and users that want it may opt into it:&lt;&#x2F;p&gt;
 514&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;[features]
 515patch-nops = [&amp;quot;iced-x86&amp;quot;]
 516
 517[dependencies]
 518iced-x86 = { version = &amp;quot;1.10.3&amp;quot;, optional = true }
 519&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 520&lt;p&gt;You can make use of it with &lt;code&gt;cargo run --features=patch-nops&lt;&#x2F;code&gt;. I don&#x27;t want to turn this blog post into a tutorial for &lt;code&gt;iced-x86&lt;&#x2F;code&gt;, but in essence, we need to make use of its &lt;code&gt;Decoder&lt;&#x2F;code&gt;. Here&#x27;s the plan:&lt;&#x2F;p&gt;
 521&lt;ol&gt;
 522&lt;li&gt;Find the memory region corresponding to the address we want to patch.&lt;&#x2F;li&gt;
 523&lt;li&gt;Read the entire region.&lt;&#x2F;li&gt;
 524&lt;li&gt;Decode the read bytes until the instruction pointer reaches our address.&lt;&#x2F;li&gt;
 525&lt;li&gt;Because we just parsed the previous instruction, we know its length, and can be replaced with NOPs.&lt;&#x2F;li&gt;
 526&lt;&#x2F;ol&gt;
 527&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;#[cfg(feature = &amp;quot;patch-nops&amp;quot;)]
 528pub fn nop_last_instruction(&amp;amp;self, addr: usize) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
 529    use iced_x86::{Decoder, DecoderOptions, Formatter, Instruction, NasmFormatter};
 530
 531    let region = self
 532        .memory_regions()
 533        .into_iter()
 534        .find(|region| {
 535            let base = region.BaseAddress as usize;
 536            base &amp;lt;= addr &amp;amp;&amp;amp; addr &amp;lt; base + region.RegionSize
 537        })
 538        .ok_or_else(|| io::Error::new(io::ErrorKind::Other, &amp;quot;no matching region found&amp;quot;))?;
 539
 540    let bytes = self.read_memory(region.BaseAddress as usize, region.RegionSize)?;
 541
 542    let mut decoder = Decoder::new(64, &amp;amp;bytes, DecoderOptions::NONE);
 543    decoder.set_ip(region.BaseAddress as _);
 544
 545    let mut instruction = Instruction::default();
 546    while decoder.can_decode() {
 547        decoder.decode_out(&amp;amp;mut instruction);
 548        if instruction.next_ip() as usize == addr {
 549            return self
 550                .write_memory(instruction.ip() as usize, &amp;amp;vec![0x90; instruction.len()])
 551                .map(drop);
 552        }
 553    }
 554
 555    Err(io::Error::new(
 556        io::ErrorKind::Other,
 557        &amp;quot;no matching instruction found&amp;quot;,
 558    ))
 559}
 560&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 561&lt;p&gt;Pretty straightforward! We can set the &amp;quot;instruction pointer&amp;quot; of the decoder so that it matches with the address we&#x27;re reading from. The &lt;code&gt;next_ip&lt;&#x2F;code&gt; method comes in really handy. Overall, it&#x27;s a bit inefficient, because we could reuse the regions retrieved previously, but other than that, there is not much room for improvement.&lt;&#x2F;p&gt;
 562&lt;p&gt;With this, we are no longer hardcoding the instruction size or guessing which instruction is doing what. You may wonder, what if the region does not start with valid executable code? It could be possible that the instructions are in some memory region with garbage except for a very specific location with real code. I don&#x27;t know how Cheat Engine handles this, but I think it&#x27;s reasonable to assume that the region starts with valid code.&lt;&#x2F;p&gt;
 563&lt;p&gt;As far as I can tell (after having asked a bit around), the encoding is usually self synchronizing (similar to UTF-8), so eventually we should end up with correct instructions. But someone can still intentionally write real code between garbage data which we would then disassemble incorrectly. This is a problem on all variable-length ISAs. Half a solution is to &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;3983735&#x2F;&quot;&gt;start at the entry point&lt;&#x2F;a&gt;, decode all instructions, and follow the jumps. The other half would be correctly identifying jumps created just to trip a disassembler up, and jumps pointing to dynamically-calculated addresses!&lt;&#x2F;p&gt;
 564&lt;h2 id=&quot;finale&quot;&gt;Finale&lt;&#x2F;h2&gt;
 565&lt;p&gt;That was quite a deep dive! We have learnt about the existence of the various breakpoint types (software, hardware, and even behaviour, such as watchpoints), how to debug a separate process, and how to correctly update the code other process is running on-the-fly. The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lonami&#x2F;memo&quot;&gt;code for this post&lt;&#x2F;a&gt; is available over at my GitHub. You can run &lt;code&gt;git checkout step5&lt;&#x2F;code&gt; after cloning the repository to get the right version of the code.&lt;&#x2F;p&gt;
 566&lt;p&gt;Although we&#x27;ve only talked about &lt;em&gt;setting&lt;&#x2F;em&gt; breakpoints, there are of course &lt;a href=&quot;https:&#x2F;&#x2F;reverseengineering.stackexchange.com&#x2F;a&#x2F;16547&quot;&gt;ways of detecting them&lt;&#x2F;a&gt;. There&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.codeproject.com&#x2F;Articles&#x2F;30815&#x2F;An-Anti-Reverse-Engineering-Guide&quot;&gt;entire guides about it&lt;&#x2F;a&gt;. Again, we currently hardcode the fact we want to add a single watchpoint using the first debug register. A proper solution here would be to actually calculate the needs that need to be set, as well as keeping track of how many breakpoints have been added so far.&lt;&#x2F;p&gt;
 567&lt;p&gt;Hardware breakpoints are also limited, since they&#x27;re simply a bunch of registers, and our machine does not have infinite registers. How are other debuggers like &lt;code&gt;gdb&lt;&#x2F;code&gt; able to create a seemingly unlimited amount of breakpoints? Well, the GDB wiki actually has a page on &lt;a href=&quot;https:&#x2F;&#x2F;sourceware.org&#x2F;gdb&#x2F;wiki&#x2F;Internals%20Watchpoints&quot;&gt;Internals Watchpoints&lt;&#x2F;a&gt;, and it&#x27;s really interesting! &lt;code&gt;gdb&lt;&#x2F;code&gt; essentially single-steps through the entire program and tests the expressions after every instruction:&lt;&#x2F;p&gt;
 568&lt;blockquote&gt;
 569&lt;p&gt;Software watchpoints are very slow, since GDB needs to single-step the program being debugged and test the value of the watched expression(s) after each instruction.&lt;&#x2F;p&gt;
 570&lt;&#x2F;blockquote&gt;
 571&lt;p&gt;However, that&#x27;s not the only way. One could &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;7805842&#x2F;&quot;&gt;change the protection level&lt;&#x2F;a&gt; of the region of interest (for example, remove the write permission), and when the program tries to write there, it will fail! In any case, the GDB wiki is actually a pretty nice resource. It also has a section on &lt;a href=&quot;https:&#x2F;&#x2F;sourceware.org&#x2F;gdb&#x2F;wiki&#x2F;Internals&#x2F;Breakpoint%20Handling&quot;&gt;Breakpoint Handling&lt;&#x2F;a&gt;, which contains some additional insight.&lt;&#x2F;p&gt;
 572&lt;p&gt;With regards to code improvements, &lt;code&gt;DebugToken::wait_event&lt;&#x2F;code&gt; could definitely be both nicer and safer to use, with a custom &lt;code&gt;enum&lt;&#x2F;code&gt;, so the user does not need to rely on magic constants or having to resort to &lt;code&gt;unsafe&lt;&#x2F;code&gt; access to get the right &lt;code&gt;union&lt;&#x2F;code&gt; variant.&lt;&#x2F;p&gt;
 573&lt;p&gt;In the next post, we&#x27;ll tackle the sixth step of the tutorial: Pointers. It reuses the debugging techniques presented here to backtrack where the pointer for our desired value is coming from, so here we will need to actually &lt;em&gt;understand&lt;&#x2F;em&gt; what the instructions are doing, not just patching them out!&lt;&#x2F;p&gt;
 574&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h3&gt;
 575&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
 576&lt;p&gt;I&#x27;m not super happy about the design of it all, but we won&#x27;t actually need anything beyond scanning for integers for the rest of the steps so it doesn&#x27;t really matter.&lt;&#x2F;p&gt;
 577&lt;&#x2F;div&gt;
 578&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
 579&lt;p&gt;There seems to be a way to pause the entire process in one go, with the &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;4062698&#x2F;&quot;&gt;undocumented &lt;code&gt;NtSuspendProcess&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function!&lt;&#x2F;p&gt;
 580&lt;&#x2F;div&gt;
 581&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
 582&lt;p&gt;It really is called that. The naming went from &amp;quot;IP&amp;quot; (instruction pointer, 16 bits), to &amp;quot;EIP&amp;quot; (extended instruction pointer, 32 bits) and currently &amp;quot;RIP&amp;quot; (64 bits). The naming convention for upgraded registers is the same (RAX, RBX, RCX, and so on). The &lt;a href=&quot;https:&#x2F;&#x2F;wiki.osdev.org&#x2F;CPU_Registers_x86_64&quot;&gt;OS Dev wiki&lt;&#x2F;a&gt; is a great resource for this kind of stuff.&lt;&#x2F;p&gt;
 583&lt;&#x2F;div&gt;
 584&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
 585&lt;p&gt;Well, we don&#x27;t need an entire disassembler. Knowing the length of each instruction is enough, but that on its own is also a lot of work.&lt;&#x2F;p&gt;
 586&lt;&#x2F;div&gt;
 587</content>
 588	</entry>
 589	<entry xml:lang="en">
 590		<title>Writing our own Cheat Engine: Floating points</title>
 591		<published>2021-02-28T00:00:00+00:00</published>
 592		<updated>2021-02-28T00:00:00+00:00</updated>
 593		<link href="https://lonami.dev/blog/woce-4/" type="text/html"/>
 594		<id>https://lonami.dev/blog/woce-4/</id>
 595		<content type="html">&lt;p&gt;This is part 4 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt;
 596&lt;ul&gt;
 597&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-1&quot;&gt;Part 1: Introduction&lt;&#x2F;a&gt; (start here if you&#x27;re new to the series!)&lt;&#x2F;li&gt;
 598&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-2&quot;&gt;Part 2: Exact Value scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
 599&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-3&quot;&gt;Part 3: Unknown initial value&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
 600&lt;li&gt;Part 4: Floating points&lt;&#x2F;li&gt;
 601&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-5&quot;&gt;Part 5: Code finder&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
 602&lt;&#x2F;ul&gt;
 603&lt;p&gt;In part 3 we did a fair amount of plumbing in order to support scan modes beyond the trivial &amp;quot;exact value scan&amp;quot;. As a result, we have abstracted away the &lt;code&gt;Scan&lt;&#x2F;code&gt;, &lt;code&gt;CandidateLocations&lt;&#x2F;code&gt; and &lt;code&gt;Value&lt;&#x2F;code&gt; types as a separate &lt;code&gt;enum&lt;&#x2F;code&gt; each. Scanning for changed memory regions in an opened process can now be achieved with three lines of code:&lt;&#x2F;p&gt;
 604&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let regions = process.memory_regions();
 605let first_scan = process.scan_regions(&amp;amp;regions, Scan::InRange(0, 500));
 606let second_scan = process.rescan_regions(&amp;amp;first_scan, Scan::DecreasedBy(7));
 607&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 608&lt;p&gt;How&#x27;s that for programmability? No need to fire up Cheat Engine&#x27;s GUI anymore!&lt;&#x2F;p&gt;
 609&lt;p&gt;The &lt;code&gt;first_scan&lt;&#x2F;code&gt; in the example above remembers all the found &lt;code&gt;Value&lt;&#x2F;code&gt; within the range specified by &lt;code&gt;Scan&lt;&#x2F;code&gt;. Up until now, we have only worked with &lt;code&gt;i32&lt;&#x2F;code&gt;, so that&#x27;s the type the scans expect and what they work with.&lt;&#x2F;p&gt;
 610&lt;p&gt;Now it&#x27;s time to introduce support for different types, like &lt;code&gt;f32&lt;&#x2F;code&gt;, &lt;code&gt;i64&lt;&#x2F;code&gt;, or even more atypical ones, like arbitrary sequences of bytes (think of strings) or even numbers in big-endian.&lt;&#x2F;p&gt;
 611&lt;p&gt;Tighten your belt, because this post is quite the ride. Let&#x27;s get right into it!&lt;&#x2F;p&gt;
 612&lt;h2 id=&quot;floating-points&quot;&gt;Floating points&lt;&#x2F;h2&gt;
 613&lt;details open&gt;&lt;summary&gt;Cheat Engine Tutorial: Step 4&lt;&#x2F;summary&gt;
 614&lt;blockquote&gt;
 615&lt;p&gt;In the previous tutorial we used bytes to scan, but some games store information in so called &#x27;floating point&#x27; notations.
 616(probably to prevent simple memory scanners from finding it the easy way). A floating point is a value with some digits behind the point. (like 5.12 or 11321.1)&lt;&#x2F;p&gt;
 617&lt;p&gt;Below you see your health and ammo. Both are stored as Floating point notations, but health is stored as a float and ammo is stored as a double.
 618Click on hit me to lose some health, and on shoot to decrease your ammo with 0.5&lt;&#x2F;p&gt;
 619&lt;p&gt;You have to set BOTH values to 5000 or higher to proceed.&lt;&#x2F;p&gt;
 620&lt;p&gt;Exact value scan will work fine here, but you may want to experiment with other types too.&lt;&#x2F;p&gt;
 621&lt;p&gt;Hint: It is recommended to disable &amp;quot;Fast Scan&amp;quot; for type double&lt;&#x2F;p&gt;
 622&lt;&#x2F;blockquote&gt;
 623&lt;&#x2F;details&gt;
 624&lt;h2 id=&quot;generic-values&quot;&gt;Generic values&lt;&#x2F;h2&gt;
 625&lt;p&gt;The &lt;code&gt;Value&lt;&#x2F;code&gt; enumeration holds scanned values, and is currently hardcoded to store &lt;code&gt;i32&lt;&#x2F;code&gt;. The &lt;code&gt;Scan&lt;&#x2F;code&gt; type also holds a value, the value we want to scan for. Changing it to support other types is trivial:&lt;&#x2F;p&gt;
 626&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Scan&amp;lt;T&amp;gt; {
 627    Exact(T),
 628    Unknown,
 629    Decreased,
 630    &#x2F;&#x2F; ...other variants...
 631}
 632
 633pub enum Value&amp;lt;T&amp;gt; {
 634    Exact(T),
 635    AnyWithin(Vec&amp;lt;u8&amp;gt;),
 636}
 637&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 638&lt;p&gt;&lt;code&gt;AnyWithin&lt;&#x2F;code&gt; is the raw memory, and &lt;code&gt;T&lt;&#x2F;code&gt; can be interpreted from any sequence of bytes thanks to our friend &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;mem&#x2F;fn.transmute.html&quot;&gt;&lt;code&gt;mem::transmute&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This change alone is enough to store an arbitrary &lt;code&gt;T&lt;&#x2F;code&gt;! So we&#x27;re done now? Not really, no.&lt;&#x2F;p&gt;
 639&lt;p&gt;First of all, we need to update all the places where &lt;code&gt;Scan&lt;&#x2F;code&gt; or &lt;code&gt;Value&lt;&#x2F;code&gt; are used. Our first stop is the scanned &lt;code&gt;Region&lt;&#x2F;code&gt;, which holds the found &lt;code&gt;Value&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
 640&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub struct Region&amp;lt;T&amp;gt; {
 641    pub info: MEMORY_BASIC_INFORMATION,
 642    pub locations: CandidateLocations,
 643    pub value: Value&amp;lt;T&amp;gt;,
 644}
 645&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 646&lt;p&gt;Then, we need to update everywhere &lt;code&gt;Region&lt;&#x2F;code&gt; is used, and on and on… All in all this process is just repeating &lt;code&gt;cargo check&lt;&#x2F;code&gt;, letting the compiler vent on you, and taking good care of it by fixing the errors. It&#x27;s quite reassuring to know you will not miss a single place. Thank you, compiler!&lt;&#x2F;p&gt;
 647&lt;p&gt;But wait, how could scanning for a decreased value work for any &lt;code&gt;T&lt;&#x2F;code&gt;? The type is not &lt;code&gt;Ord&lt;&#x2F;code&gt;, we should add some trait bounds. And also, what happens if the type is not &lt;code&gt;Copy&lt;&#x2F;code&gt;? It could implement &lt;code&gt;Drop&lt;&#x2F;code&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and we will be transmuting from raw bytes, which would trigger the &lt;code&gt;Drop&lt;&#x2F;code&gt; implementation when we&#x27;re done with the value! Not memory safe at all! And how could we possibly cast raw memory to the type without knowing its siz– oh nevermind, &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;marker&#x2F;trait.Sized.html&quot;&gt;&lt;code&gt;T&lt;&#x2F;code&gt; is already &lt;code&gt;Sized&lt;&#x2F;code&gt; by default&lt;&#x2F;a&gt;. But anyway, we need the other bounds.&lt;&#x2F;p&gt;
 648&lt;p&gt;In order to not repeat ourselves, we will implement a new &lt;code&gt;trait&lt;&#x2F;code&gt;, let&#x27;s say &lt;code&gt;Scannable&lt;&#x2F;code&gt;, which requires all other bounds:&lt;&#x2F;p&gt;
 649&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub trait Scannable: Copy + PartialEq + PartialOrd {}
 650
 651impl&amp;lt;T: Copy + PartialEq + PartialOrd&amp;gt; Scannable for T {}
 652&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 653&lt;p&gt;And fix our definitions:&lt;&#x2F;p&gt;
 654&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Scan&amp;lt;T: Scannable&amp;gt; { ... }
 655pub enum Value&amp;lt;T: Scannable&amp;gt; { ... }
 656pub struct Region&amp;lt;T: Scannable&amp;gt; { ... }
 657
 658&#x2F;&#x2F; ...and the many other places referring to T
 659&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 660&lt;p&gt;Every type which is &lt;code&gt;Copy&lt;&#x2F;code&gt;, &lt;code&gt;PartialEq&lt;&#x2F;code&gt; and &lt;code&gt;PartialOrd&lt;&#x2F;code&gt; can be scanned over&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, because we &lt;code&gt;impl Scan for T&lt;&#x2F;code&gt; where the bounds are met. Unfortunately, we cannot require &lt;code&gt;Eq&lt;&#x2F;code&gt; or &lt;code&gt;Ord&lt;&#x2F;code&gt; because the floating point types do not implement it.&lt;&#x2F;p&gt;
 661&lt;h2 id=&quot;transmuting-memory&quot;&gt;Transmuting memory&lt;&#x2F;h2&gt;
 662&lt;p&gt;Also known as reinterpreting a bunch of bytes as something else, or perhaps it stands for &amp;quot;summoning the demon&amp;quot;:&lt;&#x2F;p&gt;
 663&lt;blockquote&gt;
 664&lt;p&gt;&lt;code&gt;transmute&lt;&#x2F;code&gt; is &lt;strong&gt;incredibly&lt;&#x2F;strong&gt; unsafe. There are a vast number of ways to cause &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;reference&#x2F;behavior-considered-undefined.html&quot;&gt;undefined behavior&lt;&#x2F;a&gt; with this function. &lt;code&gt;transmute&lt;&#x2F;code&gt; should be the absolute last resort.&lt;&#x2F;p&gt;
 665&lt;&#x2F;blockquote&gt;
 666&lt;p&gt;Types like &lt;code&gt;i32&lt;&#x2F;code&gt; define methods such as &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;primitive.i32.html#method.from_ne_bytes&quot;&gt;&lt;code&gt;from_ne_bytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;primitive.i32.html#method.to_ne_bytes&quot;&gt;&lt;code&gt;to_ne_bytes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which convert raw bytes from and into its native representation. This is all really nice, but unfortunately, there&#x27;s no standard trait in the Rust&#x27;s standard library to &amp;quot;interpret a type &lt;code&gt;T&lt;&#x2F;code&gt; as the byte sequence of its native representation&amp;quot;. &lt;code&gt;transmute&lt;&#x2F;code&gt;, however, does exist, and similar to any other &lt;code&gt;unsafe&lt;&#x2F;code&gt; function, it&#x27;s safe to call &lt;strong&gt;as long as we respect its invariants&lt;&#x2F;strong&gt;. What are these invariants&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;?&lt;&#x2F;p&gt;
 667&lt;blockquote&gt;
 668&lt;p&gt;Both types must have the same size&lt;&#x2F;p&gt;
 669&lt;&#x2F;blockquote&gt;
 670&lt;p&gt;Okay, we can just assert that the window length matches the type&#x27;s length. What else?&lt;&#x2F;p&gt;
 671&lt;blockquote&gt;
 672&lt;p&gt;Neither the original, nor the result, may be an &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nomicon&#x2F;what-unsafe-does.html&quot;&gt;invalid value&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
 673&lt;&#x2F;blockquote&gt;
 674&lt;p&gt;What&#x27;s an invalid value?&lt;&#x2F;p&gt;
 675&lt;blockquote&gt;
 676&lt;ul&gt;
 677&lt;li&gt;a &lt;code&gt;bool&lt;&#x2F;code&gt; that isn&#x27;t 0 or 1&lt;&#x2F;li&gt;
 678&lt;li&gt;an &lt;code&gt;enum&lt;&#x2F;code&gt; with an invalid discriminant&lt;&#x2F;li&gt;
 679&lt;li&gt;a null &lt;code&gt;fn&lt;&#x2F;code&gt; pointer&lt;&#x2F;li&gt;
 680&lt;li&gt;a &lt;code&gt;char&lt;&#x2F;code&gt; outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF]&lt;&#x2F;li&gt;
 681&lt;li&gt;a &lt;code&gt;!&lt;&#x2F;code&gt; (all values are invalid for this type)&lt;&#x2F;li&gt;
 682&lt;li&gt;an integer (&lt;code&gt;i*&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;u*&lt;&#x2F;code&gt;), floating point value (&lt;code&gt;f*&lt;&#x2F;code&gt;), or raw pointer read from uninitialized memory, or uninitialized memory in a &lt;code&gt;str&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
 683&lt;li&gt;a reference&#x2F;&lt;code&gt;Box&lt;&#x2F;code&gt; that is dangling, unaligned, or points to an invalid value.&lt;&#x2F;li&gt;
 684&lt;li&gt;a wide reference, &lt;code&gt;Box&lt;&#x2F;code&gt;, or raw pointer that has invalid metadata:
 685&lt;ul&gt;
 686&lt;li&gt;&lt;code&gt;dyn Trait&lt;&#x2F;code&gt; metadata is invalid if it is not a pointer to a vtable for &lt;code&gt;Trait&lt;&#x2F;code&gt; that matches the actual dynamic trait the pointer or reference points to&lt;&#x2F;li&gt;
 687&lt;li&gt;slice metadata is invalid if the length is not a valid &lt;code&gt;usize&lt;&#x2F;code&gt; (i.e., it must not be read from uninitialized memory)&lt;&#x2F;li&gt;
 688&lt;&#x2F;ul&gt;
 689&lt;&#x2F;li&gt;
 690&lt;li&gt;a type with custom invalid values that is one of those values, such as a &lt;code&gt;NonNull&lt;&#x2F;code&gt; that is null. (Requesting custom invalid values is an unstable feature, but some stable libstd types, like &lt;code&gt;NonNull&lt;&#x2F;code&gt;, make use of it.)&lt;&#x2F;li&gt;
 691&lt;&#x2F;ul&gt;
 692&lt;&#x2F;blockquote&gt;
 693&lt;p&gt;Okay, that&#x27;s actually an awful lot. Types like &lt;code&gt;bool&lt;&#x2F;code&gt; implement all the trait bounds we defined, and it would be insta-UB to ever try to cast them from arbitrary bytes. The same goes for &lt;code&gt;char&lt;&#x2F;code&gt;, and all &lt;code&gt;enum&lt;&#x2F;code&gt; are out of our control, too. At least we&#x27;re safe on the &amp;quot;memory is initialized&amp;quot; front.&lt;&#x2F;p&gt;
 694&lt;p&gt;Dang it, I really wanted to use &lt;code&gt;transmute&lt;&#x2F;code&gt;! But if we were to use it for arbitrary types, it would trigger undefined behaviour sooner than later.&lt;&#x2F;p&gt;
 695&lt;p&gt;We have several options here:&lt;&#x2F;p&gt;
 696&lt;ul&gt;
 697&lt;li&gt;Make it an &lt;code&gt;unsafe trait&lt;&#x2F;code&gt;. Implementors will be responsible for ensuring that the type they&#x27;re implementing it for can be safely transmuted from and into.&lt;&#x2F;li&gt;
 698&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;api-guidelines&#x2F;future-proofing.html&quot;&gt;Seal the &lt;code&gt;trait&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and implement it only for types we know are safe&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, like &lt;code&gt;i32&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
 699&lt;li&gt;Add methods to the &lt;code&gt;trait&lt;&#x2F;code&gt; definition that do the conversion of the type into its native representation.&lt;&#x2F;li&gt;
 700&lt;&#x2F;ul&gt;
 701&lt;p&gt;We will go with the first option&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, because I really want to use &lt;code&gt;transmute&lt;&#x2F;code&gt;, and I want users to be able to implement the trait on their own types.&lt;&#x2F;p&gt;
 702&lt;p&gt;In any case, we need to change our &lt;code&gt;impl&lt;&#x2F;code&gt; to something more specific, in order to prevent it from automatically implementing the trait for types for which their memory representation has invalid values. So we get rid of this:&lt;&#x2F;p&gt;
 703&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub trait Scannable: Copy + PartialEq + PartialOrd {}
 704
 705impl&amp;lt;T: Copy + PartialEq + PartialOrd&amp;gt; Scannable for T {}
 706&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 707&lt;p&gt;And replace it with this:&lt;&#x2F;p&gt;
 708&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub unsafe trait Scannable: Copy + PartialEq + PartialOrd {}
 709
 710macro_rules! impl_many {
 711    ( unsafe impl $trait:tt for $( $ty:ty ),* ) =&amp;gt; {
 712        $( unsafe impl $trait for $ty {} )*
 713    };
 714}
 715
 716&#x2F;&#x2F; SAFETY: all these types respect `Scannable` invariants.
 717impl_many!(unsafe impl Scannable for i8, u8, i16, u16, i32, u32, i64, u64, f32, f64);
 718&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 719&lt;p&gt;Making a small macro for things like these is super useful. You could of course write &lt;code&gt;unsafe impl Scannable for T&lt;&#x2F;code&gt; for all ten &lt;code&gt;T&lt;&#x2F;code&gt; as well, but that introduces even more &lt;code&gt;unsafe&lt;&#x2F;code&gt; to read. Last but not least, let&#x27;s replace the hardcoded &lt;code&gt;i32::from_ne_bytes&lt;&#x2F;code&gt; and &lt;code&gt;i32::to_ne_bytes&lt;&#x2F;code&gt; with &lt;code&gt;mem::transmute&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
 720&lt;p&gt;All the &lt;code&gt;windows(4)&lt;&#x2F;code&gt; need to be replaced with &lt;code&gt;windows(mem::size_of::&amp;lt;T&amp;gt;())&lt;&#x2F;code&gt; because the size may no longer be &lt;code&gt;4&lt;&#x2F;code&gt;. All the &lt;code&gt;i32::from_ne_bytes(...)&lt;&#x2F;code&gt; need to be replaced with &lt;code&gt;mem::transmute::&amp;lt;_, T&amp;gt;(...)&lt;&#x2F;code&gt;. We explicitly write out &lt;code&gt;T&lt;&#x2F;code&gt; to make sure the compiler doesn&#x27;t accidentally infer something we didn&#x27;t intend.&lt;&#x2F;p&gt;
 721&lt;p&gt;And… it doesn&#x27;t work at all. We&#x27;re working with byte slices of arbitrary length. We cannot transmute a &lt;code&gt;&amp;amp;[]&lt;&#x2F;code&gt; type, which is 16 bytes (8 for the pointer and 8 for the length), to our &lt;code&gt;T&lt;&#x2F;code&gt;. My plan to use transmute can&#x27;t possibly work here. Sigh.&lt;&#x2F;p&gt;
 722&lt;h2 id=&quot;not-quite-transmuting-memory&quot;&gt;Not quite transmuting memory&lt;&#x2F;h2&gt;
 723&lt;p&gt;Okay, we can&#x27;t transmute, because we don&#x27;t have a sized value, we only have a slice of bytes pointing somewhere else. What we &lt;em&gt;could&lt;&#x2F;em&gt; do is reinterpret the pointer to those bytes as a different type, and then dereference it! This is still a form of &amp;quot;transmutation&amp;quot;, just without using &lt;code&gt;transmute&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
 724&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let value = unsafe { *(window.as_ptr() as *const T) };
 725&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 726&lt;p&gt;Woop! You can compile this and test it out on the step 2 and 3 of the tutorial, using &lt;code&gt;i32&lt;&#x2F;code&gt;, and it will still work! Something troubles me, though. Can you see what it is?&lt;&#x2F;p&gt;
 727&lt;p&gt;When we talked about invalid values, it had a note about unaligned references:&lt;&#x2F;p&gt;
 728&lt;blockquote&gt;
 729&lt;p&gt;a reference&#x2F;&lt;code&gt;Box&lt;&#x2F;code&gt; that is dangling, unaligned, or points to an invalid value.&lt;&#x2F;p&gt;
 730&lt;&#x2F;blockquote&gt;
 731&lt;p&gt;Our &lt;code&gt;window&lt;&#x2F;code&gt; is essentially a reference to &lt;code&gt;T&lt;&#x2F;code&gt;. The only difference is we&#x27;re working at the pointer level, but they&#x27;re pretty much references. Let&#x27;s see what the documentation for &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.pointer.html&quot;&gt;&lt;code&gt;pointer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; has to say as well, since we&#x27;re dereferencing pointers:&lt;&#x2F;p&gt;
 732&lt;blockquote&gt;
 733&lt;p&gt;when a raw pointer is dereferenced (using the &lt;code&gt;*&lt;&#x2F;code&gt; operator), it must be non-null and aligned.&lt;&#x2F;p&gt;
 734&lt;&#x2F;blockquote&gt;
 735&lt;p&gt;It must be aligned. The only reason why our data is aligned is because we are also performing a &amp;quot;fast scan&amp;quot;, so we only look at aligned locations. This is a time bomb waiting to blow up. Is there any other way to &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ptr&#x2F;fn.read.html&quot;&gt;&lt;code&gt;read&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; from a pointer which is safer?&lt;&#x2F;p&gt;
 736&lt;blockquote&gt;
 737&lt;p&gt;&lt;code&gt;src&lt;&#x2F;code&gt; must be properly aligned. Use &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ptr&#x2F;fn.read_unaligned.html&quot;&gt;&lt;code&gt;read_unaligned&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; if this is not the case.&lt;&#x2F;p&gt;
 738&lt;&#x2F;blockquote&gt;
 739&lt;p&gt;Bingo! Both &lt;code&gt;read&lt;&#x2F;code&gt; and &lt;code&gt;read_unaligned&lt;&#x2F;code&gt;, unlike dereferencing the pointer, will perform a copy, but if it can make the code less prone to blowing up, I&#x27;ll take it&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Let&#x27;s change the code one more time:&lt;&#x2F;p&gt;
 740&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let current = unsafe { window.as_ptr().cast::&amp;lt;T&amp;gt;().read_unaligned() };
 741&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 742&lt;p&gt;I prefer to avoid type annotations in variables where possible, which is why I use the &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;3fimgp&#x2F;why_double_colon_rather_that_dot&#x2F;ctozkd0&#x2F;&quot;&gt;turbofish&lt;&#x2F;a&gt; so often. You can get rid of the cast and use a type annotation instead, but make sure the type is known, otherwise it will think it&#x27;s &lt;code&gt;u8&lt;&#x2F;code&gt; because &lt;code&gt;window&lt;&#x2F;code&gt; is a &lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
 743&lt;p&gt;Now, this is all cool and good. You can replace &lt;code&gt;i32&lt;&#x2F;code&gt; with &lt;code&gt;f32&lt;&#x2F;code&gt; for &lt;code&gt;T&lt;&#x2F;code&gt; and you&#x27;ll be able to get halfway done with the step 4 of Cheat Engine&#x27;s tutorial. Unfortunately, as it is, this code is not enough to complete step 4 with exact scans&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. You see, comparing floating point values is not as simple as checking for bitwise equality. We were actually really lucky that the &lt;code&gt;f32&lt;&#x2F;code&gt; part works! But the values in the &lt;code&gt;f64&lt;&#x2F;code&gt; part are not as precise as our inputs, so our exact scan fails.&lt;&#x2F;p&gt;
 744&lt;p&gt;Using a fixed type parameter is pretty limiting as well. On the one hand, it is nice that, if you scan for &lt;code&gt;i32&lt;&#x2F;code&gt;, the compiler statically guarantees that subsequent scans will also happen on &lt;code&gt;i32&lt;&#x2F;code&gt; and thus be compatible. On the other, this requires us to know the type at compile time, which for an interactive program, is not possible. While we &lt;em&gt;could&lt;&#x2F;em&gt; create different methods for each supported type and, at runtime, decide to which we should jump, I am not satisfied with that solution. It also means we can&#x27;t switch from scanning an &lt;code&gt;u32&lt;&#x2F;code&gt; to an &lt;code&gt;i32&lt;&#x2F;code&gt;, for whatever reason.&lt;&#x2F;p&gt;
 745&lt;p&gt;So we need to work around this once more.&lt;&#x2F;p&gt;
 746&lt;h2 id=&quot;rethinking-the-scans&quot;&gt;Rethinking the scans&lt;&#x2F;h2&gt;
 747&lt;p&gt;What does our scanning function need, really? It needs a way to compare two chunks of memory as being equal or not (as we have seen, this isn&#x27;t trivial with types such as floating point numbers) and, for other types of scans, it needs to be able to produce an ordering, or calculate a difference.&lt;&#x2F;p&gt;
 748&lt;p&gt;Instead of having a our trait require the bounds &lt;code&gt;PartialEq&lt;&#x2F;code&gt; and &lt;code&gt;PartialOrd&lt;&#x2F;code&gt;, we can define our own methods to compare &lt;code&gt;Self&lt;&#x2F;code&gt; with &lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt;. It still should be &lt;code&gt;Clone&lt;&#x2F;code&gt;, so we can pass it around without worrying about lifetimes:&lt;&#x2F;p&gt;
 749&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&#x2F;&#x2F; Callers must `assert_eq!(memory.len(), mem::size_of::&amp;lt;Self&amp;gt;())`.
 750unsafe fn eq(&amp;amp;self, memory: &amp;amp;[u8]) -&amp;gt; bool;
 751unsafe fn cmp(&amp;amp;self, memory: &amp;amp;[u8]) -&amp;gt; Ordering;
 752&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 753&lt;p&gt;This can be trivially implemented for all integer types:&lt;&#x2F;p&gt;
 754&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;macro_rules! impl_scannable_for_int {
 755    ( $( $ty:ty ),* ) =&amp;gt; {
 756        $(
 757            &#x2F;&#x2F; SAFETY: caller is responsible to `assert_eq!(memory.len(), mem::size_of::&amp;lt;T&amp;gt;())`
 758            impl Scannable for $ty {
 759                unsafe fn eq(&amp;amp;self, memory: &amp;amp;[u8]) -&amp;gt; bool {
 760                    let other = unsafe { memory.as_ptr().cast::&amp;lt;$ty&amp;gt;().read_unaligned() };
 761                    *self == other
 762                }
 763
 764                unsafe fn cmp(&amp;amp;self, memory: &amp;amp;[u8]) -&amp;gt; Ordering {
 765                    let other = unsafe { memory.as_ptr().cast::&amp;lt;$ty&amp;gt;().read_unaligned() };
 766                    &amp;lt;$ty as Ord&amp;gt;::cmp(self, &amp;amp;other)
 767                }
 768            }
 769        )*
 770    };
 771}
 772
 773impl_scannable_for_int!(i8, u8, i16, u16, i32, u32, i64, u64);
 774&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 775&lt;p&gt;The funny &lt;code&gt;&amp;lt;$ty as Ord&amp;gt;&lt;&#x2F;code&gt; is because I decided to call the method &lt;code&gt;Scannable::cmp&lt;&#x2F;code&gt;, so I have to disambiguate between it and &lt;code&gt;Ord::cmp&lt;&#x2F;code&gt;. We can go ahead and update the code using &lt;code&gt;Scannable&lt;&#x2F;code&gt; to use these new functions instead.&lt;&#x2F;p&gt;
 776&lt;p&gt;Now, you may have noticed I only implemented it for the integer types. That&#x27;s because floats need some extra care. Unfortunately, floating point types do not have any form of &amp;quot;precision&amp;quot; embedded in them, so we can&#x27;t accurately say &amp;quot;compare these floats to the precision level the user specified&amp;quot;. What we can do, however, is drop a few bits from the mantissa, so &amp;quot;relatively close&amp;quot; quantities are considered equal. It&#x27;s definitely not as good as comparing floats to the user&#x27;s precision, but it will get the job done.&lt;&#x2F;p&gt;
 777&lt;p&gt;I&#x27;m going to arbitrarily say that we are okay comparing with &amp;quot;half&amp;quot; the precision. We can achieve that by masking half of the bits from the mantissa to zero:&lt;&#x2F;p&gt;
 778&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;
 779macro_rules! impl_scannable_for_float {
 780    ( $( $ty:ty : $int_ty:ty ),* ) =&amp;gt; {
 781        $(
 782            #[allow(unused_unsafe)] &#x2F;&#x2F; mind you, it is necessary
 783            impl Scannable for $ty {
 784                unsafe fn eq(&amp;amp;self, memory: &amp;amp;[u8]) -&amp;gt; bool {
 785                    const MASK: $int_ty = !((1 &amp;lt;&amp;lt; (&amp;lt;$ty&amp;gt;::MANTISSA_DIGITS &#x2F; 2)) - 1);
 786
 787                    &#x2F;&#x2F; SAFETY: caller is responsible to `assert_eq!(memory.len(), mem::size_of::&amp;lt;T&amp;gt;())`
 788                    let other = unsafe { memory.as_ptr().cast::&amp;lt;$ty&amp;gt;().read_unaligned() };
 789                    let left = &amp;lt;$ty&amp;gt;::from_bits(self.to_bits() &amp;amp; MASK);
 790                    let right = &amp;lt;$ty&amp;gt;::from_bits(other.to_bits() &amp;amp; MASK);
 791                    left == right
 792                }
 793
 794                ...
 795            }
 796        )*
 797    };
 798}
 799
 800impl_scannable_for_float!(f32: u32, f64: u64);
 801&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 802&lt;p&gt;You may be wondering what&#x27;s up with that weird &lt;code&gt;MASK&lt;&#x2F;code&gt;. Let&#x27;s visualize it with a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bfloat16_floating-point_format&quot;&gt;&lt;code&gt;f16&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. This type has 16 bits, 1 for sign, 5 for exponent, and 10 for the mantissa:&lt;&#x2F;p&gt;
 803&lt;pre&gt;&lt;code&gt;S EEEEE MMMMMMMMMM
 804&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 805&lt;p&gt;If we substitute the constant with the numeric value and operate:&lt;&#x2F;p&gt;
 806&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;!((1 &amp;lt;&amp;lt; (10 &#x2F; 2)) - 1)
 807!((1 &amp;lt;&amp;lt; 5) - 1)
 808!(0b00000000_00100000 - 1)
 809!(0b00000000_00011111)
 8100b11111111_11100000
 811&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 812&lt;p&gt;So effectively, half of the mantisssa bit will be masked to 0. For the &lt;code&gt;f16&lt;&#x2F;code&gt; example, this makes us lose 5 bits of precision. Comparing two floating point values with their last five bits truncated is equivalent to checking if they are &amp;quot;roughly equal&amp;quot;!&lt;&#x2F;p&gt;
 813&lt;p&gt;When Cheat Engine scans for floating point values, several additional settings show, and one such option is &amp;quot;truncated&amp;quot;. I do not know if it behaves like this, but it might.&lt;&#x2F;p&gt;
 814&lt;p&gt;Let&#x27;s try this out:&lt;&#x2F;p&gt;
 815&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;#[test]
 816fn f32_roughly_eq() {
 817    let left = 0.25f32;
 818    let right = 0.25000123f32;
 819    let memory = unsafe { mem::transmute::&amp;lt;_, [u8; 4]&amp;gt;(right) };
 820    assert_ne!(left, right);
 821    assert!(unsafe { Scannable::eq(&amp;amp;left, &amp;amp;memory) });
 822}
 823&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 824&lt;pre&gt;&lt;code&gt;&amp;gt;cargo test f32_roughly_eq
 825
 826running 1 test
 827test scan::candidate_location_tests::f32_roughly_eq ... ok
 828&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 829&lt;p&gt;Huzzah! The &lt;code&gt;assert_ne!&lt;&#x2F;code&gt; makes sure that a normal comparision would fail, and then we &lt;code&gt;assert!&lt;&#x2F;code&gt; that our custom one passes the test. When the user performs an exact scan, the code will be more tolerant to the user&#x27;s less precise inputs, which overall should result in a nicer experience.&lt;&#x2F;p&gt;
 830&lt;h2 id=&quot;dynamically-sized-scans&quot;&gt;Dynamically sized scans&lt;&#x2F;h2&gt;
 831&lt;p&gt;The second problem we need to solve is the possibility of the size not being known at compile time&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. While we can go as far as scanning over strings of a known length, this is rather limiting, because we need to know the length at compile time&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Heap allocated objects are another problem, because we don&#x27;t want to compare the memory representation of the stack object, but likely the memory where they point to (such as &lt;code&gt;String&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
 832&lt;p&gt;Instead of using &lt;code&gt;mem::size_of&lt;&#x2F;code&gt;, we can add a new method to our &lt;code&gt;Scannable&lt;&#x2F;code&gt;, &lt;code&gt;size&lt;&#x2F;code&gt;, which will tell us the size required of the memory view we&#x27;re comparing against:&lt;&#x2F;p&gt;
 833&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;unsafe impl Scannable {
 834    ...
 835
 836    fn size(&amp;amp;self) -&amp;gt; usize;
 837}
 838&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 839&lt;p&gt;It is &lt;code&gt;unsafe&lt;&#x2F;code&gt; to implement, because we are relying on the returned value to be truthful and unchanging. It should be safe to call, because it cannot have any invariants. Unfortunately, signaling &amp;quot;unsafe to implement&amp;quot; is done by marking the entire trait as &lt;code&gt;unsafe&lt;&#x2F;code&gt;, since &amp;quot;unsafe to call&amp;quot; is reserved for &lt;code&gt;unsafe fn&lt;&#x2F;code&gt;, and even though the rest of methods are not necessarily unsafe to implement, they&#x27;re treated as such.&lt;&#x2F;p&gt;
 840&lt;p&gt;At the moment, &lt;code&gt;Scannable&lt;&#x2F;code&gt; cannot be made into a trait object because it is &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;error-index.html#E0038&quot;&gt;not object safe&lt;&#x2F;a&gt;. This is caused by the &lt;code&gt;Clone&lt;&#x2F;code&gt; requirement on all &lt;code&gt;Scannable&lt;&#x2F;code&gt; object, which in turn needs the types to be &lt;code&gt;Sized&lt;&#x2F;code&gt; because &lt;code&gt;clone&lt;&#x2F;code&gt; returns &lt;code&gt;Self&lt;&#x2F;code&gt;. Because of this, the size must be known.&lt;&#x2F;p&gt;
 841&lt;p&gt;However, we &lt;em&gt;can&lt;&#x2F;em&gt; move the &lt;code&gt;Clone&lt;&#x2F;code&gt; requirement to the methods that need it! This way, &lt;code&gt;Scannable&lt;&#x2F;code&gt; can remain object safe, enabling us to do the following:&lt;&#x2F;p&gt;
 842&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;unsafe impl&amp;lt;T: AsRef&amp;lt;dyn Scannable&amp;gt; + AsMut&amp;lt;dyn Scannable&amp;gt;&amp;gt; Scannable for T {
 843    unsafe fn eq(&amp;amp;self, memory: &amp;amp;[u8]) -&amp;gt; bool {
 844        self.as_ref().eq(memory)
 845    }
 846
 847    unsafe fn cmp(&amp;amp;self, memory: &amp;amp;[u8]) -&amp;gt; Ordering {
 848        self.as_ref().cmp(memory)
 849    }
 850
 851    fn mem_view(&amp;amp;self) -&amp;gt; &amp;amp;[u8] {
 852        self.as_ref().mem_view()
 853    }
 854
 855    fn size(&amp;amp;self) -&amp;gt; usize {
 856        self.as_ref().size()
 857    }
 858}
 859&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 860&lt;p&gt;Any type which can be interpreted as a reference to &lt;code&gt;Scannable&lt;&#x2F;code&gt; is also a scannable! This enables us to perform scans over &lt;code&gt;Box&amp;lt;dyn i32&amp;gt;&lt;&#x2F;code&gt;, where the type is known at runtime! Or rather, it would, if &lt;code&gt;Box&amp;lt;dyn T&amp;gt;&lt;&#x2F;code&gt; implemented &lt;code&gt;Clone&lt;&#x2F;code&gt;, which it can&#x27;t&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#10&quot;&gt;10&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; because that&#x27;s what prompted this entire issue. Dang it! I can&#x27;t catch a breath today!&lt;&#x2F;p&gt;
 861&lt;p&gt;Okay, let&#x27;s step back. Why did we need our scannables to be clone in the first place? When we perform exact scans, we store the original value in the region, which we don&#x27;t own, so we clone it. But what if we &lt;em&gt;did&lt;&#x2F;em&gt; own the value? Instead of taking the &lt;code&gt;Scan&lt;&#x2F;code&gt; by reference, which holds &lt;code&gt;T: Scannable&lt;&#x2F;code&gt;, we could take it by value. If we get rid of all the &lt;code&gt;Clone&lt;&#x2F;code&gt; bounds and update &lt;code&gt;Scan::run&lt;&#x2F;code&gt; to take &lt;code&gt;self&lt;&#x2F;code&gt;, along with updating all the things that take a &lt;code&gt;Region&lt;&#x2F;code&gt; to take them by value as well, it should all work out.&lt;&#x2F;p&gt;
 862&lt;p&gt;But it does not. If we take &lt;code&gt;Scan&lt;&#x2F;code&gt; by value, with it not being &lt;code&gt;Clone&lt;&#x2F;code&gt;, we simply can&#x27;t use it to scan over multiple regions. After the first region, we have lost the &lt;code&gt;Scan&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
 863&lt;p&gt;Let&#x27;s take a second step back. We are scanning memory, and we want to compare memory, but we want to treat the memory with different semantics (for example, if we treat it as &lt;code&gt;f32&lt;&#x2F;code&gt;, we want to check for rough equality). Instead of storing the &lt;em&gt;value&lt;&#x2F;em&gt; itself, we could store its &lt;em&gt;memory representation&lt;&#x2F;em&gt;, and when we compare memory representations, we can do so under certain semantics.&lt;&#x2F;p&gt;
 864&lt;p&gt;First off, let&#x27;s revert getting rid of all &lt;code&gt;Clone&lt;&#x2F;code&gt;. Wherever we stored a &lt;code&gt;T&lt;&#x2F;code&gt;, we will now store a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;. We will still use a type parameter to represent the &amp;quot;implementations of &lt;code&gt;Scannable&lt;&#x2F;code&gt;&amp;quot;. For this to work, our definitions need to use &lt;code&gt;T&lt;&#x2F;code&gt; somewhere, or else the compiler refuses to compile the code with error &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;error-index.html#E0392&quot;&gt;E0392&lt;&#x2F;a&gt;. For this, I will stick a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;marker&#x2F;struct.PhantomData.html&quot;&gt;&lt;code&gt;PhantomData&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in the &lt;code&gt;Exact&lt;&#x2F;code&gt; variant. It&#x27;s a bit pointless to include it in all variants, and &lt;code&gt;Exact&lt;&#x2F;code&gt; seems the most appropriated:&lt;&#x2F;p&gt;
 865&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Scan&amp;lt;T: Scannable&amp;gt; {
 866    Exact(Vec&amp;lt;u8&amp;gt;, PhantomData&amp;lt;T&amp;gt;),
 867    Unknown,
 868    ...
 869}
 870&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 871&lt;p&gt;This keeps in line with &lt;code&gt;Value&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
 872&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Value&amp;lt;T: Scannable&amp;gt; {
 873    Exact(Vec&amp;lt;u8&amp;gt;, PhantomData&amp;lt;T&amp;gt;),
 874    ...
 875}
 876&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 877&lt;p&gt;Our &lt;code&gt;Scannable&lt;&#x2F;code&gt; will no longer work on &lt;code&gt;T&lt;&#x2F;code&gt; and &lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt;. Instead, it will work on two &lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt;. We will also need a way to interpret a &lt;code&gt;T&lt;&#x2F;code&gt; as &lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt;, which we can achieve with a new method, &lt;code&gt;mem_view&lt;&#x2F;code&gt;. This method interprets the raw memory representation of &lt;code&gt;self&lt;&#x2F;code&gt; as its raw bytes. It also lets us get rid of &lt;code&gt;size&lt;&#x2F;code&gt;, because we can simply do &lt;code&gt;mem_view().len()&lt;&#x2F;code&gt;. It&#x27;s still &lt;code&gt;unsafe&lt;&#x2F;code&gt; to implement, because it should return the same length every time:&lt;&#x2F;p&gt;
 878&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub unsafe trait Scannable {
 879    &#x2F;&#x2F; Callers must `assert_eq!(left.len(), right.len(), self.mem_view().len())`.
 880    unsafe fn eq(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; bool;
 881    unsafe fn cmp(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; Ordering;
 882    fn mem_view(&amp;amp;self) -&amp;gt; &amp;amp;[u8];
 883}
 884&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 885&lt;p&gt;But now we can&#x27;t use it in trait object, so the following no longer works:&lt;&#x2F;p&gt;
 886&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;unsafe impl&amp;lt;T: AsRef&amp;lt;dyn Scannable&amp;gt; + AsMut&amp;lt;dyn Scannable&amp;gt;&amp;gt; Scannable for T {
 887    ...
 888}
 889&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 890&lt;p&gt;Ugh! Well, to be fair, we no longer have a &amp;quot;scannable&amp;quot; at this point. It&#x27;s more like a scan mode that tells us how memory should be compared according to a certain type. Let&#x27;s split the trait into two: one for the scan mode, and other for &amp;quot;things which are scannable&amp;quot;:&lt;&#x2F;p&gt;
 891&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub trait ScanMode {
 892    unsafe fn eq(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; bool;
 893    unsafe fn cmp(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; Ordering;
 894}
 895
 896pub unsafe trait Scannable {
 897    type Mode: ScanMode;
 898
 899    fn mem_view(&amp;amp;self) -&amp;gt; &amp;amp;[u8];
 900}
 901&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 902&lt;p&gt;Note that we have an associated &lt;code&gt;type Mode&lt;&#x2F;code&gt; which contains the corresponding &lt;code&gt;ScanMode&lt;&#x2F;code&gt;. If we used a trait bound such as &lt;code&gt;Scannable: ScanMode&lt;&#x2F;code&gt;, we&#x27;d be back to square one: it would inherit the method definitions that don&#x27;t use &lt;code&gt;&amp;amp;self&lt;&#x2F;code&gt; and thus cannot be used as trait objects.&lt;&#x2F;p&gt;
 903&lt;p&gt;With these changes, it is possible to implement &lt;code&gt;Scannable&lt;&#x2F;code&gt; for any &lt;code&gt;dyn Scannable&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
 904&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;unsafe impl&amp;lt;T: ScanMode + AsRef&amp;lt;dyn Scannable&amp;lt;Mode = Self&amp;gt;&amp;gt;&amp;gt; Scannable for T {
 905    type Mode = Self;
 906
 907    fn mem_view(&amp;amp;self) -&amp;gt; &amp;amp;[u8] {
 908        self.as_ref().mem_view()
 909    }
 910}
 911&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 912&lt;p&gt;We do have to adjust a few places of the code to account for both &lt;code&gt;Scannable&lt;&#x2F;code&gt; and &lt;code&gt;ScanMode&lt;&#x2F;code&gt;, but all in all, it&#x27;s pretty straightforward. Things like &lt;code&gt;Value&lt;&#x2F;code&gt; don&#x27;t need to store the &lt;code&gt;Scannable&lt;&#x2F;code&gt; anymore, just a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;. It also doesn&#x27;t need the &lt;code&gt;ScanMode&lt;&#x2F;code&gt;, because it&#x27;s not going to be scanning anything on its own. This applies transitively to &lt;code&gt;Region&lt;&#x2F;code&gt; which was holding a &lt;code&gt;Value&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
 913&lt;p&gt;&lt;code&gt;Value&lt;&#x2F;code&gt; &lt;em&gt;does&lt;&#x2F;em&gt; need to be updated to store the size of the region we are scanning for, however, because we need that information when running a subsequent scan. For all &lt;code&gt;Scan&lt;&#x2F;code&gt; that don&#x27;t have a explicit thing to scan for (like &lt;code&gt;Decreased&lt;&#x2F;code&gt;), the &lt;code&gt;size&lt;&#x2F;code&gt; also needs to be stored in them.&lt;&#x2F;p&gt;
 914&lt;p&gt;Despite all our efforts, we&#x27;re still unable to return an &lt;code&gt;Scannable&lt;&#x2F;code&gt; chosen at runtime.&lt;&#x2F;p&gt;
 915&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;fn prompt_user_for_scan() -&amp;gt; Scan&amp;lt;Box&amp;lt;dyn Scannable&amp;lt;Mode = ???&amp;gt;&amp;gt;&amp;gt; {
 916    todo!()
 917}
 918&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 919&lt;p&gt;As far as I can tell, there&#x27;s simply no way to specify that type. We want to return a type which is scannable, which has itself (which is also a &lt;code&gt;ScanMode&lt;&#x2F;code&gt;) as the corresponding mode. Even if we just tried to return the mode, we simply can&#x27;t, because it&#x27;s not object-safe. Is this the end of the road?&lt;&#x2F;p&gt;
 920&lt;h2 id=&quot;specifying-the-scan-mode&quot;&gt;Specifying the scan mode&lt;&#x2F;h2&gt;
 921&lt;p&gt;We need a way to pass an arbitrary scan mode to our &lt;code&gt;Scan&lt;&#x2F;code&gt;. This scan mode should go in tandem with &lt;code&gt;Scannable&lt;&#x2F;code&gt; types, because it would be unsafe otherwise. We&#x27;ve seen that using a type just doesn&#x27;t cut it. What else can we do?&lt;&#x2F;p&gt;
 922&lt;p&gt;Using an enumeration is a no-go, because I want users to be able to extend it further. I also would like to avoid having to update the &lt;code&gt;enum&lt;&#x2F;code&gt; and all the matches every time I come up with a different type combination. And it could get pretty complicated if I ever built something dynamically, such as letting the user combine different scans in one pass.&lt;&#x2F;p&gt;
 923&lt;p&gt;So what if we make &lt;code&gt;Scannable&lt;&#x2F;code&gt; return a value that implements the functions we need?&lt;&#x2F;p&gt;
 924&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub struct ScanMode {
 925    eq: unsafe fn(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; bool,
 926    cmp: unsafe fn(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; Ordering,
 927}
 928&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 929&lt;p&gt;It&#x27;s definitely… non-conventional. But hey, now we&#x27;re left with the &lt;code&gt;Scannable&lt;&#x2F;code&gt; trait, which is object-safe, and does not have any type parameters!&lt;&#x2F;p&gt;
 930&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub unsafe trait Scannable {
 931    fn mem_view(&amp;amp;self) -&amp;gt; &amp;amp;[u8];
 932    fn scan_mode(&amp;amp;self) -&amp;gt; ScanMode;
 933}
 934&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 935&lt;p&gt;It is a bit weird, but defining local functions and using those in the returned value is a nice way to keep things properly scoped:&lt;&#x2F;p&gt;
 936&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;macro_rules! impl_scannable_for_int {
 937    ( $( $ty:ty ),* ) =&amp;gt; {
 938        $(
 939            unsafe impl Scannable for $ty {
 940                fn mem_view(&amp;amp;self) -&amp;gt; &amp;amp;[u8] {
 941                    unsafe { std::slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::&amp;lt;$ty&amp;gt;()) }
 942                }
 943
 944                fn scan_mode(&amp;amp;self) -&amp;gt; ScanMode {
 945                    unsafe fn eq(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; bool {
 946                        ...
 947                    }
 948
 949                    unsafe fn cmp(left: &amp;amp;[u8], right: &amp;amp;[u8]) -&amp;gt; Ordering {
 950                        ...
 951                    }
 952
 953                    ScanMode { eq, cmp }
 954                }
 955            }
 956        )*
 957    };
 958}
 959&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
 960&lt;p&gt;Our &lt;code&gt;Scan&lt;&#x2F;code&gt; needs to store the &lt;code&gt;Scannable&lt;&#x2F;code&gt; type, and not just the memory, once again. For variants that don&#x27;t need any value, they can store the &lt;code&gt;ScanMode&lt;&#x2F;code&gt; and size instead.&lt;&#x2F;p&gt;
 961&lt;p&gt;Does this solution work? Yes! It&#x27;s possible to return a &lt;code&gt;Box&amp;lt;dyn Scannable&amp;gt;&lt;&#x2F;code&gt; from a function, and underneath, it may be using any type which is &lt;code&gt;Scannable&lt;&#x2F;code&gt;. Is this the best solution? Well, that&#x27;s hard to say. This is &lt;em&gt;one&lt;&#x2F;em&gt; of the possible solutions.&lt;&#x2F;p&gt;
 962&lt;p&gt;We have been going around in circles for quite some time now, so I&#x27;ll leave it there. It&#x27;s a solution, which may not be pretty, but it works. With these changes, the code is capable of completing all of the steps in the Cheat Engine tutorial up until point!&lt;&#x2F;p&gt;
 963&lt;h2 id=&quot;finale&quot;&gt;Finale&lt;&#x2F;h2&gt;
 964&lt;p&gt;If there&#x27;s one lesson to learn from this post, it&#x27;s that there is often no single correct solution to a problem. We could have approached the scan types in many, many ways (and we tried quite a few!), but in the end, choosing one option or the other comes down to your (sometimes self-imposed) requirements.&lt;&#x2F;p&gt;
 965&lt;p&gt;You may &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lonami&#x2F;memo&quot;&gt;obtain the code for this post&lt;&#x2F;a&gt; over at my GitHub. You can run &lt;code&gt;git checkout step4&lt;&#x2F;code&gt; after cloning the repository to get the right version of the code. The code has gone through a lot of iterations, and I&#x27;d still like to polish it a bit more, so it might slightly differ from the code presented in this entry.&lt;&#x2F;p&gt;
 966&lt;p&gt;If you feel adventurous, Cheat Engine has different options for scanning floating point types: &amp;quot;rounded (default)&amp;quot;, &amp;quot;rounded (extreme)&amp;quot;, and truncated. Optionally, it can scan for &amp;quot;simple values only&amp;quot;. You could go ahead and toy around with these!&lt;&#x2F;p&gt;
 967&lt;p&gt;We didn&#x27;t touch on types with different lengths, such as strings. You could support UTF-8, UTF-16, or arbitrary byte sequences. This post also didn&#x27;t cover scanning for multiple things at once, known as &amp;quot;groupscan commands&amp;quot;, although from what I can tell, these are just a nice way to scan for arbitrary byte sequences.&lt;&#x2F;p&gt;
 968&lt;p&gt;We also didn&#x27;t look into supporting different the same scan with different alignments. All these things may be worth exploring depending on your requirements. You could even get rid of such genericity and go with something way simpler. Supporting &lt;code&gt;i32&lt;&#x2F;code&gt;, &lt;code&gt;f32&lt;&#x2F;code&gt; and &lt;code&gt;f64&lt;&#x2F;code&gt; is enough to complete the Cheat Engine tutorial. But I wanted something more powerful, although my solution currently can&#x27;t scan for a sequence such as &amp;quot;exact type, unknown, exact matching the unknown&amp;quot;. So yeah.&lt;&#x2F;p&gt;
 969&lt;p&gt;In the &lt;a href=&quot;&#x2F;blog&#x2F;woce-5&quot;&gt;next post&lt;&#x2F;a&gt;, we&#x27;ll tackle the fifth step of the tutorial: Code finder. Cheat Engine attaches its debugger to the process for this one, and then replaces the instruction that performs the write with a different no-op so that nothing is written anymore. This will be quite the challenge!&lt;&#x2F;p&gt;
 970&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h3&gt;
 971&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
 972&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;ops&#x2F;trait.Drop.html#copy-and-drop-are-exclusive&quot;&gt;&lt;code&gt;Copy&lt;&#x2F;code&gt; and &lt;code&gt;Drop&lt;&#x2F;code&gt; are exclusive&lt;&#x2F;a&gt;. See also &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;error-index.html#E0184&quot;&gt;E0184&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
 973&lt;&#x2F;div&gt;
 974&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
 975&lt;p&gt;If you added more scan types that require additional bounds, make sure to add them too. For example, the &amp;quot;decreased by&amp;quot; scan requires the type to &lt;code&gt;impl Sub&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
 976&lt;&#x2F;div&gt;
 977&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
 978&lt;p&gt;This is a good time to remind you to read the documentation. It is of special importance when dealing with &lt;code&gt;unsafe&lt;&#x2F;code&gt; methods; I recommend reading it a couple times.&lt;&#x2F;p&gt;
 979&lt;&#x2F;div&gt;
 980&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
 981&lt;p&gt;Even with this option, it would not be a bad idea to make the trait &lt;code&gt;unsafe&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
 982&lt;&#x2F;div&gt;
 983&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
 984&lt;p&gt;Not for long. As we will find out later, this approach has its limitations.&lt;&#x2F;p&gt;
 985&lt;&#x2F;div&gt;
 986&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
 987&lt;p&gt;We can still perform the pointer dereference when we know it&#x27;s aligned. This would likely be an optimization, although it would definitely complicate the code more.&lt;&#x2F;p&gt;
 988&lt;&#x2F;div&gt;
 989&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
 990&lt;p&gt;It &lt;em&gt;would&lt;&#x2F;em&gt; work if you scanned for unknown values and then checked for decreased values repeatedly. But we can&#x27;t just leave exact scan broken!&lt;&#x2F;p&gt;
 991&lt;&#x2F;div&gt;
 992&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
 993&lt;p&gt;Unfortunately, this makes some optimizations harder or even impossible to perform. Providing specialized functions for types where the size is known at compile time could be worth doing. Programming is all tradeoffs.&lt;&#x2F;p&gt;
 994&lt;&#x2F;div&gt;
 995&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
 996&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2021&#x2F;02&#x2F;26&#x2F;const-generics-mvp-beta.html&quot;&gt;Rust 1.51&lt;&#x2F;a&gt;, which was not out at the time of writing, would make it a lot easier to allow scanning for fixed-length sequences of bytes, thanks to const generics.&lt;&#x2F;p&gt;
 997&lt;&#x2F;div&gt;
 998&lt;div class=&quot;footnote-definition&quot; id=&quot;10&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;10&lt;&#x2F;sup&gt;
 999&lt;p&gt;Workarounds do exist, such as &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;dyn-clone&quot;&gt;dtolnay&#x27;s &lt;code&gt;dyn-clone&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. But I would rather not go that route.&lt;&#x2F;p&gt;
1000&lt;&#x2F;div&gt;
1001</content>
1002	</entry>
1003	<entry xml:lang="en">
1004		<title>Writing our own Cheat Engine: Unknown initial value</title>
1005		<published>2021-02-19T00:00:00+00:00</published>
1006		<updated>2021-02-19T00:00:00+00:00</updated>
1007		<link href="https://lonami.dev/blog/woce-3/" type="text/html"/>
1008		<id>https://lonami.dev/blog/woce-3/</id>
1009		<content type="html">&lt;p&gt;This is part 3 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt;
1010&lt;ul&gt;
1011&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-1&quot;&gt;Part 1: Introduction&lt;&#x2F;a&gt; (start here if you&#x27;re new to the series!)&lt;&#x2F;li&gt;
1012&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-2&quot;&gt;Part 2: Exact Value scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1013&lt;li&gt;Part 3: Unknown initial value&lt;&#x2F;li&gt;
1014&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-4&quot;&gt;Part 4: Floating points&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1015&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-5&quot;&gt;Part 5: Code finder&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1016&lt;&#x2F;ul&gt;
1017&lt;p&gt;In part 2 we left off with a bit of a cliff-hanger. Our little program is now able to scan for an exact value, remember the couple hundred addresses pointing to said value, and perform subsequent scans to narrow the list of addresses down until we&#x27;re left with a handful of them.&lt;&#x2F;p&gt;
1018&lt;p&gt;However, it is not always the case that you have an exact value to work with. The best you can do in these cases is guess what the software might be storing. For example, it could be a floating point for your current movement speed in a game, or an integer for your current health.&lt;&#x2F;p&gt;
1019&lt;p&gt;The problem with this is that there are far too many possible locations storing our desired value. If you count misaligned locations, this means there is a different location to address every single byte in memory. A program with one megabyte of memory already has a &lt;em&gt;million&lt;&#x2F;em&gt; of addresses. Clearly, we need to do better than performing one million memory reads&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
1020&lt;p&gt;This post will shift focus a bit from using &lt;code&gt;winapi&lt;&#x2F;code&gt; to possible techniques to perform the various scans.&lt;&#x2F;p&gt;
1021&lt;h2 id=&quot;unknown-initial-value&quot;&gt;Unknown initial value&lt;&#x2F;h2&gt;
1022&lt;details open&gt;&lt;summary&gt;Cheat Engine Tutorial: Step 3&lt;&#x2F;summary&gt;
1023&lt;blockquote&gt;
1024&lt;p&gt;Ok, seeing that you&#x27;ve figured out how to find a value using exact value let&#x27;s move on to the next step.&lt;&#x2F;p&gt;
1025&lt;p&gt;First things first though. Since you are doing a new scan, you have to click on New Scan first, to start a new scan. (You may think this is straighforward, but you&#x27;d be surprised how many people get stuck on that step) I won&#x27;t be explaining this step again, so keep this in mind
1026Now that you&#x27;ve started a new scan, let&#x27;s continue&lt;&#x2F;p&gt;
1027&lt;p&gt;In the previous test we knew the initial value so we could do a exact value, but now we have a status bar where we don&#x27;t know the starting value.
1028We only know that the value is between 0 and 500. And each time you click &#x27;hit me&#x27; you lose some health. The amount you lose each time is shown above the status bar.&lt;&#x2F;p&gt;
1029&lt;p&gt;Again there are several different ways to find the value. (like doing a decreased value by... scan), but I&#x27;ll only explain the easiest. &amp;quot;Unknown initial value&amp;quot;, and decreased value.
1030Because you don&#x27;t know the value it is right now, a exact value wont do any good, so choose as scantype &#x27;Unknown initial value&#x27;, again, the value type is 4-bytes. (most windows apps use 4-bytes)click first scan and wait till it&#x27;s done.&lt;&#x2F;p&gt;
1031&lt;p&gt;When it is done click &#x27;hit me&#x27;. You&#x27;ll lose some of your health. (the amount you lost shows for a few seconds and then disappears, but you don&#x27;t need that)
1032Now go to Cheat Engine, and choose &#x27;Decreased Value&#x27; and click &#x27;Next Scan&#x27;
1033When that scan is done, click hit me again, and repeat the above till you only find a few.&lt;&#x2F;p&gt;
1034&lt;p&gt;We know the value is between 0 and 500, so pick the one that is most likely the address we need, and add it to the list.
1035Now change the health to 5000, to proceed to the next step.&lt;&#x2F;p&gt;
1036&lt;&#x2F;blockquote&gt;
1037&lt;&#x2F;details&gt;
1038&lt;h2 id=&quot;dense-memory-locations&quot;&gt;Dense memory locations&lt;&#x2F;h2&gt;
1039&lt;p&gt;The key thing to notice here is that, when we read memory from another process, we do so over &lt;em&gt;entire regions&lt;&#x2F;em&gt;. A memory region is represented by a starting offset, a size, and a bunch of other things like protection level.&lt;&#x2F;p&gt;
1040&lt;p&gt;When running the first scan for an unknown value, all we need to remember is the starting offset and size for every single region. All the candidate locations that could point to our value fall within this range, so it is enough for us to store the range definition, and not every location within it.&lt;&#x2F;p&gt;
1041&lt;p&gt;To gain a better understanding of what this means, let&#x27;s come up with a more specific scenario. With our current approach of doing things, we store an address (&lt;code&gt;usize&lt;&#x2F;code&gt;) for every location pointing to our desired value. In the case of unknown values, all locations are equally valid, since we don&#x27;t know what value they should point to yet, and any value they point to is good. With this representation, we would end up with a very large vector:&lt;&#x2F;p&gt;
1042&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let locations = vec![0x2000, 0x2001, ..., 0x20ff, 0x2100];
1043&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1044&lt;p&gt;This representation is dense. Every single number in the range &lt;code&gt;0x2000..=0x2100&lt;&#x2F;code&gt; is present. So why bother storing the values individually when the range is enough?:&lt;&#x2F;p&gt;
1045&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let locations = EntireRegion { range: 0x2000..=0x2100 };
1046&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1047&lt;p&gt;Much better! With two &lt;code&gt;usize&lt;&#x2F;code&gt;, one for the starting location and another for the end, we can indicate that we care about all the locations falling in that range.&lt;&#x2F;p&gt;
1048&lt;p&gt;In fact, some accessible memory regions immediately follow eachother, so we could even compact this further and merge regions which are together. But due to their potential differences with regards to protection levels, we will not attempt to merge regions.&lt;&#x2F;p&gt;
1049&lt;p&gt;We don&#x27;t want to get rid of the old way of storing locations, because once we start narrowing them down, we will want to go back to storing just a few candidates. To keep things tidy, let&#x27;s introduce a new &lt;code&gt;enum&lt;&#x2F;code&gt; representing either possibility:&lt;&#x2F;p&gt;
1050&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use std::ops::Range;
1051
1052pub enum CandidateLocations {
1053    Discrete {
1054        locations: Vec&amp;lt;usize&amp;gt;,
1055    },
1056    Dense {
1057        range: Range&amp;lt;usize&amp;gt;,
1058    }
1059}
1060&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1061&lt;p&gt;Let&#x27;s also introduce another &lt;code&gt;enum&lt;&#x2F;code&gt; to perform the different scan types. For the time being, we will only worry about looking for &lt;code&gt;i32&lt;&#x2F;code&gt; in memory:&lt;&#x2F;p&gt;
1062&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Scan {
1063    Exact(i32),
1064    Unknown,
1065}
1066&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1067&lt;h2 id=&quot;storing-scanned-values&quot;&gt;Storing scanned values&lt;&#x2F;h2&gt;
1068&lt;p&gt;When scanning for exact values, it&#x27;s not necessary to store the value found. We already know they&#x27;re all the same, for example, value &lt;code&gt;42&lt;&#x2F;code&gt;. However, if the value is unknown, we do need to store it so that we can compare it in a subsequent scan to see if the value is the same or it changed. This means the value can be &amp;quot;any within&amp;quot; the read memory chunk:&lt;&#x2F;p&gt;
1069&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Value {
1070    Exact(i32),
1071    AnyWithin(Vec&amp;lt;u8&amp;gt;),
1072}
1073&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1074&lt;p&gt;For every region in memory, there will be some candidate locations and a value (or value range) we need to compare against in subsequent scans:&lt;&#x2F;p&gt;
1075&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub struct Region {
1076    pub info: winapi::um::winnt::MEMORY_BASIC_INFORMATION,
1077    pub locations: CandidateLocations,
1078    pub value: Value,
1079}
1080&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1081&lt;p&gt;With all the data structures needed setup, we can finally refactor our old scanning code into a new method capable of dealing with all these cases. For brevity, I will omit the exact scan, as it remains mostly unchanged:&lt;&#x2F;p&gt;
1082&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use winapi::um::winnt::MEMORY_BASIC_INFORMATION;
1083
1084...
1085
1086&#x2F;&#x2F; inside `impl Process`
1087pub fn scan_regions(&amp;amp;self, regions: &amp;amp;[MEMORY_BASIC_INFORMATION], scan: Scan) -&amp;gt; Vec&amp;lt;Region&amp;gt; {
1088    regions
1089        .iter()
1090        .flat_map(|region| match scan {
1091            Scan::Exact(n) =&amp;gt; todo!(&amp;quot;old scan implementation&amp;quot;),
1092            Scan::Unknown =&amp;gt; {
1093                let base = region.BaseAddress as usize;
1094                match self.read_memory(region.BaseAddress as _, region.RegionSize) {
1095                    Ok(memory) =&amp;gt; Some(Region {
1096                        info: region.clone(),
1097                        locations: CandidateLocations::Dense {
1098                            range: base..base + region.RegionSize,
1099                        },
1100                        value: Value::AnyWithin(memory),
1101                    }),
1102                    Err(_) =&amp;gt; None,
1103                }
1104            }
1105        })
1106        .collect()
1107}
1108&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1109&lt;p&gt;Time to try it out!&lt;&#x2F;p&gt;
1110&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;impl CandidateLocations {
1111    pub fn len(&amp;amp;self) -&amp;gt; usize {
1112        match self {
1113            CandidateLocations::Discrete { locations } =&amp;gt; locations.len(),
1114            CandidateLocations::Dense { range } =&amp;gt; range.len(),
1115        }
1116    }
1117}
1118
1119...
1120
1121fn main() {
1122    &#x2F;&#x2F; -snip-
1123
1124    println!(&amp;quot;Scanning {} memory regions&amp;quot;, regions.len());
1125    let last_scan = process.scan_regions(&amp;amp;regions, Scan::Unknown);
1126    println!(
1127        &amp;quot;Found {} locations&amp;quot;,
1128        last_scan.iter().map(|r| r.locations.len()).sum::&amp;lt;usize&amp;gt;()
1129    );
1130}
1131&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1132&lt;pre&gt;&lt;code&gt;Scanning 88 memory regions
1133Found 3014656 locations
1134&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1135&lt;p&gt;If we consider misaligned locations, there is a lot of potential addresses where we could look for. Running the same scan on Cheat Engine yields &lt;code&gt;2,449,408&lt;&#x2F;code&gt; addresses, which is pretty close. It&#x27;s probably skipping some additional regions that we are considering. Emulating Cheat Engine to perfection is not a concern for us at the moment, so I&#x27;m not going to investigate what regions it actually uses.&lt;&#x2F;p&gt;
1136&lt;h2 id=&quot;comparing-scanned-values&quot;&gt;Comparing scanned values&lt;&#x2F;h2&gt;
1137&lt;p&gt;Now that we have performed the initial scan and have stored all the &lt;code&gt;CandidateLocations&lt;&#x2F;code&gt; and &lt;code&gt;Value&lt;&#x2F;code&gt;, we can re-implement the &amp;quot;next scan&amp;quot; step to handle any variant of our &lt;code&gt;Scan&lt;&#x2F;code&gt; enum. This enables us to mix-and-match any &lt;code&gt;Scan&lt;&#x2F;code&gt; mode in any order. For example, one could perform an exact scan, then one for decreased values, or start with unknown scan and scan for unchanged values.&lt;&#x2F;p&gt;
1138&lt;p&gt;The tutorial suggests using &amp;quot;decreased value&amp;quot; scan, so let&#x27;s start with that:&lt;&#x2F;p&gt;
1139&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub enum Scan {
1140    Exact(i32),
1141    Unknown,
1142    Decreased, &#x2F;&#x2F; new!
1143}
1144&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1145&lt;p&gt;Other scanning modes, such as decreased by a known amount rather than any decrease, increased, unchanged, changed and so on, are not very different from the &amp;quot;decreased&amp;quot; scan, so I won&#x27;t bore you with the details.&lt;&#x2F;p&gt;
1146&lt;p&gt;I will use a different method to perform a &amp;quot;rescan&amp;quot;, since the first one is a bit more special in that it doesn&#x27;t start with any previous values:&lt;&#x2F;p&gt;
1147&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rescan_regions(&amp;amp;self, regions: &amp;amp;[Region], scan: Scan) -&amp;gt; Vec&amp;lt;Region&amp;gt; {
1148    regions
1149        .iter()
1150        .flat_map(|region| match scan {
1151            Scan::Decreased =&amp;gt; {
1152                let mut locations = Vec::new();
1153                match region.locations {
1154                    CandidateLocations::Dense { range } =&amp;gt; {
1155                        match self.read_memory(range.start, range.end - range.start) {
1156                            Ok(memory) =&amp;gt; match region.value {
1157                                Value::AnyWithin(previous) =&amp;gt; {
1158                                    memory
1159                                        .windows(4)
1160                                        .zip(previous.windows(4))
1161                                        .enumerate()
1162                                        .step_by(4)
1163                                        .for_each(|(offset, (new, old))| {
1164                                            let new = i32::from_ne_bytes([
1165                                                new[0], new[1], new[2], new[3],
1166                                            ]);
1167                                            let old = i32::from_ne_bytes([
1168                                                old[0], old[1], old[2], old[3],
1169                                            ]);
1170                                            if new &amp;lt; old {
1171                                                locations.push(range.start + offset);
1172                                            }
1173                                        });
1174
1175                                    Some(Region {
1176                                        info: region.info.clone(),
1177                                        locations: CandidateLocations::Discrete { locations },
1178                                        value: Value::AnyWithin(memory),
1179                                    })
1180                                }
1181                                _ =&amp;gt; todo!(),
1182                            },
1183                            _ =&amp;gt; todo!(),
1184                        }
1185                    }
1186                    _ =&amp;gt; todo!(),
1187                }
1188            }
1189            _ =&amp;gt; todo!(),
1190        })
1191        .collect()
1192}
1193&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1194&lt;p&gt;If you&#x27;ve skimmed over that, I do not blame you. Here&#x27;s the summary: for every existing region, when executing the scan mode &amp;quot;decreased&amp;quot;, if the previous locations were dense, read the entire memory region. On success, if the previous values were a chunk of memory, iterate over the current and old memory at the same time, and for every aligned &lt;code&gt;i32&lt;&#x2F;code&gt;, if the new value is less, store it.&lt;&#x2F;p&gt;
1195&lt;p&gt;It&#x27;s also making me ill. Before I leave a mess on the floor, does it work?&lt;&#x2F;p&gt;
1196&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;std::thread::sleep(std::time::Duration::from_secs(10));
1197let last_scan = process.rescan_regions(&amp;amp;last_scan, Scan::Decreased);
1198println!(
1199    &amp;quot;Found {} locations&amp;quot;,
1200    last_scan.iter().map(|r| r.locations.len()).sum::&amp;lt;usize&amp;gt;()
1201);
1202&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1203&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;Found 3014656 locations
1204Found 177 locations
1205&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1206&lt;p&gt;Okay, great, let&#x27;s clean up this mess…&lt;&#x2F;p&gt;
1207&lt;h2 id=&quot;refactoring&quot;&gt;Refactoring&lt;&#x2F;h2&gt;
1208&lt;p&gt;Does it also make you uncomfortable to be writing something that you know will end up &lt;em&gt;huge&lt;&#x2F;em&gt; unless you begin refactoring other parts right now? I definitely feel that way. But I think it&#x27;s good discipline to push through with something that works first, even if it&#x27;s nasty, before going on a tangent. Now that we have the basic implementation working, let&#x27;s take on this monster before it eats us alive.&lt;&#x2F;p&gt;
1209&lt;p&gt;First things first, that method is inside an &lt;code&gt;impl&lt;&#x2F;code&gt; block. The deepest nesting level is 13. I almost have to turn around my chair to read the entire thing out!&lt;&#x2F;p&gt;
1210&lt;p&gt;Second, we&#x27;re nesting four matches. Three of them we care about: scan, candidate location, and value. If each of these &lt;code&gt;enum&lt;&#x2F;code&gt; has &lt;code&gt;S&lt;&#x2F;code&gt;, &lt;code&gt;C&lt;&#x2F;code&gt; and &lt;code&gt;V&lt;&#x2F;code&gt; variants respectively, writing each of these by hand will require &lt;code&gt;S * C * V&lt;&#x2F;code&gt; different implementations! Cheat Engine offers 10 different scans, I can think of at least 3 different ways to store candidate locations, and another 3 ways to store the values found. That&#x27;s &lt;code&gt;10 * 3 * 3 = 90&lt;&#x2F;code&gt; different combinations. I am not willing to write out all these&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, so we need to start introducing some abstractions. Just imagine what a monster function you would end with! The horror!&lt;&#x2F;p&gt;
1211&lt;p&gt;Third, why is the scan being executed in the process? This is something that should be done in the &lt;code&gt;impl Scan&lt;&#x2F;code&gt; instead!&lt;&#x2F;p&gt;
1212&lt;p&gt;Let&#x27;s begin the cleanup:&lt;&#x2F;p&gt;
1213&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rescan_regions(&amp;amp;self, regions: &amp;amp;[Region], scan: Scan) -&amp;gt; Vec&amp;lt;Region&amp;gt; {
1214    todo!()
1215}
1216&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1217&lt;p&gt;I already feel ten times better.&lt;&#x2F;p&gt;
1218&lt;p&gt;Now, this method will unconditionally read the entire memory region, even if the scan or the previous candidate locations don&#x27;t need it&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. In the worst case with a single discrete candidate location, we will be reading a very large chunk of memory when we could have read just the 4 bytes needed for the &lt;code&gt;i32&lt;&#x2F;code&gt;. On the bright side, if there &lt;em&gt;are&lt;&#x2F;em&gt; more locations in this memory region, we will get read of them at the same time&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. So even if we&#x27;re moving more memory around all the time, it isn&#x27;t &lt;em&gt;too&lt;&#x2F;em&gt; bad.&lt;&#x2F;p&gt;
1219&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;regions
1220    .iter()
1221    .flat_map(
1222        |region| match self.read_memory(region.info.BaseAddress as _, region.info.RegionSize) {
1223            Ok(memory) =&amp;gt; todo!(),
1224            Err(err) =&amp;gt; {
1225                eprintln!(
1226                    &amp;quot;Failed to read {} bytes at {:?}: {}&amp;quot;,
1227                    region.info.RegionSize, region.info.BaseAddress, err,
1228                );
1229                None
1230            }
1231        },
1232    )
1233    .collect()
1234&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1235&lt;p&gt;Great! If reading memory succeeds, we want to rerun the scan:&lt;&#x2F;p&gt;
1236&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;Ok(memory) =&amp;gt; Some(scan.rerun(region, memory)),
1237&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1238&lt;p&gt;The rerun will live inside &lt;code&gt;impl Scan&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
1239&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rerun(&amp;amp;self, region: &amp;amp;Region, memory: Vec&amp;lt;u8&amp;gt;) -&amp;gt; Region {
1240    match self {
1241        Scan::Exact(_) =&amp;gt; self.run(region.info.clone(), memory),
1242        Scan::Unknown =&amp;gt; region.clone(),
1243        Scan::Decreased =&amp;gt; todo!(),
1244    }
1245}
1246&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1247&lt;p&gt;An exact scan doesn&#x27;t care about any previous values, so it behaves like a first scan. The first scan is done by the &lt;code&gt;run&lt;&#x2F;code&gt; function (it contains the implementation factored out of the &lt;code&gt;Process::scan_regions&lt;&#x2F;code&gt; method), which only needs the region information and the current memory chunk we just read.&lt;&#x2F;p&gt;
1248&lt;p&gt;The unknown scan leaves the region unchanged: any value stored is still valid, because it is unknown what we&#x27;re looking for.&lt;&#x2F;p&gt;
1249&lt;p&gt;The decreased scan will have to iterate over all the candidate locations, and compare them with the current memory chunk. But this time, we&#x27;ll abstract this iteration too:&lt;&#x2F;p&gt;
1250&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;impl Region {
1251    fn iter_locations&amp;lt;&#x27;a&amp;gt;(
1252        &amp;amp;&#x27;a self,
1253        new_memory: &amp;amp;&#x27;a [u8],
1254    ) -&amp;gt; impl Iterator&amp;lt;Item = (usize, i32, i32)&amp;gt; + &#x27;a {
1255        match &amp;amp;self.locations {
1256            CandidateLocations::Dense { range } =&amp;gt; range.clone().step_by(4).map(move |addr| {
1257                let old = self.value_at(addr);
1258                let new = i32::from_ne_bytes([
1259                    new_memory[0],
1260                    new_memory[1],
1261                    new_memory[2],
1262                    new_memory[3],
1263                ]);
1264                (addr, old, new)
1265            }),
1266            _ =&amp;gt; todo!(),
1267        }
1268    }
1269}
1270&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1271&lt;p&gt;For a dense candidate location, we iterate over all the 4-aligned addresses (fast scan for &lt;code&gt;i32&lt;&#x2F;code&gt; values), and yield &lt;code&gt;(current address, old value, new value)&lt;&#x2F;code&gt;. This way, the &lt;code&gt;Scan&lt;&#x2F;code&gt; can do anything it wants with the old and new values, and if it finds a match, it can use the address.&lt;&#x2F;p&gt;
1272&lt;p&gt;The &lt;code&gt;value_at&lt;&#x2F;code&gt; method will deal with all the &lt;code&gt;Value&lt;&#x2F;code&gt; variants:&lt;&#x2F;p&gt;
1273&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;fn value_at(&amp;amp;self, addr: usize) -&amp;gt; i32 {
1274    match &amp;amp;self.value {
1275        Value::AnyWithin(chunk) =&amp;gt; {
1276            let base = addr - self.info.BaseAddress as usize;
1277            let bytes = &amp;amp;chunk[base..base + 4];
1278            i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
1279        }
1280        _ =&amp;gt; todo!(),
1281    }
1282}
1283&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1284&lt;p&gt;This way, &lt;code&gt;iter_locations&lt;&#x2F;code&gt; can easily use any value type. With this, we have all &lt;code&gt;enum&lt;&#x2F;code&gt; covered: &lt;code&gt;Scan&lt;&#x2F;code&gt; in &lt;code&gt;rerun&lt;&#x2F;code&gt;, &lt;code&gt;CandidateLocation&lt;&#x2F;code&gt; in &lt;code&gt;iter_locations&lt;&#x2F;code&gt;, and &lt;code&gt;Value&lt;&#x2F;code&gt; in &lt;code&gt;value_at&lt;&#x2F;code&gt;. Now we can add as many variants as we want, and we will only need to update a single &lt;code&gt;match&lt;&#x2F;code&gt; arm for each of them. Let&#x27;s implement &lt;code&gt;Scan::Decreased&lt;&#x2F;code&gt; and try it out:&lt;&#x2F;p&gt;
1285&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn rerun(&amp;amp;self, region: &amp;amp;Region, memory: Vec&amp;lt;u8&amp;gt;) -&amp;gt; Region {
1286    match self {
1287        Scan::Decreased =&amp;gt; Region {
1288            info: region.info.clone(),
1289            locations: CandidateLocations::Discrete {
1290                locations: region
1291                    .iter_locations(&amp;amp;memory)
1292                    .flat_map(|(addr, old, new)| if new &amp;lt; old { Some(addr) } else { None })
1293                    .collect(),
1294            },
1295            value: Value::AnyWithin(memory),
1296        },,
1297    }
1298}
1299&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1300&lt;pre&gt;&lt;code&gt;Found 3014656 locations
1301Found 223791 locations
1302&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1303&lt;p&gt;Hmm… before we went down from &lt;code&gt;3014656&lt;&#x2F;code&gt; to &lt;code&gt;177&lt;&#x2F;code&gt; locations, and now we went down to &lt;code&gt;223791&lt;&#x2F;code&gt;. Where did we go wrong?&lt;&#x2F;p&gt;
1304&lt;p&gt;After spending several hours on this, I can tell you where we went wrong. &lt;code&gt;iter_locations&lt;&#x2F;code&gt; is always accessing the memory range &lt;code&gt;0..4&lt;&#x2F;code&gt;, and not the right address. Here&#x27;s the fix:&lt;&#x2F;p&gt;
1305&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;CandidateLocations::Dense { range } =&amp;gt; range.clone().step_by(4).map(move |addr| {
1306    let old = self.value_at(addr);
1307    let base = addr - self.info.BaseAddress as usize;
1308    let bytes = &amp;amp;new_memory[base..base + 4];
1309    let new = i32::from_ne_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
1310    (addr, old, new)
1311}),
1312&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1313&lt;h2 id=&quot;going-beyond&quot;&gt;Going beyond&lt;&#x2F;h2&gt;
1314&lt;p&gt;Let&#x27;s take a look at other possible &lt;code&gt;Scan&lt;&#x2F;code&gt; types. Cheat Engine supports the following initial scan types:&lt;&#x2F;p&gt;
1315&lt;ul&gt;
1316&lt;li&gt;Exact Value&lt;&#x2F;li&gt;
1317&lt;li&gt;Bigger than…&lt;&#x2F;li&gt;
1318&lt;li&gt;Smaller than…&lt;&#x2F;li&gt;
1319&lt;li&gt;Value between…&lt;&#x2F;li&gt;
1320&lt;li&gt;Unknown initial value&lt;&#x2F;li&gt;
1321&lt;&#x2F;ul&gt;
1322&lt;p&gt;&amp;quot;Bigger than&amp;quot; and &amp;quot;Smaller than&amp;quot; can both be represented by &amp;quot;Value between&amp;quot;, so it&#x27;s pretty much just three.&lt;&#x2F;p&gt;
1323&lt;p&gt;For subsequent scans, in addition to the scan types described above, we find:&lt;&#x2F;p&gt;
1324&lt;ul&gt;
1325&lt;li&gt;Increased value&lt;&#x2F;li&gt;
1326&lt;li&gt;Increased value by…&lt;&#x2F;li&gt;
1327&lt;li&gt;Decreased value&lt;&#x2F;li&gt;
1328&lt;li&gt;Decreased value by…&lt;&#x2F;li&gt;
1329&lt;li&gt;Changed value&lt;&#x2F;li&gt;
1330&lt;li&gt;Unchanged value&lt;&#x2F;li&gt;
1331&lt;&#x2F;ul&gt;
1332&lt;p&gt;Not only does Cheat Engine provide all of these scans, but all of them can also be negated. For example, &amp;quot;find values that were not increased by 7&amp;quot;. One could imagine to also support things like &amp;quot;increased value by range&amp;quot;. For the increased and decreased scans, Cheat Engine also supports &amp;quot;at least xx%&amp;quot;, so that if the value changed within the specified percentage interval, it will be considered.&lt;&#x2F;p&gt;
1333&lt;p&gt;What about &lt;code&gt;CandidateLocations&lt;&#x2F;code&gt;? I can&#x27;t tell you how Cheat Engine stores these, but I can tell you that &lt;code&gt;CandidateLocations::Discrete&lt;&#x2F;code&gt; can still be quite inefficient. Imagine you&#x27;ve started with a scan for unknown values and then ran a scan for unchanged valueus. Most values in memory will have been unchanged, but with our current implementation, we are now storing an entire &lt;code&gt;usize&lt;&#x2F;code&gt; address for each of these. One option would be to introduce &lt;code&gt;CandidateLocations::Sparse&lt;&#x2F;code&gt;, which would be a middle ground. You could implement it like &lt;code&gt;Dense&lt;&#x2F;code&gt; and include a vector of booleans telling you which values to consider, or go smaller and use a bitstring or bit vector. You could use a sparse vector data structure.&lt;&#x2F;p&gt;
1334&lt;p&gt;&lt;code&gt;Value&lt;&#x2F;code&gt; is very much like &lt;code&gt;CandidateLocations&lt;&#x2F;code&gt;, except that it stores a value to compare against and not an address. Here we can either have an exact value, or an older copy of the memory. Again, keeping a copy of the entire memory chunk when all we need is a handful of values is inefficient. You could keep a mapping from addresses to values if you don&#x27;t have too many. Or you could shrink and fragment the copied memory in a more optimal way. There&#x27;s a lot of room for improvement!&lt;&#x2F;p&gt;
1335&lt;p&gt;What if, despite all of the efforts above, we still don&#x27;t have enough RAM to store all this information? The Cheat Engine Tutorial doesn&#x27;t use a lot of memory, but as soon as you try scanning bigger programs, like games, you may find yourself needing several gigabytes worth of memory to remember all the found values in order to compare them in subsequent scans. You may even need to consider dumping all the regions to a file and read from it to run the comparisons. For example, running a scan for &amp;quot;unknown value&amp;quot; in Cheat Engine brings its memory up by the same amount of memory used by the process scanned (which makes sense), but as soon as I ran a scan for &amp;quot;unchanged value&amp;quot; over the misaligned values, Cheat Engine&#x27;s disk usage skyrocketed to 1GB&#x2F;s (!) for several seconds on my SSD. After it finished, memory usage went down to normal. It was very likely writing out all candidate locations to disk.&lt;&#x2F;p&gt;
1336&lt;h2 id=&quot;finale&quot;&gt;Finale&lt;&#x2F;h2&gt;
1337&lt;p&gt;There is a lot of things to learn from Cheat Engine just by observing its behaviour, and we&#x27;re only scratching its surface.&lt;&#x2F;p&gt;
1338&lt;p&gt;In the &lt;a href=&quot;&#x2F;blog&#x2F;woce-4&quot;&gt;next post&lt;&#x2F;a&gt;, we&#x27;ll tackle the fourth step of the tutorial: Floating points. So far, we have only been working with &lt;code&gt;i32&lt;&#x2F;code&gt; for simplicity. We will need to update our code to be able to account for different data types, which will make it easy to support other types like &lt;code&gt;i16&lt;&#x2F;code&gt;, &lt;code&gt;i64&lt;&#x2F;code&gt;, or even strings, represented as an arbitrary sequence of bytes.&lt;&#x2F;p&gt;
1339&lt;p&gt;As usual, you can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lonami&#x2F;memo&quot;&gt;obtain the code for this post&lt;&#x2F;a&gt; over at my GitHub. You can run &lt;code&gt;git checkout step3&lt;&#x2F;code&gt; after cloning the repository to get the right version of the code. This version is a bit cleaner than the one presented in the blog, and contains some of the things described in the &lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;woce-3&#x2F;#going-beyond&quot;&gt;Going beyond&lt;&#x2F;a&gt; section. Until next time!&lt;&#x2F;p&gt;
1340&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h3&gt;
1341&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
1342&lt;p&gt;Well, technically, we will perform a million memory reads&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The issue here is the million calls to &lt;code&gt;ReadProcessMemory&lt;&#x2F;code&gt;, not reading memory per se.&lt;&#x2F;p&gt;
1343&lt;&#x2F;div&gt;
1344&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
1345&lt;p&gt;Not currently. After a basic implementation works, writing each implementation by hand and fine-tuning them by treating each of them as a special case could yield significant speed improvements. So although it would be a lot of work, this option shouldn&#x27;t be ruled out completely.&lt;&#x2F;p&gt;
1346&lt;&#x2F;div&gt;
1347&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
1348&lt;p&gt;You could ask the candidate locations where one should read, which would still keep the code reasonably simple.&lt;&#x2F;p&gt;
1349&lt;&#x2F;div&gt;
1350&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
1351&lt;p&gt;You could also optimize for this case by determining both the smallest and largest address, and reading enough to cover them both. Or apply additional heuristics to only do so if the ratio of the size you&#x27;re reading compared to the size you need isn&#x27;t too large and abort the joint read otherwise. There is a lot of room for optimization here.&lt;&#x2F;p&gt;
1352&lt;&#x2F;div&gt;
1353&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
1354&lt;p&gt;(A footnote in a footnote?) The machine registers, memory cache and compiler will all help lower this cost, so the generated executable might not actually need that many reads from RAM. But that&#x27;s getting way too deep into the details now.&lt;&#x2F;p&gt;
1355&lt;&#x2F;div&gt;
1356</content>
1357	</entry>
1358	<entry xml:lang="en">
1359		<title>Writing our own Cheat Engine: Exact Value scanning</title>
1360		<published>2021-02-12T00:00:00+00:00</published>
1361		<updated>2021-02-19T00:00:00+00:00</updated>
1362		<link href="https://lonami.dev/blog/woce-2/" type="text/html"/>
1363		<id>https://lonami.dev/blog/woce-2/</id>
1364		<content type="html">&lt;p&gt;This is part 2 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt;
1365&lt;ul&gt;
1366&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-1&quot;&gt;Part 1: Introduction&lt;&#x2F;a&gt; (start here if you&#x27;re new to the series!)&lt;&#x2F;li&gt;
1367&lt;li&gt;Part 2: Exact Value scanning&lt;&#x2F;li&gt;
1368&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-3&quot;&gt;Part 3: Unknown initial value&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1369&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-4&quot;&gt;Part 4: Floating points&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1370&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-5&quot;&gt;Part 5: Code finder&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1371&lt;&#x2F;ul&gt;
1372&lt;p&gt;In the introduction, we spent a good deal of time enumerating all running processes just so we could find out the pid we cared about. With the pid now in our hands, we can do pretty much anything to its corresponding process.&lt;&#x2F;p&gt;
1373&lt;p&gt;It&#x27;s now time to read the process&#x27; memory and write to it. If our process was a single-player game, this would enable us to do things like setting a very high value on the player&#x27;s current health pool, making us invincible. This technique will often not work for multi-player games, because the server likely knows your true current health (the most you could probably do is make the client render an incorrect value). However, if the server is crappy and it trusts the client, then you&#x27;re still free to mess around with your current health.&lt;&#x2F;p&gt;
1374&lt;p&gt;Even if we don&#x27;t want to write to the process&#x27; memory, reading is still very useful. Maybe you could enhance your experience by making a custom overlay that displays useful information, or something that makes noise if it detects the life is too low, or even simulating a keyboard event to automatically recover some mana when you&#x27;re running low.&lt;&#x2F;p&gt;
1375&lt;p&gt;Be warned about anti-cheat systems. Anything beyond a basic game is likely to have some protection measures in place, making the analysis more difficult (perhaps the values are scrambled in memory), or even pinging the server if it detects something fishy.&lt;&#x2F;p&gt;
1376&lt;p&gt;&lt;strong&gt;I am not responsible for any bans!&lt;&#x2F;strong&gt; Use your brain before messing with online games, and don&#x27;t ruin the fun for everyone else. If you get caught for cheating, I don&#x27;t want to know about it.&lt;&#x2F;p&gt;
1377&lt;p&gt;Now that all &lt;a href=&quot;https:&#x2F;&#x2F;www.urbandictionary.com&#x2F;define.php?term=script%20kiddie&quot;&gt;script kiddies&lt;&#x2F;a&gt; have left the room, let&#x27;s proceed with the post.&lt;&#x2F;p&gt;
1378&lt;h2 id=&quot;exact-value-scanning&quot;&gt;Exact Value scanning&lt;&#x2F;h2&gt;
1379&lt;details open&gt;&lt;summary&gt;Cheat Engine Tutorial: Step 2&lt;&#x2F;summary&gt;
1380&lt;blockquote&gt;
1381&lt;p&gt;Now that you have opened the tutorial with Cheat Engine let&#x27;s get on with the next step.&lt;&#x2F;p&gt;
1382&lt;p&gt;You can see at the bottom of this window is the text Health: xxx. Each time you click &#x27;Hit me&#x27; your health gets decreased.&lt;&#x2F;p&gt;
1383&lt;p&gt;To get to the next step you have to find this value and change it to 1000&lt;&#x2F;p&gt;
1384&lt;p&gt;To find the value there are different ways, but I&#x27;ll tell you about the easiest, &#x27;Exact Value&#x27;: First make sure value type is set to at least 2-bytes or 4-bytes. 1-byte will also work, but you&#x27;ll run into an easy to fix problem when you&#x27;ve found the address and want to change it. The 8-byte may perhaps works if the bytes after the address are 0, but I wouldn&#x27;t take the bet. Single, double, and the other scans just don&#x27;t work, because they store the value in a different way.&lt;&#x2F;p&gt;
1385&lt;p&gt;When the value type is set correctly, make sure the scantype is set to &#x27;Exact Value&#x27;. Then fill in the number your health is in the value box. And click &#x27;First Scan&#x27;. After a while (if you have a extremely slow pc) the scan is done and the results are shown in the list on the left&lt;&#x2F;p&gt;
1386&lt;p&gt;If you find more than 1 address and you don&#x27;t know for sure which address it is, click &#x27;Hit me&#x27;, fill in the new health value into the value box, and click &#x27;Next Scan&#x27;. Repeat this until you&#x27;re sure you&#x27;ve found it. (that includes that there&#x27;s only 1 address in the list.....)&lt;&#x2F;p&gt;
1387&lt;p&gt;Now double click the address in the list on the left. This makes the address pop-up in the list at the bottom, showing you the current value. Double click the value, (or select it and press enter), and change the value to 1000.&lt;&#x2F;p&gt;
1388&lt;p&gt;If everything went ok the next button should become enabled, and you&#x27;re ready for the next step.&lt;&#x2F;p&gt;
1389&lt;p&gt;Note: If you did anything wrong while scanning, click &amp;quot;New Scan&amp;quot; and repeat the scanning again. Also, try playing around with the value and click &#x27;hit me&#x27;&lt;&#x2F;p&gt;
1390&lt;&#x2F;blockquote&gt;
1391&lt;&#x2F;details&gt;
1392&lt;h2 id=&quot;our-first-scan&quot;&gt;Our First Scan&lt;&#x2F;h2&gt;
1393&lt;p&gt;The Cheat Engine tutorial talks about &amp;quot;value types&amp;quot; and &amp;quot;scan types&amp;quot; like &amp;quot;exact value&amp;quot;.&lt;&#x2F;p&gt;
1394&lt;p&gt;The &lt;strong&gt;value types&lt;&#x2F;strong&gt; will help us narrow down &lt;em&gt;what&lt;&#x2F;em&gt; we&#x27;re looking for. For example, the integer type &lt;code&gt;i32&lt;&#x2F;code&gt; is represented in memory as 32 bits, or 4 bytes. However, &lt;code&gt;f32&lt;&#x2F;code&gt; is &lt;em&gt;also&lt;&#x2F;em&gt; represented by 4 bytes, and so is &lt;code&gt;u32&lt;&#x2F;code&gt;. Or perhaps the 4 bytes represent RGBA values of a color! So any 4 bytes in memory can be interpreted in many ways, and it&#x27;s up to us to decide which way we interpret the bytes in.&lt;&#x2F;p&gt;
1395&lt;p&gt;When programming, numbers which are 32-bit wide are common, as they&#x27;re a good (and fast) size to work with. Scanning for this type is often a good bet. For positive numbers, &lt;code&gt;i32&lt;&#x2F;code&gt; is represented the same as &lt;code&gt;u32&lt;&#x2F;code&gt; in memory, so even if the value turns out to not be signed, the scan is likely to work. Focusing on &lt;code&gt;i32&lt;&#x2F;code&gt; will save us from scanning for &lt;code&gt;f32&lt;&#x2F;code&gt; or even other types, like interpreting 8 bytes for &lt;code&gt;i64&lt;&#x2F;code&gt;, &lt;code&gt;f64&lt;&#x2F;code&gt;, or less bytes like &lt;code&gt;i16&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
1396&lt;p&gt;The &lt;strong&gt;scan types&lt;&#x2F;strong&gt; will help us narrow down &lt;em&gt;how&lt;&#x2F;em&gt; we&#x27;re looking for a value. Scanning for an exact value means what you think it does: interpret all 4 bytes in the process&#x27; memory as our value type, and check if they exactly match our value. This will often yield a lot of candidates, but it will be enough to get us started. Variations of the exact scan include checking for all values below a threshold, above, in between, or even just… unknown.&lt;&#x2F;p&gt;
1397&lt;p&gt;What&#x27;s the point of scanning for unknown values if &lt;em&gt;everything&lt;&#x2F;em&gt; in memory is unknown? Sometimes you don&#x27;t have a concrete value. Maybe your health pool is a bar and it nevers tell you how much health you actually have, just a visual indicator of your percentage left, even if the health is not stored as a percentage. As we will find later on, scanning for unknown values is more useful than it might appear at first.&lt;&#x2F;p&gt;
1398&lt;p&gt;We can access the memory of our own program by guessing random pointers and trying to read from them. But Windows isolates the memory of each program, so no pointer we could ever guess will let us read from the memory of another process. Luckily for us, searching for &amp;quot;read process memory winapi&amp;quot; leads us to the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;memoryapi&#x2F;nf-memoryapi-readprocessmemory&quot;&gt;&lt;code&gt;ReadProcessMemory&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function. Spot on.&lt;&#x2F;p&gt;
1399&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn read_memory(&amp;amp;self, addr: usize, n: usize) -&amp;gt; io::Result&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt; {
1400    todo!()
1401}
1402&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1403&lt;p&gt;Much like trying to dereference a pointer pointing to released memory or even null, reading from an arbitrary address can fail for the same reasons (and more). We will want to signal this with &lt;code&gt;io::Result&lt;&#x2F;code&gt;. It&#x27;s funny to note that, even though we&#x27;re doing something that seems wildly unsafe (reading arbitrary memory, even if the other process is mutating it at the same time), the function is perfectly safe. If we cannot read something, it will return &lt;code&gt;Err&lt;&#x2F;code&gt;, but if it succeeds, it has taken a snapshot of the memory of the process, and the returned value will be correctly initialized.&lt;&#x2F;p&gt;
1404&lt;p&gt;The function will be defined inside our &lt;code&gt;impl Process&lt;&#x2F;code&gt;, since it conveniently holds an open handle to the process in question. It takes &lt;code&gt;&amp;amp;self&lt;&#x2F;code&gt;, because we do not need to mutate anything in the &lt;code&gt;Process&lt;&#x2F;code&gt; instance. After adding the &lt;code&gt;memoryapi&lt;&#x2F;code&gt; feature to &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, we can perform the call:&lt;&#x2F;p&gt;
1405&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let mut buffer = Vec::&amp;lt;u8&amp;gt;::with_capacity(n);
1406let mut read = 0;
1407
1408&#x2F;&#x2F; SAFETY: the buffer points to valid memory, and the buffer size is correctly set.
1409if unsafe {
1410    winapi::um::memoryapi::ReadProcessMemory(
1411        self.handle.as_ptr(),
1412        addr as *const _,
1413        buffer.as_mut_ptr().cast(),
1414        buffer.capacity(),
1415        &amp;amp;mut read,
1416    )
1417} == FALSE
1418{
1419    Err(io::Error::last_os_error())
1420} else {
1421    &#x2F;&#x2F; SAFETY: the call succeeded and `read` contains the amount of bytes written.
1422    unsafe { buffer.set_len(read as usize) };
1423    Ok(buffer)
1424}
1425&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1426&lt;p&gt;Great! But the address space is somewhat large. 64 bits large. Eighteen quintillion, four hundred and forty-six quadrillion, seven hundred and forty-four trillion, seventy-three billion, seven hundred and nine million, five hundred and fifty-one thousand, six hundred and sixteen&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; large. You gave up reading that, didn&#x27;t you? Anyway, 18&#x27;446&#x27;744&#x27;073&#x27;709&#x27;551&#x27;616 is a &lt;em&gt;big&lt;&#x2F;em&gt; number.&lt;&#x2F;p&gt;
1427&lt;p&gt;I am not willing to wait for the program to scan over so many values. I don&#x27;t even have 16 &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Orders_of_magnitude_(data)&quot;&gt;exbibytes&lt;&#x2F;a&gt; of RAM installed on my laptop yet&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;! What&#x27;s up with that?&lt;&#x2F;p&gt;
1428&lt;h2 id=&quot;memory-regions&quot;&gt;Memory regions&lt;&#x2F;h2&gt;
1429&lt;p&gt;The program does not actually have all that memory allocated (surprise!). Random-guessing an address is extremely likely to point out to invalid memory. Reading from the start of the address space all the way to the end would not be any better. And we &lt;strong&gt;need&lt;&#x2F;strong&gt; to do better.&lt;&#x2F;p&gt;
1430&lt;p&gt;We need to query for the memory regions allocated to the program. For this purpose we can use &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;memoryapi&#x2F;nf-memoryapi-virtualqueryex&quot;&gt;&lt;code&gt;VirtualQueryEx&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
1431&lt;blockquote&gt;
1432&lt;p&gt;Retrieves information about a range of pages within the virtual address space of a specified process.&lt;&#x2F;p&gt;
1433&lt;&#x2F;blockquote&gt;
1434&lt;p&gt;We have enumerated things before, and this function is not all that different.&lt;&#x2F;p&gt;
1435&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;fn memory_regions(&amp;amp;self) -&amp;gt; io::Result&amp;lt;winapi::um::winnt::MEMORY_BASIC_INFORMATION&amp;gt; {
1436    let mut info = MaybeUninit::uninit();
1437
1438    &#x2F;&#x2F; SAFETY: the info structure points to valid memory.
1439    let written = unsafe {
1440        winapi::um::memoryapi::VirtualQueryEx(
1441            self.handle.as_ptr(),
1442            std::ptr::null(),
1443            info.as_mut_ptr(),
1444            mem::size_of::&amp;lt;winapi::um::winnt::MEMORY_BASIC_INFORMATION&amp;gt;(),
1445        )
1446    };
1447    if written == 0 {
1448        Err(io::Error::last_os_error())
1449    } else {
1450        &#x2F;&#x2F; SAFETY: a non-zero amount was written to the structure
1451        Ok(unsafe { info.assume_init() })
1452    }
1453}
1454&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1455&lt;p&gt;We start with a base address of zero&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; (&lt;code&gt;std::ptr::null()&lt;&#x2F;code&gt;), and ask the function to tell us what&#x27;s in there. Let&#x27;s try it out, with the &lt;code&gt;impl-debug&lt;&#x2F;code&gt; crate feature in &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
1456&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;dbg!(process.memory_regions());
1457&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1458&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
1459Compiling memo v0.1.0
1460
1461error[E0277]: `winapi::um::winnt::MEMORY_BASIC_INFORMATION` doesn&#x27;t implement `std::fmt::Debug`
1462   --&amp;gt; src\main.rs:185:5
1463    |
1464185 |     dbg!(process.memory_regions());
1465    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `winapi::um::winnt::MEMORY_BASIC_INFORMATION` cannot be formatted using `{:?}` because it doesn&#x27;t implement `std::fmt::Debug`
1466&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1467&lt;p&gt;That&#x27;s annoying. It seems not everything has an &lt;code&gt;impl std::fmt::Debug&lt;&#x2F;code&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;retep998&#x2F;winapi-rs&#x2F;issues&#x2F;548#issuecomment-355278090&quot;&gt;you&#x27;re supposed to send a PR&lt;&#x2F;a&gt; if you want it to have debug, even if the &lt;code&gt;impl-debug&lt;&#x2F;code&gt; feature is set. I&#x27;m surprised they don&#x27;t auto-generate all of this and have to rely on manually adding &lt;code&gt;Debug&lt;&#x2F;code&gt; as needed? Oh well, let&#x27;s get rid of the feature and print it out ourselves:&lt;&#x2F;p&gt;
1468&lt;pre&gt;&lt;code&gt;eprintln!(
1469    &amp;quot;Region:
1470    BaseAddress: {:?}
1471    AllocationBase: {:?}
1472    AllocationProtect: {:?}
1473    RegionSize: {:?}
1474    State: {:?}
1475    Protect: {:?}
1476    Type: {:?}&amp;quot;,
1477    region.BaseAddress,
1478    region.AllocationBase,
1479    region.AllocationProtect,
1480    region.RegionSize,
1481    region.State,
1482    region.Protect,
1483    region.Type,
1484);
1485&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1486&lt;p&gt;Hopefully we don&#x27;t need to do this often:&lt;&#x2F;p&gt;
1487&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
1488   Compiling memo v0.1.0
1489    Finished dev [unoptimized + debuginfo] target(s) in 0.60s
1490     Running `target\debug\memo.exe`
1491
1492Region:
1493    BaseAddress: 0x0
1494    AllocationBase: 0x0
1495    AllocationProtect: 0
1496    RegionSize: 65536
1497    State: 65536
1498    Protect: 1
1499    Type: 0
1500&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1501&lt;p&gt;Awesome! There is a region at &lt;code&gt;null&lt;&#x2F;code&gt;, and the &lt;code&gt;AllocationProtect&lt;&#x2F;code&gt; of zero indicates that &amp;quot;the caller does not have access&amp;quot; when the region was created. However, &lt;code&gt;Protect&lt;&#x2F;code&gt; is &lt;code&gt;1&lt;&#x2F;code&gt;, and that is the &lt;em&gt;current&lt;&#x2F;em&gt; protection level. A value of one indicates &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;memory&#x2F;memory-protection-constants&quot;&gt;&lt;code&gt;PAGE_NOACCESS&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
1502&lt;blockquote&gt;
1503&lt;p&gt;Disables all access to the committed region of pages. An attempt to read from, write to, or execute the committed region results in an access violation.&lt;&#x2F;p&gt;
1504&lt;&#x2F;blockquote&gt;
1505&lt;p&gt;Now that we know that the first region starts at 0 and has a size of 64 KiB, we can simply query for the page at &lt;code&gt;(current base + current size)&lt;&#x2F;code&gt; to fetch the next region. Essentially, we want to loop until it fails, after which we&#x27;ll know there are no more pages&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
1506&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn memory_regions(&amp;amp;self) -&amp;gt; Vec&amp;lt;winapi::um::winnt::MEMORY_BASIC_INFORMATION&amp;gt; {
1507    let mut base = 0;
1508    let mut regions = Vec::new();
1509    let mut info = MaybeUninit::uninit();
1510
1511    loop {
1512        &#x2F;&#x2F; SAFETY: the info structure points to valid memory.
1513        let written = unsafe {
1514            winapi::um::memoryapi::VirtualQueryEx(
1515                self.handle.as_ptr(),
1516                base as *const _,
1517                info.as_mut_ptr(),
1518                mem::size_of::&amp;lt;winapi::um::winnt::MEMORY_BASIC_INFORMATION&amp;gt;(),
1519            )
1520        };
1521        if written == 0 {
1522            break regions;
1523        }
1524        &#x2F;&#x2F; SAFETY: a non-zero amount was written to the structure
1525        let info = unsafe { info.assume_init() };
1526        base = info.BaseAddress as usize + info.RegionSize;
1527        regions.push(info);
1528    }
1529}
1530&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1531&lt;p&gt;&lt;code&gt;RegionSize&lt;&#x2F;code&gt; is:&lt;&#x2F;p&gt;
1532&lt;blockquote&gt;
1533&lt;p&gt;The size of the region beginning at the base address in which all pages have identical attributes, in bytes.&lt;&#x2F;p&gt;
1534&lt;&#x2F;blockquote&gt;
1535&lt;p&gt;…which also hints that the value we want is &amp;quot;base address&amp;quot;, not the &amp;quot;allocation base&amp;quot;. With these two values, we can essentially iterate over all the page ranges:&lt;&#x2F;p&gt;
1536&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;dbg!(process.memory_regions().len());
1537&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1538&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
1539   Compiling memo v0.1.0
1540    Finished dev [unoptimized + debuginfo] target(s) in 0.63s
1541     Running `target\debug\memo.exe`
1542
1543[src\main.rs:189] process.memory_regions().len() = 367
1544&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1545&lt;p&gt;That&#x27;s a lot of pages!&lt;&#x2F;p&gt;
1546&lt;h2 id=&quot;protection-levels&quot;&gt;Protection levels&lt;&#x2F;h2&gt;
1547&lt;p&gt;Let&#x27;s try to narrow the amount of pages down. How many pages aren&#x27;t &lt;code&gt;PAGE_NOACCESS&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
1548&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;dbg!(process
1549    .memory_regions()
1550    .into_iter()
1551    .filter(|p| p.Protect != winapi::um::winnt::PAGE_NOACCESS)
1552    .count());
1553&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1554&lt;pre&gt;&lt;code&gt;295
1555&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1556&lt;p&gt;Still a fair bit! Most likely, there are just a few interleaved &lt;code&gt;NOACCESS&lt;&#x2F;code&gt; pages, and the rest are allocated each with different protection levels. How much memory do we need to scan through?&lt;&#x2F;p&gt;
1557&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;dbg!(process
1558    .memory_regions()
1559    .into_iter()
1560    .filter(|p| p.Protect != winapi::um::winnt::PAGE_NOACCESS)
1561    .map(|p| p.RegionSize)
1562    .sum::&amp;lt;usize&amp;gt;());
1563&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1564&lt;pre&gt;&lt;code&gt;4480434176
1565&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1566&lt;p&gt;Wait, what? What do you mean over 4 GiB? The Task Manager claims that the Cheat Engine Tutorial is only using 2.1 MB worth of RAM! Perhaps we can narrow down the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;memory&#x2F;memory-protection-constants&quot;&gt;protection levels&lt;&#x2F;a&gt; a bit more. If you look at the scan options in Cheat Engine, you will notice the &amp;quot;Memory Scan Options&amp;quot; groupbox. By default, it only scans for memory that is writable, and doesn&#x27;t care if it&#x27;s executable or not:&lt;&#x2F;p&gt;
1567&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let mask = winnt::PAGE_EXECUTE_READWRITE
1568    | winnt::PAGE_EXECUTE_WRITECOPY
1569    | winnt::PAGE_READWRITE
1570    | winnt::PAGE_WRITECOPY;
1571
1572dbg!(process
1573    .memory_regions()
1574    .into_iter()
1575    .filter(|p| (p.Protect &amp;amp; mask) != 0)
1576    .map(|p| p.RegionSize)
1577    .sum::&amp;lt;usize&amp;gt;());
1578&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1579&lt;p&gt;Each memory protection level has its own bit, so we can OR them all together to have a single mask. When ANDing this mask with the protection level, if any bit is set, it will be non-zero, meaning we want to keep this region.&lt;&#x2F;p&gt;
1580&lt;p&gt;Don&#x27;t ask me why there isn&#x27;t a specific bit for &amp;quot;write&amp;quot;, &amp;quot;read&amp;quot;, &amp;quot;execute&amp;quot;, and there are only bits for combinations. I guess this way Windows forbids certain combinations.&lt;&#x2F;p&gt;
1581&lt;pre&gt;&lt;code&gt;2580480
1582&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1583&lt;p&gt;Hey, that&#x27;s close to the value shown by the Task Manager! A handfull of megabytes is a lot more manageable than 4 entire gigabytes.&lt;&#x2F;p&gt;
1584&lt;h2 id=&quot;actually-running-our-first-scan&quot;&gt;Actually running our First Scan&lt;&#x2F;h2&gt;
1585&lt;p&gt;Okay, we have all the memory regions from which the program can read, write, or execute. Now we also can read the memory in these regions:&lt;&#x2F;p&gt;
1586&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let regions = process
1587    .memory_regions()
1588    .into_iter()
1589    .filter(|p| (p.Protect &amp;amp; mask) != 0)
1590    .collect::&amp;lt;Vec&amp;lt;_&amp;gt;&amp;gt;();
1591
1592println!(&amp;quot;Scanning {} memory regions&amp;quot;, regions.len());
1593
1594regions.into_iter().for_each(|region| {
1595    match process.read_memory(region.BaseAddress as _, region.RegionSize) {
1596        Ok(memory) =&amp;gt; todo!(),
1597        Err(err) =&amp;gt; eprintln!(
1598            &amp;quot;Failed to read {} bytes at {:?}: {}&amp;quot;,
1599            region.RegionSize, region.BaseAddress, err,
1600        ),
1601    }
1602})
1603&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1604&lt;p&gt;All that&#x27;s left is for us to scan for a target value. To do this, we want to iterate over all the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;primitive.slice.html#method.windows&quot;&gt;&lt;code&gt;slice::windows&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; of size equal to the size of our scan type.&lt;&#x2F;p&gt;
1605&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let target: i32 = ...;
1606let target = target.to_ne_bytes();
1607
1608&#x2F;&#x2F; -snip-
1609
1610&#x2F;&#x2F; inside the Ok match, replacing the todo!() -- this is where the first scan happens
1611Ok(memory) =&amp;gt; memory
1612    .windows(target.len())
1613    .enumerate()
1614    .for_each(|(offset, window)| {
1615        if window == target {
1616            println!(
1617                &amp;quot;Found exact value at [{:?}+{:x}]&amp;quot;,
1618                region.BaseAddress, offset
1619            );
1620        }
1621    })
1622&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1623&lt;p&gt;We convert the 32-bit exact target value to its memory representation as a byte array in &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;primitive.i32.html#method.to_ne_bytes&quot;&gt;native byte order&lt;&#x2F;a&gt;. This way we can compare the target bytes with the window bytes. Another option is to interpret the window bytes as an &lt;code&gt;i32&lt;&#x2F;code&gt; with &lt;code&gt;from_be_bytes&lt;&#x2F;code&gt;, but &lt;code&gt;slice::windows&lt;&#x2F;code&gt; gives us slices of type &lt;code&gt;&amp;amp;[u8]&lt;&#x2F;code&gt;, and &lt;code&gt;from_be_bytes&lt;&#x2F;code&gt; wants an &lt;code&gt;[u8; 4]&lt;&#x2F;code&gt; array, so it&#x27;s a bit more annoying to convert.&lt;&#x2F;p&gt;
1624&lt;p&gt;This is enough to find the value in the process&#x27; memory!&lt;&#x2F;p&gt;
1625&lt;pre&gt;&lt;code&gt;Found exact value at [0x10000+aec]
1626Failed to read 12288 bytes at 0x13f8000: Only part of a ReadProcessMemory or WriteProcessMemory request was completed. (os error 299)
1627Found exact value at [0x14f0000+3188]
1628Found exact value at [0x14f0000+ac74]
1629...
1630Found exact value at [0x10030e000+1816]
1631Found exact value at [0x7ff8f7b93000+441a]
1632...
1633Found exact value at [0x7ff8fb381000+4023]
1634&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1635&lt;p&gt;The tutorial starts out with health &amp;quot;100&amp;quot;, which is what I scanned. Apparently, there are nearly a hundred of &lt;code&gt;100&lt;&#x2F;code&gt;-valued integers stored in the memory of the tutorial.&lt;&#x2F;p&gt;
1636&lt;p&gt;Attentive readers will notice that some values are located at an offset modulo 4. In Cheat Engine, this is known as &amp;quot;Fast Scan&amp;quot;, which is enabled by default with an alignment of 4. Most of the time, values are aligned in memory, and this alignment often corresponds with the size of the type itself. For 4-byte integers, it&#x27;s common that they&#x27;re 4-byte aligned.&lt;&#x2F;p&gt;
1637&lt;p&gt;We can perform a fast scan ourselves with &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.step_by&quot;&gt;&lt;code&gt;step_by&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
1638&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;memory
1639    .windows(target.len())
1640    .enumerate()
1641    .step_by(4)
1642    .for_each(...)
1643&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1644&lt;p&gt;As a bonus, over half the addresses are gone, so we have less results to worry about&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
1645&lt;h2 id=&quot;next-scan&quot;&gt;Next Scan&lt;&#x2F;h2&gt;
1646&lt;p&gt;The first scan gave us way too many results. We have no way to tell which is the correct one, as they all have the same value. What we need to do is a &lt;em&gt;second&lt;&#x2F;em&gt; scan at the &lt;em&gt;locations we just found&lt;&#x2F;em&gt;. This way, we can get a second reading, and compare it against a new value. If it&#x27;s the same, we&#x27;re on good track, and if not, we can discard a location. Repeating this process lets us cut the hundreds of potential addresses to just a handful of them.&lt;&#x2F;p&gt;
1647&lt;p&gt;For example, let&#x27;s say we&#x27;re scanning our current health of &lt;code&gt;100&lt;&#x2F;code&gt; in a game. This gives us over a hundred addresses that point to the value of &lt;code&gt;100&lt;&#x2F;code&gt;. If we go in-game and get hit&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; by some enemy and get our health down to, say, &lt;code&gt;99&lt;&#x2F;code&gt; (we have a lot of defense), we can then read the memory at the hundred memory locations we found before. If this second reading is not &lt;code&gt;99&lt;&#x2F;code&gt;, we know the address does not actually point to our health pool and it just happened to also contain a &lt;code&gt;100&lt;&#x2F;code&gt; on the first scan. This address can be removed from the list of potential addresses pointing to our health.&lt;&#x2F;p&gt;
1648&lt;p&gt;Let&#x27;s do that:&lt;&#x2F;p&gt;
1649&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&#x2F;&#x2F; new vector to hold the locations, before getting into `memory.windows`&#x27; for-each
1650let mut locations = Vec::with_capacity(regions.len());
1651
1652&#x2F;&#x2F; -snip-
1653
1654&#x2F;&#x2F; updating the `println!(&amp;quot;Found exact value...&amp;quot;)` to store the location instead.
1655if window == target {
1656    locations.push(region.BaseAddress as usize + offset);
1657}
1658
1659&#x2F;&#x2F; -snip-
1660
1661&#x2F;&#x2F; performing a second scan on the locations the first scan found.
1662let target: i32 = ...;
1663let target = target.to_ne_bytes();
1664locations.retain(|addr| match process.read_memory(*addr, target.len()) {
1665    Ok(memory) =&amp;gt; memory == target,
1666    Err(_) =&amp;gt; false,
1667});
1668
1669println!(&amp;quot;Now have {} locations&amp;quot;, locations.len());
1670&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1671&lt;p&gt;We create a vector to store all the locations the first scan finds, and then retain those that match a second target value. You may have noticed that we perform a memory read, and thus a call to the Windows API, for every single address. With a hundred locations to read from, this is not a big deal, but oftentimes you will have tens of thousands of addresses. For the time being, we will not worry about this inefficiency, but we will get back to it once it matters:&lt;&#x2F;p&gt;
1672&lt;pre&gt;&lt;code&gt;Scanning 98 memory regions
1673Which exact value to scan for?: 100
1674Failed to read 12288 bytes at 0x13f8000: Only part of a ReadProcessMemory or WriteProcessMemory request was completed. (os error 299)
1675...
1676Found 49 locations
1677Which exact value to scan for next?: 99
1678Now have 1 locations
1679&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1680&lt;p&gt;Sweet! In a real-world scenario, you will likely need to perform these additional scans a couple of times, and even then, there may be more than one value left no matter what.&lt;&#x2F;p&gt;
1681&lt;p&gt;For good measure, we&#x27;ll wrap our &lt;code&gt;retain&lt;&#x2F;code&gt; in a &lt;code&gt;while&lt;&#x2F;code&gt; loop&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
1682&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;while locations.len() != 1 {
1683    let target: i32 = ...;
1684    let target = target.to_ne_bytes();
1685    locations.retain(...);
1686}
1687&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1688&lt;h2 id=&quot;modifying-memory&quot;&gt;Modifying memory&lt;&#x2F;h2&gt;
1689&lt;p&gt;Now that we have very likely locations pointing to our current health in memory, all that&#x27;s left is writing our new desired value to gain infinite health&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#9&quot;&gt;9&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Much like how we&#x27;re able to read memory with &lt;code&gt;ReadProcessMemory&lt;&#x2F;code&gt;, we can write to it with &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;memoryapi&#x2F;nf-memoryapi-writeprocessmemory&quot;&gt;&lt;code&gt;WriteProcessMemory&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Its usage is straightforward:&lt;&#x2F;p&gt;
1690&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;pub fn write_memory(&amp;amp;self, addr: usize, value: &amp;amp;[u8]) -&amp;gt; io::Result&amp;lt;usize&amp;gt; {
1691    let mut written = 0;
1692
1693    &#x2F;&#x2F; SAFETY: the input value buffer points to valid memory.
1694    if unsafe {
1695        winapi::um::memoryapi::WriteProcessMemory(
1696            self.handle.as_ptr(),
1697            addr as *mut _,
1698            value.as_ptr().cast(),
1699            value.len(),
1700            &amp;amp;mut written,
1701        )
1702    } == FALSE
1703    {
1704        Err(io::Error::last_os_error())
1705    } else {
1706        Ok(written)
1707    }
1708}
1709&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1710&lt;p&gt;Similar to how writing to a file can return short, writing to a memory location could also return short. Here we mimic the API for writing files and return the number of bytes written. The documentation indicates that we could actually ignore the amount written by passing &lt;code&gt;ptr::null_mut()&lt;&#x2F;code&gt; as the last parameter, but it does no harm to retrieve the written count as well.&lt;&#x2F;p&gt;
1711&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let new_value: i32 = ...;
1712locations
1713    .into_iter()
1714    .for_each(|addr| match process.write_memory(addr, &amp;amp;new_value) {
1715        Ok(n) =&amp;gt; eprintln!(&amp;quot;Written {} bytes to [{:x}]&amp;quot;, n, addr),
1716        Err(e) =&amp;gt; eprintln!(&amp;quot;Failed to write to [{:x}]: {}&amp;quot;, addr, e),
1717    });
1718&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1719&lt;p&gt;And just like that:&lt;&#x2F;p&gt;
1720&lt;pre&gt;&lt;code&gt;Now have 1 location(s)
1721Enter new memory value: 1000
1722Failed to write to [15d8b90]: Access is denied. (os error 5)
1723&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1724&lt;p&gt;…oh noes. Oh yeah. The documentation, which I totally didn&#x27;t forget to read, mentions:&lt;&#x2F;p&gt;
1725&lt;blockquote&gt;
1726&lt;p&gt;The handle must have &lt;code&gt;PROCESS_VM_WRITE&lt;&#x2F;code&gt; and &lt;code&gt;PROCESS_VM_OPERATION&lt;&#x2F;code&gt; access to the process.&lt;&#x2F;p&gt;
1727&lt;&#x2F;blockquote&gt;
1728&lt;p&gt;We currently open our process with &lt;code&gt;PROCESS_QUERY_INFORMATION&lt;&#x2F;code&gt; and &lt;code&gt;PROCESS_VM_READ&lt;&#x2F;code&gt;, which is enough for reading, but not for writing. Let&#x27;s adjust &lt;code&gt;OpenProcess&lt;&#x2F;code&gt; to accomodate for our new requirements:&lt;&#x2F;p&gt;
1729&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;winapi::um::processthreadsapi::OpenProcess(
1730    winnt::PROCESS_QUERY_INFORMATION
1731        | winnt::PROCESS_VM_READ
1732        | winnt::PROCESS_VM_WRITE
1733        | winnt::PROCESS_VM_OPERATION,
1734    FALSE,
1735    pid,
1736)
1737&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1738&lt;p&gt;Behold:&lt;&#x2F;p&gt;
1739&lt;pre&gt;&lt;code&gt;Now have 1 location(s)
1740Enter new memory value: 1000
1741Written 4 bytes to [15d8b90]
1742&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1743&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;user-images.githubusercontent.com&#x2F;6297805&#x2F;107829541-3f4f2d00-6d8a-11eb-87c4-e2f2d505afbc.png&quot; alt=&quot;Tutorial complete with memo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
1744&lt;p&gt;Isn&#x27;t that active &lt;em&gt;Next&lt;&#x2F;em&gt; button just beautiful?&lt;&#x2F;p&gt;
1745&lt;h2 id=&quot;finale&quot;&gt;Finale&lt;&#x2F;h2&gt;
1746&lt;p&gt;This post somehow ended up being longer than part one, but look at what we&#x27;ve achieved! We completed a step of the Cheat Engine Tutorial &lt;em&gt;without using Cheat Engine&lt;&#x2F;em&gt;. Just pure Rust. Figuring out how a program works and reimplementing it yourself is a great way to learn what it&#x27;s doing behind the scenes. And now that this code is yours, you can extend it as much as you like, without being constrained by Cheat Engine&#x27;s UI. You can automate it as much as you want.&lt;&#x2F;p&gt;
1747&lt;p&gt;And we&#x27;re not even done. The current tutorial has nine steps, and three additional graphical levels.&lt;&#x2F;p&gt;
1748&lt;p&gt;In the &lt;a href=&quot;&#x2F;blog&#x2F;woce-3&quot;&gt;next post&lt;&#x2F;a&gt;, we&#x27;ll tackle the third step of the tutorial: Unknown initial value. This will pose a challenge, because with just 2 MiB of memory, storing all the 4-byte aligned locations would require 524288 addresses (&lt;code&gt;usize&lt;&#x2F;code&gt;, 8 bytes). This adds up to twice as much memory as the original program (4 MiB), but that&#x27;s not our main concern, having to perform over five hundred thousand API calls is!&lt;&#x2F;p&gt;
1749&lt;p&gt;Remember that you can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lonami&#x2F;memo&quot;&gt;obtain the code for this post&lt;&#x2F;a&gt; over at my GitHub. You can run &lt;code&gt;git checkout step2&lt;&#x2F;code&gt; after cloning the repository to get the right version of the code.&lt;&#x2F;p&gt;
1750&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h3&gt;
1751&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
1752&lt;p&gt;I did in fact use an online tool to spell it out for me.&lt;&#x2F;p&gt;
1753&lt;&#x2F;div&gt;
1754&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
1755&lt;p&gt;16 GiB is good enough for my needs. I don&#x27;t think I&#x27;ll ever upgrade to 16 EiB.&lt;&#x2F;p&gt;
1756&lt;&#x2F;div&gt;
1757&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
1758&lt;p&gt;Every address we query should have a corresponding region, even if it&#x27;s not allocated or we do not have access. This is why we can query for the memory address zero to get its corresponding region.&lt;&#x2F;p&gt;
1759&lt;&#x2F;div&gt;
1760&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
1761&lt;p&gt;Another option is to &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;sysinfoapi&#x2F;nf-sysinfoapi-getsysteminfo&quot;&gt;&lt;code&gt;GetSystemInfo&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to determine the &lt;code&gt;lpMinimumApplicationAddress&lt;&#x2F;code&gt; and &lt;code&gt;lpMaximumApplicationAddress&lt;&#x2F;code&gt; and only work within bounds.&lt;&#x2F;p&gt;
1762&lt;&#x2F;div&gt;
1763&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
1764&lt;p&gt;Memory regions are page-aligned, which is a large power of two. Our alignment of 4 is much lower than this, so we&#x27;re guaranteed to start off at an aligned address.&lt;&#x2F;p&gt;
1765&lt;&#x2F;div&gt;
1766&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
1767&lt;p&gt;If it turns out that the value was actually misaligned, we will miss it. You will notice this if, after going through the whole process, there are no results. It could mean that either the value type is wrong, or the value type is misaligned. In the worst case, the value is not stored directly but is rather computed with something like &lt;code&gt;maximum - stored&lt;&#x2F;code&gt;, or XORed with some magic value, or a myriad other things.&lt;&#x2F;p&gt;
1768&lt;&#x2F;div&gt;
1769&lt;div class=&quot;footnote-definition&quot; id=&quot;7&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;7&lt;&#x2F;sup&gt;
1770&lt;p&gt;You could do this without getting hit, and just keep on repeating the scan for the same value over and over again. This does work, but the results are suboptimal, because there are also many other values that didn&#x27;t change. Scanning for a changed value is a better option.&lt;&#x2F;p&gt;
1771&lt;&#x2F;div&gt;
1772&lt;div class=&quot;footnote-definition&quot; id=&quot;8&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;8&lt;&#x2F;sup&gt;
1773&lt;p&gt;You could actually just go ahead and try to modify the memory at the hundred addresses you just found, although don&#x27;t be surprised if the program starts to misbehave!&lt;&#x2F;p&gt;
1774&lt;&#x2F;div&gt;
1775&lt;div class=&quot;footnote-definition&quot; id=&quot;9&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;9&lt;&#x2F;sup&gt;
1776&lt;p&gt;Okay, we cannot fit infinity in an &lt;code&gt;i32&lt;&#x2F;code&gt;. However, we can fit sufficiently large numbers. Like &lt;code&gt;1000&lt;&#x2F;code&gt;, which is enough to complete the tutorial.&lt;&#x2F;p&gt;
1777&lt;&#x2F;div&gt;
1778</content>
1779	</entry>
1780	<entry xml:lang="en">
1781		<title>Writing our own Cheat Engine: Introduction</title>
1782		<published>2021-02-07T00:00:00+00:00</published>
1783		<updated>2021-02-19T00:00:00+00:00</updated>
1784		<link href="https://lonami.dev/blog/woce-1/" type="text/html"/>
1785		<id>https://lonami.dev/blog/woce-1/</id>
1786		<content type="html">&lt;p&gt;This is part 1 on the &lt;em&gt;Writing our own Cheat Engine&lt;&#x2F;em&gt; series:&lt;&#x2F;p&gt;
1787&lt;ul&gt;
1788&lt;li&gt;Part 1: Introduction&lt;&#x2F;li&gt;
1789&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-2&quot;&gt;Part 2: Exact Value scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1790&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-3&quot;&gt;Part 3: Unknown initial value&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1791&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-4&quot;&gt;Part 4: Floating points&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1792&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;woce-5&quot;&gt;Part 5: Code finder&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
1793&lt;&#x2F;ul&gt;
1794&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cheatengine.org&#x2F;&quot;&gt;Cheat Engine&lt;&#x2F;a&gt; is a tool designed to modify single player games and contains other useful tools within itself that enable its users to debug games or other applications. It comes with a memory scanner, (dis)assembler, inspection tools and a handful other things. In this series, we will be writing our own tiny Cheat Engine capable of solving all steps of the tutorial, and diving into how it all works underneath.&lt;&#x2F;p&gt;
1795&lt;p&gt;Needless to say, we&#x27;re doing this for private and educational purposes only. One has to make sure to not violate the EULA or ToS of the specific application we&#x27;re attaching to. This series, much like cheatengine.org, does not condone the illegal use of the code shared.&lt;&#x2F;p&gt;
1796&lt;p&gt;Cheat Engine is a tool for Windows, so we will be developing for Windows as well. However, you can also &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;12977179&#x2F;4759433&quot;&gt;read memory from Linux-like systems&lt;&#x2F;a&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scanmem&#x2F;scanmem&quot;&gt;GameConqueror&lt;&#x2F;a&gt; is a popular alternative to Cheat Engine on Linux systems, so if you feel adventurous, you could definitely follow along too! The techniques shown in this series apply regardless of how we read memory from a process. You will learn a fair bit about doing FFI in Rust too.&lt;&#x2F;p&gt;
1797&lt;p&gt;We will be developing the application in Rust, because it enables us to interface with the Windows API easily, is memory safe (as long as we&#x27;re careful with &lt;code&gt;unsafe&lt;&#x2F;code&gt;!), and is speedy (we will need this for later steps in the Cheat Engine tutorial). You could use any language of your choice though. For example, &lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;ctypes-and-windows&#x2F;&quot;&gt;Python also makes it relatively easy to use the Windows API&lt;&#x2F;a&gt;. You don&#x27;t need to be a Rust expert to follow along, but this series assumes some familiarity with C-family languages. Slightly advanced concepts like the use of &lt;code&gt;unsafe&lt;&#x2F;code&gt; or the &lt;code&gt;MaybeUninit&lt;&#x2F;code&gt; type will be briefly explained. What a &lt;code&gt;fn&lt;&#x2F;code&gt; is or what &lt;code&gt;let&lt;&#x2F;code&gt; does will not be explained.&lt;&#x2F;p&gt;
1798&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cheat-engine&#x2F;cheat-engine&#x2F;&quot;&gt;Cheat Engine&#x27;s source code&lt;&#x2F;a&gt; is mostly written in Pascal and C. And it&#x27;s &lt;em&gt;a lot&lt;&#x2F;em&gt; of code, with a very flat project structure, and files ranging in the thousand lines of code each. It&#x27;s daunting&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. It&#x27;s a mature project, with a lot of knowledge encoded in the code base, and a lot of features like distributed scanning or an entire disassembler. Unfortunately, there&#x27;s not a lot of comments. For these reasons, I&#x27;ll do some guesswork when possible as to how it&#x27;s working underneath, rather than actually digging into what Cheat Engine is actually doing.&lt;&#x2F;p&gt;
1799&lt;p&gt;With that out of the way, let&#x27;s get started!&lt;&#x2F;p&gt;
1800&lt;h2 id=&quot;welcome-to-the-cheat-engine-tutorial&quot;&gt;Welcome to the Cheat Engine Tutorial&lt;&#x2F;h2&gt;
1801&lt;details open&gt;&lt;summary&gt;Cheat Engine Tutorial: Step 1&lt;&#x2F;summary&gt;
1802&lt;blockquote&gt;
1803&lt;p&gt;This tutorial will teach you the basics of cheating in video games. It will also show you foundational aspects of using Cheat Engine (or CE for short). Follow the steps below to get started.&lt;&#x2F;p&gt;
1804&lt;ol&gt;
1805&lt;li&gt;Open Cheat Engine if it currently isn&#x27;t running.&lt;&#x2F;li&gt;
1806&lt;li&gt;Click on the &amp;quot;Open Process&amp;quot; icon (it&#x27;s the top-left icon with the computer on it, below &amp;quot;File&amp;quot;.).&lt;&#x2F;li&gt;
1807&lt;li&gt;With the Process List window now open, look for this tutorial&#x27;s process in the list. It will look something like &amp;gt; &amp;quot;00001F98-Tutorial-x86_64.exe&amp;quot; or &amp;quot;0000047C-Tutorial-i386.exe&amp;quot;. (The first 8 numbers&#x2F;letters will probably be different.)&lt;&#x2F;li&gt;
1808&lt;li&gt;Once you&#x27;ve found the process, click on it to select it, then click the &amp;quot;Open&amp;quot; button. (Don&#x27;t worry about all the &amp;gt; other buttons right now. You can learn about them later if you&#x27;re interested.)&lt;&#x2F;li&gt;
1809&lt;&#x2F;ol&gt;
1810&lt;p&gt;Congratulations! If you did everything correctly, the process window should be gone with Cheat Engine now attached to the &amp;gt; tutorial (you will see the process name towards the top-center of CE).&lt;&#x2F;p&gt;
1811&lt;p&gt;Click the &amp;quot;Next&amp;quot; button below to continue, or fill in the password and click the &amp;quot;OK&amp;quot; button to proceed to that step.)&lt;&#x2F;p&gt;
1812&lt;p&gt;If you&#x27;re having problems, simply head over to forum.cheatengine.org, then click on &amp;quot;Tutorials&amp;quot; to view beginner-friendly &amp;gt; guides!&lt;&#x2F;p&gt;
1813&lt;&#x2F;blockquote&gt;
1814&lt;&#x2F;details&gt;
1815&lt;h2 id=&quot;enumerating-processes&quot;&gt;Enumerating processes&lt;&#x2F;h2&gt;
1816&lt;p&gt;Our first step is attaching to the process we want to work with. But we need a way to find that process in the first place! Having to open the task manager, look for the process we care about, noting down the process ID (PID), and slapping it in the source code is not satisfying at all. Instead, let&#x27;s enumerate all the processes from within the program, and let the user select one by typing its name.&lt;&#x2F;p&gt;
1817&lt;p&gt;From a quick &lt;a href=&quot;https:&#x2F;&#x2F;ddg.gg&#x2F;winapi%20enumerate%20all%20processes&quot;&gt;DuckDuckGo search&lt;&#x2F;a&gt;, we find an official tutorial for &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;psapi&#x2F;enumerating-all-processes&quot;&gt;Enumerating All Processes&lt;&#x2F;a&gt;, which leads to the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;psapi&#x2F;nf-psapi-enumprocesses&quot;&gt;&lt;code&gt;EnumProcesses&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; call. Cool! Let&#x27;s slap in the &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;winapi&quot;&gt;&lt;code&gt;winapi&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; crate on &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, because I don&#x27;t want to write all the definitions by myself:&lt;&#x2F;p&gt;
1818&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;[dependencies]
1819winapi = { version = &amp;quot;0.3.9&amp;quot;, features = [&amp;quot;psapi&amp;quot;] }
1820&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1821&lt;p&gt;Because &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;psapi&#x2F;nf-psapi-enumprocesses&quot;&gt;&lt;code&gt;EnumProcesses&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is in &lt;code&gt;Psapi.h&lt;&#x2F;code&gt; (you can see this in the online page of its documentation), we know we&#x27;ll need the &lt;code&gt;psapi&lt;&#x2F;code&gt; crate feature. Another option is to search for it in the &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;winapi&#x2F;&quot;&gt;&lt;code&gt;winapi&lt;&#x2F;code&gt; documentation&lt;&#x2F;a&gt; and noting down the parent module where its stored.&lt;&#x2F;p&gt;
1822&lt;p&gt;The documentation for the method has the following remark:&lt;&#x2F;p&gt;
1823&lt;blockquote&gt;
1824&lt;p&gt;It is a good idea to use a large array, because it is hard to predict how many processes there will be at the time you call &lt;strong&gt;EnumProcesses&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
1825&lt;&#x2F;blockquote&gt;
1826&lt;p&gt;&lt;em&gt;Sidenote: reading the documentation for the methods we&#x27;ll use from the Windows API is extremely important. There&#x27;s a lot of gotchas involved, so we need to make sure we&#x27;re extra careful.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
1827&lt;p&gt;1024 is a pretty big number, so let&#x27;s go with that:&lt;&#x2F;p&gt;
1828&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use std::io;
1829use std::mem;
1830use winapi::shared::minwindef::{DWORD, FALSE};
1831
1832pub fn enum_proc() -&amp;gt; io::Result&amp;lt;Vec&amp;lt;u32&amp;gt;&amp;gt; {
1833    let mut pids = Vec::&amp;lt;DWORD&amp;gt;::with_capacity(1024);
1834    let mut size = 0;
1835    &#x2F;&#x2F; SAFETY: the pointer is valid and the size matches the capacity.
1836    if unsafe {
1837        winapi::um::psapi::EnumProcesses(
1838            pids.as_mut_ptr(),
1839            (pids.capacity() * mem::size_of::&amp;lt;DWORD&amp;gt;()) as u32,
1840            &amp;amp;mut size,
1841        )
1842    } == FALSE
1843    {
1844        return Err(io::Error::last_os_error());
1845    }
1846
1847    todo!()
1848}
1849&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1850&lt;p&gt;We allocate enough space&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; for 1024 &lt;code&gt;pids&lt;&#x2F;code&gt; in a vector&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, and pass a mutable pointer to the contents to &lt;code&gt;EnumProcesses&lt;&#x2F;code&gt;. Note that the size of the array is in &lt;em&gt;bytes&lt;&#x2F;em&gt;, not items, so we need to multiply the capacity by the size of &lt;code&gt;DWORD&lt;&#x2F;code&gt;. The API likes to use &lt;code&gt;u32&lt;&#x2F;code&gt; for sizes, unlike Rust which uses &lt;code&gt;usize&lt;&#x2F;code&gt;, so we need a cast.&lt;&#x2F;p&gt;
1851&lt;p&gt;Last, we need another mutable variable where the amount of bytes written is stored, &lt;code&gt;size&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
1852&lt;blockquote&gt;
1853&lt;p&gt;If the function fails, the return value is zero. To get extended error information, call &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;errhandlingapi&#x2F;nf-errhandlingapi-getlasterror&quot;&gt;&lt;code&gt;GetLastError&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
1854&lt;&#x2F;blockquote&gt;
1855&lt;p&gt;That&#x27;s precisely what we do. If it returns false (zero), we return the last OS error. Rust provides us with &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;io&#x2F;struct.Error.html#method.last_os_error&quot;&gt;&lt;code&gt;std::io::Error::last_os_error&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which essentially makes that same call but returns a proper &lt;code&gt;io::Error&lt;&#x2F;code&gt; instance. Cool!&lt;&#x2F;p&gt;
1856&lt;blockquote&gt;
1857&lt;p&gt;To determine how many processes were enumerated, divide the &lt;em&gt;lpcbNeeded&lt;&#x2F;em&gt; value by &lt;code&gt;sizeof(DWORD)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
1858&lt;&#x2F;blockquote&gt;
1859&lt;p&gt;Easy enough:&lt;&#x2F;p&gt;
1860&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let count = size as usize &#x2F; mem::size_of::&amp;lt;DWORD&amp;gt;();
1861&#x2F;&#x2F; SAFETY: the call succeeded and count equals the right amount of items.
1862unsafe { pids.set_len(count) };
1863Ok(pids)
1864&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1865&lt;p&gt;Rust doesn&#x27;t know that the memory for &lt;code&gt;count&lt;&#x2F;code&gt; items were initialized by the call, but we do, so we make use of the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;vec&#x2F;struct.Vec.html#method.set_len&quot;&gt;&lt;code&gt;Vec::set_len&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; call to indicate this. The Rust documentation even includes a FFI similar to our code!&lt;&#x2F;p&gt;
1866&lt;p&gt;Let&#x27;s give it a ride:&lt;&#x2F;p&gt;
1867&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;fn main() {
1868    dbg!(enum_proc().unwrap().len());
1869}
1870&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1871&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
1872   Compiling memo v0.1.0
1873    Finished dev [unoptimized + debuginfo] target(s) in 0.20s
1874     Running `target\debug\memo.exe`
1875[src\main.rs:27] enum_proc().unwrap().len() = 178
1876&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1877&lt;p&gt;It works! But currently we only have a bunch of process identifiers, with no way of knowing which process they refer to.&lt;&#x2F;p&gt;
1878&lt;blockquote&gt;
1879&lt;p&gt;To obtain process handles for the processes whose identifiers you have just obtained, call the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;processthreadsapi&#x2F;nf-processthreadsapi-openprocess&quot;&gt;&lt;code&gt;OpenProcess&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function.&lt;&#x2F;p&gt;
1880&lt;&#x2F;blockquote&gt;
1881&lt;p&gt;Oh!&lt;&#x2F;p&gt;
1882&lt;h2 id=&quot;opening-a-process&quot;&gt;Opening a process&lt;&#x2F;h2&gt;
1883&lt;p&gt;The documentation for &lt;code&gt;OpenProcess&lt;&#x2F;code&gt; also contains the following:&lt;&#x2F;p&gt;
1884&lt;blockquote&gt;
1885&lt;p&gt;When you are finished with the handle, be sure to close it using the &lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;woce-1&#x2F;closehandle&quot;&gt;&lt;code&gt;CloseHandle&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; function.&lt;&#x2F;p&gt;
1886&lt;&#x2F;blockquote&gt;
1887&lt;p&gt;This sounds to me like the perfect time to introduce a custom &lt;code&gt;struct Process&lt;&#x2F;code&gt; with an &lt;code&gt;impl Drop&lt;&#x2F;code&gt;! We&#x27;re using &lt;code&gt;Drop&lt;&#x2F;code&gt; to cleanup resources, not behaviour, so it&#x27;s fine. &lt;a href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;pre-rfc-leave-auto-trait-for-reliable-destruction&#x2F;13825&quot;&gt;Using &lt;code&gt;Drop&lt;&#x2F;code&gt; to cleanup behaviour is a bad idea&lt;&#x2F;a&gt;. But anyway, let&#x27;s get back to the code:&lt;&#x2F;p&gt;
1888&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use std::ptr::NonNull;
1889use winapi::ctypes::c_void;
1890
1891pub struct Process {
1892    pid: u32,
1893    handle: NonNull&amp;lt;c_void&amp;gt;,
1894}
1895
1896impl Process {
1897    pub fn open(pid: u32) -&amp;gt; io::Result&amp;lt;Self&amp;gt; {
1898        todo!()
1899    }
1900}
1901
1902impl Drop for Process {
1903    fn drop(&amp;amp;mut self) {
1904        todo!()
1905    }
1906}
1907&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1908&lt;p&gt;For &lt;code&gt;open&lt;&#x2F;code&gt;, we&#x27;ll want to use &lt;code&gt;OpenProcess&lt;&#x2F;code&gt; (and we also need to add the &lt;code&gt;processthreadsapi&lt;&#x2F;code&gt; feature to the &lt;code&gt;winapi&lt;&#x2F;code&gt; dependency in &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;). It returns a &lt;code&gt;HANDLE&lt;&#x2F;code&gt;, which is a nullable mutable pointer to &lt;code&gt;c_void&lt;&#x2F;code&gt;. If it&#x27;s null, the call failed, and if it&#x27;s non-null, it succeeded and we have a valid handle. This is why we use Rust&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;ptr&#x2F;struct.NonNull.html&quot;&gt;&lt;code&gt;NonNull&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
1909&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&#x2F;&#x2F; SAFETY: the call doesn&#x27;t have dangerous side-effects.
1910NonNull::new(unsafe { winapi::um::processthreadsapi::OpenProcess(0, FALSE, pid) })
1911    .map(|handle| Self { pid, handle })
1912    .ok_or_else(io::Error::last_os_error)
1913&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1914&lt;p&gt;&lt;code&gt;NonNull&lt;&#x2F;code&gt; will return &lt;code&gt;Some&lt;&#x2F;code&gt; if the pointer is non-null. We map the non-null pointer to a &lt;code&gt;Process&lt;&#x2F;code&gt; instance with &lt;code&gt;Self { .. }&lt;&#x2F;code&gt;. &lt;code&gt;ok_or_else&lt;&#x2F;code&gt; converts the &lt;code&gt;Option&lt;&#x2F;code&gt; to a &lt;code&gt;Result&lt;&#x2F;code&gt; with the error builder function we provide if it was &lt;code&gt;None&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
1915&lt;p&gt;The first parameter is a bitflag of permissions we want to have. For now, we can leave it as zero (all bits unset, no specific permissions granted). The second one is whether we want to inherit the handle, which we don&#x27;t, and the third one is the process identifier. Let&#x27;s close the resource handle on &lt;code&gt;Drop&lt;&#x2F;code&gt; (after adding &lt;code&gt;handleapi&lt;&#x2F;code&gt; to the crate features):&lt;&#x2F;p&gt;
1916&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&#x2F;&#x2F; SAFETY: the handle is valid and non-null.
1917unsafe { winapi::um::handleapi::CloseHandle(self.handle.as_mut()) };
1918&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1919&lt;p&gt;&lt;code&gt;CloseHandle&lt;&#x2F;code&gt; can actually fail (for example, on double-close), but given our invariants, it won&#x27;t. You could add an &lt;code&gt;assert!&lt;&#x2F;code&gt; to panic if this is not the case.&lt;&#x2F;p&gt;
1920&lt;p&gt;We can now open processes, and they will be automatically closed on &lt;code&gt;Drop&lt;&#x2F;code&gt;. Does any of this work though?&lt;&#x2F;p&gt;
1921&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;fn main() {
1922    let mut success = 0;
1923    let mut failed = 0;
1924    enum_proc().unwrap().into_iter().for_each(|pid| match Process::open(pid) {
1925        Ok(_) =&amp;gt; success += 1,
1926        Err(_) =&amp;gt; failed += 1,
1927    });
1928
1929    eprintln!(&amp;quot;Successfully opened {}&#x2F;{} processes&amp;quot;, success, success + failed);
1930}
1931&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1932&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
1933   Compiling memo v0.1.0
1934    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
1935     Running `target\debug\memo.exe`
1936Successfully opened 0&#x2F;191 processes
1937&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1938&lt;p&gt;…nope. Maybe the documentation for &lt;code&gt;OpenProcess&lt;&#x2F;code&gt; says something?&lt;&#x2F;p&gt;
1939&lt;blockquote&gt;
1940&lt;p&gt;&lt;code&gt;dwDesiredAccess&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
1941&lt;p&gt;The access to the process object. This access right is checked against the security descriptor for the process. This parameter can be &lt;strong&gt;one or more&lt;&#x2F;strong&gt; of the process access rights.&lt;&#x2F;p&gt;
1942&lt;&#x2F;blockquote&gt;
1943&lt;p&gt;One or more, but we&#x27;re setting zero permissions. I told you, reading the documentation is important&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;! The &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;procthread&#x2F;process-security-and-access-rights&quot;&gt;Process Security and Access Rights&lt;&#x2F;a&gt; page lists all possible values we could use. &lt;code&gt;PROCESS_QUERY_INFORMATION&lt;&#x2F;code&gt; seems to be appropriated:&lt;&#x2F;p&gt;
1944&lt;blockquote&gt;
1945&lt;p&gt;Required to retrieve certain information about a process, such as its token, exit code, and priority class&lt;&#x2F;p&gt;
1946&lt;&#x2F;blockquote&gt;
1947&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;OpenProcess(winapi::um::winnt::PROCESS_QUERY_INFORMATION, ...)
1948&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1949&lt;p&gt;Does this fix it?&lt;&#x2F;p&gt;
1950&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&amp;gt;cargo run
1951   Compiling memo v0.1.0
1952    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
1953     Running `target\debug\memo.exe`
1954Successfully opened 69&#x2F;188 processes
1955&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1956&lt;p&gt;&lt;em&gt;Nice&lt;&#x2F;em&gt;. It does solve it. But why did we only open 69 processes out of 188? Does it help if we run our code as administrator? Let&#x27;s search for &lt;code&gt;cmd&lt;&#x2F;code&gt; in the Windows menu and right click to Run as administrator, then &lt;code&gt;cd&lt;&#x2F;code&gt; into our project and try again:&lt;&#x2F;p&gt;
1957&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
1958    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
1959     Running `target\debug\memo.exe`
1960Successfully opened 77&#x2F;190 processes
1961&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1962&lt;p&gt;We&#x27;re able to open a few more, so it does help. In general, we&#x27;ll want to run as administrator, so normal programs can&#x27;t sniff on what we&#x27;re doing, and so that we have permission to do more things.&lt;&#x2F;p&gt;
1963&lt;h2 id=&quot;getting-the-name-of-a-process&quot;&gt;Getting the name of a process&lt;&#x2F;h2&gt;
1964&lt;p&gt;We&#x27;re not done enumerating things just yet. To get the &amp;quot;name&amp;quot; of a process, we need to enumerate the modules that it has loaded, and only then can we get the module base name. The first module is the program itself, so we don&#x27;t need to enumerate &lt;em&gt;all&lt;&#x2F;em&gt; modules, just the one is enough.&lt;&#x2F;p&gt;
1965&lt;p&gt;For this we want &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;psapi&#x2F;nf-psapi-enumprocessmodules&quot;&gt;&lt;code&gt;EnumProcessModules&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;psapi&#x2F;nf-psapi-getmodulebasenamea&quot;&gt;&lt;code&gt;GetModuleBaseNameA&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. I&#x27;m using the ASCII variant of &lt;code&gt;GetModuleBaseName&lt;&#x2F;code&gt; because I&#x27;m too lazy to deal with UTF-16 of the &lt;code&gt;W&lt;&#x2F;code&gt; (wide, unicode) variants.&lt;&#x2F;p&gt;
1966&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use std::mem::MaybeUninit;
1967use winapi::shared::minwindef::HMODULE;
1968
1969pub fn name(&amp;amp;self) -&amp;gt; io::Result&amp;lt;String&amp;gt; {
1970    let mut module = MaybeUninit::&amp;lt;HMODULE&amp;gt;::uninit();
1971    let mut size = 0;
1972    &#x2F;&#x2F; SAFETY: the pointer is valid and the size is correct.
1973    if unsafe {
1974        winapi::um::psapi::EnumProcessModules(
1975            self.handle.as_ptr(),
1976            module.as_mut_ptr(),
1977            mem::size_of::&amp;lt;HMODULE&amp;gt;() as u32,
1978            &amp;amp;mut size,
1979        )
1980    } == FALSE
1981    {
1982        return Err(io::Error::last_os_error());
1983    }
1984
1985    &#x2F;&#x2F; SAFETY: the call succeeded, so module is initialized.
1986    let module = unsafe { module.assume_init() };
1987    todo!()
1988}
1989&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
1990&lt;p&gt;&lt;code&gt;EnumProcessModules&lt;&#x2F;code&gt; takes a pointer to an array of &lt;code&gt;HMODULE&lt;&#x2F;code&gt;. We could use a &lt;code&gt;Vec&lt;&#x2F;code&gt; of capacity one to hold the single module, but in memory, a pointer a single item can be seen as a pointer to an array of items. &lt;code&gt;MaybeUninit&lt;&#x2F;code&gt; helps us reserve enough memory for the one item we need.&lt;&#x2F;p&gt;
1991&lt;p&gt;With the module handle, we can retrieve its base name:&lt;&#x2F;p&gt;
1992&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;let mut buffer = Vec::&amp;lt;u8&amp;gt;::with_capacity(64);
1993&#x2F;&#x2F; SAFETY: the handle, module and buffer are all valid.
1994let length = unsafe {
1995    winapi::um::psapi::GetModuleBaseNameA(
1996        self.handle.as_ptr(),
1997        module,
1998        buffer.as_mut_ptr().cast(),
1999        buffer.capacity() as u32,
2000    )
2001};
2002if length == 0 {
2003    return Err(io::Error::last_os_error());
2004}
2005
2006&#x2F;&#x2F; SAFETY: the call succeeded and length represents bytes.
2007unsafe { buffer.set_len(length as usize) };
2008Ok(String::from_utf8(buffer).unwrap())
2009&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2010&lt;p&gt;Similar to how we did with &lt;code&gt;EnumProcesses&lt;&#x2F;code&gt;, we create a buffer that will hold the ASCII string of the module&#x27;s base name&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The call wants us to pass a pointer to a mutable buffer of &lt;code&gt;i8&lt;&#x2F;code&gt;, but Rust&#x27;s &lt;code&gt;String::from_utf8&lt;&#x2F;code&gt; wants a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;&#x2F;code&gt;, so instead we declare a buffer of &lt;code&gt;u8&lt;&#x2F;code&gt; and &lt;code&gt;.cast()&lt;&#x2F;code&gt; the pointer in the call. You could also do this with &lt;code&gt;as _&lt;&#x2F;code&gt;, and Rust would infer the right type, but &lt;code&gt;cast&lt;&#x2F;code&gt; is neat.&lt;&#x2F;p&gt;
2011&lt;p&gt;We &lt;code&gt;unwrap&lt;&#x2F;code&gt; the creation of the UTF-8 string because the buffer should contain only ASCII characters (which are also valid UTF-8). We could use the &lt;code&gt;unsafe&lt;&#x2F;code&gt; variant to create the string, but what if somehow it contains non-ASCII characters? The less &lt;code&gt;unsafe&lt;&#x2F;code&gt;, the better.&lt;&#x2F;p&gt;
2012&lt;p&gt;Let&#x27;s see it in action:&lt;&#x2F;p&gt;
2013&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;fn main() {
2014    enum_proc()
2015        .unwrap()
2016        .into_iter()
2017        .for_each(|pid| match Process::open(pid) {
2018            Ok(proc) =&amp;gt; match proc.name() {
2019                Ok(name) =&amp;gt; println!(&amp;quot;{}: {}&amp;quot;, pid, name),
2020                Err(e) =&amp;gt; println!(&amp;quot;{}: (failed to get name: {})&amp;quot;, pid, e),
2021            },
2022            Err(e) =&amp;gt; eprintln!(&amp;quot;failed to open {}: {}&amp;quot;, pid, e),
2023        });
2024}
2025&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2026&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
2027   Compiling memo v0.1.0
2028    Finished dev [unoptimized + debuginfo] target(s) in 0.32s
2029     Running `target\debug\memo.exe`
2030failed to open 0: The parameter is incorrect. (os error 87)
2031failed to open 4: Access is denied. (os error 5)
2032...
2033failed to open 5940: Access is denied. (os error 5)
20345608: (failed to get name: Access is denied. (os error 5))
2035...
20361704: (failed to get name: Access is denied. (os error 5))
2037failed to open 868: Access is denied. (os error 5)
2038...
2039&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2040&lt;p&gt;That&#x27;s not good. What&#x27;s up with that? Maybe…&lt;&#x2F;p&gt;
2041&lt;blockquote&gt;
2042&lt;p&gt;The handle must have the &lt;code&gt;PROCESS_QUERY_INFORMATION&lt;&#x2F;code&gt; and &lt;code&gt;PROCESS_VM_READ&lt;&#x2F;code&gt; access rights.&lt;&#x2F;p&gt;
2043&lt;&#x2F;blockquote&gt;
2044&lt;p&gt;…I should&#x27;ve read the documentation. Okay, fine:&lt;&#x2F;p&gt;
2045&lt;pre&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;use winapi::um::winnt;
2046OpenProcess(winnt::PROCESS_QUERY_INFORMATION | winnt::PROCESS_VM_READ, ...)
2047&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2048&lt;pre&gt;&lt;code&gt;&amp;gt;cargo run
2049   Compiling memo v0.1.0 (C:\Users\L\Desktop\memo)
2050    Finished dev [unoptimized + debuginfo] target(s) in 0.35s
2051     Running `target\debug\memo.exe`
2052failed to open 0: The parameter is incorrect. (os error 87)
2053failed to open 4: Access is denied. (os error 5)
2054...
20559348: cheatengine-x86_64.exe
20563288: Tutorial-x86_64.exe
20578396: cmd.exe
20584620: firefox.exe
20597964: cargo.exe
206010052: cargo.exe
20615756: memo.exe
2062&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2063&lt;p&gt;Hooray 🎉! There&#x27;s some processes we can&#x27;t open, but that&#x27;s because they&#x27;re system processes. Security works!&lt;&#x2F;p&gt;
2064&lt;h2 id=&quot;finale&quot;&gt;Finale&lt;&#x2F;h2&gt;
2065&lt;p&gt;That was a fairly long post when all we did was print a bunch of pids and their corresponding name. But in all fairness, we also laid out a good foundation for what&#x27;s coming next.&lt;&#x2F;p&gt;
2066&lt;p&gt;You can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lonami&#x2F;memo&quot;&gt;obtain the code for this post&lt;&#x2F;a&gt; over at my GitHub. At the end of every post, the last commit will be tagged, so you can &lt;code&gt;git checkout step1&lt;&#x2F;code&gt; to see the final code for any blog post.&lt;&#x2F;p&gt;
2067&lt;p&gt;In the &lt;a href=&quot;&#x2F;blog&#x2F;woce-2&quot;&gt;next post&lt;&#x2F;a&gt;, we&#x27;ll tackle the second step of the tutorial: Exact Value scanning.&lt;&#x2F;p&gt;
2068&lt;h3 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h3&gt;
2069&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
2070&lt;p&gt;You could say I simply love reinventing the wheel, which I do, but in this case, the codebase contains &lt;em&gt;far&lt;&#x2F;em&gt; more features than we&#x27;re interested in. The (apparent) lack of structure and documentation regarding the code, along with the unfortunate &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cheat-engine&#x2F;cheat-engine&#x2F;issues&#x2F;60&quot;&gt;lack of license&lt;&#x2F;a&gt; for the source code, make it a no-go. There&#x27;s a license, but I think that&#x27;s for the distributed program itself.&lt;&#x2F;p&gt;
2071&lt;&#x2F;div&gt;
2072&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
2073&lt;p&gt;If it turns out that there are more than 1024 processes, our code will be unaware of those extra processes. The documentation suggests to perform the call again with a larger buffer if &lt;code&gt;count == provided capacity&lt;&#x2F;code&gt;, but given I have under 200 processes on my system, it seems unlikely we&#x27;ll reach this limit. If you&#x27;re worried about hitting this limit, simply use a larger limit or retry with a larger vector.&lt;&#x2F;p&gt;
2074&lt;&#x2F;div&gt;
2075&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
2076&lt;p&gt;C code would likely use &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winbase&#x2F;nf-winbase-globalalloc&quot;&gt;&lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; here, but Rust&#x27;s &lt;code&gt;Vec&lt;&#x2F;code&gt; handles the allocation for us, making the code both simpler and more idiomatic. In general, if you see calls to &lt;code&gt;GlobalAlloc&lt;&#x2F;code&gt; when porting some code to Rust, you can probably replace it with a &lt;code&gt;Vec&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2077&lt;&#x2F;div&gt;
2078&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
2079&lt;p&gt;This will be a recurring theme.&lt;&#x2F;p&gt;
2080&lt;&#x2F;div&gt;
2081&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
2082&lt;p&gt;…and similar to &lt;code&gt;EnumProcesses&lt;&#x2F;code&gt;, if the name doesn&#x27;t fit in our buffer, the result will be truncated.&lt;&#x2F;p&gt;
2083&lt;&#x2F;div&gt;
2084</content>
2085	</entry>
2086	<entry xml:lang="en">
2087		<title>Data Mining, Warehousing and Information Retrieval</title>
2088		<published>2020-07-03T00:00:00+00:00</published>
2089		<updated>2020-07-03T00:00:00+00:00</updated>
2090		<link href="https://lonami.dev/blog/university/" type="text/html"/>
2091		<id>https://lonami.dev/blog/university/</id>
2092		<content type="html">&lt;p&gt;During university, there were a few subjects where I had to write blog posts for (either as evaluable tasks or just for fun). I thought it was really fun and I wanted to preserve that work here, with the hopes it&#x27;s interesting to someone.&lt;&#x2F;p&gt;
2093&lt;p&gt;The posts series were auto-generated from the original HTML files and manually anonymized later.&lt;&#x2F;p&gt;
2094&lt;ul&gt;
2095&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;mdad&quot;&gt;Data Mining and Data Warehousing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
2096&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;ribw&quot;&gt;Information Retrieval and Web Search&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
2097&lt;&#x2F;ul&gt;
2098</content>
2099	</entry>
2100	<entry xml:lang="en">
2101		<title>My new computer</title>
2102		<published>2020-06-19T00:00:00+00:00</published>
2103		<updated>2020-07-03T00:00:00+00:00</updated>
2104		<link href="https://lonami.dev/blog/new-computer/" type="text/html"/>
2105		<id>https://lonami.dev/blog/new-computer/</id>
2106		<content type="html">&lt;p&gt;This post will be mostly me ranting about setting up a new laptop, but I also just want to share my upgrade. If you&#x27;re considering installing Arch Linux with dual-boot for Windows, maybe this post will help. Or perhaps you will learn something new to troubleshoot systems in the future. Let&#x27;s begin!&lt;&#x2F;p&gt;
2107&lt;p&gt;Last Sunday, I ordered a Asus Rog Strix G531GT-BQ165 for 900€ (on a 20% discount) with the following specifications:&lt;&#x2F;p&gt;
2108&lt;ul&gt;
2109&lt;li&gt;Intel® Core i7-9750H (6 cores, 12MB cache, 2.6GHz up to 4.5GHz, 64-bit)&lt;&#x2F;li&gt;
2110&lt;li&gt;16GB RAM (8GB*2) DDR4 2666MHz&lt;&#x2F;li&gt;
2111&lt;li&gt;512GB SSD M.2 PCIe® NVMe&lt;&#x2F;li&gt;
2112&lt;li&gt;Display 15.6&amp;quot; (1920x1080&#x2F;16:9) 60Hz&lt;&#x2F;li&gt;
2113&lt;li&gt;Graphics NVIDIA® GeForce® GTX1650 4GB GDDR5 VRAM&lt;&#x2F;li&gt;
2114&lt;li&gt;LAN 10&#x2F;100&#x2F;1000&lt;&#x2F;li&gt;
2115&lt;li&gt;Wi-Fi 5 (802.11ac) 2x2 RangeBoost&lt;&#x2F;li&gt;
2116&lt;li&gt;Bluetooth 5.0&lt;&#x2F;li&gt;
2117&lt;li&gt;48Wh battery with 3 cells&lt;&#x2F;li&gt;
2118&lt;li&gt;3 x USB 3.1 (GEN1)&lt;&#x2F;li&gt;
2119&lt;&#x2F;ul&gt;
2120&lt;p&gt;I was mostly interested in a general upgrade (better processor, disk, more RAM), although the graphics card is a really nice addition which will allow me to take some time off on more games. After using it for a bit, I really love the feel of the keyboard, and I love the lack of numpad! (No sarcasm, I really don&#x27;t like numpads.)&lt;&#x2F;p&gt;
2121&lt;p&gt;This is an upgrade from my previous laptop (Asus X554LA-XX822T), which I won in a competition before entering university in a programming challenge. It has served me really well for the past five years, and had the following specifications:&lt;&#x2F;p&gt;
2122&lt;ul&gt;
2123&lt;li&gt;Intel® Core™ i5-5200U&lt;&#x2F;li&gt;
2124&lt;li&gt;4GB RAM DDR3L 1600MHz (which I upgraded to have 8GB)&lt;&#x2F;li&gt;
2125&lt;li&gt;1TB HDD&lt;&#x2F;li&gt;
2126&lt;li&gt;Display 15.6&amp;quot; (1366x768&#x2F;16:9)&lt;&#x2F;li&gt;
2127&lt;li&gt;Intel® HD Graphics 4400&lt;&#x2F;li&gt;
2128&lt;li&gt;LAN 10&#x2F;100&#x2F;1000&lt;&#x2F;li&gt;
2129&lt;li&gt;Wifi 802.11 bgn&lt;&#x2F;li&gt;
2130&lt;li&gt;Bluetooth 4.0&lt;&#x2F;li&gt;
2131&lt;li&gt;Battery 2 cells&lt;&#x2F;li&gt;
2132&lt;li&gt;1 x USB 2.0&lt;&#x2F;li&gt;
2133&lt;li&gt;2 x USB 3.0&lt;&#x2F;li&gt;
2134&lt;&#x2F;ul&gt;
2135&lt;p&gt;Prior to this one, I had a Lenovo (also won in the same competition of the previous year), and prior to that (just for the sake of history), it was HP Pavilion, AMD A4-3300M processor, which unfortunately ended with heating problems. But that&#x27;s very old now.&lt;&#x2F;p&gt;
2136&lt;h2 id=&quot;laptop-arrival&quot;&gt;Laptop arrival&lt;&#x2F;h2&gt;
2137&lt;p&gt;The laptop arrived 2 days ago at roughly 19:00, which I put charged for 3 hours as the book said. The day after, nightmares began!&lt;&#x2F;p&gt;
2138&lt;p&gt;Trying to boot it the first two times was fun, as it comes with a somewhat loud sound on boot. I don&#x27;t know why they would do this, and I immediately turned it off in the BIOS.&lt;&#x2F;p&gt;
2139&lt;h2 id=&quot;installation-journey&quot;&gt;Installation journey&lt;&#x2F;h2&gt;
2140&lt;p&gt;I spent all of yesterday trying to setup Windows and Arch Linux (and didn&#x27;t even finish, it took me this morning too and even now it&#x27;s only half functional). I absolutely &lt;em&gt;hate&lt;&#x2F;em&gt; the amount of partitions the Windows installer creates on a clean disk. So instead, I first went with Arch Linux, and followed the &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Installation_guide&quot;&gt;installation guide on the Arch wiki&lt;&#x2F;a&gt;. Pre-installation, setting up the wireless network, creating the partitions and formatting them went all good. I decided to avoid GRUB at first and go with rEFInd, but alas I missed a big warning on the wiki and after reboot (I would later find out) it was not mounting root properly, so all I had was whatever was in the Initramfs. Reboot didn&#x27;t work, so I had to hold the power button.&lt;&#x2F;p&gt;
2141&lt;p&gt;Anyway, once the partitions were created, I went to install Windows (there was a lot of back and forth burning different &lt;code&gt;.iso&lt;&#x2F;code&gt; images on the USB, which was a bit annoying because it wasn&#x27;t the fastest thing in the world). This was pretty painless, and the process was standard: select advanced to let me choose the right partition, pick the one, say &amp;quot;no&amp;quot; to everything in the services setup, and done. But this was the first Windows &lt;code&gt;.iso&lt;&#x2F;code&gt; I tried. It was an old revision, and the drivers were causing issues when running (something weird about their &lt;code&gt;.dll&lt;&#x2F;code&gt;, manually installing the &lt;code&gt;.ini&lt;&#x2F;code&gt; driver files seemed to work?). The Nvidia drivers didn&#x27;t want to be installed on such an old revision, after updating everything I could via Windows updates. So back I went to burning a newer Windows &lt;code&gt;.iso&lt;&#x2F;code&gt; and going through the same process again…&lt;&#x2F;p&gt;
2142&lt;p&gt;Once Windows was ready and I verified that I could boot to it correctly, it was time to have a second go at Arch Linux. And I went through the setup at least three times, getting it wrong every single time, formatting root every single time, redownloading the packages every single pain. If only had I known earlier what the issue was!&lt;&#x2F;p&gt;
2143&lt;p&gt;Why bother with Arch? I was pretty happy with Linux Mint, and I lowkey wanted to try NixOS, but I had used Arch before and it&#x27;s a really nice distro overall (up-to-date, has AUR, quite minimal, imperative), except for trying to install rEFInd while chrooted…&lt;&#x2F;p&gt;
2144&lt;p&gt;In the end I managed to get something half-working, I still need to properly configure WiFi and pulseaudio in my system but hey it works.&lt;&#x2F;p&gt;
2145&lt;p&gt;I like to be able to dual-boot Windows and Linux because Linux is amazing for productivity, but unfortunately, some games only work fine on Windows. Might as well have both systems and use one for gaming, while the other is my daily driver.&lt;&#x2F;p&gt;
2146&lt;h2 id=&quot;setting-up-arch-linux&quot;&gt;Setting up Arch Linux&lt;&#x2F;h2&gt;
2147&lt;p&gt;This is the process I followed to install Arch Linux in the end, along with a brief explanation on what I think the things are doing and why we are doing them. I think the wiki could do a better job at this, but I also know it&#x27;s hard to get it right for everyone. Something I do dislike is the link colour, after opening a link it becomes gray and it&#x27;s a lot easier to miss the fact that it is a link in the first place, which was tough when re-reading it because some links actually matter a lot. Furthermore, important information may just be a single line, also easy to skim over. Anyway, on to the installation process…&lt;&#x2F;p&gt;
2148&lt;p&gt;The first thing we want to do is configure our keyboard layout or else the keys won&#x27;t correspond to what we expect:&lt;&#x2F;p&gt;
2149&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;loadkeys es
2150&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2151&lt;p&gt;Because we&#x27;re on a recent system, we want to verify that UEFI works correctly. If we see files listed, then it works fine:&lt;&#x2F;p&gt;
2152&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;ls &#x2F;sys&#x2F;firmware&#x2F;efi&#x2F;efivars
2153&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2154&lt;p&gt;The next thing we want to do is configure the WiFi, because I don&#x27;t have any ethernet cable nearby. To do this, we check what network interfaces our laptop has (we&#x27;re looking for the one prefixed with &amp;quot;w&amp;quot;, presumably for wireless, such as &amp;quot;wlan0&amp;quot; or &amp;quot;wlo1&amp;quot;), we set it up, scan for available wireless network, and finally connect. In my case, the network has WPA security so we rely on &lt;code&gt;wpa_supplicant&lt;&#x2F;code&gt; to connect, passing the SSID (network name) and password:&lt;&#x2F;p&gt;
2155&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;ip link
2156ip link set &amp;lt;IFACE&amp;gt; up
2157iw dev &amp;lt;IFACE&amp;gt; scan | less
2158wpa_supplicant -B -i &amp;lt;IFACE&amp;gt; -c &amp;lt;(wpa_passphrase &amp;lt;SSID&amp;gt; &amp;lt;PASS&amp;gt;)
2159&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2160&lt;p&gt;After that&#x27;s done, pinging an IP address like &amp;quot;1.1.1.1&amp;quot; should Just Work™, but to be able to resolve hostnames, we need to also setup a nameserver. I&#x27;m using Cloudflare&#x27;s, but you could use any other:&lt;&#x2F;p&gt;
2161&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;echo nameserver 1.1.1.1 &amp;gt; &#x2F;etc&#x2F;resolv.conf
2162ping archlinux.org
2163^C
2164&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2165&lt;p&gt;If the ping works, then network works! If you still have issues, you may need to &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Network_configuration#Static_IP_address&quot;&gt;manually configure a static IP address&lt;&#x2F;a&gt; and add a route with the address of your, well, router. This basically shows if we have any address, adds a static address (so people know who we are), shows what route we have, and adds a default one (so our packets know where to go):&lt;&#x2F;p&gt;
2166&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;ip address show
2167ip address add &amp;lt;YOUR ADDR&amp;gt;&#x2F;24 broadcast + dev &amp;lt;IFACE&amp;gt;
2168ip route show
2169ip route add default via &amp;lt;ROUTER ADDR&amp;gt; dev &amp;lt;IFACE&amp;gt;
2170&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2171&lt;p&gt;Now that we have network available, we can enable NTP to synchronize our system time (this may be required for network operations where certificates have a validity period, not sure; in any case nobody wants a wrong system time):&lt;&#x2F;p&gt;
2172&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;timedatectl set-ntp true
2173&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2174&lt;p&gt;After that, we can manage our disk and partitions using &lt;code&gt;fdisk&lt;&#x2F;code&gt;. We want to define partitions to tell the system where it should live. To determine the disk name, we first list them, and then edit it. &lt;code&gt;fdisk&lt;&#x2F;code&gt; is really nice and reminds you at every step that help can be accessed with &amp;quot;m&amp;quot;, which you should constantly use to guide you through.&lt;&#x2F;p&gt;
2175&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;fdisk -l
2176fdisk &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;
2177&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2178&lt;p&gt;The partitions I made are the following:&lt;&#x2F;p&gt;
2179&lt;ul&gt;
2180&lt;li&gt;A 100MB one for the EFI system.&lt;&#x2F;li&gt;
2181&lt;li&gt;A 32GB one for Linux&#x27; root &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; partition.&lt;&#x2F;li&gt;
2182&lt;li&gt;A 200GB one for Linux&#x27; home &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt; partition.&lt;&#x2F;li&gt;
2183&lt;li&gt;The rest was unallocated for Windows because I did this first.&lt;&#x2F;li&gt;
2184&lt;&#x2F;ul&gt;
2185&lt;p&gt;I like to have &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; separate because I can reinstall root without losing anything from home (projects, music, photos, screenshots, videos…).&lt;&#x2F;p&gt;
2186&lt;p&gt;After the partitions are made, we format them in FAT32 and EXT4 which are good defaults for EFI, root and home. They need to have a format, or else they won&#x27;t be usable:&lt;&#x2F;p&gt;
2187&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;mkfs.fat -F32 &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;&amp;lt;PART1&amp;gt;
2188mkfs.ext4 &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;&amp;lt;PART2&amp;gt;
2189mkfs.ext4 &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;&amp;lt;PART3&amp;gt;
2190&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2191&lt;p&gt;Because the laptop was new, there was no risk to lose anything, but if you&#x27;re doing a install on a previous system, be very careful with the partition names. Make sure they match with the ones in &lt;code&gt;fdisk -l&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2192&lt;p&gt;Now that we have usable partitions, we need to mount them or they won&#x27;t be accessible. We can do this with &lt;code&gt;mount&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2193&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;mount &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;&amp;lt;PART2&amp;gt; &#x2F;mnt
2194mkdir &#x2F;mnt&#x2F;efi
2195mount &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;&amp;lt;PART1&amp;gt; &#x2F;mnt&#x2F;efi
2196mkdir &#x2F;mnt&#x2F;home
2197mount &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;&amp;lt;PART3&amp;gt; &#x2F;mnt&#x2F;home
2198&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2199&lt;p&gt;Remember to use the correct partitions while mounting. We mount everything so that the system knows which partitions we care about, which we will let know about later on.&lt;&#x2F;p&gt;
2200&lt;p&gt;Next step is to setup the basic Arch Linux system on root, which can be done with &lt;code&gt;pacstrap&lt;&#x2F;code&gt;. What follows the directory is a list of packages, and you may choose any you wish (at least add &lt;code&gt;base&lt;&#x2F;code&gt;, &lt;code&gt;linux&lt;&#x2F;code&gt; and &lt;code&gt;linux-firmware&lt;&#x2F;code&gt;). These can be installed later, but I&#x27;d recommend having them from the beginning, just in case:&lt;&#x2F;p&gt;
2201&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;pacstrap &#x2F;mnt base linux linux-firmware sudo vim-minimal dhcpcd wpa_supplicant man-db man-pages intel-ucode grub efibootmgr os-prober ntfs-3g
2202&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2203&lt;p&gt;Because my system has an intel CPU, I also installed &lt;code&gt;intel-ucode&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2204&lt;p&gt;Next up is generating the &lt;code&gt;fstab&lt;&#x2F;code&gt; file, which we tell to use UUIDs to be on the safe side through &lt;code&gt;-U&lt;&#x2F;code&gt;. This file is important, because without it the system won&#x27;t know what partitions exist and will happily only boot with the initramfs, without anything of what we just installed at root. Not knowing this made me restart the entire installation process a few times.&lt;&#x2F;p&gt;
2205&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;genfstab -U &#x2F;mnt &amp;gt;&amp;gt; &#x2F;mnt&#x2F;etc&#x2F;fstab
2206&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2207&lt;p&gt;After that&#x27;s done, we can change our root into our mount point and finish up configuration. We setup our timezone (so DST can be handled correctly if needed), synchronize the hardware clock (to persist the current time to the BIOS), uncomment our locales (exit &lt;code&gt;vim&lt;&#x2F;code&gt; by pressing ESC, then type &lt;code&gt;:wq&lt;&#x2F;code&gt; and press enter), generate locale files (which some applications need), configure language and keymap, update the hostname of our laptop and what indicate what &lt;code&gt;localhost&lt;&#x2F;code&gt; means…&lt;&#x2F;p&gt;
2208&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;ln -sf &#x2F;usr&#x2F;share&#x2F;zoneinfo&#x2F;&amp;lt;REGION&amp;gt;&#x2F;&amp;lt;CITY&amp;gt; &#x2F;etc&#x2F;localtime
2209hwclock --systohc
2210vim &#x2F;etc&#x2F;locale.gen
2211locale-gen
2212echo LANG=es_ES.UTF-8 &amp;gt; &#x2F;etc&#x2F;locale.conf
2213echo KEYMAP=es &amp;gt; &#x2F;etc&#x2F;vconsole.conf
2214echo &amp;lt;HOST&amp;gt; &#x2F;etc&#x2F;hostname
2215cat &amp;lt;&amp;lt;EOF &amp;gt; &#x2F;etc&#x2F;hosts
2216127.0.0.1 localhost
2217::1 localhost
2218127.0.1.1 &amp;lt;HOST&amp;gt;.localdomain &amp;lt;HOST&amp;gt;
2219EOF
2220&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2221&lt;p&gt;Really, we could&#x27;ve done all of this later, and the same goes for setting root&#x27;s password with &lt;code&gt;passwd&lt;&#x2F;code&gt; or creating users (some of the groups you probably want are &lt;code&gt;power&lt;&#x2F;code&gt; and &lt;code&gt;wheel&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
2222&lt;p&gt;The important part here is installing GRUB (which also needed the &lt;code&gt;efibootmgr&lt;&#x2F;code&gt; package):&lt;&#x2F;p&gt;
2223&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;grub-install --target=x86_64-efi --efi-directory=&#x2F;efi --bootloader-id=GRUB
2224&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2225&lt;p&gt;If we want GRUB to find our Windows install, we also need the &lt;code&gt;os-prober&lt;&#x2F;code&gt; and &lt;code&gt;ntfs-3g&lt;&#x2F;code&gt; packages that we installed earlier with &lt;code&gt;pacstrap&lt;&#x2F;code&gt;, and with those we need to mount the Windows partition somewhere. It doesn&#x27;t matter where. With that done, we can generate the GRUB configuration file which lists all the boot options:&lt;&#x2F;p&gt;
2226&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;mkdir &#x2F;windows
2227mount &#x2F;dev&#x2F;&amp;lt;DISK&amp;gt;&amp;lt;PART5&amp;gt; &#x2F;windows
2228grub-mkconfig -o &#x2F;boot&#x2F;grub&#x2F;grub.cfg
2229&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2230&lt;p&gt;(In my case, I installed Windows before completing the Arch install, which created an additional partition in between).&lt;&#x2F;p&gt;
2231&lt;p&gt;With GRUB ready, we can exit the chroot and reboot the system, and if all went well, you should be greeted with a choice of operating system to use:&lt;&#x2F;p&gt;
2232&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;exit
2233reboot
2234&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2235&lt;p&gt;If for some reason you need to find what mountpoints were active prior to rebooting (to &lt;code&gt;unmount&lt;&#x2F;code&gt; them for example), you can use &lt;code&gt;findmnt&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2236&lt;p&gt;Before GRUB I tried rEFInd, which as I explained had issues with for missing a warning. Then I tried systemd-boot, which did not pick up Arch at first. That&#x27;s where the several reinstalls come from, I didn&#x27;t want to work with a half-worked system so I mostly redid the entire process quite a few times.&lt;&#x2F;p&gt;
2237&lt;h2 id=&quot;migrating-to-the-new-laptop&quot;&gt;Migrating to the new laptop&lt;&#x2F;h2&gt;
2238&lt;p&gt;I had a external disk formatted with NTFS. Of course, after moving every file I cared about from my previous Linux install caused all the permissions to reset. All my &lt;code&gt;.git&lt;&#x2F;code&gt; repositories, dirty with file permission changes! This is going to take a while to fix, or maybe I should just &lt;code&gt;git config core.fileMode false&lt;&#x2F;code&gt;. Here is a &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;2083563&quot;&gt;lovely command&lt;&#x2F;a&gt; to sort them out on a per-repository basis:&lt;&#x2F;p&gt;
2239&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;git diff --summary | grep --color &#x27;mode change 100644 =&amp;gt; 100755&#x27; | cut -d&#x27; &#x27; -f7- | xargs -d&#x27;\n&#x27; chmod -x
2240&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2241&lt;p&gt;I never realized how much I had stored over the years, but it really was a lot. While moving things to the external disk, I tried to do some cleanup, such as removing some build artifacts which needlessly occupy space, or completely skipping all the binary application files. If I need those I will install them anyway. The process was mostly focused on finding all the projects and program data that I did care about, or even some game saves. Nothing too difficult, but definitely time consuming.&lt;&#x2F;p&gt;
2242&lt;h2 id=&quot;tuning-arch&quot;&gt;Tuning Arch&lt;&#x2F;h2&gt;
2243&lt;p&gt;Now that our system is ready, install &lt;code&gt;pacman-contrib&lt;&#x2F;code&gt; to grab a copy of the &lt;code&gt;rankmirrors&lt;&#x2F;code&gt; speed. It should help speed up the download of whatever packages you want to install, since it will help us &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Mirrors#List_by_speed&quot;&gt;rank the mirrors by download speed&lt;&#x2F;a&gt;. Making a copy of the file is important, otherwise whenever you try to install something it will fail saying it can&#x27;t find anything.&lt;&#x2F;p&gt;
2244&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;cp &#x2F;etc&#x2F;pacman.d&#x2F;mirrorlist &#x2F;etc&#x2F;pacman.d&#x2F;mirrorlist.backup
2245sed -i &#x27;s&#x2F;^#Server&#x2F;Server&#x2F;&#x27; &#x2F;etc&#x2F;pacman.d&#x2F;mirrorlist.backup
2246rankmirrors -n 6 &#x2F;etc&#x2F;pacman.d&#x2F;mirrorlist.backup | tee &#x2F;etc&#x2F;pacman.d&#x2F;mirrorlist
2247&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2248&lt;p&gt;This will take a while, but it should be well worth it. We&#x27;re using &lt;code&gt;tee&lt;&#x2F;code&gt; to see the progress as it goes.&lt;&#x2F;p&gt;
2249&lt;p&gt;Some other packages I installed after I had a working system in no particular order:&lt;&#x2F;p&gt;
2250&lt;ul&gt;
2251&lt;li&gt;&lt;code&gt;xfce4&lt;&#x2F;code&gt; and &lt;code&gt;xorg-server&lt;&#x2F;code&gt;. I just love the simplicity of XFCE.&lt;&#x2F;li&gt;
2252&lt;li&gt;&lt;code&gt;xfce4-whiskermenu-plugin&lt;&#x2F;code&gt;, a really nice start menu.&lt;&#x2F;li&gt;
2253&lt;li&gt;&lt;code&gt;xfce4-pulseaudio-plugin&lt;&#x2F;code&gt; and &lt;code&gt;pavucontrol&lt;&#x2F;code&gt;, to quickly adjust the audio with my mouse.&lt;&#x2F;li&gt;
2254&lt;li&gt;&lt;code&gt;xfce4-taskmanager&lt;&#x2F;code&gt;, a GUI alternative I generally prefer to &lt;code&gt;htop&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
2255&lt;li&gt;&lt;code&gt;pulseaudio&lt;&#x2F;code&gt; and &lt;code&gt;pulseaudio-alsa&lt;&#x2F;code&gt; to get nice integration with XFCE4 and audio mixing.&lt;&#x2F;li&gt;
2256&lt;li&gt;&lt;code&gt;firefox&lt;&#x2F;code&gt;, which comes with fonts too. A really good web browser.&lt;&#x2F;li&gt;
2257&lt;li&gt;&lt;code&gt;git&lt;&#x2F;code&gt;, to commit &lt;del&gt;crimes&lt;&#x2F;del&gt; code.&lt;&#x2F;li&gt;
2258&lt;li&gt;&lt;code&gt;code&lt;&#x2F;code&gt;, a wonderful editor which I used to write this blog entry.&lt;&#x2F;li&gt;
2259&lt;li&gt;&lt;code&gt;nano&lt;&#x2F;code&gt;, so much nicer to write a simple commit message.&lt;&#x2F;li&gt;
2260&lt;li&gt;&lt;code&gt;python&lt;&#x2F;code&gt; and &lt;code&gt;python-pip&lt;&#x2F;code&gt;, my favourite language to toy around ideas or use as a calculator.&lt;&#x2F;li&gt;
2261&lt;li&gt;&lt;code&gt;telegram-desktop&lt;&#x2F;code&gt;, for my needs on sharing memes.&lt;&#x2F;li&gt;
2262&lt;li&gt;&lt;code&gt;cmus&lt;&#x2F;code&gt; and &lt;code&gt;mpv&lt;&#x2F;code&gt;, a simple terminal music player and media player.&lt;&#x2F;li&gt;
2263&lt;li&gt;&lt;code&gt;openssh&lt;&#x2F;code&gt;, to connect into any VPS I have access to.&lt;&#x2F;li&gt;
2264&lt;li&gt;&lt;code&gt;base-devel&lt;&#x2F;code&gt;, necessary to build most projects I&#x27;ll find myself working with (or even compiling some projects Rust which I installed via &lt;code&gt;rustup&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
2265&lt;li&gt;&lt;code&gt;flac&lt;&#x2F;code&gt;, &lt;code&gt;libmad&lt;&#x2F;code&gt;, &lt;code&gt;opus&lt;&#x2F;code&gt;, and &lt;code&gt;libvorbis&lt;&#x2F;code&gt;, to be able to play more audio files.&lt;&#x2F;li&gt;
2266&lt;li&gt;&lt;code&gt;inkscape&lt;&#x2F;code&gt;, to make random drawings.&lt;&#x2F;li&gt;
2267&lt;li&gt;&lt;code&gt;ffmpeg&lt;&#x2F;code&gt;, to convert media or record screen.&lt;&#x2F;li&gt;
2268&lt;li&gt;&lt;code&gt;xclip&lt;&#x2F;code&gt;, to automatically copy screenshots to my clipboard.&lt;&#x2F;li&gt;
2269&lt;li&gt;&lt;code&gt;gvfs&lt;&#x2F;code&gt;, needed by Thunar to handle mounting and having a trash (perma-deletion by default can be nasty sometimes).&lt;&#x2F;li&gt;
2270&lt;li&gt;&lt;code&gt;noto-fonts&lt;&#x2F;code&gt;, &lt;code&gt;noto-fonts-cjk&lt;&#x2F;code&gt;, &lt;code&gt;noto-fonts-extra&lt;&#x2F;code&gt; and &lt;code&gt;noto-fonts-emoji&lt;&#x2F;code&gt;, if you don&#x27;t want missing gliphs everywhere.&lt;&#x2F;li&gt;
2271&lt;li&gt;&lt;code&gt;xfce4-notifyd&lt;&#x2F;code&gt; and &lt;code&gt;libnotify&lt;&#x2F;code&gt;, for notifications.&lt;&#x2F;li&gt;
2272&lt;li&gt;&lt;code&gt;cronie&lt;&#x2F;code&gt;, to be able to &lt;code&gt;crontab -e&lt;&#x2F;code&gt;. Make sure to &lt;code&gt;system enable cronie&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
2273&lt;li&gt;&lt;code&gt;xarchiver&lt;&#x2F;code&gt; (with &lt;code&gt;p7zip&lt;&#x2F;code&gt;, &lt;code&gt;zip&lt;&#x2F;code&gt;, &lt;code&gt;unzip&lt;&#x2F;code&gt; and &lt;code&gt;unrar&lt;&#x2F;code&gt;) to uncompress stuff.&lt;&#x2F;li&gt;
2274&lt;li&gt;&lt;code&gt;xreader&lt;&#x2F;code&gt; to read &lt;code&gt;.pdf&lt;&#x2F;code&gt; files.&lt;&#x2F;li&gt;
2275&lt;li&gt;&lt;code&gt;sqlitebrowser&lt;&#x2F;code&gt; is always nice to tinker around with SQLite databases.&lt;&#x2F;li&gt;
2276&lt;li&gt;&lt;code&gt;jre8-openjdk&lt;&#x2F;code&gt; if you want to run Java applications.&lt;&#x2F;li&gt;
2277&lt;li&gt;&lt;code&gt;smartmontools&lt;&#x2F;code&gt; is nice with a SSD to view your disk statistics.&lt;&#x2F;li&gt;
2278&lt;&#x2F;ul&gt;
2279&lt;p&gt;After that, I configured my Super L key to launch &lt;code&gt;xfce4-popup-whiskermenu&lt;&#x2F;code&gt; so that it opens the application menu, pretty much the same as it would on Windows, moved the panels around and configured them to my needs, and it feels like home once more.&lt;&#x2F;p&gt;
2280&lt;p&gt;I made some mistakes while &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Systemd-networkd&quot;&gt;configuring systemd-networkd&lt;&#x2F;a&gt; and accidentally added a service that was incorrect, which caused boot to wait for it to timeout before completing. My boot time was taking 90 seconds longer because of this! &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;archlinux&#x2F;comments&#x2F;4nv9yi&#x2F;my_arch_greets_me_now_with_a_start_job&#x2F;&quot;&gt;The solution was to remove said service&lt;&#x2F;a&gt;, so this is something to look out for.&lt;&#x2F;p&gt;
2281&lt;p&gt;In order to find what was taking long, I had to edit the &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;kernel_parameters&quot;&gt;kernel parameters&lt;&#x2F;a&gt; to remove the &lt;code&gt;quiet&lt;&#x2F;code&gt; option. I prefer seeing the output on what my computer is doing anyway, because it gives me a sense of progress and most importantly is of great value when things go wrong. Another interesting option is &lt;code&gt;noauto,x-systemd.automount&lt;&#x2F;code&gt;, which makes a disk lazily-mounted. If you have a slow disk, this could help speed things up.&lt;&#x2F;p&gt;
2282&lt;p&gt;If you see a service taking long, you can also use &lt;code&gt;systemd-analyze blame&lt;&#x2F;code&gt; to see what takes the longest, and &lt;code&gt;systemctl list-dependencies&lt;&#x2F;code&gt; is also helpful to find what services are active.&lt;&#x2F;p&gt;
2283&lt;p&gt;My &lt;code&gt;locale charmap&lt;&#x2F;code&gt; was spitting out a bunch of warnings:&lt;&#x2F;p&gt;
2284&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;$ locale charmap
2285locale: Cannot set LC_CTYPE to default locale: No such file or directory
2286locale: Cannot set LC_MESSAGES to default locale: No such file or directory
2287locale: Cannot set LC_ALL to default locale: No such file or directory
2288ANSI_X3.4-1968
2289&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2290&lt;p&gt;…ANSI encoding? Immediately I added the following to &lt;code&gt;~&#x2F;.bashrc&lt;&#x2F;code&gt; and &lt;code&gt;~&#x2F;.profile&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2291&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;export LC_ALL=en_US.UTF-8
2292export LANG=en_US.UTF-8
2293export LANGUAGE=en_US.UTF-8
2294&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2295&lt;p&gt;For some reason, I also had to edit &lt;code&gt;xfce4-terminal&lt;&#x2F;code&gt;&#x27;s preferences in advanced to change the default character encoding to UTF-8. This also solved my issues with pasting things into the terminal, and also proper rendering! I guess pastes were not working because it had some characters that could not be encoded.&lt;&#x2F;p&gt;
2296&lt;p&gt;To have working notifications, I added the following to &lt;code&gt;~&#x2F;.bash_profile&lt;&#x2F;code&gt; after &lt;code&gt;exec startx&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2297&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;systemctl --user start xfce4-notifyd.service
2298&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2299&lt;p&gt;I&#x27;m pretty sure there&#x27;s a better way to do this, or maybe it&#x27;s not even necessary, but this works for me.&lt;&#x2F;p&gt;
2300&lt;p&gt;Some of the other things I had left to do was setting up &lt;code&gt;sccache&lt;&#x2F;code&gt; to speed up Rust builds:&lt;&#x2F;p&gt;
2301&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;cargo install sccache
2302echo export RUSTC_WRAPPER=sccache &amp;gt;&amp;gt; ~&#x2F;.bashrc
2303&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2304&lt;p&gt;Once I had &lt;code&gt;cargo&lt;&#x2F;code&gt; ready, installed &lt;code&gt;hacksaw&lt;&#x2F;code&gt; and &lt;code&gt;shotgun&lt;&#x2F;code&gt; with it to perform screenshots.&lt;&#x2F;p&gt;
2305&lt;p&gt;I also disabled the security delay when downloading files in Firefox because it&#x27;s just annoying, in &lt;code&gt;about:config&lt;&#x2F;code&gt; setting &lt;code&gt;security.dialog_enable_delay&lt;&#x2F;code&gt; to &lt;code&gt;0&lt;&#x2F;code&gt;, and added the &lt;a href=&quot;https:&#x2F;&#x2F;alisdair.mcdiarmid.org&#x2F;kill-sticky-headers&#x2F;&quot;&gt;Kill sticky headers&lt;&#x2F;a&gt; to my bookmarks (you may prefer &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;t-mart&#x2F;kill-sticky&quot;&gt;the updated version&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
2306&lt;p&gt;The &lt;code&gt;utils-linux&lt;&#x2F;code&gt; comes with a &lt;code&gt;fstrim&lt;&#x2F;code&gt; utility to &lt;a href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;index.php&#x2F;Solid_state_drive#Periodic_TRIM&quot;&gt;trim the SSD weekly&lt;&#x2F;a&gt;, which I want enabled via &lt;code&gt;systemctl enable fstrim.timer&lt;&#x2F;code&gt; (you may also want to &lt;code&gt;start&lt;&#x2F;code&gt; it if you don&#x27;t reboot often). For more SSD tips, check &lt;a href=&quot;https:&#x2F;&#x2F;easylinuxtipsproject.blogspot.com&#x2F;p&#x2F;ssd.html&quot;&gt;How to optimize your Solid State Drive&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
2307&lt;p&gt;If the sound is funky prior to reboot, try &lt;code&gt;pulseaudio --kill&lt;&#x2F;code&gt; and &lt;code&gt;pulseaudio --start&lt;&#x2F;code&gt;, or delete &lt;code&gt;~&#x2F;.config&#x2F;pulse&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2308&lt;p&gt;I haven&#x27;t been able to get the brightness keys to work yet, but it&#x27;s not a big deal, because scrolling on the power manager plugin of Xfce does work (and also &lt;code&gt;xbacklight&lt;&#x2F;code&gt; works, or writing directly to &lt;code&gt;&#x2F;sys&#x2F;class&#x2F;backlight&#x2F;*&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
2309&lt;h2 id=&quot;tuning-windows&quot;&gt;Tuning Windows&lt;&#x2F;h2&gt;
2310&lt;p&gt;On the Windows side, I disabled the annoying Windows defender by running (&lt;kbd&gt;Ctrl+R&lt;&#x2F;kbd&gt;) &lt;code&gt;gpedit.msc&lt;&#x2F;code&gt; and editing:&lt;&#x2F;p&gt;
2311&lt;ul&gt;
2312&lt;li&gt;&lt;em&gt;Computer Configuration &amp;gt; Administrative Templates &amp;gt; Windows Components &amp;gt; Windows Defender » Turn off Windows Defender » Enable&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
2313&lt;li&gt;&lt;em&gt;User Configuration &amp;gt; Administrative Templates &amp;gt; Start Menu and Taskbar » Remove Notifications and Action Center » Enable&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
2314&lt;&#x2F;ul&gt;
2315&lt;p&gt;I also updated the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;WindowsLies&#x2F;BlockWindows&#x2F;raw&#x2F;master&#x2F;hosts&quot;&gt;&lt;code&gt;hosts&lt;&#x2F;code&gt; file&lt;&#x2F;a&gt; (located at &lt;code&gt;%windir%\system32\Drivers\etc\hosts&lt;&#x2F;code&gt;) with the hope that it will stop some of the telemetry.&lt;&#x2F;p&gt;
2316&lt;p&gt;Last, to have consistent time on Windows and Linux, I changed the following registry key for a &lt;code&gt;qword&lt;&#x2F;code&gt; with value &lt;code&gt;1&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2317&lt;pre&gt;&lt;code&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal
2318&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2319&lt;p&gt;(The key might not exist, but you can create it if that&#x27;s the case).&lt;&#x2F;p&gt;
2320&lt;p&gt;All this time, my laptop had the keyboard lights on, which have been quite annoying. Apparently, they also can cause &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;ValveIndex&#x2F;comments&#x2F;cm6pos&#x2F;psa_uninstalldisable_aura_sync_lighting_if_you&#x2F;&quot;&gt;massive FPS drops&lt;&#x2F;a&gt;. I headed over to &lt;a href=&quot;https:&#x2F;&#x2F;rog.asus.com&#x2F;downloads&#x2F;&quot;&gt;Asus Rog downloads&lt;&#x2F;a&gt;, selected Aura Sync…&lt;&#x2F;p&gt;
2321&lt;pre&gt;&lt;code class=&quot;language-md&quot; data-lang=&quot;md&quot;&gt;# Not Found
2322
2323The requested URL &#x2F;campaign&#x2F;aura&#x2F;us&#x2F;Sync.html was not found on this server.
2324
2325Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
2326&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2327&lt;p&gt;…great! I&#x27;ll just find the &lt;a href=&quot;https:&#x2F;&#x2F;www.asus.com&#x2F;campaign&#x2F;aura&#x2F;global&#x2F;&quot;&gt;Aura site&lt;&#x2F;a&gt; somewhere else…&lt;&#x2F;p&gt;
2328&lt;pre&gt;&lt;code class=&quot;language-md&quot; data-lang=&quot;md&quot;&gt;# ASUS
2329
2330# We&#x27;ll be back.
2331
2332Hi, our website is temporarily closed for service enhancements.
2333
2334We&#x27;ll be back shortly.Thank you for your patience!
2335&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2336&lt;p&gt;Oh come on. After waiting for the next day, I headed over, downloaded their software, tried to install it and it was an awful experience. It felt like I was purposedly installing malware. It spammed and flashed a lot of &lt;code&gt;cmd&lt;&#x2F;code&gt;&#x27;s on screen as if it was a virus. It was stuck at 100% doing that and then, Windows blue-screened with &lt;code&gt;KERNEL_MODE_HEAP_CORRUPTION&lt;&#x2F;code&gt;. Amazing. How do you screw up this bad?&lt;&#x2F;p&gt;
2337&lt;p&gt;Well, at least rebooting worked. I tried to &lt;a href=&quot;https:&#x2F;&#x2F;answers.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;forum&#x2F;all&#x2F;unable-to-uninstall-asus-aura-sync-utility&#x2F;e9bec36c-e62f-4773-80be-88fb68dace16&quot;&gt;uninstall Aura, but of course that failed&lt;&#x2F;a&gt;. Using the &lt;a href=&quot;https:&#x2F;&#x2F;support.microsoft.com&#x2F;en-us&#x2F;help&#x2F;17588&#x2F;windows-fix-problems-that-block-programs-being-installed-or-removed&quot;&gt;troubleshooter to uninstall programs&lt;&#x2F;a&gt; helped me remove most of the crap that was installed.&lt;&#x2F;p&gt;
2338&lt;p&gt;After searching around how to disable the lights (because &lt;a href=&quot;https:&#x2F;&#x2F;rog.asus.com&#x2F;forum&#x2F;showthread.php?112786-Option-to-Disable-Aura-Lights-on-Strix-G-series-(G531GT)-irrespective-of-OSes&quot;&gt;my BIOS did not have this setting&lt;&#x2F;a&gt;), I stumbled upon &lt;a href=&quot;https:&#x2F;&#x2F;rog.asus.com&#x2F;us&#x2F;innovation&#x2F;armoury_crate&#x2F;&quot;&gt;&amp;quot;Armoury Crate&amp;quot;&lt;&#x2F;a&gt;. Okay, fine, I will install that.&lt;&#x2F;p&gt;
2339&lt;p&gt;The experience wasn&#x27;t much better. It did the same thing with a lot of consoles flashing on screen. And of course, it resulted in another blue-screen, this time &lt;code&gt;KERNEL_SECURITY_CHECK_FAILURE&lt;&#x2F;code&gt;. To finish up, the BSOD kept happening as I rebooted the system. &lt;del&gt;Time to reinstall Windows once more.&lt;&#x2F;del&gt; After booting and crashing a few more times I could get into secure mode and perform the reinstall from there, which saved me from burning the &lt;code&gt;.iso&lt;&#x2F;code&gt; again.&lt;&#x2F;p&gt;
2340&lt;p&gt;Asus software might be good, but the software is utter crap.&lt;&#x2F;p&gt;
2341&lt;p&gt;After trying out &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wroberts&#x2F;rogauracore&quot;&gt;rogauracore&lt;&#x2F;a&gt; (which didn&#x27;t list my model), it worked! I could disable the stupid lights from Linux, and &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;CalcProgrammer1&#x2F;OpenRGB&#x2F;-&#x2F;wikis&#x2F;home&quot;&gt;OpenRGB&lt;&#x2F;a&gt; also works on Windows which may be worth checking out too.&lt;&#x2F;p&gt;
2342&lt;p&gt;Because &lt;code&gt;rougauracore&lt;&#x2F;code&gt; helped me and they linked to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;linuxhw&#x2F;hw-probe&#x2F;blob&#x2F;master&#x2F;README.md#appimage&quot;&gt;hw-probe&lt;&#x2F;a&gt;, I decided to &lt;a href=&quot;https:&#x2F;&#x2F;linux-hardware.org&#x2F;?probe=0e3e48c501&quot;&gt;run it on my system&lt;&#x2F;a&gt;, with the hopes it is useful for other people.&lt;&#x2F;p&gt;
2343&lt;h2 id=&quot;closing-words&quot;&gt;Closing words&lt;&#x2F;h2&gt;
2344&lt;p&gt;I hope the installation journey is at least useful to someone, or that you enjoyed reading about it all. If not, sorry!&lt;&#x2F;p&gt;
2345</content>
2346	</entry>
2347	<entry xml:lang="en">
2348		<title>Tips for Outpost</title>
2349		<published>2020-05-10T00:00:00+00:00</published>
2350		<updated>2020-05-22T00:00:00+00:00</updated>
2351		<link href="https://lonami.dev/blog/tips-outpost/" type="text/html"/>
2352		<id>https://lonami.dev/blog/tips-outpost/</id>
2353		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;1127110&#x2F;Outpost&#x2F;&quot;&gt;Outpost&lt;&#x2F;a&gt; is a fun little game by Open Mid Interactive that has popped in recently in my recommended section of Steam, and I decided to give it a try.&lt;&#x2F;p&gt;
2354&lt;p&gt;It&#x27;s a fun tower-defense game with progression, different graphics and random world generation which makes it quite fun for a few hours. In this post I want to talk about some tips I found useful to get past night 50.&lt;&#x2F;p&gt;
2355&lt;h2 id=&quot;build-pattern&quot;&gt;Build Pattern&lt;&#x2F;h2&gt;
2356&lt;p&gt;At first, you may be inclined to design a checkerboard pattern like the following, where &amp;quot;C&amp;quot; is the Crystal shrine, &amp;quot;S&amp;quot; is a stone launcher and &amp;quot;B&amp;quot; is a booster:&lt;&#x2F;p&gt;
2357&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;tips-outpost&#x2F;outpost-bad-pattern.svg&quot; alt=&quot;Bad Outpost build pattern&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
2358&lt;p&gt;Indeed, this pattern will apply &lt;strong&gt;4&lt;&#x2F;strong&gt; boosts to every turret, but unfortunately, the other 4 slots of the booster are wasted! This is because boosters are able to power 8 different towers, and you really want to maximize that. Here&#x27;s a better design:&lt;&#x2F;p&gt;
2359&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;tips-outpost&#x2F;outpost-good-pattern.svg&quot; alt=&quot;Good Outpost build pattern&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
2360&lt;p&gt;The shrine&#x27;s tower does get boosted, but it&#x27;s still not really worth it to boost it. This pattern works good, and it&#x27;s really easy to tile: just repeat the same 3x3 pattern.&lt;&#x2F;p&gt;
2361&lt;p&gt;Nonetheless, we can do better. What if we applied multiple boosters to the same tower while still applying all 8 boosts?&lt;&#x2F;p&gt;
2362&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;tips-outpost&#x2F;outpost-best-pattern.svg&quot; alt=&quot;Best Outpost build pattern&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
2363&lt;p&gt;That&#x27;s what peak performance looks like. You can actually apply multiple boosters to the same tower, and it works great.&lt;&#x2F;p&gt;
2364&lt;p&gt;Now, is it really worth it building anywhere except around the shrine? Not really. You never know where a boss will come from, so all sides need a lot of defense if you want to stand a chance.&lt;&#x2F;p&gt;
2365&lt;p&gt;The addition of traps in 1.6 is amazing. You want to build these outside your strong &amp;quot;core&amp;quot;, mostly to slow the enemies down so your turrets have more time to finish them off. Don&#x27;t waste boosters on the traps, and build them at a reasonable distance from the center (the sixth tile is a good spot):&lt;&#x2F;p&gt;
2366&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;tips-outpost&#x2F;outpost-trap-pattern.svg&quot; alt=&quot;Trap Outpost build pattern&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
2367&lt;p&gt;If you gather enough materials, you can build more trap and cannon layers outside, roughly at enough distance to slow them for enough duration until they reach the next layer of traps, and so on. Probably a single gap of &amp;quot;cannon, booster, cannon&amp;quot; is enough between trap layers, just not in the center where you need a lot of fire power.&lt;&#x2F;p&gt;
2368&lt;h2 id=&quot;talents&quot;&gt;Talents&lt;&#x2F;h2&gt;
2369&lt;p&gt;Talents are the way progression works in the game. Generally, after a run, you will have enough experience to upgrade nearly all talents of roughly the same tier. However, some are worth upgrading more than others (which provide basically no value).&lt;&#x2F;p&gt;
2370&lt;p&gt;The best ones to upgrade are:&lt;&#x2F;p&gt;
2371&lt;ul&gt;
2372&lt;li&gt;Starting supplies. Amazing to get good tools early.&lt;&#x2F;li&gt;
2373&lt;li&gt;Shrine shield. Very useful to hold against tough bosses.&lt;&#x2F;li&gt;
2374&lt;li&gt;Better buildings (cannon, boosters, bed and traps). They&#x27;re a must to deal the most damage.&lt;&#x2F;li&gt;
2375&lt;li&gt;Better pickaxe. Stone is limited, so better make good use of it.&lt;&#x2F;li&gt;
2376&lt;li&gt;Better chests. They provide an insane amount of resources early.&lt;&#x2F;li&gt;
2377&lt;li&gt;Winter slow. Turrets will have more time to deal damage, it&#x27;s perfect.&lt;&#x2F;li&gt;
2378&lt;li&gt;More time. Useful if you&#x27;re running out, although generally you enter nights early after having a good core anyway.&lt;&#x2F;li&gt;
2379&lt;li&gt;More rocks. Similar to a better pickaxe, more stone is always better.&lt;&#x2F;li&gt;
2380&lt;&#x2F;ul&gt;
2381&lt;p&gt;Some decent ones:&lt;&#x2F;p&gt;
2382&lt;ul&gt;
2383&lt;li&gt;In-shrine turret. It&#x27;s okay to get past the first night without building but not much beyond that.&lt;&#x2F;li&gt;
2384&lt;li&gt;Better axe and greaves. Great to save some energy and really nice quality of life to move around.&lt;&#x2F;li&gt;
2385&lt;li&gt;Tree growth. Normally there&#x27;s enough trees for this not to be an issue but it can save some time gathering wood.&lt;&#x2F;li&gt;
2386&lt;li&gt;Wisps. They&#x27;re half-decent since they can provide materials once you max out or max out expensive gear.&lt;&#x2F;li&gt;
2387&lt;&#x2F;ul&gt;
2388&lt;p&gt;Some okay ones:&lt;&#x2F;p&gt;
2389&lt;ul&gt;
2390&lt;li&gt;Extra XP while playing. Generally not needed due to the way XP scales per night, but can be a good boost.&lt;&#x2F;li&gt;
2391&lt;li&gt;Runestones. Not as reliable as chests but some can grant more energy per day.&lt;&#x2F;li&gt;
2392&lt;&#x2F;ul&gt;
2393&lt;p&gt;Some crap ones:&lt;&#x2F;p&gt;
2394&lt;ul&gt;
2395&lt;li&gt;Boosts for other seasons. I mean, winter is already the best, no use there.&lt;&#x2F;li&gt;
2396&lt;li&gt;Bow. The bow is very useless at the moment, it&#x27;s not worth your experience.&lt;&#x2F;li&gt;
2397&lt;li&gt;More energy per bush. Not really worth hunting for bushes since you will have enough energy to do well.&lt;&#x2F;li&gt;
2398&lt;&#x2F;ul&gt;
2399&lt;h2 id=&quot;turrets&quot;&gt;Turrets&lt;&#x2F;h2&gt;
2400&lt;p&gt;Always build the highest tier, there&#x27;s no point in anything lower than that. You will need to deal a lot of damage in a small area, which means space is a premium.&lt;&#x2F;p&gt;
2401&lt;h2 id=&quot;boosters&quot;&gt;Boosters&lt;&#x2F;h2&gt;
2402&lt;p&gt;If you&#x27;re very early in the game, I recommend alternating both the flag and torch in a checkerboard pattern where the boosters should go in the pattern above. This way your towers will get extra speed and extra range, which works great.&lt;&#x2F;p&gt;
2403&lt;p&gt;When you&#x27;re in mid-game (stone launchers, gears and campfires), I do not recommend using campfires. The issue is their range boost is way too long, and the turrets will miss quite a few shots. It&#x27;s better to put all your power into fire speed for increased DPS, at least near the center. If you manage to build too far out and some of the turrets hardly ever shoot, you may put campfires there.&lt;&#x2F;p&gt;
2404&lt;p&gt;In end-game, of course alternate both of the highest tier upgrades. They are really good, and provide the best benefit &#x2F; cost ratio.&lt;&#x2F;p&gt;
2405&lt;h2 id=&quot;gathering-materials&quot;&gt;Gathering Materials&lt;&#x2F;h2&gt;
2406&lt;p&gt;It is &lt;strong&gt;very&lt;&#x2F;strong&gt; important to use all your energy every day! Otherwise it will go to waste, and you will need a lot of materials.&lt;&#x2F;p&gt;
2407&lt;p&gt;As of 1.6, you can mine two things at once if they&#x27;re close enough! I don&#x27;t know if this is intended or a bug, but it sure is great.&lt;&#x2F;p&gt;
2408&lt;p&gt;Once you&#x27;re in mid-game, your stone-based fort should stand pretty well against the nights on its own. After playing for a while you will notice, if your base can defend a boss, then it will have no issue carrying you through the nights until the next boss. You can (and should!) spend the nights gathering materials, but only when you&#x27;re confident that the night won&#x27;t run out.&lt;&#x2F;p&gt;
2409&lt;p&gt;Before the boss hits (every fifth night), come back to your base and use all of your materials. This is the next fort upgrade that will carry it the five next nights.&lt;&#x2F;p&gt;
2410&lt;p&gt;You may also speed up time during night, but make sure you use all your energy before hand. And also take care, in the current version of the game speeding up time only speeds up monster movement, not the fire rate or projectile speed of your turrets! This means they will miss more shots and can be pretty dangerous. If you&#x27;re speeding up time, consider speeding it up for a little bit, then go back to normal until things are more calm, and repeat.&lt;&#x2F;p&gt;
2411&lt;p&gt;If you&#x27;re in the end-game, try to rush for chests. They provide a huge amount of materials which is really helpful to upgrade all your tools early so you can make sure to get the most out of every rock left in the map.&lt;&#x2F;p&gt;
2412&lt;p&gt;In the end-game, after all stone has been collected, you don&#x27;t really need to use all of your energy anymore. Just enough to have enough wood to build with the remaining stone. This will also be nice with the bow upgrades, which admitedly can get quite powerful, but it&#x27;s best to have a strong fort first.&lt;&#x2F;p&gt;
2413&lt;h2 id=&quot;season&quot;&gt;Season&lt;&#x2F;h2&gt;
2414&lt;p&gt;In my opinion, winter is just the best of the seasons. You don&#x27;t &lt;em&gt;really&lt;&#x2F;em&gt; need that much energy (it gets tiresome), or extra tree drops, or luck. Slower movement means your turrets will be able to shoot enemies for longer, dealing more damage over time, giving them more chance to take enemies out before they reach the shrine.&lt;&#x2F;p&gt;
2415&lt;p&gt;Feel free to re-roll the map a few times (play and exit, or even restart the game) until you get winter if you want to go for The Play.&lt;&#x2F;p&gt;
2416&lt;h2 id=&quot;gear&quot;&gt;Gear&lt;&#x2F;h2&gt;
2417&lt;p&gt;In my opinion, you really should rush for the best pickaxe you can afford. Stone is a limited resource that doesn&#x27;t regrow like trees, so once you run out, it&#x27;s over. Better to make the best use out of it with a good pickaxe!&lt;&#x2F;p&gt;
2418&lt;p&gt;You may also upgrade your greaves, we all known faster movement is a &lt;em&gt;really&lt;&#x2F;em&gt; nice quality of life improvement.&lt;&#x2F;p&gt;
2419&lt;p&gt;Of course, you will eventually upgrade your axe to chop wood (otherwise it&#x27;s wasted energy, really), but it&#x27;s not as much of a priority as the pickaxe.&lt;&#x2F;p&gt;
2420&lt;p&gt;Now, the bow is completely useless. Don&#x27;t bother with it. Your energy is better spent gathering materials to build permanent turrets that deal constant damage while you&#x27;re away, and the damage adds up with every extra turret you build.&lt;&#x2F;p&gt;
2421&lt;p&gt;With regards to items you carry (like sword, or helmet), look for these (from best to worst):&lt;&#x2F;p&gt;
2422&lt;ul&gt;
2423&lt;li&gt;Less minion life.&lt;&#x2F;li&gt;
2424&lt;li&gt;Chance to not consume energy.&lt;&#x2F;li&gt;
2425&lt;li&gt;+1 turret damage.&lt;&#x2F;li&gt;
2426&lt;li&gt;Extra energy.&lt;&#x2F;li&gt;
2427&lt;li&gt;+1 drop from trees or stones.&lt;&#x2F;li&gt;
2428&lt;li&gt;+1 free wood or stone per day.&lt;&#x2F;li&gt;
2429&lt;&#x2F;ul&gt;
2430&lt;p&gt;Less minion life, nothing to say. You will need it near end-game.&lt;&#x2F;p&gt;
2431&lt;p&gt;The chance to not consume energy is better the more energy you have. With a 25% chance not to consume energy, you can think of it as 1 extra energy for every 4 energy you have on average.&lt;&#x2F;p&gt;
2432&lt;p&gt;Turret damage is a tough one, it&#x27;s &lt;em&gt;amazing&lt;&#x2F;em&gt; mid-game (it basically doubles your damage) but falls short once you unlock the cannon where you may prefer other items. Definitely recommended if you&#x27;re getting started. You may even try to roll it on low tiers by dying on the second night, because it&#x27;s that good.&lt;&#x2F;p&gt;
2433&lt;p&gt;Extra energy is really good, because it means you can get more materials before it gets too rough. Make sure you have built at least two beds in the first night! This extra energy will pay of for the many nights to come.&lt;&#x2F;p&gt;
2434&lt;p&gt;The problem with free wood or stone per day is that you have, often, five times as much energy per day. By this I mean you can get easily 5 stone every day, which means 5 extra stone, whereas the other would provide just 1 per night. On a good run, you will get around 50 free stone or 250 extra stone. It&#x27;s a clear winner.&lt;&#x2F;p&gt;
2435&lt;p&gt;In end-game, more quality of life are revealing chests so that you can rush them early, if you like to hunt for them try to make better use of the slot.&lt;&#x2F;p&gt;
2436&lt;h2 id=&quot;closing-words&quot;&gt;Closing words&lt;&#x2F;h2&gt;
2437&lt;p&gt;I hope you enjoy the game as much as I do! Movement is sometimes janky and there&#x27;s the occassional lag spikes, but despite this it should provide at least a few good hours of gameplay. Beware however a good run can take up to an hour!&lt;&#x2F;p&gt;
2438</content>
2439	</entry>
2440	<entry xml:lang="en">
2441		<title>Python ctypes and Windows</title>
2442		<published>2019-06-19T00:00:00+00:00</published>
2443		<updated>2019-06-19T00:00:00+00:00</updated>
2444		<link href="https://lonami.dev/blog/ctypes-and-windows/" type="text/html"/>
2445		<id>https://lonami.dev/blog/ctypes-and-windows/</id>
2446		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;&quot;&gt;Python&lt;&#x2F;a&gt;&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;ctypes.html&quot;&gt;&lt;code&gt;ctypes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is quite a nice library to easily load and invoke C methods available in already-compiled &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Dynamic-link_library&quot;&gt;&lt;code&gt;.dll&lt;&#x2F;code&gt; files&lt;&#x2F;a&gt; without any additional dependencies. And I &lt;em&gt;love&lt;&#x2F;em&gt; depending on as little as possible.&lt;&#x2F;p&gt;
2447&lt;p&gt;In this blog post, we will walk through my endeavors to use &lt;code&gt;ctypes&lt;&#x2F;code&gt; with the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;&quot;&gt;Windows API&lt;&#x2F;a&gt;, and do some cool stuff with it.&lt;&#x2F;p&gt;
2448&lt;p&gt;We will assume some knowledge of C&#x2F;++ and Python, since we will need to read and write a bit of both. Please note that this post is only an introduction to &lt;code&gt;ctypes&lt;&#x2F;code&gt;, and if you need more information you should consult the &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;ctypes.html&quot;&gt;Python&#x27;s documentation for &lt;code&gt;ctypes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
2449&lt;p&gt;While the post focuses on Windows&#x27; API, the code here probably applies to unix-based systems with little modifications.&lt;&#x2F;p&gt;
2450&lt;h2 id=&quot;basics&quot;&gt;Basics&lt;&#x2F;h2&gt;
2451&lt;p&gt;First of all, let&#x27;s learn how to load a library. Let&#x27;s say we want to load &lt;code&gt;User32.dll&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2452&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;import ctypes
2453
2454ctypes.windll.user32
2455&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2456&lt;p&gt;Yes, it&#x27;s that simple. When you access an attribute of &lt;code&gt;windll&lt;&#x2F;code&gt;, said library will load. Since Windows is case-insensitive, we will use lowercase consistently.&lt;&#x2F;p&gt;
2457&lt;p&gt;Calling a function is just as simple. Let&#x27;s say you want to call &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;winuser&#x2F;nf-winuser-setcursorpos&quot;&gt;&lt;code&gt;SetCursorPos&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which is defined as follows:&lt;&#x2F;p&gt;
2458&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;BOOL SetCursorPos(
2459    int X,
2460    int Y
2461);
2462&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2463&lt;p&gt;Okay, it returns a &lt;code&gt;bool&lt;&#x2F;code&gt; and takes two inputs, &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt;. So we can call it like so:&lt;&#x2F;p&gt;
2464&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;ctypes.windll.user32.SetCursorPos(100, 100)
2465&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2466&lt;p&gt;Try it! Your cursor will move!&lt;&#x2F;p&gt;
2467&lt;h2 id=&quot;funky-stuff&quot;&gt;Funky Stuff&lt;&#x2F;h2&gt;
2468&lt;p&gt;We can go a bit more crazy and make it form a spiral:&lt;&#x2F;p&gt;
2469&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;import math
2470import time
2471
2472for i in range(200):
2473    x = int(500 + math.cos(i &#x2F; 5) * i)
2474    y = int(500 + math.sin(i &#x2F; 5) * i)
2475    ctypes.windll.user32.SetCursorPos(x, y)
2476    time.sleep(0.05)
2477&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2478&lt;p&gt;Ah, it&#x27;s always so pleasant to do random stuff when programming. Sure makes it more fun.&lt;&#x2F;p&gt;
2479&lt;h2 id=&quot;complex-structures&quot;&gt;Complex Structures&lt;&#x2F;h2&gt;
2480&lt;p&gt;&lt;code&gt;SetCursorPos&lt;&#x2F;code&gt; was really simple. It took two parameters and they both were integers. Let&#x27;s go with something harder. Let&#x27;s go with &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;winuser&#x2F;nf-winuser-sendinput&quot;&gt;&lt;code&gt;SendInput&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;! Emulating input will be a fun exercise:&lt;&#x2F;p&gt;
2481&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;UINT SendInput(
2482    UINT    cInputs,
2483    LPINPUT pInputs,
2484    int     cbSize
2485);
2486&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2487&lt;p&gt;Okay, &lt;code&gt;LPINPUT&lt;&#x2F;code&gt;, what are you? Microsoft likes to prefix types with what they are. In this case, &lt;code&gt;LP&lt;&#x2F;code&gt; stands for &amp;quot;Long Pointer&amp;quot; (I guess?), so &lt;code&gt;LPINPUT&lt;&#x2F;code&gt; is just a Long Pointer to &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;winuser&#x2F;ns-winuser-taginput&quot;&gt;&lt;code&gt;INPUT&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
2488&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;typedef struct tagINPUT {
2489    DWORD type;
2490    union {
2491        MOUSEINPUT    mi;
2492        KEYBDINPUT    ki;
2493        HARDWAREINPUT hi;
2494    } DUMMYUNIONNAME;
2495} INPUT, *PINPUT, *LPINPUT;
2496&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2497&lt;p&gt;Alright, that&#x27;s new. We have a &lt;code&gt;struct&lt;&#x2F;code&gt; and &lt;code&gt;union&lt;&#x2F;code&gt;, two different concepts. We can define both with &lt;code&gt;ctypes&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2498&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;INPUT_MOUSE = 0
2499INPUT_KEYBOARD = 1
2500INPUT_HARDWARE = 2
2501
2502class INPUT(ctypes.Structure):
2503    _fields_ = [
2504        (&#x27;type&#x27;, ctypes.c_long),
2505        ...
2506    ]
2507&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2508&lt;p&gt;Structures are classes that subclass &lt;code&gt;ctypes.Structure&lt;&#x2F;code&gt;, and you define their fields in the &lt;code&gt;_fields_&lt;&#x2F;code&gt; class-level variable, which is a list of tuples &lt;code&gt;(field name, field type)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2509&lt;p&gt;The C structure had a &lt;code&gt;DWORD type&lt;&#x2F;code&gt;. &lt;code&gt;DWORD&lt;&#x2F;code&gt; is a &lt;code&gt;c_long&lt;&#x2F;code&gt;, and &lt;code&gt;type&lt;&#x2F;code&gt; is a name like any other, which is why we did &lt;code&gt;(&#x27;type&#x27;, ctypes.c_long)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2510&lt;p&gt;But what about the union? It&#x27;s anonymous, and we can&#x27;t make anonymous unions (&lt;em&gt;citation needed&lt;&#x2F;em&gt;) with &lt;code&gt;ctypes&lt;&#x2F;code&gt;. We will give it a concrete name and a type.&lt;&#x2F;p&gt;
2511&lt;p&gt;Before defining the union, we need to define its inner structures, &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;winuser&#x2F;ns-winuser-tagmouseinput&quot;&gt;&lt;code&gt;MOUSEINPUT&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;winuser&#x2F;ns-winuser-tagkeybdinput&quot;&gt;&lt;code&gt;KEYBDINPUT&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;winuser&#x2F;ns-winuser-taghardwareinput&quot;&gt;&lt;code&gt;HARDWAREINPUT&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. We won&#x27;t be using them all, but since they count towards the final struct size (C will choose the largest structure as the final size), we need them, or Windows&#x27; API will get confused and refuse to work (personal experience):&lt;&#x2F;p&gt;
2512&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;class MOUSEINPUT(ctypes.Structure):
2513    _fields_ = [
2514        (&#x27;dx&#x27;, ctypes.c_long),
2515        (&#x27;dy&#x27;, ctypes.c_long),
2516        (&#x27;mouseData&#x27;, ctypes.c_long),
2517        (&#x27;dwFlags&#x27;, ctypes.c_long),
2518        (&#x27;time&#x27;, ctypes.c_long),
2519        (&#x27;dwExtraInfo&#x27;, ctypes.POINTER(ctypes.c_ulong))
2520    ]
2521
2522
2523class KEYBDINPUT(ctypes.Structure):
2524    _fields_ = [
2525        (&#x27;wVk&#x27;, ctypes.c_short),
2526        (&#x27;wScan&#x27;, ctypes.c_short),
2527        (&#x27;dwFlags&#x27;, ctypes.c_long),
2528        (&#x27;time&#x27;, ctypes.c_long),
2529        (&#x27;dwExtraInfo&#x27;, ctypes.POINTER(ctypes.c_ulong))
2530    ]
2531
2532
2533class HARDWAREINPUT(ctypes.Structure):
2534    _fields_ = [
2535        (&#x27;uMsg&#x27;, ctypes.c_long),
2536        (&#x27;wParamL&#x27;, ctypes.c_short),
2537        (&#x27;wParamH&#x27;, ctypes.c_short)
2538    ]
2539
2540
2541class INPUTUNION(ctypes.Union):
2542    _fields_ = [
2543        (&#x27;mi&#x27;, MOUSEINPUT),
2544        (&#x27;ki&#x27;, KEYBDINPUT),
2545        (&#x27;hi&#x27;, HARDWAREINPUT)
2546    ]
2547
2548
2549class INPUT(ctypes.Structure):
2550    _fields_ = [
2551        (&#x27;type&#x27;, ctypes.c_long),
2552        (&#x27;value&#x27;, INPUTUNION)
2553    ]
2554&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2555&lt;p&gt;Some things to note:&lt;&#x2F;p&gt;
2556&lt;ul&gt;
2557&lt;li&gt;Pointers are defined as &lt;code&gt;ctypes.POINTER(inner type)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
2558&lt;li&gt;The field names can be anything you want. You can make them more &amp;quot;pythonic&amp;quot; if you want (such as changing &lt;code&gt;dwExtraInfo&lt;&#x2F;code&gt; for just &lt;code&gt;extra_info&lt;&#x2F;code&gt;), but I chose to stick with the original naming.&lt;&#x2F;li&gt;
2559&lt;li&gt;The union is very similar, but it uses &lt;code&gt;ctypes.Union&lt;&#x2F;code&gt; instead of &lt;code&gt;ctypes.Structure&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
2560&lt;li&gt;We gave a name to the anonymous union, &lt;code&gt;INPUTUNION&lt;&#x2F;code&gt;, and used it inside &lt;code&gt;INPUT&lt;&#x2F;code&gt; with also a made-up name, &lt;code&gt;(&#x27;value&#x27;, INPUTUNION)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
2561&lt;&#x2F;ul&gt;
2562&lt;p&gt;Now that we have all the types we need defined, we can use them:&lt;&#x2F;p&gt;
2563&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;KEYEVENTF_KEYUP = 0x0002
2564
2565def press(vk, down):
2566    inputs = INPUT(type=INPUT_KEYBOARD, value=INPUTUNION(ki=KEYBDINPUT(
2567        wVk=vk,
2568        wScan=0,
2569        dwFlags=0 if down else KEYEVENTF_KEYUP,
2570        time=0,
2571        dwExtraInfo=None
2572    )))
2573    ctypes.windll.user32.SendInput(1, ctypes.byref(inputs), ctypes.sizeof(inputs))
2574
2575
2576for char in &#x27;HELLO&#x27;:
2577    press(ord(char), down=True)
2578    press(ord(char), down=False)
2579&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2580&lt;p&gt;Run it! It will press and release the keys &lt;code&gt;hello&lt;&#x2F;code&gt; to type the word &lt;code&gt;&amp;quot;hello&amp;quot;&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
2581&lt;p&gt;&lt;code&gt;vk&lt;&#x2F;code&gt; stands for &amp;quot;virtual key&amp;quot;. Letters correspond with their upper-case ASCII value, which is what we did above. You can find all the available keys in the page with all the &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;inputdev&#x2F;virtual-key-codes&quot;&gt;Virtual Key Codes&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
2582&lt;h2 id=&quot;dynamic-inputs-and-pointers&quot;&gt;Dynamic Inputs and Pointers&lt;&#x2F;h2&gt;
2583&lt;p&gt;What happens if a method wants something by reference? That is, a pointer to your thing? For example, &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;winuser&#x2F;nf-winuser-getcursorpos&quot;&gt;&lt;code&gt;GetCursorPos&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
2584&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;typedef struct tagPOINT {
2585    LONG x;
2586    LONG y;
2587} POINT, *PPOINT, *NPPOINT, *LPPOINT;
2588
2589BOOL GetCursorPos(
2590    LPPOINT lpPoint
2591);
2592&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2593&lt;p&gt;It wants a Long Pointer to &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;desktop&#x2F;api&#x2F;windef&#x2F;ns-windef-point&quot;&gt;&lt;code&gt;POINT&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. We can do just that with &lt;code&gt;ctypes.byref&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2594&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;class POINT(ctypes.Structure):
2595    _fields_ = [
2596        (&#x27;x&#x27;, ctypes.c_long),
2597        (&#x27;y&#x27;, ctypes.c_long)
2598    ]
2599
2600
2601def get_mouse():
2602    point = POINT()
2603    ctypes.windll.user32.GetCursorPos(ctypes.byref(point))
2604    #                  pass our point by ref ^^^^^
2605    # this lets GetCursorPos fill its x and y fields
2606
2607    return point.x, point.y
2608
2609
2610while True:
2611    print(get_mouse())
2612    time.sleep(0.05)
2613&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2614&lt;p&gt;Now you can track the mouse position! Make sure to &lt;code&gt;Ctrl+C&lt;&#x2F;code&gt; the program when you&#x27;re tired of it.&lt;&#x2F;p&gt;
2615&lt;p&gt;What happens if a method wants a dynamically-sized input?&lt;&#x2F;p&gt;
2616&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;buffer = ctypes.create_string_buffer(size)
2617&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2618&lt;p&gt;In that case, you can create an in-memory &lt;code&gt;buffer&lt;&#x2F;code&gt; of &lt;code&gt;size&lt;&#x2F;code&gt; with &lt;code&gt;ctypes.create_string_buffer&lt;&#x2F;code&gt;. It will return a character array of that size, which you can pass as a pointer directly (without &lt;code&gt;ctypes.byref&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
2619&lt;p&gt;To access the buffer&#x27;s contents, you can use either &lt;code&gt;.raw&lt;&#x2F;code&gt; or &lt;code&gt;.value&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2620&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;entire_buffer_as_bytes = buffer.raw
2621up_until_null = buffer.value
2622&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2623&lt;p&gt;When the method fills in the data, you can &lt;code&gt;cast&lt;&#x2F;code&gt; your buffer back into a pointer of a concrete type:&lt;&#x2F;p&gt;
2624&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;result_ptr = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_long))
2625&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2626&lt;p&gt;And you can de-reference pointers with &lt;code&gt;.contents&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2627&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;first_result = result_ptr.contents
2628&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2629&lt;h2 id=&quot;arrays&quot;&gt;Arrays&lt;&#x2F;h2&gt;
2630&lt;p&gt;Arrays are defined as &lt;code&gt;type * size&lt;&#x2F;code&gt;. Your linter may not like that, and if you don&#x27;t know the size beforehand, consider creating a 0-sized array. For example:&lt;&#x2F;p&gt;
2631&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;# 10 longs
2632ten_longs = (ctypes.c_long * 10)()
2633for i in range(10):
2634    ten_longs[i] = 2 ** i
2635
2636# Unknown size of longs, e.g. inside some Structure
2637longs = (ctypes.c_long * 0)
2638
2639# Now you know how many longs it actually was
2640known_longs = ctypes.cast(
2641    ctypes.byref(longs),
2642    ctypes.POINTER(ctypes.c_long * size)
2643).contents
2644&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2645&lt;p&gt;If there&#x27;s a better way to initialize arrays, please let me know.&lt;&#x2F;p&gt;
2646&lt;h2 id=&quot;wintypes&quot;&gt;wintypes&lt;&#x2F;h2&gt;
2647&lt;p&gt;Under Windows, the &lt;code&gt;ctypes&lt;&#x2F;code&gt; module has a &lt;code&gt;wintypes&lt;&#x2F;code&gt; submodule. This one contains definitions like &lt;code&gt;HWND&lt;&#x2F;code&gt; which may be useful and can be imported as:&lt;&#x2F;p&gt;
2648&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;from ctypes.wintypes import HWND, LPCWSTR, UINT
2649&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2650&lt;h2 id=&quot;callbacks&quot;&gt;Callbacks&lt;&#x2F;h2&gt;
2651&lt;p&gt;Some functions (I&#x27;m looking at you, &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;winuser&#x2F;nf-winuser-enumwindows&quot;&gt;&lt;code&gt;EnumWindows&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;) ask us to pass a callback. In this case, it wants a &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;previous-versions&#x2F;windows&#x2F;desktop&#x2F;legacy&#x2F;ms633498(v=vs.85)&quot;&gt;&lt;code&gt;EnumWindowsProc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
2652&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;BOOL EnumWindows(
2653    WNDENUMPROC lpEnumFunc,
2654    LPARAM      lParam
2655);
2656
2657BOOL CALLBACK EnumWindowsProc(
2658    _In_ HWND   hwnd,
2659    _In_ LPARAM lParam
2660);
2661&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2662&lt;p&gt;The naive approach won&#x27;t work:&lt;&#x2F;p&gt;
2663&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;def callback(hwnd, lParam):
2664    print(hwnd)
2665    return True
2666
2667ctypes.windll.user32.EnumWindows(callback, 0)
2668# ctypes.ArgumentError: argument 1: &amp;lt;class &#x27;TypeError&#x27;&amp;gt;: Don&#x27;t know how to convert parameter 1
2669# Aww.
2670&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2671&lt;p&gt;Instead, you must wrap your function as a C definition like so:&lt;&#x2F;p&gt;
2672&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;from ctypes.wintypes import BOOL, HWND, LPARAM
2673
2674EnumWindowsProc = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
2675
2676def callback(hwnd, lParam):
2677    print(hwnd)
2678    return True
2679
2680# Wrap the function in the C definition
2681callback = EnumWindowsProc(callback)
2682
2683ctypes.windll.user32.EnumWindows(callback, 0)
2684# Yay, it works.
2685&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2686&lt;p&gt;You may have noticed this is what decorators do, wrap the function. So…&lt;&#x2F;p&gt;
2687&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;from ctypes.wintypes import BOOL, HWND, LPARAM
2688
2689@ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
2690def callback(hwnd, lParam):
2691    print(hwnd)
2692    return True
2693
2694ctypes.windll.user32.EnumWindows(callback, 0)
2695&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2696&lt;p&gt;…will also work. And it is a &lt;em&gt;lot&lt;&#x2F;em&gt; fancier.&lt;&#x2F;p&gt;
2697&lt;h2 id=&quot;closing-words&quot;&gt;Closing Words&lt;&#x2F;h2&gt;
2698&lt;p&gt;With the knowledge above and some experimentation, you should be able to call and do (almost) anything you want. That was pretty much all I needed on my project anyway :)&lt;&#x2F;p&gt;
2699&lt;p&gt;We have been letting Python convert Python values into C values, but you can do so explicitly too. For example, you can use &lt;code&gt;ctypes.c_short(17)&lt;&#x2F;code&gt; to make sure to pass that &lt;code&gt;17&lt;&#x2F;code&gt; as a &lt;code&gt;short&lt;&#x2F;code&gt;. And if you have a &lt;code&gt;c_short&lt;&#x2F;code&gt;, you can convert or cast it to its Python &lt;code&gt;.value&lt;&#x2F;code&gt; as &lt;code&gt;some_short.value&lt;&#x2F;code&gt;. The same applies for integers, longs, floats, doubles… pretty much anything, char pointers (strings) included.&lt;&#x2F;p&gt;
2700&lt;p&gt;If you can&#x27;t find something in their online documentation, you can always &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;BurntSushi&#x2F;ripgrep&quot;&gt;&lt;code&gt;rg&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for it in the &lt;code&gt;C:\Program Files (x86)\Windows Kits\10\Include\*&lt;&#x2F;code&gt; directory.&lt;&#x2F;p&gt;
2701&lt;p&gt;Note that the &lt;code&gt;ctypes.Structure&lt;&#x2F;code&gt;&#x27;s that you define can have more methods of your own. For example, you can write them a &lt;code&gt;__str__&lt;&#x2F;code&gt; to easily view its fields, or define a &lt;code&gt;@property&lt;&#x2F;code&gt; to re-interpret some data in a meaningful way.&lt;&#x2F;p&gt;
2702&lt;p&gt;For enumerations, you can pass just the right integer number, make a constant for it, or if you prefer, use a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;enum.html#enum.IntEnum&quot;&gt;&lt;code&gt;enum.IntEnum&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. For example, &lt;a href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows-hardware&#x2F;manufacture&#x2F;desktop&#x2F;dism&#x2F;dismloglevel-enumeration&quot;&gt;&lt;code&gt;DismLogLevel&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; would be:&lt;&#x2F;p&gt;
2703&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;class DismLogLevel(enum.IntEnum):
2704    DismLogErrors = 0
2705    DismLogErrorsWarnings = 1
2706    DismLogErrorsWarningsInfo = 2
2707&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2708&lt;p&gt;And you &lt;em&gt;should&lt;&#x2F;em&gt; be able to pass &lt;code&gt;DismLogLevel.DismLogErrors&lt;&#x2F;code&gt; as the parameter now.&lt;&#x2F;p&gt;
2709&lt;p&gt;If you see a function definition like &lt;code&gt;Function(void)&lt;&#x2F;code&gt;, that&#x27;s C&#x27;s way of saying it takes no parameters, so just call it as &lt;code&gt;Function()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2710&lt;p&gt;Make sure to pass all parameters, even if they seem optional they probably still want a &lt;code&gt;NULL&lt;&#x2F;code&gt; at least, and of course, read the documentation well. Some methods have certain pre-conditions.&lt;&#x2F;p&gt;
2711&lt;p&gt;Have fun hacking!&lt;&#x2F;p&gt;
2712</content>
2713	</entry>
2714	<entry xml:lang="en">
2715		<title>Shattered Pixel Dungeon</title>
2716		<published>2019-06-03T00:00:00+00:00</published>
2717		<updated>2019-06-03T00:00:00+00:00</updated>
2718		<link href="https://lonami.dev/blog/pixel-dungeon/" type="text/html"/>
2719		<id>https://lonami.dev/blog/pixel-dungeon/</id>
2720		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;shatteredpixel.com&#x2F;shatteredpd&#x2F;&quot;&gt;Shattered Pixel Dungeon&lt;&#x2F;a&gt; is the classic roguelike RPG game with randomly-generated dungeons. As a new player, it was a bit frustrating to be constantly killed on the first levels of the dungeon, but with some practice it&#x27;s easy to reach high levels if you can kill the first boss.&lt;&#x2F;p&gt;
2721&lt;h2 id=&quot;basic-tips&quot;&gt;Basic Tips&lt;&#x2F;h2&gt;
2722&lt;p&gt;The game comes with its own tips, but here&#x27;s a short and straight-forward summary:&lt;&#x2F;p&gt;
2723&lt;ul&gt;
2724&lt;li&gt;&lt;strong&gt;Don&#x27;t rush into enemies&lt;&#x2F;strong&gt;. Abuse doors and small corridors to kill them one by one. You can use the clock on the bottom left to wait a turn without moving.&lt;&#x2F;li&gt;
2725&lt;li&gt;&lt;strong&gt;Explore each level at full&lt;&#x2F;strong&gt;. You will find goodies and gain XP while doing so.&lt;&#x2F;li&gt;
2726&lt;li&gt;&lt;strong&gt;Upon finding a special room&lt;&#x2F;strong&gt; (e.g. has a chest but is protected by piranhas), drink all potions that you found in that level until there&#x27;s one that helps you (e.g. be invisible so piranhas leave you alone). There is guaranteed to be a helpful one per level with special rooms.&lt;&#x2F;li&gt;
2727&lt;li&gt;&lt;strong&gt;Drink potions as early as possible&lt;&#x2F;strong&gt;. Harmful potions do less damage on early levels (and if you die, you lose less). This will keep them identified early for the rest of the game.&lt;&#x2F;li&gt;
2728&lt;li&gt;&lt;strong&gt;Read scrolls as early as possible&lt;&#x2F;strong&gt; as well. This will keep them identified. It may be worth to wait until you have an item which may be cursed and until the level is clear, because some scrolls clean curses and others alert enemies.&lt;&#x2F;li&gt;
2729&lt;li&gt;&lt;strong&gt;Food and health are resources&lt;&#x2F;strong&gt; that you have to &lt;em&gt;manage&lt;&#x2F;em&gt;, not keep them always at full. Even if you are starving and taking damage, you may not need to eat &lt;em&gt;just yet&lt;&#x2F;em&gt;, since food is scarce. Eat when you are low on health or in possible danger.&lt;&#x2F;li&gt;
2730&lt;li&gt;&lt;strong&gt;Piranhas&lt;&#x2F;strong&gt;. Seriously, just leave them alone if you are melee. They&#x27;re free food if you&#x27;re playing ranged, though.&lt;&#x2F;li&gt;
2731&lt;li&gt;&lt;strong&gt;Prefer armor over weapons&lt;&#x2F;strong&gt;. And make sure to identify or clean it from curses before wearing anything!&lt;&#x2F;li&gt;
2732&lt;li&gt;&lt;strong&gt;Find a dew vial early&lt;&#x2F;strong&gt;. It&#x27;s often a better idea to store dew (health) for later than to use it as soon as possible.&lt;&#x2F;li&gt;
2733&lt;&#x2F;ul&gt;
2734&lt;h2 id=&quot;bosses&quot;&gt;Bosses&lt;&#x2F;h2&gt;
2735&lt;p&gt;There is a boss every 5 levels.&lt;&#x2F;p&gt;
2736&lt;ul&gt;
2737&lt;li&gt;&lt;strong&gt;Level 5 boss&lt;&#x2F;strong&gt;. Try to stay on water, but don&#x27;t let &lt;em&gt;it&lt;&#x2F;em&gt; stay on water since it will heal. Be careful when he starts enraging.&lt;&#x2F;li&gt;
2738&lt;li&gt;&lt;strong&gt;Level 10 boss&lt;&#x2F;strong&gt;. Ranged weapons are good against it.&lt;&#x2F;li&gt;
2739&lt;li&gt;&lt;strong&gt;Level 15 boss&lt;&#x2F;strong&gt;. I somehow managed to tank it with a health potion.&lt;&#x2F;li&gt;
2740&lt;li&gt;&lt;strong&gt;Level 20 boss&lt;&#x2F;strong&gt;. I didn&#x27;t get this far just yet. You are advised to use scrolls of magic mapping in the last levels to skip straight to the boss, since there&#x27;s nothing else of value.&lt;&#x2F;li&gt;
2741&lt;li&gt;&lt;strong&gt;Level 25 boss&lt;&#x2F;strong&gt;. The final boss. Good job if you made it this far!&lt;&#x2F;li&gt;
2742&lt;&#x2F;ul&gt;
2743&lt;h2 id=&quot;mage&quot;&gt;Mage&lt;&#x2F;h2&gt;
2744&lt;p&gt;If you followed the basic tips, you will sooner or later make use of two scrolls of upgrade in a single run. This will unlock the mage class, which is ridiculously powerful. He starts with a ranged-weapon, a magic missile wand, which is really helpful to keep enemies at a distance. Normally, you want to use this at first to surprise attack them soon, and if you are low on charges, you may go melee on normal enemies if you are confident.&lt;&#x2F;p&gt;
2745&lt;h2 id=&quot;luck&quot;&gt;Luck&lt;&#x2F;h2&gt;
2746&lt;p&gt;This game is all about luck and patience! Some runs will be better than others, and you should thank and pray the RNG gods for them. If you don&#x27;t, they will only give you cursed items and not a single scroll to clean them. So, good luck and enjoy playing!&lt;&#x2F;p&gt;
2747</content>
2748	</entry>
2749	<entry xml:lang="en">
2750		<title>Installing NixOS, Take 2</title>
2751		<published>2019-02-15T00:00:00+00:00</published>
2752		<updated>2019-02-16T00:00:00+00:00</updated>
2753		<link href="https://lonami.dev/blog/installing-nixos-2/" type="text/html"/>
2754		<id>https://lonami.dev/blog/installing-nixos-2/</id>
2755		<content type="html">&lt;p&gt;This is my second take at installing NixOS, after a while being frustrated with Arch Linux and the fact that a few kernel upgrades ago, the system crashed randomly from time to time. &lt;code&gt;journalctl&lt;&#x2F;code&gt; did not have any helpful hints and I thought reinstalling could be worthwhile anyway.&lt;&#x2F;p&gt;
2756&lt;p&gt;This time, I started with more knowledge! The first step is heading to the &lt;a href=&quot;https:&#x2F;&#x2F;nixos.org&quot;&gt;NixOS website&lt;&#x2F;a&gt; and downloading their minimal installation CD for 64 bits. I didn&#x27;t go with their graphical live CD, because their &lt;a href=&quot;https:&#x2F;&#x2F;nixos.org&#x2F;nixos&#x2F;manual&quot;&gt;installation manual&lt;&#x2F;a&gt; is a wonderful resource that guides you nicely.&lt;&#x2F;p&gt;
2757&lt;p&gt;Once you have downloaded their &lt;code&gt;.iso&lt;&#x2F;code&gt;, you should probably verify it&#x27;s &lt;code&gt;sha256sum&lt;&#x2F;code&gt; and make sure that it matches. The easiest thing to do in my opinion is using an USB to burn the image in it. Plug it in and check its device name with &lt;code&gt;fdisk -l&lt;&#x2F;code&gt;. In my case, it was &lt;code&gt;&#x2F;dev&#x2F;sdb&lt;&#x2F;code&gt;, so I went ahead with it and ran &lt;code&gt;dd if=nixos.iso of=&#x2F;dev&#x2F;sdb status=progress&lt;&#x2F;code&gt;. Make sure to run &lt;code&gt;sync&lt;&#x2F;code&gt; once that&#x27;s done.&lt;&#x2F;p&gt;
2758&lt;p&gt;If either &lt;code&gt;dd&lt;&#x2F;code&gt; or &lt;code&gt;sync&lt;&#x2F;code&gt; seem &amp;quot;stuck&amp;quot; in the end, they are just flushing the changes to disk to make sure all is good. This is normal, and depends on your drives.&lt;&#x2F;p&gt;
2759&lt;p&gt;Now, reboot your computer with the USB plugged in and make sure to boot into it. You should be welcome with a pretty screen. Just select the first option and wait until it logs you in as root. Once you&#x27;re there you probably want to &lt;code&gt;loadkeys es&lt;&#x2F;code&gt; or whatever your keyboard layout is, or you will have a hard time with passwords, since the characters are all over the place.&lt;&#x2F;p&gt;
2760&lt;p&gt;In a clean disk, you would normally create the partitions now. In my case, I already had the partitions made (100MB for the EFI system, where &lt;code&gt;&#x2F;boot&lt;&#x2F;code&gt; lives, 40GB for the root &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; partition with my old Linux installation, and 700G for &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt;), so I didn&#x27;t need to do anything here. The manual showcases &lt;code&gt;parted&lt;&#x2F;code&gt;, but I personally use &lt;code&gt;fdisk&lt;&#x2F;code&gt;, which has very helpful help I check every time I use it.&lt;&#x2F;p&gt;
2761&lt;p&gt;&lt;strong&gt;Important&lt;&#x2F;strong&gt;: The &lt;code&gt;XY&lt;&#x2F;code&gt; in &lt;code&gt;&#x2F;dev&#x2F;sdXY&lt;&#x2F;code&gt; is probably different in your system! Make sure you use &lt;code&gt;fdisk -l&lt;&#x2F;code&gt; to see the correct letters and numbers!&lt;&#x2F;p&gt;
2762&lt;p&gt;With the partitions ready in my UEFI system, I formatted both &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;boot&lt;&#x2F;code&gt; just to be safe with &lt;code&gt;mkfs.ext4 -L nixos &#x2F;dev&#x2F;sda2&lt;&#x2F;code&gt; and &lt;code&gt;mkfs.fat -F 32 -n boot &#x2F;dev&#x2F;sda1&lt;&#x2F;code&gt; (remember that these are the letters and numbers used in my partition scheme). Don&#x27;t worry about the warning in the second command regarding lowercase letters and Windows. It&#x27;s not really an issue.&lt;&#x2F;p&gt;
2763&lt;p&gt;Now, since we gave each partition a label, we can easily mount them through &lt;code&gt;mount &#x2F;dev&#x2F;disk&#x2F;by-label&#x2F;nixos &#x2F;mnt&lt;&#x2F;code&gt; and, in UEFI systems, be sure to &lt;code&gt;mkdir -p &#x2F;mnt&#x2F;boot&lt;&#x2F;code&gt; and &lt;code&gt;mount &#x2F;dev&#x2F;disk&#x2F;by-label&#x2F;boot &#x2F;mnt&#x2F;boot&lt;&#x2F;code&gt;. I didn&#x27;t bother setting up swap, since I have 8GB of RAM in my laptop and that&#x27;s really enough for my use case.&lt;&#x2F;p&gt;
2764&lt;p&gt;With that done, we will now ask the configuration wizard to do some work for us (in particular, generate a template) with &lt;code&gt;nixos-generate-config --root &#x2F;mnt&lt;&#x2F;code&gt;. This generates a very well documented file that we should edit right now (and this is important!) with whatever editor you prefer. I used &lt;code&gt;vim&lt;&#x2F;code&gt;, but you can change it for &lt;code&gt;nano&lt;&#x2F;code&gt; if you prefer.&lt;&#x2F;p&gt;
2765&lt;p&gt;On to the configuration file, we need to enable a few things, so &lt;code&gt;vim &#x2F;mnt&#x2F;etc&#x2F;nixos&#x2F;configuration.nix&lt;&#x2F;code&gt; and start scrolling down. We want to make sure to uncomment:&lt;&#x2F;p&gt;
2766&lt;pre&gt;&lt;code&gt;# We really want network!
2767networking.wireless.enable = true;
2768
2769# This &amp;quot;fixes&amp;quot; the keyboard layout. Put the one you use.
2770i18n = {
2771consoleKeyMap = &amp;quot;es&amp;quot;;
2772}
2773
2774# Timezones are tricky so let&#x27;s get this right.
2775time.timeZone = &amp;quot;Europe&#x2F;Madrid&amp;quot;;
2776
2777# We *really* want some base packages installed, such as
2778# wpa_supplicant, or we won&#x27;t have a way to connect to the
2779# network once we install...
2780environment.systemPackages = with pkgs; [
2781wpa_supplicant wget curl vim neovim cmus mpv firefox git tdesktop
2782];
2783
2784# Printing is useful, sure, enable CUPS
2785services.printing.enable = true;
2786
2787# We have speakers, let&#x27;s make use of them.
2788sound.enable = true;
2789hardware.pulseaudio.enable = true;
2790
2791# We want the X11 windowing system enabled, in Spanish.
2792services.xserver.enable = true;
2793services.xserver.layout = &amp;quot;es&amp;quot;;
2794
2795# I want a desktop manager in my laptop.
2796# I personally prefer XFCE, but the manual shows plenty
2797# of other options, such as Plasma, i3 WM, or whatever.
2798services.xserver.desktopManager.xfce.enable = true;
2799services.xserver.desktopManager.default = &amp;quot;xfce&amp;quot;;
2800
2801# Touchpad is useful (although sometimes annoying) in a laptop
2802services.xserver.libinput.enable = true;
2803
2804# We don&#x27;t want to do everything as root!
2805users.users.lonami = {
2806isNormalUser = true;
2807uid = 1000;
2808home = &amp;quot;&#x2F;home&#x2F;lonami&amp;quot;;
2809extraGroups = [ &amp;quot;wheel&amp;quot; &amp;quot;networkmanager&amp;quot; &amp;quot;audio&amp;quot; ];
2810};
2811&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2812&lt;p&gt;&lt;em&gt;(Fun fact, I overlooked the configuration file until I wrote this and hadn&#x27;t noticed sound&#x2F;pulseaudio was there. It wasn&#x27;t hard to find online how to enable it though!)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
2813&lt;p&gt;Now, let&#x27;s modify &lt;code&gt;hardware-configuration.nix&lt;&#x2F;code&gt;. But if you have &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt; in a separate partition like me, you should run &lt;code&gt;blkid&lt;&#x2F;code&gt; to figure out its UUID. To avoid typing it out myself, I just ran &lt;code&gt;blkid &amp;gt;&amp;gt; &#x2F;mnt&#x2F;etc&#x2F;nixos&#x2F;hardware-configuration.nix&lt;&#x2F;code&gt; so that I could easily move it around with &lt;code&gt;vim&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
2814&lt;pre&gt;&lt;code&gt;# (stuff...)
2815
2816fileSystems.&amp;quot;&#x2F;home&amp;quot; =
2817{ device = &amp;quot;&#x2F;dev&#x2F;disk&#x2F;by-uuid&#x2F;d344c686-cae7-4dd3-840e-308eddf86608&amp;quot;;
2818fsType = &amp;quot;ext4&amp;quot;;
2819};
2820
2821# (more stuff...)
2822&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2823&lt;p&gt;Note that, obviously, you should put your own partition&#x27;s UUID there. Modifying the configuration is where I think the current NixOS&#x27; manual should have made more emphasis, at this step of the installation. They do detail it below, but that was already too late in my first attempt. Anyway, you can boot from the USB and run &lt;code&gt;nixos-install&lt;&#x2F;code&gt; as many times as you need until you get it working!&lt;&#x2F;p&gt;
2824&lt;p&gt;But before installing, we need to configure the network since there are plenty of things to download. If you want to work from WiFi, you should first figure out the name of your network card with &lt;code&gt;ip link show&lt;&#x2F;code&gt;. In my case it&#x27;s called &lt;code&gt;wlp3s0&lt;&#x2F;code&gt;. So with that knowledge we can run &lt;code&gt;wpa_supplicant -B -i wlp3s0 -c &amp;lt;(wpa_passphrase SSID key)&lt;&#x2F;code&gt;. Be sure to replace both &lt;code&gt;SSID&lt;&#x2F;code&gt; and &lt;code&gt;key&lt;&#x2F;code&gt; with the name of your network and password key, respectively. If they have spaces, surround them in quotes.&lt;&#x2F;p&gt;
2825&lt;p&gt;Another funny pitfall was typing &lt;code&gt;wpa_supplicant&lt;&#x2F;code&gt; in the command above twice (instead of &lt;code&gt;wpa_passphrase&lt;&#x2F;code&gt;). That sure spit out a few funny errors! Once you have ran that, wait a few seconds and &lt;code&gt;ping 1.1.1.1&lt;&#x2F;code&gt; to make sure that you can reach the internet. If you do, &lt;code&gt;^C&lt;&#x2F;code&gt; and let&#x27;s install NixOS!&lt;&#x2F;p&gt;
2826&lt;pre&gt;&lt;code&gt;nixos-install
2827&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
2828&lt;p&gt;Well, that was pretty painless. You can now &lt;code&gt;reboot&lt;&#x2F;code&gt; and enjoy your new, functional system.&lt;&#x2F;p&gt;
2829&lt;h2 id=&quot;afterword&quot;&gt;Afterword&lt;&#x2F;h2&gt;
2830&lt;p&gt;The process of installing NixOS was really painless once you have made sense out of what things mean. I was far more pleased this time than in my previous attempt, despite the four attempts I needed to have it up and running.&lt;&#x2F;p&gt;
2831&lt;p&gt;However not all is so good. I&#x27;m not sure where I went wrong, but the first time I tried with &lt;code&gt;i3&lt;&#x2F;code&gt; instead of &lt;code&gt;xfce&lt;&#x2F;code&gt;, all I was welcome with was a white, small terminal in the top left corner. I even generated a configuration file with &lt;code&gt;i3-config-wizard&lt;&#x2F;code&gt; to make sure it could detect my Mod1&#x2F;Mod4 keys (which, it did), but even after rebooting, my commands weren&#x27;t responding. For example, I couldn&#x27;t manage to open another terminal with &lt;code&gt;Mod1+Enter&lt;&#x2F;code&gt;. I&#x27;m not even sure that I was in &lt;code&gt;i3&lt;&#x2F;code&gt;…&lt;&#x2F;p&gt;
2832&lt;p&gt;In my very first attempt, I pressed &lt;code&gt;Alt+F8&lt;&#x2F;code&gt; as suggested in the welcome message. This took me an offline copy of the manual, which is really nicely done. Funny enough, though, I couldn&#x27;t exit &lt;code&gt;w3m&lt;&#x2F;code&gt;. Both &lt;code&gt;Q&lt;&#x2F;code&gt; and &lt;code&gt;B&lt;&#x2F;code&gt; to quit and take me back wouldn&#x27;t work. Somehow, it kept throwing me back into &lt;code&gt;w3m&lt;&#x2F;code&gt;, so I had to forcibly shutdown.&lt;&#x2F;p&gt;
2833&lt;p&gt;In my second attempt, I also forgot to configure network, so I had no way to download &lt;code&gt;wpa_supplicant&lt;&#x2F;code&gt; without having &lt;code&gt;wpa_supplicant&lt;&#x2F;code&gt; itself to connect my laptop to the network! So, it was important to do that through the USB before installing it (which comes with the program preinstalled), just by making sure to add it in the configuration file.&lt;&#x2F;p&gt;
2834&lt;p&gt;Some other notes, if you can&#x27;t reach the internet, don&#x27;t add any DNS in &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt;. This should be done declaratively in &lt;code&gt;configuration.nix&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2835&lt;p&gt;In the end, I spent the entire afternoon playing around with it, taking breaks and what-not. I still haven&#x27;t figured out why &lt;code&gt;nvim&lt;&#x2F;code&gt; was printing the literal escape character when going from normal to insert mode in the &lt;code&gt;xfce4-terminal&lt;&#x2F;code&gt; (and other actions also made it print this &amp;quot;garbage&amp;quot; to the console), why sometimes the network can reach the internet (and only some sites!) and sometimes not, and how to setup dualboot.&lt;&#x2F;p&gt;
2836&lt;p&gt;But despite all of this, I think it was a worth installing it again. One sure sees things from a different perspective, and gets the chance to write another blog post!&lt;&#x2F;p&gt;
2837&lt;p&gt;If there&#x27;s something I overlooked or that could be done better, or maybe you can explain it differently, please be sure to &lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;contact&quot;&gt;contact me&lt;&#x2F;a&gt; to let me know!&lt;&#x2F;p&gt;
2838&lt;h2 id=&quot;update&quot;&gt;Update&lt;&#x2F;h2&gt;
2839&lt;p&gt;Well, that was surprisingly fast feedback. Thank you very much &lt;a href=&quot;https:&#x2F;&#x2F;bb010g.keybase.pub&#x2F;&quot;&gt;@bb010g&lt;&#x2F;a&gt; for it! As they rightfully pointed out, one can avoid adding &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt; manually to &lt;code&gt;hardware-configuration.nix&lt;&#x2F;code&gt; if you mount it before generating the configuration files. However, the installation process doesn&#x27;t need &lt;code&gt;&#x2F;home&lt;&#x2F;code&gt; mounted, so I didn&#x27;t do it.&lt;&#x2F;p&gt;
2840&lt;p&gt;The second weird issue with &lt;code&gt;w3m&lt;&#x2F;code&gt; is actually a funny one. &lt;code&gt;Alt+F8&lt;&#x2F;code&gt; &lt;em&gt;switches to another TTY&lt;&#x2F;em&gt;! That&#x27;s why quitting the program wouldn&#x27;t do anything. You&#x27;d still be in a different TTY! Normally, this is &lt;code&gt;Ctrl+Alt+FX&lt;&#x2F;code&gt;, so I hadn&#x27;t even thought that this is what could be happening. Anyway, the solution is not quitting the program, but rather going back to the main TTY with &lt;code&gt;Alt+F1&lt;&#x2F;code&gt;. You can switch back and forth all you need to consult the manual.&lt;&#x2F;p&gt;
2841&lt;p&gt;More suggestions are having &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rycee&#x2F;home-manager&quot;&gt;&lt;code&gt;home-manager&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; manage the graphical sessions, since it should be easier to deal with than the alternatives.&lt;&#x2F;p&gt;
2842&lt;p&gt;Despite having followed the guide and having read it over and over several times, it seems like my thoughts in this blog post may be a bit messy. So I recommend you also reading through the guide to have two versions of all this, just in case.&lt;&#x2F;p&gt;
2843&lt;p&gt;Regarding network issues, they use &lt;code&gt;connman&lt;&#x2F;code&gt; so that may be worth checking out.&lt;&#x2F;p&gt;
2844&lt;p&gt;Regarding terminal issues with &lt;code&gt;nvim&lt;&#x2F;code&gt; printing the literal escape character, I was told off for not having checked what my &lt;code&gt;$TERM&lt;&#x2F;code&gt; was. I hadn&#x27;t really looked into it much myself, just complained about it here, so sorry for being annoying about that. A quick search in the &lt;code&gt;nixpkgs&lt;&#x2F;code&gt; repository lets us find &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;NixOS&#x2F;nixpkgs&#x2F;blob&#x2F;release-18.09&#x2F;pkgs&#x2F;applications&#x2F;editors&#x2F;neovim&#x2F;default.nix&quot;&gt;neovim&#x2F;default.nix&lt;&#x2F;a&gt;, with version 0.3.1. Looking at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&quot;&gt;Neovim&#x27;s main repository&lt;&#x2F;a&gt; we can see that this is a bit outdated, but that is fine.&lt;&#x2F;p&gt;
2845&lt;p&gt;If only I had bothered to look at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&#x2F;wiki&#x2F;FAQ#nvim-shows-weird-symbols-2-q-when-changing-modes&quot;&gt;Neovim&#x27;s wiki&lt;&#x2F;a&gt;, (which they found through &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&#x2F;issues&#x2F;7749&quot;&gt;Neovim&#x27;s GitHub issues&lt;&#x2F;a&gt;) I would&#x27;ve seen that some terminals just don&#x27;t support the program properly. The solution is, of course, to use a different terminal emulator with better support or to disable the &lt;code&gt;guicursor&lt;&#x2F;code&gt; in Neovim&#x27;s config.&lt;&#x2F;p&gt;
2846&lt;p&gt;This is a pretty good life lesson. 30 seconds of searching, maybe two minutes and a half for also checking XFCE issues, are often more than enough to troubleshoot your issues. The internet is a big place and more people have surely came across the problem before, so make sure to look online first. In my defense I&#x27;ll say that it didn&#x27;t bother me so much so I didn&#x27;t bother looking for that soon either.&lt;&#x2F;p&gt;
2847</content>
2848	</entry>
2849	<entry xml:lang="en">
2850		<title>Breaking Risk of Rain</title>
2851		<published>2019-01-12T00:00:00+00:00</published>
2852		<updated>2019-01-12T00:00:00+00:00</updated>
2853		<link href="https://lonami.dev/blog/breaking-ror/" type="text/html"/>
2854		<id>https://lonami.dev/blog/breaking-ror/</id>
2855		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;riskofraingame.com&#x2F;&quot;&gt;Risk of Rain&lt;&#x2F;a&gt; is a fun little game you can spend a lot of hours on. It&#x27;s incredibly challenging for new players, and fun once you have learnt the basics. This blog will go through what I&#x27;ve learnt and how to play the game correctly.&lt;&#x2F;p&gt;
2856&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;&#x2F;h2&gt;
2857&lt;p&gt;If you&#x27;re new to the game, you may find it frustrating. You must learn very well to dodge.&lt;&#x2F;p&gt;
2858&lt;p&gt;Your first &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Category:Characters&quot;&gt;character&lt;&#x2F;a&gt; will be &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Commando&quot;&gt;Commando&lt;&#x2F;a&gt;. He&#x27;s actually a very nice character. Use your third skill (dodge) to move faster, pass through large groups of enemies, and negate fall damage.&lt;&#x2F;p&gt;
2859&lt;p&gt;If there are a lot of monsters, remember to &lt;strong&gt;leave&lt;&#x2F;strong&gt; from there! It&#x27;s really important for survival. Most enemies &lt;strong&gt;don&#x27;t do body damage&lt;&#x2F;strong&gt;. Not even the body of the &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Magma_Worm&quot;&gt;Magma Worm&lt;&#x2F;a&gt; or the &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Wandering_Vagrant&quot;&gt;Wandering Vagrant&lt;&#x2F;a&gt; (just dodge the head and projectiles respectively).&lt;&#x2F;p&gt;
2860&lt;p&gt;The first thing you must do is always &lt;strong&gt;rush for the teleporter&lt;&#x2F;strong&gt;. Completing the levels quick will make the game easier. But make sure to take note of &lt;strong&gt;where the chests are&lt;&#x2F;strong&gt;! When you have time (even when the countdown finishes), go back for them and buy as many as you can. Generally, prefer &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Chest&quot;&gt;chests&lt;&#x2F;a&gt; over &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Shrine&quot;&gt;shrines&lt;&#x2F;a&gt; since they may eat all your money.&lt;&#x2F;p&gt;
2861&lt;p&gt;Completing the game on &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Difficulty&quot;&gt;Drizzle&lt;&#x2F;a&gt; is really easy if you follow these tips.&lt;&#x2F;p&gt;
2862&lt;h2 id=&quot;requisites&quot;&gt;Requisites&lt;&#x2F;h2&gt;
2863&lt;p&gt;Before breaking the game, you must obtain several &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Item#Artifacts&quot;&gt;artifacts&lt;&#x2F;a&gt;. We are interested in particular in the following:&lt;&#x2F;p&gt;
2864&lt;ul&gt;
2865&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Sacrifice&quot;&gt;Sacrifice&lt;&#x2F;a&gt;. You really need this one, and may be a bit hard to get. With it, you will be able to farm the first level for 30 minutes and kill the final boss in 30 seconds.&lt;&#x2F;li&gt;
2866&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Command&quot;&gt;Command&lt;&#x2F;a&gt;. You need this unless you want to grind for hours to get enough of the items you really need for the rest of the game. Getting this one is easy.&lt;&#x2F;li&gt;
2867&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Glass&quot;&gt;Glass&lt;&#x2F;a&gt;. Your life will be very small (at the beginning…), but you will be able to one-shot everything easily.&lt;&#x2F;li&gt;
2868&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Kin&quot;&gt;Kin&lt;&#x2F;a&gt; (optional). It makes it easier to obtain a lot of boxes if you restart the first level until you get &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Lemurian&quot;&gt;lemurians&lt;&#x2F;a&gt; or &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Jellyfish&quot;&gt;jellyfish&lt;&#x2F;a&gt; as the monster, since they&#x27;re cheap to spawn.&lt;&#x2F;li&gt;
2869&lt;&#x2F;ul&gt;
2870&lt;p&gt;With those, the game becomes trivial. Playing as &lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Huntress&quot;&gt;Huntress&lt;&#x2F;a&gt; is excellent since she can move at high speed while killing everything on screen.&lt;&#x2F;p&gt;
2871&lt;h2 id=&quot;breaking-the-game&quot;&gt;Breaking the Game&lt;&#x2F;h2&gt;
2872&lt;p&gt;The rest is easy! With the command artifact you want the following items.&lt;&#x2F;p&gt;
2873&lt;h3 id=&quot;common-items&quot;&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Category:Common_Items&quot;&gt;Common Items&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
2874&lt;ul&gt;
2875&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Soldier&amp;#x27;s_Syringe&quot;&gt;Soldier&#x27;s Syringe&lt;&#x2F;a&gt;. &lt;strong&gt;Stack 13&lt;&#x2F;strong&gt; of these and you will triple your attack speed. You can get started with 4 or so.&lt;&#x2F;li&gt;
2876&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Paul&amp;#x27;s_Goat_Hoof&quot;&gt;Paul&#x27;s Goat Hoof&lt;&#x2F;a&gt;. &lt;strong&gt;Stack +30&lt;&#x2F;strong&gt; of these and your movement speed will be insane. You can get a very good speed with 8 or so.&lt;&#x2F;li&gt;
2877&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Crowbar&quot;&gt;Crowbar&lt;&#x2F;a&gt;. &lt;strong&gt;Stack +20&lt;&#x2F;strong&gt; to guarantee you can one-shot bosses.&lt;&#x2F;li&gt;
2878&lt;&#x2F;ul&gt;
2879&lt;p&gt;If you want to be safer:&lt;&#x2F;p&gt;
2880&lt;ul&gt;
2881&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Hermit&amp;#x27;s_Scarf&quot;&gt;Hermit&#x27;s Scarf&lt;&#x2F;a&gt;. &lt;strong&gt;Stack 6&lt;&#x2F;strong&gt; of these to dodge 1&#x2F;3 of the attacks.&lt;&#x2F;li&gt;
2882&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Monster_Tooth&quot;&gt;Monster Tooth&lt;&#x2F;a&gt;. &lt;strong&gt;Stack 9&lt;&#x2F;strong&gt; of these to recover 50 life on kill. This is plenty, since you will be killing &lt;em&gt;a lot&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
2883&lt;&#x2F;ul&gt;
2884&lt;p&gt;If you don&#x27;t have enough and want more fun, get one of these:&lt;&#x2F;p&gt;
2885&lt;ul&gt;
2886&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Gasoline&quot;&gt;Gasoline&lt;&#x2F;a&gt;. Burn the ground on kill, and more will die!&lt;&#x2F;li&gt;
2887&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Headstompers&quot;&gt;Headstompers&lt;&#x2F;a&gt;. They make a pleasing sound on fall, and hurt.&lt;&#x2F;li&gt;
2888&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Lens-Maker&amp;#x27;s_Glasses&quot;&gt;Lens-Maker&#x27;s Glasses&lt;&#x2F;a&gt;. &lt;strong&gt;Stack 14&lt;&#x2F;strong&gt; and you will always deal a critical strike for double the damage.&lt;&#x2F;li&gt;
2889&lt;&#x2F;ul&gt;
2890&lt;h3 id=&quot;uncommon-items&quot;&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Category:Uncommon_Items&quot;&gt;Uncommon Items&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
2891&lt;ul&gt;
2892&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Infusion&quot;&gt;Infusion&lt;&#x2F;a&gt;. You only really need one of this. Your life will skyrocket after a while, since this gives you 1HP per kill.&lt;&#x2F;li&gt;
2893&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Hopoo_Feather&quot;&gt;Hopoo Feather&lt;&#x2F;a&gt;. &lt;strong&gt;Stack +10&lt;&#x2F;strong&gt; of these. You will pretty much be able to fly with so many jumps.&lt;&#x2F;li&gt;
2894&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Guardian&amp;#x27;s_Heart&quot;&gt;Guardian&#x27;s Heart&lt;&#x2F;a&gt;. Not really necessary, but useful for early and late game, since it will absorb infinite damage the first hit.&lt;&#x2F;li&gt;
2895&lt;&#x2F;ul&gt;
2896&lt;p&gt;If, again, you want more fun, get one of these:&lt;&#x2F;p&gt;
2897&lt;ul&gt;
2898&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Ukulele&quot;&gt;Ukelele&lt;&#x2F;a&gt;. Spazz your enemies!&lt;&#x2F;li&gt;
2899&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Will-o&amp;#x27;-the-wisp&quot;&gt;Will-o&#x27;-the-wisp&lt;&#x2F;a&gt;. Explode your enemies!&lt;&#x2F;li&gt;
2900&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Chargefield_Generator&quot;&gt;Chargefield Generator&lt;&#x2F;a&gt;. It should cover your entire screen after a bit, hurting all enemies without moving a finger.&lt;&#x2F;li&gt;
2901&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Golden_Gun&quot;&gt;Golden Gun&lt;&#x2F;a&gt;. You will be rich, so this gives you +40% damage.&lt;&#x2F;li&gt;
2902&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Predatory_Instincts&quot;&gt;Predatory Instincts&lt;&#x2F;a&gt;. If you got 14 glasses, you will always be doing critical strikes, and this will give even more attack speed.&lt;&#x2F;li&gt;
2903&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;56_Leaf_Clover&quot;&gt;56 Leaf Clover&lt;&#x2F;a&gt;. More drops, in case you didn&#x27;t have enough.&lt;&#x2F;li&gt;
2904&lt;&#x2F;ul&gt;
2905&lt;h3 id=&quot;rare-items&quot;&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Category:Rare_Items&quot;&gt;Rare Items&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
2906&lt;ul&gt;
2907&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Ceremonial_Dagger&quot;&gt;Ceremonial Dagger&lt;&#x2F;a&gt;. &lt;strong&gt;Stack +3&lt;&#x2F;strong&gt;, then killing one thing kills another thing and makes a chain reaction.&lt;&#x2F;li&gt;
2908&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Alien_Head&quot;&gt;Alien Head&lt;&#x2F;a&gt;. &lt;strong&gt;Stack 3&lt;&#x2F;strong&gt;, and you will be able to use your abilities more often.&lt;&#x2F;li&gt;
2909&lt;&#x2F;ul&gt;
2910&lt;p&gt;For more fun:&lt;&#x2F;p&gt;
2911&lt;ul&gt;
2912&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;riskofrain.wikia.com&#x2F;wiki&#x2F;Brilliant_Behemoth&quot;&gt;Brilliant Behemoth&lt;&#x2F;a&gt;. Boom boom.&lt;&#x2F;li&gt;
2913&lt;&#x2F;ul&gt;
2914&lt;h2 id=&quot;closing-words&quot;&gt;Closing Words&lt;&#x2F;h2&gt;
2915&lt;p&gt;You can now beat the game in Monsoon solo with any character. Have fun! And be careful with the sadly common crashes.&lt;&#x2F;p&gt;
2916</content>
2917	</entry>
2918	<entry xml:lang="en">
2919		<title>WorldEdit Commands</title>
2920		<published>2018-07-11T00:00:00+00:00</published>
2921		<updated>2018-07-11T00:00:00+00:00</updated>
2922		<link href="https://lonami.dev/blog/world-edit/" type="text/html"/>
2923		<id>https://lonami.dev/blog/world-edit/</id>
2924		<content type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dev.bukkit.org&#x2F;projects&#x2F;worldedit&quot;&gt;WorldEdit&lt;&#x2F;a&gt; is an extremely powerful tool for modifying entire worlds within &lt;a href=&quot;https:&#x2F;&#x2F;minecraft.net&quot;&gt;Minecraft&lt;&#x2F;a&gt;, which can be used as either a mod for your single-player worlds or as a plugin for your &lt;a href=&quot;https:&#x2F;&#x2F;getbukkit.org&#x2F;&quot;&gt;Bukkit&lt;&#x2F;a&gt; servers.&lt;&#x2F;p&gt;
2925&lt;p&gt;This command guide was written for Minecraft 1.12.1, version &lt;a href=&quot;https:&#x2F;&#x2F;dev.bukkit.org&#x2F;projects&#x2F;worldedit&#x2F;files&#x2F;2460562&quot;&gt;6.1.7.3&lt;&#x2F;a&gt;, but should work for newer versions too. All WorldEdit commands can be used with a double slash (&lt;code&gt;&#x2F;&#x2F;&lt;&#x2F;code&gt;) so they don&#x27;t conlict with built-in commands. This means you can get a list of all commands with &lt;code&gt;&#x2F;&#x2F;help&lt;&#x2F;code&gt;. Let&#x27;s explore different categories!&lt;&#x2F;p&gt;
2926&lt;h2 id=&quot;movement&quot;&gt;Movement&lt;&#x2F;h2&gt;
2927&lt;p&gt;In order to edit a world properly you need to learn how to move in said world properly. There are several straightforward commands that let you move:&lt;&#x2F;p&gt;
2928&lt;ul&gt;
2929&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;ascend&lt;&#x2F;code&gt; goes up one floor.&lt;&#x2F;li&gt;
2930&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;descend&lt;&#x2F;code&gt; goes down one floor.&lt;&#x2F;li&gt;
2931&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;thru&lt;&#x2F;code&gt; let&#x27;s you pass through walls.&lt;&#x2F;li&gt;
2932&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;jumpto&lt;&#x2F;code&gt; to go wherever you are looking.&lt;&#x2F;li&gt;
2933&lt;&#x2F;ul&gt;
2934&lt;h2 id=&quot;information&quot;&gt;Information&lt;&#x2F;h2&gt;
2935&lt;p&gt;Knowing your world properly is as important as knowing how to move within it, and will also let you change the information in said world if you need to.&lt;&#x2F;p&gt;
2936&lt;ul&gt;
2937&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;biomelist&lt;&#x2F;code&gt; shows all known biomes.&lt;&#x2F;li&gt;
2938&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;biomeinfo&lt;&#x2F;code&gt; shows the current biome.&lt;&#x2F;li&gt;
2939&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;setbiome&lt;&#x2F;code&gt; lets you change the biome.&lt;&#x2F;li&gt;
2940&lt;&#x2F;ul&gt;
2941&lt;h2 id=&quot;blocks&quot;&gt;Blocks&lt;&#x2F;h2&gt;
2942&lt;p&gt;You can act over all blocks in a radius around you with quite a few commands. Some won&#x27;t actually act over the entire range you specify, so 100 is often a good number.&lt;&#x2F;p&gt;
2943&lt;h3 id=&quot;filling&quot;&gt;Filling&lt;&#x2F;h3&gt;
2944&lt;p&gt;You can fill pools with &lt;code&gt;&#x2F;&#x2F;fill water 100&lt;&#x2F;code&gt; or caves with &lt;code&gt;&#x2F;&#x2F;fillr water 100&lt;&#x2F;code&gt;, both of which act below your feet.&lt;&#x2F;p&gt;
2945&lt;h3 id=&quot;fixing&quot;&gt;Fixing&lt;&#x2F;h3&gt;
2946&lt;p&gt;If the water or lava is buggy use &lt;code&gt;&#x2F;&#x2F;fixwater 100&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;&#x2F;fixlava 100&lt;&#x2F;code&gt; respectively.&lt;&#x2F;p&gt;
2947&lt;p&gt;Some creeper removed the snow or the grass? Fear not, you can use &lt;code&gt;&#x2F;&#x2F;snow 10&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;&#x2F;grass 10&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2948&lt;h3 id=&quot;emptying&quot;&gt;Emptying&lt;&#x2F;h3&gt;
2949&lt;p&gt;You can empty a pool completely with &lt;code&gt;&#x2F;&#x2F;drain 100&lt;&#x2F;code&gt;, remove the snow with &lt;code&gt;&#x2F;&#x2F;thaw 10&lt;&#x2F;code&gt;, and remove fire with &lt;code&gt;&#x2F;&#x2F;ex 10&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2950&lt;h3 id=&quot;removing&quot;&gt;Removing&lt;&#x2F;h3&gt;
2951&lt;p&gt;You can remove blocks above and below you in some area with the &lt;code&gt;&#x2F;&#x2F;removeabove N&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;&#x2F;removebelow N&lt;&#x2F;code&gt;. You probably want to set a limit though, or you could fall off the world with &lt;code&gt;&#x2F;&#x2F;removebelow 1 10&lt;&#x2F;code&gt; for radius and depth. You can also remove near blocks with &lt;code&gt;&#x2F;&#x2F;removenear block 10&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2952&lt;h3 id=&quot;shapes&quot;&gt;Shapes&lt;&#x2F;h3&gt;
2953&lt;p&gt;Making a cylinder (or circle) can be done with through &lt;code&gt;&#x2F;&#x2F;cyl stone 10&lt;&#x2F;code&gt;, a third argument for the height. The radius can be comma-separated to make a ellipses instead, such as &lt;code&gt;&#x2F;&#x2F;cyl stone 5,10&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2954&lt;p&gt;Spheres are done with &lt;code&gt;&#x2F;&#x2F;sphere stone 5&lt;&#x2F;code&gt;. This will build one right at your center, so you can raise it to be on your feet with &lt;code&gt;&#x2F;&#x2F;sphere stone 5 yes&lt;&#x2F;code&gt;. Similar to cylinders, you can comma separate the radius &lt;code&gt;x,y,z&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2955&lt;p&gt;Pyramids can be done with &lt;code&gt;&#x2F;&#x2F;pyramic stone 5&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2956&lt;p&gt;All these commands can be prefixed with &amp;quot;h&amp;quot; to make them hollow. For instance, &lt;code&gt;&#x2F;&#x2F;hsphere stone 10&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2957&lt;h2 id=&quot;regions&quot;&gt;Regions&lt;&#x2F;h2&gt;
2958&lt;h3 id=&quot;basics&quot;&gt;Basics&lt;&#x2F;h3&gt;
2959&lt;p&gt;Operating over an entire region is really important, and the first thing you need to work comfortably with them is a tool to make selections. The default wooden-axe tool can be obtained with &lt;code&gt;&#x2F;&#x2F;wand&lt;&#x2F;code&gt;, but you must be near the blocks to select. You can use a different tool, like a golden axe, to use as your &amp;quot;far wand&amp;quot; (wand usable over distance). Once you have one in your hand type &lt;code&gt;&#x2F;&#x2F;farwand&lt;&#x2F;code&gt; to use it as your &amp;quot;far wand&amp;quot;. You can select the two corners of your region with left and right click. If you have selected the wrong tool, use &lt;code&gt;&#x2F;&#x2F;none&lt;&#x2F;code&gt; to clear it.&lt;&#x2F;p&gt;
2960&lt;p&gt;If there are no blocks but you want to use your current position as a corner, use &lt;code&gt;&#x2F;&#x2F;pos1&lt;&#x2F;code&gt; or 2.&lt;&#x2F;p&gt;
2961&lt;p&gt;If you made a region too small, you can enlarge it with &lt;code&gt;&#x2F;&#x2F;expand 10 up&lt;&#x2F;code&gt;, or &lt;code&gt;&#x2F;&#x2F;expand vert&lt;&#x2F;code&gt; for the entire vertical range, etc., or make it smaller with &lt;code&gt;&#x2F;&#x2F;contract 10 up&lt;&#x2F;code&gt; etc., or &lt;code&gt;&#x2F;&#x2F;inset&lt;&#x2F;code&gt; it to contract in both directions. You can use short-names for the cardinal directions (NSEW).&lt;&#x2F;p&gt;
2962&lt;p&gt;Finally, if you want to move your selection, you can &lt;code&gt;&#x2F;&#x2F;shift 1 north&lt;&#x2F;code&gt; it to wherever you need.&lt;&#x2F;p&gt;
2963&lt;h3 id=&quot;information-1&quot;&gt;Information&lt;&#x2F;h3&gt;
2964&lt;p&gt;You can get the &lt;code&gt;&#x2F;&#x2F;size&lt;&#x2F;code&gt; of the selection or even &lt;code&gt;&#x2F;&#x2F;count torch&lt;&#x2F;code&gt; in some area. If you want to count all blocks, get their distribution &lt;code&gt;&#x2F;&#x2F;distr&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2965&lt;h3 id=&quot;filling-1&quot;&gt;Filling&lt;&#x2F;h3&gt;
2966&lt;p&gt;With a region selected, you can &lt;code&gt;&#x2F;&#x2F;set&lt;&#x2F;code&gt; it to be any block! For instance, you can use &lt;code&gt;&#x2F;&#x2F;set air&lt;&#x2F;code&gt; to clear it entirely. You can use more than one block evenly by separting them with a comma &lt;code&gt;&#x2F;&#x2F;set stone,dirt&lt;&#x2F;code&gt;, or with a custom chance &lt;code&gt;&#x2F;&#x2F;set 20%stone,80%dirt&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2967&lt;p&gt;You can use &lt;code&gt;&#x2F;&#x2F;replace from to&lt;&#x2F;code&gt; instead if you don&#x27;t want to override all blocks in your selection.&lt;&#x2F;p&gt;
2968&lt;p&gt;You can make an hollow set with &lt;code&gt;&#x2F;&#x2F;faces&lt;&#x2F;code&gt;, and if you just want the walls, use &lt;code&gt;&#x2F;&#x2F;walls&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2969&lt;h3 id=&quot;cleaning&quot;&gt;Cleaning&lt;&#x2F;h3&gt;
2970&lt;p&gt;If someone destroyed your wonderful snow landscape, fear not, you can use &lt;code&gt;&#x2F;&#x2F;overlay snow&lt;&#x2F;code&gt; over it (although for this you actually have &lt;code&gt;&#x2F;&#x2F;snow N&lt;&#x2F;code&gt; and its opposite &lt;code&gt;&#x2F;&#x2F;thaw&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
2971&lt;p&gt;If you set some rough area, you can always &lt;code&gt;&#x2F;&#x2F;smooth&lt;&#x2F;code&gt; it, even more than one time with &lt;code&gt;&#x2F;&#x2F;smooth 3&lt;&#x2F;code&gt;. You can get your dirt and stone back with &lt;code&gt;&#x2F;&#x2F;naturalize&lt;&#x2F;code&gt; and put some plants with &lt;code&gt;&#x2F;&#x2F;flora&lt;&#x2F;code&gt; or &lt;code&gt;&#x2F;&#x2F;forest&lt;&#x2F;code&gt;, both of which support a density or even the type for the trees. If you already have the dirt use &lt;code&gt;&#x2F;&#x2F;green&lt;&#x2F;code&gt; instead. If you want some pumpkins, with &lt;code&gt;&#x2F;&#x2F;pumpkins&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2972&lt;h3 id=&quot;moving&quot;&gt;Moving&lt;&#x2F;h3&gt;
2973&lt;p&gt;You can repeat an entire selection many times by stacking them with &lt;code&gt;&#x2F;&#x2F;stack N DIR&lt;&#x2F;code&gt;. This is extremely useful to make things like corridors or elevators. For instance, you can make a small section of the corridor, select it entirely, and then repeat it 10 times with &lt;code&gt;&#x2F;&#x2F;stack 10 north&lt;&#x2F;code&gt;. Or you can make the elevator and then &lt;code&gt;&#x2F;&#x2F;stack 10 up&lt;&#x2F;code&gt;. If you need to also copy the air use &lt;code&gt;&#x2F;&#x2F;stackair&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2974&lt;p&gt;Finally, if you don&#x27;t need to repeat it and simply move it just a bit towards the right direction, you can use &lt;code&gt;&#x2F;&#x2F;move N&lt;&#x2F;code&gt;. The default direction is &amp;quot;me&amp;quot; (towards where you are facing) but you can set one with &lt;code&gt;&#x2F;&#x2F;move 1 up&lt;&#x2F;code&gt; for example.&lt;&#x2F;p&gt;
2975&lt;h3 id=&quot;selecting&quot;&gt;Selecting&lt;&#x2F;h3&gt;
2976&lt;p&gt;You can not only select cuboids. You can also select different shapes, or even just points:&lt;&#x2F;p&gt;
2977&lt;ul&gt;
2978&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;sel cuboid&lt;&#x2F;code&gt; is the default.&lt;&#x2F;li&gt;
2979&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;sel extend&lt;&#x2F;code&gt; expands the default.&lt;&#x2F;li&gt;
2980&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;sel poly&lt;&#x2F;code&gt; first point with left click and right click to add new points.&lt;&#x2F;li&gt;
2981&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;sel ellipsoid&lt;&#x2F;code&gt; first point to select the center and right click to select the different radius.&lt;&#x2F;li&gt;
2982&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;sel sphere&lt;&#x2F;code&gt; first point to select the center and one more right click for the radius.&lt;&#x2F;li&gt;
2983&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;sel cyl&lt;&#x2F;code&gt; for cylinders, first click being the center.&lt;&#x2F;li&gt;
2984&lt;li&gt;&lt;code&gt;&#x2F;&#x2F;sel convex&lt;&#x2F;code&gt; for convex shapes. This one is extremely useful for &lt;code&gt;&#x2F;&#x2F;curve&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
2985&lt;&#x2F;ul&gt;
2986&lt;h2 id=&quot;brushes&quot;&gt;Brushes&lt;&#x2F;h2&gt;
2987&lt;p&gt;Brushes are a way to paint in 3D without first bothering about making a selection, and there are spherical and cylinder brushes with e.g. &lt;code&gt;&#x2F;&#x2F;brush sphere stone 2&lt;&#x2F;code&gt;, or the shorter form &lt;code&gt;&#x2F;&#x2F;br s stone&lt;&#x2F;code&gt;. For cylinder, one must use &lt;code&gt;cyl&lt;&#x2F;code&gt; instead &lt;code&gt;sphere&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2988&lt;p&gt;There also exists a brush to smooth the terrain which can be enabled on the current item with &lt;code&gt;&#x2F;&#x2F;br smooth&lt;&#x2F;code&gt;, which can be used with right-click like any other brush.&lt;&#x2F;p&gt;
2989&lt;h2 id=&quot;clipboard&quot;&gt;Clipboard&lt;&#x2F;h2&gt;
2990&lt;p&gt;Finally, you can copy and cut things around like you would do with normal text with &lt;code&gt;&#x2F;&#x2F;copy&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;&#x2F;cut&lt;&#x2F;code&gt;. The copy is issued from wherever you issue the command, so when you use &lt;code&gt;&#x2F;&#x2F;paste&lt;&#x2F;code&gt;, remember that if you were 4 blocks apart when copying, it will be 4 blocks apart when pasting.&lt;&#x2F;p&gt;
2991&lt;p&gt;The contents of the clipboard can be flipped to wherever you are looking via &lt;code&gt;&#x2F;&#x2F;flip&lt;&#x2F;code&gt;, and can be rotated via the &lt;code&gt;&#x2F;&#x2F;rotate 90&lt;&#x2F;code&gt; command (in degrees).&lt;&#x2F;p&gt;
2992&lt;p&gt;To remove the copy use &lt;code&gt;&#x2F;&#x2F;clearclipboard&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
2993</content>
2994	</entry>
2995	<entry xml:lang="en">
2996		<title>An Introduction to Asyncio</title>
2997		<published>2018-06-13T00:00:00+00:00</published>
2998		<updated>2020-10-03T00:00:00+00:00</updated>
2999		<link href="https://lonami.dev/blog/asyncio/" type="text/html"/>
3000		<id>https://lonami.dev/blog/asyncio/</id>
3001		<content type="html">&lt;h2 id=&quot;index&quot;&gt;Index&lt;&#x2F;h2&gt;
3002&lt;ul&gt;
3003&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;#background&quot;&gt;Background&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
3004&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;#input_output&quot;&gt;Input &#x2F; Output&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
3005&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;#diving_in&quot;&gt;Diving In&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
3006&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;#a_toy_example&quot;&gt;A Toy Example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
3007&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;#a_real_example&quot;&gt;A Real Example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
3008&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;#extra_material&quot;&gt;Extra Material&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
3009&lt;&#x2F;ul&gt;
3010&lt;h2 id=&quot;background&quot;&gt;Background&lt;&#x2F;h2&gt;
3011&lt;p&gt;After seeing some friends struggle with &lt;code&gt;asyncio&lt;&#x2F;code&gt; I decided that it could be a good idea to write a blog post using my own words to explain how I understand the world of asynchronous IO. I will focus on Python&#x27;s &lt;code&gt;asyncio&lt;&#x2F;code&gt; module but this post should apply to any other language easily.&lt;&#x2F;p&gt;
3012&lt;p&gt;So what is &lt;code&gt;asyncio&lt;&#x2F;code&gt; and what makes it good? Why don&#x27;t we just use the old and known threads to run several parts of the code concurrently, at the same time?&lt;&#x2F;p&gt;
3013&lt;p&gt;The first reason is that &lt;code&gt;asyncio&lt;&#x2F;code&gt; makes your code easier to reason about, as opposed to using threads, because the amount of ways in which your code can run grows exponentially. Let&#x27;s see that with an example. Imagine you have this code:&lt;&#x2F;p&gt;
3014&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;def method():
3015	line 1
3016	line 2
3017	line 3
3018	line 4
3019	line 5
3020&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3021&lt;p&gt;And you start two threads to run the method at the same time. What is the order in which the lines of code get executed? The answer is that you can&#x27;t know! The first thread can run the entire method before the second thread even starts. Or it could be the first thread that runs after the second thread. Perhaps both run the &amp;quot;line 1&amp;quot;, and then the line 2. Maybe the first thread runs lines 1 and 2, and then the second thread only runs the line 1 before the first thread finishes.&lt;&#x2F;p&gt;
3022&lt;p&gt;As you can see, any combination of the order in which the lines run is possible. If the lines modify some global shared state, that will get messy quickly.&lt;&#x2F;p&gt;
3023&lt;p&gt;Second, in Python, threads &lt;em&gt;won&#x27;t&lt;&#x2F;em&gt; make your code faster most of the time. It will only increase the concurrency of your program (which is okay if it makes many blocking calls), allowing you to run several things at the same time.&lt;&#x2F;p&gt;
3024&lt;p&gt;If you have a lot of CPU work to do though, threads aren&#x27;t a real advantage. Indeed, your code will probably run slower under the most common Python implementation, CPython, which makes use of a Global Interpreter Lock (GIL) that only lets a thread run at once. The operations won&#x27;t run in parallel!&lt;&#x2F;p&gt;
3025&lt;h2 id=&quot;input-output&quot;&gt;Input &#x2F; Output&lt;&#x2F;h2&gt;
3026&lt;p&gt;Before we go any further, let&#x27;s first stop to talk about input and output, commonly known as &amp;quot;IO&amp;quot;. There are two main ways to perform IO operations, such as reading or writing from a file or a network socket.&lt;&#x2F;p&gt;
3027&lt;p&gt;The first one is known as &amp;quot;blocking IO&amp;quot;. What this means is that, when you try performing IO, the current application thread is going to &lt;em&gt;block&lt;&#x2F;em&gt; until the Operative System can tell you it&#x27;s done. Normally, this is not a problem, since disks are pretty fast anyway, but it can soon become a performance bottleneck. And network IO will be much slower than disk IO!&lt;&#x2F;p&gt;
3028&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;import socket
3029
3030# Setup a network socket and a very simple HTTP request.
3031# By default, sockets are open in blocking mode.
3032sock = socket.socket()
3033request = b&#x27;&#x27;&#x27;HEAD &#x2F; HTTP&#x2F;1.0\r
3034Host: example.com\r
3035\r
3036&#x27;&#x27;&#x27;
3037
3038# &amp;quot;connect&amp;quot; will block until a successful TCP connection
3039# is made to the host &amp;quot;example.com&amp;quot; on port 80.
3040sock.connect((&#x27;example.com&#x27;, 80))
3041
3042# &amp;quot;sendall&amp;quot; will repeatedly call &amp;quot;send&amp;quot; until all the data in &amp;quot;request&amp;quot; is
3043# sent to the host we just connected, which blocks until the data is sent.
3044sock.sendall(request)
3045
3046# &amp;quot;recv&amp;quot; will try to receive up to 1024 bytes from the host, and block until
3047# there is any data to receive (or empty if the host closes the connection).
3048response = sock.recv(1024)
3049
3050# After all those blocking calls, we got out data! These are the headers from
3051# making a HTTP request to example.com.
3052print(response.decode())
3053&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3054&lt;p&gt;Blocking IO offers timeouts, so that you can get control back in your code if the operation doesn&#x27;t finish. Imagine that the remote host doesn&#x27;t want to reply, your code would be stuck for as long as the connection remains alive!&lt;&#x2F;p&gt;
3055&lt;p&gt;But wait, what if we make the timeout small? Very, very small? If we do that, we will never block waiting for an answer. That&#x27;s how asynchronous IO works, and it&#x27;s the opposite of blocking IO (you can also call it non-blocking IO if you want to).&lt;&#x2F;p&gt;
3056&lt;p&gt;How does non-blocking IO work if the IO device needs a while to answer with the data? In that case, the operative system responds with &amp;quot;not ready&amp;quot;, and your application gets control back so it can do other stuff while the IO device completes your request. It works a bit like this:&lt;&#x2F;p&gt;
3057&lt;pre&gt;&lt;code&gt;&amp;lt;app&amp;gt; Hey, I would like to read 16 bytes from this file
3058&amp;lt;OS&amp;gt; Okay, but the disk hasn&#x27;t sent me the data yet
3059&amp;lt;app&amp;gt; Alright, I will do something else then
3060(a lot of computer time passes)
3061&amp;lt;app&amp;gt; Do you have my 16 bytes now?
3062&amp;lt;OS&amp;gt; Yes, here they are! &amp;quot;Hello, world !!\n&amp;quot;
3063&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3064&lt;p&gt;In reality, you can tell the OS to notify you when the data is ready, as opposed to polling (constantly asking the OS whether the data is ready yet or not), which is more efficient.&lt;&#x2F;p&gt;
3065&lt;p&gt;But either way, that&#x27;s the difference between blocking and non-blocking IO, and what matters is that your application gets to run more without ever needing to wait for data to arrive, because the data will be there immediately when you ask, and if it&#x27;s not yet, your app can do more things meanwhile.&lt;&#x2F;p&gt;
3066&lt;h2 id=&quot;diving-in&quot;&gt;Diving In&lt;&#x2F;h2&gt;
3067&lt;p&gt;Now we&#x27;ve seen what blocking and non-blocking IO is, and how threads make your code harder to reason about, but they give concurrency (yet not more speed). Is there any other way to achieve this concurrency that doesn&#x27;t involve threads? Yes! The answer is &lt;code&gt;asyncio&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
3068&lt;p&gt;So how does &lt;code&gt;asyncio&lt;&#x2F;code&gt; help? First we need to understand a very crucial concept before we can dive any deeper, and I&#x27;m talking about the &lt;em&gt;event loop&lt;&#x2F;em&gt;. What is it and why do we need it?&lt;&#x2F;p&gt;
3069&lt;p&gt;You can think of the event loop as a &lt;em&gt;loop&lt;&#x2F;em&gt; that will be responsible for calling your &lt;code&gt;async&lt;&#x2F;code&gt; functions:&lt;&#x2F;p&gt;
3070&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;eventloop.svg&quot; alt=&quot;The Event Loop&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
3071&lt;p&gt;That&#x27;s silly you may think. Now not only we run our code but we also have to run some &amp;quot;event loop&amp;quot;. It doesn&#x27;t sound beneficial at all. What are these events? Well, they are the IO events we talked about before!&lt;&#x2F;p&gt;
3072&lt;p&gt;&lt;code&gt;asyncio&lt;&#x2F;code&gt;&#x27;s event loop is responsible for handling those IO events, such as file is ready, data arrived, flushing is done, and so on. As we saw before, we can make these events non-blocking by setting their timeout to 0.&lt;&#x2F;p&gt;
3073&lt;p&gt;Let&#x27;s say you want to read from 10 files at the same time. You will ask the OS to read data from 10 files, and at first none of the reads will be ready. But the event loop will be constantly asking the OS to know which are done, and when they are done, you will get your data.&lt;&#x2F;p&gt;
3074&lt;p&gt;This has some nice advantages. It means that, instead of waiting for a network request to send you a response or some file, instead of blocking there, the event loop can decide to run other code meanwhile. Whenever the contents are ready, they can be read, and your code can continue. Waiting for the contents to be received is done with the &lt;code&gt;await&lt;&#x2F;code&gt; keyword, and it tells the loop that it can run other code meanwhile:&lt;&#x2F;p&gt;
3075&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;awaitkwd1.svg&quot; alt=&quot;Step 1, await keyword&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
3076&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;asyncio&#x2F;awaitkwd2.svg&quot; alt=&quot;Step 2, await keyword&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
3077&lt;p&gt;Start reading the code of the event loop and follow the arrows. You can see that, in the beginning, there are no events yet, so the loop calls one of your functions. The code runs until it has to &lt;code&gt;await&lt;&#x2F;code&gt; for some IO operation to complete, such as sending a request over the network. The method is &amp;quot;paused&amp;quot; until an event occurs (for example, an &amp;quot;event&amp;quot; occurs when the request has been sent completely).&lt;&#x2F;p&gt;
3078&lt;p&gt;While the first method is busy, the event loop can enter the second method, and run its code until the first &lt;code&gt;await&lt;&#x2F;code&gt;. But it can happen that the event of the second query occurs before the request on the first method, so the event loop can re-enter the second method because it has already sent the query, but the first method isn&#x27;t done sending the request yet.&lt;&#x2F;p&gt;
3079&lt;p&gt;Then, the second method &lt;code&gt;await&lt;&#x2F;code&gt;&#x27;s for an answer, and an event occurs telling the event loop that the request from the first method was sent. The code can be resumed again, until it has to &lt;code&gt;await&lt;&#x2F;code&gt; for a response, and so on. Here&#x27;s an explanation with pseudo-code for this process if you prefer:&lt;&#x2F;p&gt;
3080&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;async def method(request):
3081    prepare request
3082    await send request
3083
3084    await receive request
3085
3086    process request
3087    return result
3088
3089run in parallel (
3090	method with request 1,
3091	method with request 2,
3092)
3093&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3094&lt;p&gt;This is what the event loop will do on the above pseudo-code:&lt;&#x2F;p&gt;
3095&lt;pre&gt;&lt;code&gt;no events pending, can advance
3096
3097enter method with request 1
3098	prepare request
3099	await sending request
3100pause method with request 1
3101
3102no events ready, can advance
3103
3104enter method with request 2
3105	prepare request
3106	await sending request
3107pause method with request 2
3108
3109both requests are paused, cannot advance
3110wait for events
3111event for request 2 arrives (sending request completed)
3112
3113enter method with request 2
3114	await receiving response
3115pause method with request 2
3116
3117event for request 1 arrives (sending request completed)
3118
3119enter method with request 1
3120	await receiving response
3121pause method with request 1
3122
3123...and so on
3124&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3125&lt;p&gt;You may be wondering &amp;quot;okay, but threads work for me, so why should I change?&amp;quot;. There are some important things to note here. The first is that we only need one thread to be running! The event loop decides when and which methods should run. This results in less pressure for the operating system. The second is that we know when it may run other methods. Those are the &lt;code&gt;await&lt;&#x2F;code&gt; keywords! Whenever there is one of those, we know that the loop is able to run other things until the resource (again, like network) becomes ready (when a event occurs telling us it&#x27;s ready to be used without blocking or it has completed).&lt;&#x2F;p&gt;
3126&lt;p&gt;So far, we already have two advantages. We are only using a single thread so the cost for switching between methods is low, and we can easily reason about where our program may interleave operations.&lt;&#x2F;p&gt;
3127&lt;p&gt;Another advantage is that, with the event loop, you can easily schedule when a piece of code should run, such as using the method &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;asyncio-eventloop.html#asyncio.loop.call_at&quot;&gt;&lt;code&gt;loop.call_at&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, without the need for spawning another thread at all.&lt;&#x2F;p&gt;
3128&lt;p&gt;To tell the &lt;code&gt;asyncio&lt;&#x2F;code&gt; to run the two methods shown above, we can use &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;asyncio-future.html#asyncio.ensure_future&quot;&gt;&lt;code&gt;asyncio.ensure_future&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which is a way of saying &amp;quot;I want the future of my method to be ensured&amp;quot;. That is, you want to run your method in the future, whenever the loop is free to do so. This method returns a &lt;code&gt;Future&lt;&#x2F;code&gt; object, so if your method returns a value, you can &lt;code&gt;await&lt;&#x2F;code&gt; this future to retrieve its result.&lt;&#x2F;p&gt;
3129&lt;p&gt;What is a &lt;code&gt;Future&lt;&#x2F;code&gt;? This object represents the value of something that will be there in the future, but might not be there yet. Just like you can &lt;code&gt;await&lt;&#x2F;code&gt; your own &lt;code&gt;async def&lt;&#x2F;code&gt; functions, you can &lt;code&gt;await&lt;&#x2F;code&gt; these &lt;code&gt;Future&lt;&#x2F;code&gt;&#x27;s.&lt;&#x2F;p&gt;
3130&lt;p&gt;The &lt;code&gt;async def&lt;&#x2F;code&gt; functions are also called &amp;quot;coroutines&amp;quot;, and Python does some magic behind the scenes to turn them into such. The coroutines can be &lt;code&gt;await&lt;&#x2F;code&gt;&#x27;ed, and this is what you normally do.&lt;&#x2F;p&gt;
3131&lt;h2 id=&quot;a-toy-example&quot;&gt;A Toy Example&lt;&#x2F;h2&gt;
3132&lt;p&gt;That&#x27;s all about &lt;code&gt;asyncio&lt;&#x2F;code&gt;! Let&#x27;s wrap up with some example code. We will create a server that replies with the text a client sends, but reversed. First, we will show what you could write with normal synchronous code, and then we will port it.&lt;&#x2F;p&gt;
3133&lt;p&gt;Here is the &lt;strong&gt;synchronous version&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
3134&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;# server.py
3135import socket
3136
3137
3138def server_method():
3139	# create a new server socket to listen for connections
3140	server = socket.socket()
3141
3142	# bind to localhost:6789 for new connections
3143	server.bind((&#x27;localhost&#x27;, 6789))
3144
3145	# we will listen for one client at most
3146	server.listen(1)
3147
3148	# *block* waiting for a new client
3149	client, _ = server.accept()
3150
3151	# *block* waiting for some data
3152	data = client.recv(1024)
3153
3154	# reverse the data
3155	data = data[::-1]
3156
3157	# *block* sending the data
3158	client.sendall(data)
3159
3160	# close client and server
3161	server.close()
3162	client.close()
3163
3164
3165if __name__ == &#x27;__main__&#x27;:
3166	# block running the server
3167	server_method()
3168&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3169&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;# client.py
3170import socket
3171
3172
3173def client_method():
3174	message = b&#x27;Hello Server!\n&#x27;
3175	client = socket.socket()
3176
3177	# *block* trying to stabilish a connection
3178	client.connect((&#x27;localhost&#x27;, 6789))
3179
3180	# *block* trying to send the message
3181	print(&#x27;Sending&#x27;, message)
3182	client.sendall(message)
3183
3184	# *block* until we receive a response
3185	response = client.recv(1024)
3186	print(&#x27;Server replied&#x27;, response)
3187
3188	client.close()
3189
3190
3191if __name__ == &#x27;__main__&#x27;:
3192	client_method()
3193&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3194&lt;p&gt;From what we&#x27;ve seen, this code will block on all the lines with a comment above them saying that they will block. This means that for running more than one client or server, or both in the same file, you will need threads. But we can do better, we can rewrite it into &lt;code&gt;asyncio&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
3195&lt;p&gt;The first step is to mark all your &lt;code&gt;def&lt;&#x2F;code&gt;initions that may block with &lt;code&gt;async&lt;&#x2F;code&gt;. This marks them as coroutines, which can be &lt;code&gt;await&lt;&#x2F;code&gt;ed on.&lt;&#x2F;p&gt;
3196&lt;p&gt;Second, since we&#x27;re using low-level sockets, we need to make use of the methods that &lt;code&gt;asyncio&lt;&#x2F;code&gt; provides directly. If this was a third-party library, this would be just like using their &lt;code&gt;async def&lt;&#x2F;code&gt;initions.&lt;&#x2F;p&gt;
3197&lt;p&gt;Here is the &lt;strong&gt;asynchronous version&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
3198&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;# server.py
3199import asyncio
3200import socket
3201
3202# get the default &amp;quot;event loop&amp;quot; that we will run
3203loop = asyncio.get_event_loop()
3204
3205
3206# notice our new &amp;quot;async&amp;quot; before the definition
3207async def server_method():
3208	server = socket.socket()
3209	server.bind((&#x27;localhost&#x27;, 6789))
3210	server.listen(1)
3211
3212	# await for a new client
3213	# the event loop can run other code while we wait here!
3214	client, _ = await loop.sock_accept(server)
3215
3216	# await for some data
3217	data = await loop.sock_recv(client, 1024)
3218	data = data[::-1]
3219
3220	# await for sending the data
3221	await loop.sock_sendall(client, data)
3222
3223	server.close()
3224	client.close()
3225
3226
3227if __name__ == &#x27;__main__&#x27;:
3228	# run the loop until &amp;quot;server method&amp;quot; is complete
3229	loop.run_until_complete(server_method())
3230&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3231&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;# client.py
3232import asyncio
3233import socket
3234
3235loop = asyncio.get_event_loop()
3236
3237
3238async def client_method():
3239	message = b&#x27;Hello Server!\n&#x27;
3240	client = socket.socket()
3241
3242	# await to stabilish a connection
3243	await loop.sock_connect(client, (&#x27;localhost&#x27;, 6789))
3244
3245	# await to send the message
3246	print(&#x27;Sending&#x27;, message)
3247	await loop.sock_sendall(client, message)
3248
3249	# await to receive a response
3250	response = await loop.sock_recv(client, 1024)
3251	print(&#x27;Server replied&#x27;, response)
3252
3253	client.close()
3254
3255
3256if __name__ == &#x27;__main__&#x27;:
3257	loop.run_until_complete(client_method())
3258&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3259&lt;p&gt;That&#x27;s it! You can place these two files separately and run, first the server, then the client. You should see output in the client.&lt;&#x2F;p&gt;
3260&lt;p&gt;The big difference here is that you can easily modify the code to run more than one server or clients at the same time. Whenever you &lt;code&gt;await&lt;&#x2F;code&gt; the event loop will run other of your code. It seems to &amp;quot;block&amp;quot; on the &lt;code&gt;await&lt;&#x2F;code&gt; parts, but remember it&#x27;s actually jumping to run more code, and the event loop will get back to you whenever it can.&lt;&#x2F;p&gt;
3261&lt;p&gt;In short, you need an &lt;code&gt;async def&lt;&#x2F;code&gt; to &lt;code&gt;await&lt;&#x2F;code&gt; things, and you run them with the event loop instead of calling them directly. So this…&lt;&#x2F;p&gt;
3262&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;def main():
3263	...  # some code
3264
3265
3266if __name__ == &#x27;__main__&#x27;:
3267	main()
3268&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3269&lt;p&gt;…becomes this:&lt;&#x2F;p&gt;
3270&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;import asyncio
3271
3272
3273async def main():
3274	...  # some code
3275
3276
3277if __name__ == &#x27;__main__&#x27;:
3278	asyncio.get_event_loop().run_until_complete(main)
3279&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3280&lt;p&gt;This is pretty much how most of your &lt;code&gt;async&lt;&#x2F;code&gt; scripts will start, running the main method until its completion.&lt;&#x2F;p&gt;
3281&lt;h2 id=&quot;a-real-example&quot;&gt;A Real Example&lt;&#x2F;h2&gt;
3282&lt;p&gt;Let&#x27;s have some fun with a real library. We&#x27;ll be using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;LonamiWebs&#x2F;Telethon&quot;&gt;Telethon&lt;&#x2F;a&gt; to broadcast a message to our three best friends, all at the same time, thanks to the magic of &lt;code&gt;asyncio&lt;&#x2F;code&gt;. We&#x27;ll dive right into the code, and then I&#x27;ll explain our new friend &lt;code&gt;asyncio.wait(...)&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
3283&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;# broadcast.py
3284import asyncio
3285import sys
3286
3287from telethon import TelegramClient
3288
3289# (you need your own values here, check Telethon&#x27;s documentation)
3290api_id = 123
3291api_hash = &#x27;123abc&#x27;
3292friends = [
3293	&#x27;@friend1__username&#x27;,
3294	&#x27;@friend2__username&#x27;,
3295	&#x27;@bestie__username&#x27;
3296]
3297
3298# we will have to await things, so we need an async def
3299async def main(message):
3300	# start is a coroutine, so we need to await it to run it
3301	client = await TelegramClient(&#x27;me&#x27;, api_id, api_hash).start()
3302
3303	# wait for all three client.send_message to complete
3304	await asyncio.wait([
3305		client.send_message(friend, message)
3306		for friend in friends
3307	])
3308
3309	# and close our client
3310	await client.disconnect()
3311
3312
3313if __name__ == &#x27;__main__&#x27;:
3314	if len(sys.argv) != 2:
3315		print(&#x27;You must pass the message to broadcast!&#x27;)
3316		quit()
3317
3318	message = sys.argv[1]
3319	asyncio.get_event_loop().run_until_complete(main(message))
3320&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3321&lt;p&gt;Wait… how did that send a message to all three of
3322my friends? The magic is done here:&lt;&#x2F;p&gt;
3323&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;[
3324	client.send_message(friend, message)
3325	for friend in friends
3326]
3327&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3328&lt;p&gt;This list comprehension creates another list with three
3329coroutines, the three &lt;code&gt;client.send_message(...)&lt;&#x2F;code&gt;.
3330Then we just pass that list to &lt;code&gt;asyncio.wait&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
3331&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;await asyncio.wait([...])
3332&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
3333&lt;p&gt;This method, by default, waits for the list of coroutines to run until they&#x27;ve all finished. You can read more on the Python &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;asyncio-task.html#asyncio.wait&quot;&gt;documentation&lt;&#x2F;a&gt;. Truly a good function to know about!&lt;&#x2F;p&gt;
3334&lt;p&gt;Now whenever you have some important news for your friends, you can simply &lt;code&gt;python3 broadcast.py &#x27;I bought a car!&#x27;&lt;&#x2F;code&gt; to tell all your friends about your new car! All you need to remember is that you need to &lt;code&gt;await&lt;&#x2F;code&gt; on coroutines, and you will be good. &lt;code&gt;asyncio&lt;&#x2F;code&gt; will warn you when you forget to do so.&lt;&#x2F;p&gt;
3335&lt;h2 id=&quot;extra-material&quot;&gt;Extra Material&lt;&#x2F;h2&gt;
3336&lt;p&gt;If you want to understand how &lt;code&gt;asyncio&lt;&#x2F;code&gt; works under the hood, I recommend you to watch this hour-long talk &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;M-UcUs7IMIM&quot;&gt;Get to grips with asyncio in Python 3&lt;&#x2F;a&gt; by Robert Smallshire. In the video, they will explain the differences between concurrency and parallelism, along with others concepts, and how to implement your own &lt;code&gt;asyncio&lt;&#x2F;code&gt; &amp;quot;scheduler&amp;quot; from scratch.&lt;&#x2F;p&gt;
3337</content>
3338	</entry>
3339	<entry xml:lang="en">
3340		<title>Atemporal Blog Posts</title>
3341		<published>2018-02-03T00:00:00+00:00</published>
3342		<updated>2021-02-19T00:00:00+00:00</updated>
3343		<link href="https://lonami.dev/blog/posts/" type="text/html"/>
3344		<id>https://lonami.dev/blog/posts/</id>
3345		<content type="html">&lt;p&gt;These are some interesting posts and links I&#x27;ve found around the web. I believe they are quite interesting and nice reads, so if you have the time, I encourage you to check some out.&lt;&#x2F;p&gt;
3346&lt;h2 id=&quot;algorithms&quot;&gt;Algorithms&lt;&#x2F;h2&gt;
3347&lt;ul&gt;
3348&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.tannerhelland.com&#x2F;4660&#x2F;dithering-eleven-algorithms-source-code&#x2F;&quot;&gt;Image Dithering: Eleven Algorithms and Source Code&lt;&#x2F;a&gt;. What does it mean and how to achieve it?&lt;&#x2F;li&gt;
3349&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cristian.io&#x2F;post&#x2F;bloom-filters&#x2F;&quot;&gt;Idempotence layer on bloom filters&lt;&#x2F;a&gt;. What are they and how can they help?&lt;&#x2F;li&gt;
3350&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Huffman_coding&quot;&gt;Huffman coding&lt;&#x2F;a&gt;. This encoding is a simple yet interesting way of compressing information.&lt;&#x2F;li&gt;
3351&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mxgmn&#x2F;WaveFunctionCollapse&quot;&gt;Wave Function Collapse&lt;&#x2F;a&gt;. Bitmap &amp;amp; tilemap generation from a single example with the help of ideas from quantum mechanics.&lt;&#x2F;li&gt;
3352&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.nelhage.com&#x2F;2015&#x2F;02&#x2F;regular-expression-search-with-suffix-arrays&#x2F;&quot;&gt;Regular Expression Search with Suffix Arrays&lt;&#x2F;a&gt;. A way to efficiently search large amounts of text.&lt;&#x2F;li&gt;
3353&lt;&#x2F;ul&gt;
3354&lt;h2 id=&quot;culture&quot;&gt;Culture&lt;&#x2F;h2&gt;
3355&lt;ul&gt;
3356&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.wired.com&#x2F;story&#x2F;ideas-joi-ito-robot-overlords&#x2F;&quot;&gt;Why Westerners Fear Robots and the Japanese Do Not&lt;&#x2F;a&gt;. Explains some possible reasons for this case.&lt;&#x2F;li&gt;
3357&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;catb.org&#x2F;%7Eesr&#x2F;faqs&#x2F;smart-questions.html&quot;&gt;How To Ask Questions The Smart Way&lt;&#x2F;a&gt;. Some bits of hacker culture and amazing tips on how to ask a question.&lt;&#x2F;li&gt;
3358&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;apenwarr.ca&#x2F;log&#x2F;?m=201809#14&quot;&gt;XML, blockchains, and the strange shapes of progress&lt;&#x2F;a&gt;. Some of history about XML and blockchain.&lt;&#x2F;li&gt;
3359&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;czep.net&#x2F;17&#x2F;legion-of-lobotomized-unices.html&quot;&gt;Legion of lobotomized unices&lt;&#x2F;a&gt;. A time where computers are treated a lot more nicely.&lt;&#x2F;li&gt;
3360&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2016&#x2F;the-expression-problem-and-its-solutions&#x2F;&quot;&gt;The Expression Problem and its solutions&lt;&#x2F;a&gt;. What is it and what can we do to solve it?&lt;&#x2F;li&gt;
3361&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;allendowney.blogspot.com&#x2F;2015&#x2F;08&#x2F;the-inspection-paradox-is-everywhere.html&quot;&gt;The Inspection Paradox is Everywhere&lt;&#x2F;a&gt;. Interesting and very common phenomena.&lt;&#x2F;li&gt;
3362&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ChrisKnott&#x2F;Algojammer&quot;&gt;An experimental code editor for writing algorithms&lt;&#x2F;a&gt;. Contains several links to different tools for reverse debugging.&lt;&#x2F;li&gt;
3363&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;habitatchronicles.com&#x2F;2017&#x2F;05&#x2F;what-are-capabilities&#x2F;&quot;&gt;What Are Capabilities?&lt;&#x2F;a&gt; Good ideas with great security implications.&lt;&#x2F;li&gt;
3364&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.aurynn.com&#x2F;2015&#x2F;12&#x2F;16-contempt-culture&quot;&gt;Contempt Culture&lt;&#x2F;a&gt;. Or why you should not speak crap about your non-favourite programming languages.&lt;&#x2F;li&gt;
3365&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.lesswrong.com&#x2F;posts&#x2F;tscc3e5eujrsEeFN4&#x2F;well-kept-gardens-die-by-pacifism&quot;&gt;Well-Kept Gardens Die By Pacifism&lt;&#x2F;a&gt;. Risks any online community can run into.&lt;&#x2F;li&gt;
3366&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;ncase.me&#x2F;&quot;&gt;It&#x27;s Nicky Case!&lt;&#x2F;a&gt; They make some cool things worth checking out, I really like &amp;quot;we become what we behold&amp;quot;.&lt;&#x2F;li&gt;
3367&lt;&#x2F;ul&gt;
3368&lt;h2 id=&quot;debate&quot;&gt;Debate&lt;&#x2F;h2&gt;
3369&lt;ul&gt;
3370&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;steemit.com&#x2F;opensource&#x2F;@crell&#x2F;open-source-is-awful&quot;&gt;Open Source is awful&lt;&#x2F;a&gt;. Has some points about why is it bad and how it could improve.&lt;&#x2F;li&gt;
3371&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.mondo2000.com&#x2F;2018&#x2F;01&#x2F;17&#x2F;pink-lexical-goop-dark-side-autocorrect&#x2F;&quot;&gt;Pink Lexical Goop: The Dark Side of Autocorrect&lt;&#x2F;a&gt;. It can shape how you think.&lt;&#x2F;li&gt;
3372&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.ploeh.dk&#x2F;2015&#x2F;08&#x2F;03&#x2F;idiomatic-or-idiosyncratic&#x2F;&quot;&gt;Idiomatic or idiosyncratic?&lt;&#x2F;a&gt; Can porting code constructs from other languages have a positive effect?&lt;&#x2F;li&gt;
3373&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gamasutra.com&#x2F;view&#x2F;news&#x2F;169296&#x2F;Indepth_Functional_programming_in_C.php&quot;&gt;In-depth: Functional programming in C++&lt;&#x2F;a&gt;. Is it useful to bother with functional concepts in a language like C++?&lt;&#x2F;li&gt;
3374&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;vorpus.org&#x2F;blog&#x2F;notes-on-structured-concurrency-or-go-statement-considered-harmful&#x2F;&quot;&gt;Notes on structured concurrency, or: Go statement considered harmful&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
3375&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;queue.acm.org&#x2F;detail.cfm?id=3212479&quot;&gt;C Is Not a Low-level Language&lt;&#x2F;a&gt;. Could there be alternative programming models designed for more specialized CPUs?&lt;&#x2F;li&gt;
3376&lt;&#x2F;ul&gt;
3377&lt;h2 id=&quot;food-for-thought&quot;&gt;Food for Thought&lt;&#x2F;h2&gt;
3378&lt;ul&gt;
3379&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.hillelwayne.com&#x2F;post&#x2F;divide-by-zero&#x2F;&quot;&gt;1&#x2F;0 = 0&lt;&#x2F;a&gt;. Explores why it makes sense to redefine mathemathics under some circumstances, and why it is possible to do so.&lt;&#x2F;li&gt;
3380&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;jeremykun.com&#x2F;2018&#x2F;04&#x2F;13&#x2F;for-mathematicians-does-not-mean-equality&#x2F;&quot;&gt;For mathematicians, = does not mean equality&lt;&#x2F;a&gt;. What other definitions does the equal sign have?&lt;&#x2F;li&gt;
3381&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.lesswrong.com&#x2F;posts&#x2F;2MD3NMLBPCqPfnfre&#x2F;cached-thoughts&quot;&gt;Cached Thoughts&lt;&#x2F;a&gt;. How is it possible that our brains work at all?&lt;&#x2F;li&gt;
3382&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;tonsky.me&#x2F;blog&#x2F;disenchantment&#x2F;&quot;&gt;Software disenchantment&lt;&#x2F;a&gt;. Faster hardware and slower software is a trend.
3383&lt;ul&gt;
3384&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blackhole12.com&#x2F;blog&#x2F;software-engineering-is-bad-but-it-s-not-that-bad&#x2F;&quot;&gt;Software Engineering Is Bad, But That&#x27;s Not Why&lt;&#x2F;a&gt;. This post has some good counterpoints to Software disenchantment.&lt;&#x2F;li&gt;
3385&lt;&#x2F;ul&gt;
3386&lt;&#x2F;li&gt;
3387&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-your-function&#x2F;&quot;&gt;What Color is Your Function?&lt;&#x2F;a&gt;. Spoiler: can we approach asynchronous IO better?&lt;&#x2F;li&gt;
3388&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hackernoon.com&#x2F;im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5&quot;&gt;I&#x27;m harvesting credit card numbers and passwords from your site&lt;&#x2F;a&gt;. A word of warning when mindlessly adding dependencies.&lt;&#x2F;li&gt;
3389&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;message&#x2F;everything-is-broken-81e5f33a24e1&quot;&gt;Everything Is Broken&lt;&#x2F;a&gt;. Some of the (probable) truths about our world.&lt;&#x2F;li&gt;
3390&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;johnsalvatier.org&#x2F;blog&#x2F;2017&#x2F;reality-has-a-surprising-amount-of-detail&quot;&gt;Reality has a surprising amount of detail&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
3391&lt;&#x2F;ul&gt;
3392&lt;h2 id=&quot;funny&quot;&gt;Funny&lt;&#x2F;h2&gt;
3393&lt;ul&gt;
3394&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;We-Use-BobX&quot;&gt;We Use BobX&lt;&#x2F;a&gt;. BobX.&lt;&#x2F;li&gt;
3395&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;the-inner-json-effect&quot;&gt;The Inner JSON Effect&lt;&#x2F;a&gt;. For some reason, custom languages are in.&lt;&#x2F;li&gt;
3396&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;exponential-backup&quot;&gt;Exponential Backup&lt;&#x2F;a&gt;. Far better than git.&lt;&#x2F;li&gt;
3397&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;ITAPPMONROBOT&quot;&gt;ITAPPMONROBOT&lt;&#x2F;a&gt;. Solving software problems with hardware.&lt;&#x2F;li&gt;
3398&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;thedailywtf.com&#x2F;articles&#x2F;a-tapestry-of-threads&quot;&gt;A Tapestry of Threads&lt;&#x2F;a&gt;. More threads must mean faster code, right?&lt;&#x2F;li&gt;
3399&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;commitlog&#x2F;a-brief-totally-accurate-history-of-programming-languages-cd93ec806124&quot;&gt;A Brief Totally Accurate History Of Programming Languages&lt;&#x2F;a&gt;. Don&#x27;t take offense for it!&lt;&#x2F;li&gt;
3400&lt;&#x2F;ul&gt;
3401&lt;h2 id=&quot;graphics&quot;&gt;Graphics&lt;&#x2F;h2&gt;
3402&lt;ul&gt;
3403&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;shaunlebron.github.io&#x2F;visualizing-projections&#x2F;&quot;&gt;Visualizing Projections&lt;&#x2F;a&gt;. Small post about different projection methods.&lt;&#x2F;li&gt;
3404&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.iquilezles.org&#x2F;www&#x2F;index.htm&quot;&gt;Inigo Quilez :: fractals, computer graphics, mathematics, shaders, demoscene and more&lt;&#x2F;a&gt; A &lt;em&gt;lot&lt;&#x2F;em&gt; of useful and quality articles regarding computer graphics.&lt;&#x2F;li&gt;
3405&lt;&#x2F;ul&gt;
3406&lt;h2 id=&quot;history&quot;&gt;History&lt;&#x2F;h2&gt;
3407&lt;ul&gt;
3408&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twobithistory.org&#x2F;2018&#x2F;08&#x2F;18&#x2F;ada-lovelace-note-g.html&quot;&gt;What Did Ada Lovelace&#x27;s Program Actually Do?&lt;&#x2F;a&gt;. And other characters that took part in the beginning&#x27;s of programming.&lt;&#x2F;li&gt;
3409&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chrisdown.name&#x2F;2018&#x2F;01&#x2F;02&#x2F;in-defence-of-swap.html&quot;&gt;In defence of swap: common misconceptions&lt;&#x2F;a&gt;. Swap is still an useful concept.&lt;&#x2F;li&gt;
3410&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.pacifict.com&#x2F;Story&#x2F;&quot;&gt;The Graphing Calculator Story&lt;&#x2F;a&gt;. A great classic Apple tale.&lt;&#x2F;li&gt;
3411&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twobithistory.org&#x2F;2018&#x2F;10&#x2F;14&#x2F;lisp.html&quot;&gt;How Lisp Became God&#x27;s Own Programming Language&lt;&#x2F;a&gt;. Lisp as a foundational programming language.&lt;&#x2F;li&gt;
3412&lt;&#x2F;ul&gt;
3413&lt;h2 id=&quot;motivational&quot;&gt;Motivational&lt;&#x2F;h2&gt;
3414&lt;ul&gt;
3415&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2002&#x2F;01&#x2F;06&#x2F;fire-and-motion&#x2F;&quot;&gt;Fire And Motion&lt;&#x2F;a&gt;. What does actually take to get things done?&lt;&#x2F;li&gt;
3416&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;realmensch.org&#x2F;2017&#x2F;08&#x2F;25&#x2F;the-parable-of-the-two-programmers&#x2F;&quot;&gt;The Parable of the Two Programmers&lt;&#x2F;a&gt;. This tale is about two different types of programmer and their respective endings in a company, illustrating how the one you wouldn&#x27;t expect to actually ends in a better situation.&lt;&#x2F;li&gt;
3417&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;byorgey.wordpress.com&#x2F;2018&#x2F;05&#x2F;06&#x2F;conversations-with-a-six-year-old-on-functional-programming&#x2F;&quot;&gt;Conversations with a six-year-old on functional programming&lt;&#x2F;a&gt;. Little kids today can be really interested in technological topics.&lt;&#x2F;li&gt;
3418&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bulletproofmusician.com&#x2F;how-many-hours-a-day-should-you-practice&#x2F;&quot;&gt;How Many Hours a Day Should You Practice?&lt;&#x2F;a&gt;. While the article is about music, it applies to any other areas.&lt;&#x2F;li&gt;
3419&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;nathanmarz.com&#x2F;blog&#x2F;suffering-oriented-programming.html&quot;&gt;Suffering-oriented programming&lt;&#x2F;a&gt;. A possibly new approach on how you could tackle your new projects.&lt;&#x2F;li&gt;
3420&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.joelonsoftware.com&#x2F;2000&#x2F;04&#x2F;06&#x2F;things-you-should-never-do-part-i&#x2F;&quot;&gt;Things You Should Never Do, Part I&lt;&#x2F;a&gt;. There is no need to rewrite your code.&lt;&#x2F;li&gt;
3421&lt;&#x2F;ul&gt;
3422&lt;h2 id=&quot;optimization&quot;&gt;Optimization&lt;&#x2F;h2&gt;
3423&lt;ul&gt;
3424&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.llvm.org&#x2F;2011&#x2F;05&#x2F;what-every-c-programmer-should-know.html&quot;&gt;What Every C Programmer Should Know About Undefined Behavior #1&#x2F;3&lt;&#x2F;a&gt;. Explains what undefined behaviour is and why it makes sense.&lt;&#x2F;li&gt;
3425&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;ridiculousfish.com&#x2F;blog&#x2F;posts&#x2F;labor-of-division-episode-i.html&quot;&gt;Labor of Division (Episode I)&lt;&#x2F;a&gt;. Some tricks to divide without division.&lt;&#x2F;li&gt;
3426&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.moertel.com&#x2F;posts&#x2F;2013-12-14-great-old-timey-game-programming-hack.html&quot;&gt;A Great Old-Timey Game-Programming Hack&lt;&#x2F;a&gt;. Abusing instructions to make games playable even on the slowest hardware.&lt;&#x2F;li&gt;
3427&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20191213224640&#x2F;https:&#x2F;&#x2F;people.eecs.berkeley.edu&#x2F;%7Esangjin&#x2F;2012&#x2F;12&#x2F;21&#x2F;epoll-vs-kqueue.html&quot;&gt;Scalable Event Multiplexing: epoll vs kqueue&lt;&#x2F;a&gt;. How good OS primitives can really help performance and scability.&lt;&#x2F;li&gt;
3428&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;adamdrake.com&#x2F;command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html&quot;&gt;Command-line Tools can be 235x Faster than your Hadoop Cluster&lt;&#x2F;a&gt;. Or how to use the right tool for the right job.&lt;&#x2F;li&gt;
3429&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nullprogram.com&#x2F;blog&#x2F;2018&#x2F;05&#x2F;27&#x2F;&quot;&gt;When FFI Function Calls Beat Native C&lt;&#x2F;a&gt;. How lua beat C at it and the explanation behind it.&lt;&#x2F;li&gt;
3430&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;igoro.com&#x2F;archive&#x2F;gallery-of-processor-cache-effects&#x2F;&quot;&gt;Gallery of Processor Cache Effects&lt;&#x2F;a&gt;. Knowing a few things about the cache can make a big difference.&lt;&#x2F;li&gt;
3431&lt;&#x2F;ul&gt;
3432</content>
3433	</entry>
3434	<entry xml:lang="en">
3435		<title>Graphs</title>
3436		<published>2017-06-02T00:00:00+00:00</published>
3437		<updated>2017-06-02T00:00:00+00:00</updated>
3438		<link href="https://lonami.dev/blog/graphs/" type="text/html"/>
3439		<id>https://lonami.dev/blog/graphs/</id>
3440		<content type="html">&lt;p&gt;&lt;noscript&gt;There are a few things which won&#x27;t render unless you enable
3441JavaScript. No tracking, I promise!&lt;&#x2F;noscript&gt;&lt;&#x2F;p&gt;
3442&lt;blockquote&gt;
3443&lt;p&gt;Don&#x27;t know English? &lt;a href=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;graphs&#x2F;spanish.html&quot;&gt;Read the Spanish version instead&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
3444&lt;&#x2F;blockquote&gt;
3445&lt;p&gt;Let&#x27;s imagine we have 5 bus stations, which we&#x27;ll denote by ((s_i)):&lt;&#x2F;p&gt;
3446&lt;div class=&quot;matrix&quot;&gt;
3447      &#x27; s_1 &#x27; s_2 &#x27; s_3 &#x27; s_4 &#x27; s_5 \\
3448s_1   &#x27;     &#x27;  V  &#x27;     &#x27;     &#x27;     \\
3449s_2   &#x27;  V  &#x27;     &#x27;     &#x27;     &#x27;  V  \\
3450s_3   &#x27;     &#x27;     &#x27;     &#x27;  V  &#x27;     \\
3451s_4   &#x27;     &#x27;  V  &#x27;  V  &#x27;     &#x27;     \\
3452s_5   &#x27;  V  &#x27;     &#x27;     &#x27;  V  &#x27;
3453&lt;&#x2F;div&gt;
3454&lt;p&gt;This is known as a &amp;quot;table of direct interconnections&amp;quot;.
3455The ((V)) represent connected paths. For instance, on the first
3456row starting at ((s_1)), reaching the ((V)),
3457allows us to turn up to get to ((s_2)).&lt;&#x2F;p&gt;
3458&lt;p&gt;We can see the above table represented in a more graphical way:&lt;&#x2F;p&gt;
3459&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;lonami.dev&#x2F;blog&#x2F;graphs&#x2F;example1.svg&quot; alt=&quot;Table 1 as a Graph&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
3460&lt;p&gt;This type of graph is called, well, a graph, and it&#x27;s a directed
3461graph (or digraph), since the direction on which the arrows go does
3462matter. It&#x27;s made up of vertices, joined together by edges (also known as
3463lines or directed arcs).&lt;&#x2F;p&gt;
3464&lt;p&gt;One can walk from a node to another through different paths. For
3465example, ((s_4 $rightarrow s_2 $rightarrow s_5)) is an indirect path of order
3466two, because we must use two edges to go from ((s_4)) to
3467((s_5)).&lt;&#x2F;p&gt;
3468&lt;p&gt;Let&#x27;s now represent its adjacency matrix called A which represents the
3469same table, but uses 1 instead V to represent
3470a connection:&lt;&#x2F;p&gt;
3471&lt;div class=&quot;matrix&quot;&gt;
3472  0 &#x27; 1 &#x27; 0 &#x27; 0 &#x27; 0 \\
3473  1 &#x27; 0 &#x27; 0 &#x27; 0 &#x27; 1 \\
3474  0 &#x27; 0 &#x27; 0 &#x27; 1 &#x27; 0 \\
3475  0 &#x27; 1 &#x27; 1 &#x27; 0 &#x27; 0 \\
3476  1 &#x27; 0 &#x27; 0 &#x27; 1 &#x27; 0
3477&lt;&#x2F;div&gt;
3478&lt;p&gt;This way we can see how the ((a_{2,1})) element represents the
3479connection ((s_2 $rightarrow s_1)), and the ((a_{5,1})) element the
3480((s_5 $rightarrow s_1)) connection, etc.&lt;&#x2F;p&gt;
3481&lt;p&gt;In general, ((a_{i,j})) represents a connection from
3482((s_i $rightarrow s_j))as long as ((a_{i,j}$geq 1)).&lt;&#x2F;p&gt;
3483&lt;p&gt;Working with matrices allows us to have a computable representation of
3484any graph, which is very useful.&lt;&#x2F;p&gt;
3485&lt;hr &#x2F;&gt;
3486&lt;p&gt;Graphs have a lot of interesting properties besides being representable
3487by a computer. What would happen if, for instance, we calculated
3488((A^2))? We obtain the following matrix:&lt;&#x2F;p&gt;
3489&lt;div class=&quot;matrix&quot;&gt;
34901 &#x27; 0 &#x27; 0 &#x27; 0 &#x27; 1 \\
34911 &#x27; 1 &#x27; 0 &#x27; 1 &#x27; 0 \\
34920 &#x27; 1 &#x27; 1 &#x27; 0 &#x27; 0 \\
34931 &#x27; 0 &#x27; 0 &#x27; 1 &#x27; 1 \\
34940 &#x27; 2 &#x27; 1 &#x27; 0 &#x27; 0
3495&lt;&#x2F;div&gt;
3496&lt;p&gt;We can interpret this as the paths of order two.
3497But what does the element ((a_{5,2}=2)) represent? It indicates
3498the amount of possible ways to go from  ((s_5 $rightarrow s_i $rightarrow s_2)).&lt;&#x2F;p&gt;
3499&lt;p&gt;One can manually multiply the involved row and column to determine which
3500element is the one we need to pass through, this way we have the row
3501(([1 0 0 1 0])) and the column (([1 0 0 1 0])) (on
3502vertical). The elements ((s_i$geq 1)) are ((s_1)) and
3503((s_4)). This is, we can go from ((s_5)) to
3504((s_2)) via ((s_5 $rightarrow s_1 $rightarrow s_2)) or via
3505((s_5 $rightarrow s_4 $rightarrow s_2)):
3506&lt;img src=&quot;example2.svg&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
3507&lt;p&gt;It&#x27;s important to note that graphs to not consider self-connections, this
3508is, ((s_i $rightarrow s_i)) is not allowed; neither we work with multigraphs
3509here (those which allow multiple connections, for instance, an arbitrary
3510number ((n)) of times).&lt;&#x2F;p&gt;
3511&lt;div class=&quot;matrix&quot;&gt;
35121 &#x27; 1 &#x27; 0          &#x27; 1 &#x27; 0 \\
35131 &#x27; 2 &#x27; \textbf{1} &#x27; 0 &#x27; 1 \\
35141 &#x27; 0 &#x27; 0          &#x27; 1 &#x27; 1 \\
35151 &#x27; 2 &#x27; 1          &#x27; 1 &#x27; 0 \\
35162 &#x27; 0 &#x27; 0          &#x27; 1 &#x27; 2
3517&lt;&#x2F;div&gt;
3518&lt;p&gt;We can see how the first ((1)) just appeared on the element
3519((a_{2,3})), which means that the shortest path to it is at least
3520of order three.&lt;&#x2F;p&gt;
3521&lt;hr &#x2F;&gt;
3522&lt;p&gt;A graph is said to be strongly connected as long as there is a
3523way to reach all its elements.&lt;&#x2F;p&gt;
3524&lt;p&gt;We can see all the available paths until now by simply adding up all the
3525direct and indirect ways to reach a node, so for now, we can add
3526((A+A^2+A^3)) in such a way that:&lt;&#x2F;p&gt;
3527&lt;div class=&quot;matrix&quot;&gt;
35282 &#x27; 2 &#x27; 0 &#x27; 1 &#x27; 1 \\
35293 &#x27; 3 &#x27; 1 &#x27; 1 &#x27; 3 \\
35301 &#x27; 1 &#x27; 1 &#x27; 2 &#x27; 1 \\
35312 &#x27; 3 &#x27; 2 &#x27; 2 &#x27; 1 \\
35323 &#x27; 2 &#x27; 1 &#x27; 2 &#x27; 2
3533&lt;&#x2F;div&gt;
3534&lt;p&gt;There isn&#x27;t a connection between ((s_1)) and ((s_3)) yet.
3535If we were to calculate ((A^4)):&lt;&#x2F;p&gt;
3536&lt;div class=&quot;matrix&quot;&gt;
35371 &#x27; 2 &#x27; 1 &#x27;   &#x27;   \\
3538  &#x27;   &#x27;   &#x27;   &#x27;   \\
3539  &#x27;   &#x27;   &#x27;   &#x27;   \\
3540  &#x27;   &#x27;   &#x27;   &#x27;   \\
3541  &#x27;   &#x27;   &#x27;   &#x27;
3542&lt;&#x2F;div&gt;
3543&lt;p&gt;We don&#x27;t need to calculate anymore. We now know that the graph is
3544strongly connected!&lt;&#x2F;p&gt;
3545&lt;hr &#x2F;&gt;
3546&lt;p&gt;Congratulations! You&#x27;ve completed this tiny introduction to graphs.
3547Now you can play around with them and design your own connections.&lt;&#x2F;p&gt;
3548&lt;p&gt;Hold the left mouse button on the above area and drag it down to create
3549a new node, or drag a node to this area to delete it.&lt;&#x2F;p&gt;
3550&lt;p&gt;To create new connections, hold the right mouse button on the node you
3551want to start with, and drag it to the node you want it to be connected to.&lt;&#x2F;p&gt;
3552&lt;p&gt;To delete the connections coming from a specific node, middle click it.&lt;&#x2F;p&gt;
3553&lt;table&gt;&lt;tr&gt;&lt;td style=&quot;width:100%;&quot;&gt;
3554  &lt;button onclick=&quot;resetConnections()&quot;&gt;Reset connections&lt;&#x2F;button&gt;
3555  &lt;button onclick=&quot;clearNodes()&quot;&gt;Clear all the nodes&lt;&#x2F;button&gt;
3556  &lt;br &#x2F;&gt;
3557  &lt;br &#x2F;&gt;
3558  &lt;label for=&quot;matrixOrder&quot;&gt;Show matrix of order:&lt;&#x2F;label&gt;
3559  &lt;input id=&quot;matrixOrder&quot; type=&quot;number&quot; min=&quot;1&quot; max=&quot;5&quot;
3560                          value=&quot;1&quot; oninput=&quot;updateOrder()&quot;&gt;
3561  &lt;br &#x2F;&gt;
3562  &lt;label for=&quot;matrixAccum&quot;&gt;Show accumulated matrix&lt;&#x2F;label&gt;
3563  &lt;input id=&quot;matrixAccum&quot; type=&quot;checkbox&quot; onchange=&quot;updateOrder()&quot;&gt;
3564  &lt;br &#x2F;&gt;
3565  &lt;br &#x2F;&gt;
3566  &lt;div&gt;
3567    &lt;table id=&quot;matrixTable&quot;&gt;&lt;&#x2F;table&gt;
3568  &lt;&#x2F;div&gt;
3569&lt;&#x2F;td&gt;&lt;td&gt;
3570  &lt;canvas id=&quot;canvas&quot; width=&quot;400&quot; height=&quot;400&quot; oncontextmenu=&quot;return false;&quot;&gt;
3571  Looks like your browser won&#x27;t let you see this fancy example :(
3572  &lt;&#x2F;canvas&gt;
3573  &lt;br &#x2F;&gt;
3574&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;table&gt;
3575&lt;script src=&quot;tinyparser.js&quot;&gt;&lt;&#x2F;script&gt;
3576&lt;script src=&quot;enhancements.js&quot;&gt;&lt;&#x2F;script&gt;
3577&lt;script src=&quot;graphs.js&quot;&gt;&lt;&#x2F;script&gt;
3578</content>
3579	</entry>
3580	<entry xml:lang="en">
3581		<title>Installing NixOS</title>
3582		<published>2017-05-13T00:00:00+00:00</published>
3583		<updated>2019-02-16T00:00:00+00:00</updated>
3584		<link href="https://lonami.dev/blog/installing-nixos/" type="text/html"/>
3585		<id>https://lonami.dev/blog/installing-nixos/</id>
3586		<content type="html">&lt;h2 id=&quot;update&quot;&gt;Update&lt;&#x2F;h2&gt;
3587&lt;p&gt;&lt;em&gt;Please see &lt;a href=&quot;..&#x2F;installing_nixos_2&#x2F;index.html&quot;&gt;my followup post with NixOS&lt;&#x2F;a&gt; for a far better experience with it&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
3588&lt;hr &#x2F;&gt;
3589&lt;p&gt;Today I decided to install &lt;a href=&quot;http:&#x2F;&#x2F;nixos.org&#x2F;&quot;&gt;NixOS&lt;&#x2F;a&gt; as a recommendation, a purely functional Linux distribution, since &lt;a href=&quot;https:&#x2F;&#x2F;xubuntu.org&#x2F;&quot;&gt;Xubuntu&lt;&#x2F;a&gt; kept crashing. Here&#x27;s my journey, and how I managed to install it from a terminal for the first time in my life. Steps aren&#x27;t hard, but they may not seem obvious at first.&lt;&#x2F;p&gt;
3590&lt;ul&gt;
3591&lt;li&gt;
3592&lt;p&gt;Grab the Live CD, burn it on a USB stick and boot. I recommend using &lt;a href=&quot;https:&#x2F;&#x2F;etcher.io&#x2F;&quot;&gt;Etcher&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
3593&lt;&#x2F;li&gt;
3594&lt;li&gt;
3595&lt;p&gt;Type &lt;code&gt;systemctl start display-manager&lt;&#x2F;code&gt; and wait.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
3596&lt;&#x2F;li&gt;
3597&lt;li&gt;
3598&lt;p&gt;Open both the manual and the &lt;code&gt;konsole&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
3599&lt;&#x2F;li&gt;
3600&lt;li&gt;
3601&lt;p&gt;Connect to the network using the GUI.&lt;&#x2F;p&gt;
3602&lt;&#x2F;li&gt;
3603&lt;li&gt;
3604&lt;p&gt;Create the disk partitions by using &lt;code&gt;fdisk&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
3605&lt;p&gt;You can list them with &lt;code&gt;fdisk -l&lt;&#x2F;code&gt;, modify a certain drive with &lt;code&gt;fdisk &#x2F;dev&#x2F;sdX&lt;&#x2F;code&gt; (for instance, &lt;code&gt;&#x2F;dev&#x2F;sda&lt;&#x2F;code&gt;) and follow the instructions.&lt;&#x2F;p&gt;
3606&lt;p&gt;To create the file system, use &lt;code&gt;mkfs.ext4 -L &amp;lt;label&amp;gt; &#x2F;dev&#x2F;sdXY&lt;&#x2F;code&gt; and swap with &lt;code&gt;mkswap -L &amp;lt;label&amp;gt; &#x2F;dev&#x2F;sdXY&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
3607&lt;p&gt;The EFI partition should be done with &lt;code&gt;mkfs.vfat&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
3608&lt;&#x2F;li&gt;
3609&lt;li&gt;
3610&lt;p&gt;Mount the target to &lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt; e.g. if the label was &lt;code&gt;nixos&lt;&#x2F;code&gt;, &lt;code&gt;mount &#x2F;dev&#x2F;disk&#x2F;by-label&#x2F;nixos &#x2F;mnt&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
3611&lt;&#x2F;li&gt;
3612&lt;li&gt;
3613&lt;p&gt;&lt;code&gt;mkdir &#x2F;mnt&#x2F;boot&lt;&#x2F;code&gt; and then mount your EFI partition to it.&lt;&#x2F;p&gt;
3614&lt;&#x2F;li&gt;
3615&lt;li&gt;
3616&lt;p&gt;Generate a configuration template with &lt;code&gt;nixos-generate-config --root &#x2F;mnt&lt;&#x2F;code&gt;, and modify it with &lt;code&gt;nano &#x2F;etc&#x2F;nixos&#x2F;configuration.nix&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
3617&lt;&#x2F;li&gt;
3618&lt;li&gt;
3619&lt;p&gt;While modifying the configuration, make sure to add &lt;code&gt;boot.loader.grub.device = &amp;quot;&#x2F;dev&#x2F;sda&amp;quot;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
3620&lt;&#x2F;li&gt;
3621&lt;li&gt;
3622&lt;p&gt;More useful configuration things are:&lt;&#x2F;p&gt;
3623&lt;ul&gt;
3624&lt;li&gt;Uncomment the whole &lt;code&gt;i18n&lt;&#x2F;code&gt; block.&lt;&#x2F;li&gt;
3625&lt;li&gt;Add some essential packages like &lt;code&gt;environment.systemPackages = with pkgs; [wget git firefox pulseaudio networkmanagerapplet];&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
3626&lt;li&gt;If you want to use XFCE, add &lt;code&gt;services.xserver.desktopManager.xfce.enable = true;&lt;&#x2F;code&gt;, otherwise, you don&#x27;t need &lt;code&gt;networkmanagerapplet&lt;&#x2F;code&gt; either. Make sure to add &lt;code&gt;networking.networkmanager.enable = true;&lt;&#x2F;code&gt; too.&lt;&#x2F;li&gt;
3627&lt;li&gt;Define some user for yourself (modify &lt;code&gt;guest&lt;&#x2F;code&gt; name) and use a UID greater than 1000. Also, add yourself to &lt;code&gt;extraGroups = [&amp;quot;wheel&amp;quot; &amp;quot;networkmanager&amp;quot;];&lt;&#x2F;code&gt; (the first to be able to &lt;code&gt;sudo&lt;&#x2F;code&gt;, the second to use network related things).&lt;&#x2F;li&gt;
3628&lt;&#x2F;ul&gt;
3629&lt;&#x2F;li&gt;
3630&lt;li&gt;
3631&lt;p&gt;Run &lt;code&gt;nixos-install&lt;&#x2F;code&gt;. If you ever modify that file again, to add more packages for instance (this is how they&#x27;re installed), run &lt;code&gt;nixos-rebuild switch&lt;&#x2F;code&gt; (or use &lt;code&gt;test&lt;&#x2F;code&gt; to test but don&#x27;t boot to it, or &lt;code&gt;boot&lt;&#x2F;code&gt; not to switch but to use on next boot.&lt;&#x2F;p&gt;
3632&lt;&#x2F;li&gt;
3633&lt;li&gt;
3634&lt;p&gt;&lt;code&gt;reboot&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
3635&lt;&#x2F;li&gt;
3636&lt;li&gt;
3637&lt;p&gt;Login as &lt;code&gt;root&lt;&#x2F;code&gt;, and set a password for your user with &lt;code&gt;passwd &amp;lt;user&amp;gt;&lt;&#x2F;code&gt;. Done!&lt;&#x2F;p&gt;
3638&lt;&#x2F;li&gt;
3639&lt;&#x2F;ul&gt;
3640&lt;p&gt;I enjoyed the process of installing it, and it&#x27;s really cool that it has versioning and is so clean to keep track of which packages you install. But not being able to run arbitrary binaries by default is something very limitting in my opinion, though they&#x27;ve done a good job.&lt;&#x2F;p&gt;
3641&lt;p&gt;I&#x27;m now back to Xubuntu, with a fresh install.&lt;&#x2F;p&gt;
3642&lt;h2 id=&quot;update-1&quot;&gt;Update&lt;&#x2F;h2&gt;
3643&lt;p&gt;It is not true that &amp;quot;they don&#x27;t allow running arbitrary binaries by default&amp;quot;, as pointed out in their &lt;a href=&quot;https:&#x2F;&#x2F;nixos.org&#x2F;nixpkgs&#x2F;manual&#x2F;#sec-fhs-environments&quot;&gt;manual, buildFHSUserEnv&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
3644&lt;blockquote&gt;
3645&lt;p&gt;&lt;code&gt;buildFHSUserEnv&lt;&#x2F;code&gt; provides a way to build and run FHS-compatible lightweight sandboxes. It creates an isolated root with bound &lt;code&gt;&#x2F;nix&#x2F;store&lt;&#x2F;code&gt;, so its footprint in terms of disk space needed is quite small. This allows one to run software which is hard or unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions, games distributed as tarballs, software with integrity checking and&#x2F;or external self-updated binaries. It uses Linux namespaces feature to create temporary lightweight environments which are destroyed after all child processes exit, without root user rights requirement.&lt;&#x2F;p&gt;
3646&lt;&#x2F;blockquote&gt;
3647&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bb010g&quot;&gt;@bb010g&lt;&#x2F;a&gt; for pointing this out.&lt;&#x2F;p&gt;
3648&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;&#x2F;h2&gt;
3649&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
3650&lt;p&gt;The keyboard mapping is a bit strange. On my Spanish keyboard, the keys were as follows:&lt;&#x2F;p&gt;
3651&lt;&#x2F;div&gt;
3652&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Keyboard&lt;&#x2F;th&gt;&lt;th&gt;Maps to&lt;&#x2F;th&gt;&lt;th&gt;Shift&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
3653&lt;tr&gt;&lt;td&gt;&#x27;&lt;&#x2F;td&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;td&gt;_&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
3654&lt;tr&gt;&lt;td&gt;´&lt;&#x2F;td&gt;&lt;td&gt;&#x27;&lt;&#x2F;td&gt;&lt;td&gt;&amp;quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
3655&lt;tr&gt;&lt;td&gt;`&lt;&#x2F;td&gt;&lt;td&gt;[&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
3656&lt;tr&gt;&lt;td&gt;+&lt;&#x2F;td&gt;&lt;td&gt;]&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
3657&lt;tr&gt;&lt;td&gt;¡&lt;&#x2F;td&gt;&lt;td&gt;=&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
3658&lt;tr&gt;&lt;td&gt;-&lt;&#x2F;td&gt;&lt;td&gt;&#x2F;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
3659&lt;tr&gt;&lt;td&gt;ñ&lt;&#x2F;td&gt;&lt;td&gt;;&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
3660&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
3661</content>
3662	</entry>
3663</feed>