<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8584570627780730363</atom:id><lastBuildDate>Sat, 31 Oct 2026 06:45:20 +0000</lastBuildDate><category>Retrospective</category><category>Cloud</category><category>Master System</category><category>MonoGame</category><category>devkitSMS</category><category>Candy Kid</category><category>Sega</category><category>XNA</category><category>Agile</category><category>Archive</category><category>Python</category><category>Unity3D</category><category>Data</category><category>Design</category><category>Source Control</category><category>Linux</category><category>Z80</category><category>AI</category><category>App Hub</category><category>Cpp</category><category>GBDK</category><category>Henway</category><category>MacOS</category><category>OpenAI</category><category>Performance</category><category>Quality</category><category>SGDK</category><category>eBPF</category><category>z88dk</category><category>DOOM</category><category>Mega Drive</category><category>PyGame</category><title>SteveProXNA</title><description>Senior Software Engineer [Retro Indie Game Developer]</description><link>http://steveproxna.blogspot.com/</link><managingEditor>noreply@blogger.com (SteveProXNA)</managingEditor><generator>Blogger</generator><openSearch:totalResults>125</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-6220892505508753064</guid><pubDate>Tue, 15 Sep 2026 08:00:15 +0000</pubDate><atom:updated>2026-09-15T01:00:15.612-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">PyGame</category><title>PyGame Programming Setup</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In 2020, we checked out &lt;a href=&quot;https://steveproxna.blogspot.com/2020/07/python-setup-cheat-sheet.html&quot;&gt;Python Setup Cheat Sheet&lt;/a&gt; to create development environment.  However, working through code exercises to improve code skills is tedious; we would like to build video games using &lt;a href=&quot;https://www.pygame.org&quot;&gt;PyGame&lt;/a&gt;!
&lt;br /&gt;  
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheCshljvVjOpFiBvRjqE6X4OSEwF-ygGtY-_-Tm30VKNCP_ZAT2F1lQkq7O7aEG1SxznikR-f7PPhoZGYc1Nmx8weV5wiMquaZ7kG4GWVLkNGzxizhwDyv6ys3hsKmRrGuad6_ZI91msgPzdj3IXdnv6Dqf_mYdpaiW8qlI6Pa25syIv4Rp84JkGPJLXM/s1610/PyGame.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheCshljvVjOpFiBvRjqE6X4OSEwF-ygGtY-_-Tm30VKNCP_ZAT2F1lQkq7O7aEG1SxznikR-f7PPhoZGYc1Nmx8weV5wiMquaZ7kG4GWVLkNGzxizhwDyv6ys3hsKmRrGuad6_ZI91msgPzdj3IXdnv6Dqf_mYdpaiW8qlI6Pa25syIv4Rp84JkGPJLXM/s600/PyGame.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt; 
Let’s check it out!
&lt;br /&gt;&lt;br /&gt; 
&lt;u&gt;PyGame&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/pygame/pygame&quot;&gt;PyGame&lt;/a&gt; is a free and open-source cross-platform library for the development of video games using Python. Using Simple &lt;a href=&quot;https://en.wikipedia.org/wiki/Simple_DirectMedia_Layer&quot;&gt;DirectMedia Layer&lt;/a&gt; to abstract most common functions makes it easier to write these programs.
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Tutorials&lt;/u&gt;&lt;br /&gt;
In order to build video games in Python we first need to learn PyGame APIs.  Here are some great resources:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://www.pygame.org/docs&quot;&gt;PyGame Docs&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Comprehensive documentation reference for using Pygame to create games&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/pygame/pygame/tree/main/examples&quot;&gt;PyGame Examples&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;GitHub repository with sample programs that demonstrate how to use Pygame&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://coderslegacy.com/python/python-pygame-tutorial&quot;&gt;PyGame Coders&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Beginner-friendly Pygame tutorial that teaches the game development basics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://www.tutorialspoint.com/pygame/pygame_tutorial.pdf&quot;&gt;PyGame Tutorial&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Extremely thorough Pygame tutorial used to drive examples in this blog post&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/01-Example&quot;&gt;Example I&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello PyGame&lt;/i&gt;&lt;br /&gt;
All examples listed are Python 3.11.11 &lt;a href=&quot;https://steveproxna.blogspot.com/2026/02/python-package-cheat-sheet.html&quot;&gt;compatible&lt;/a&gt;. Launch PyCharm | New Project. Enter the following info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq5l3KiTMSXnoXq2jsStUVRWz1U_KlYd6bp1CLheDWj8vwN6UgSnNaaA4cNqcP3jmpp7jIdZ6XTXk01V-MG7I6NaMEbAX9d08TNy5-vZU1pKrvXapc39grPOhauwHDAFHZ8pzOnba9Ls-AIcwEuhZbw6ZTFCndHyXS7iuLF0v3m3hsmazewzym2SvCSuo/s1000/HelloPyGameProject.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjq5l3KiTMSXnoXq2jsStUVRWz1U_KlYd6bp1CLheDWj8vwN6UgSnNaaA4cNqcP3jmpp7jIdZ6XTXk01V-MG7I6NaMEbAX9d08TNy5-vZU1pKrvXapc39grPOhauwHDAFHZ8pzOnba9Ls-AIcwEuhZbw6ZTFCndHyXS7iuLF0v3m3hsmazewzym2SvCSuo/s600/HelloPyGameProject.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyGame&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.11&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
PyCharm should setup UV virtual environment and configure Python interpreter if not then enter commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.11
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.11.11
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyGameSetup/01-Example/pyproject.toml&quot;&gt;dependencies&lt;/a&gt;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv lock
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following file: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyGameSetup/01-Example/main.py&quot;&gt;main.py&lt;/a&gt;.  Enter the command &lt;b&gt;uv run main.py&lt;/b&gt;.  Verify Hello PyGame is working OK!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example I&lt;/strong&gt; - &lt;i&gt;Hello PyGame&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pygame
&amp;nbsp;&amp;nbsp;pygame.init()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;screen = pygame.display.set_mode((640, 480))
&amp;nbsp;&amp;nbsp;pygame.display.set_caption(&amp;quot;Hello PyGame!&amp;quot;)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;font = pygame.font.Font(None, 48)  # Built-in default font
&amp;nbsp;&amp;nbsp;text = font.render(&amp;quot;Hello PyGame!&amp;quot;, True, (255, 255, 255))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;running = True
&amp;nbsp;&amp;nbsp;while running:
&amp;nbsp;&amp;nbsp;    for event in pygame.event.get():
&amp;nbsp;&amp;nbsp;        if event.type == pygame.QUIT:
&amp;nbsp;&amp;nbsp;            running = False
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    screen.fill((0, 0, 0))
&amp;nbsp;&amp;nbsp;    screen.blit(text, (220, 220))
&amp;nbsp;&amp;nbsp;    pygame.display.flip()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;pygame.quit()
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- &lt;br /&gt; --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVOZjJ2hYKZSy2JYCUUWVeA02D7eelwzuSvkY5T6P3ma_EASH_x37IEb-bVr6AZoXHh9YGjCOrtA5sPtyQHyme-_DOtuK_dZoRs8Sg2y_Mwb_gWYNZmsFBpddftv4dljt4twReIO0fwit8TPZ2P09OmoVLOhK_g5hSFCi9vk6EDgf8FNatCUeot91lHh4/s642/HelloPyGameText.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVOZjJ2hYKZSy2JYCUUWVeA02D7eelwzuSvkY5T6P3ma_EASH_x37IEb-bVr6AZoXHh9YGjCOrtA5sPtyQHyme-_DOtuK_dZoRs8Sg2y_Mwb_gWYNZmsFBpddftv4dljt4twReIO0fwit8TPZ2P09OmoVLOhK_g5hSFCi9vk6EDgf8FNatCUeot91lHh4/s600/HelloPyGameText.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;br /&gt;  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/02-Example&quot;&gt;Example II&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello Splash&lt;/i&gt;&lt;br /&gt;
Repeat previous exercise but render splash screen. Launch PyCharm | New Project. Enter the following info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloSplash&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.11&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyGameSetup/02-Example/pyproject.toml&quot;&gt;dependencies&lt;/a&gt;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.11
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.11.11
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following file: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyGameSetup/02-Example/main.py&quot;&gt;main.py&lt;/a&gt;.  Enter the command &lt;b&gt;uv run main.py&lt;/b&gt;.  Verify splash screen renders OK!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example II&lt;/strong&gt; - &lt;i&gt;Hello Splash&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pygame
&amp;nbsp;&amp;nbsp;pygame.init()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;screen = pygame.display.set_mode((640, 480))
&amp;nbsp;&amp;nbsp;pygame.display.set_caption(&amp;quot;Hello Splash&amp;quot;)
&amp;nbsp;&amp;nbsp;sms_surface = pygame.Surface((640, 480))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;splash = pygame.image.load(&amp;quot;StevePro.bmp&amp;quot;).convert()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;running = True
&amp;nbsp;&amp;nbsp;while running:
&amp;nbsp;&amp;nbsp;    for event in pygame.event.get():
&amp;nbsp;&amp;nbsp;        if event.type == pygame.QUIT:
&amp;nbsp;&amp;nbsp;            running = False
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    wide: int = (640 - splash.get_width()) / 2
&amp;nbsp;&amp;nbsp;    high: int = (480 - splash.get_height()) / 2
&amp;nbsp;&amp;nbsp;    sms_surface.blit(splash, dest=(wide, high))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    screen.fill((0, 0, 0))
&amp;nbsp;&amp;nbsp;    scaled = pygame.transform.scale(sms_surface, (640, 480))
&amp;nbsp;&amp;nbsp;    screen.blit(scaled, (0, 0))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    pygame.display.flip()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;pygame.quit()
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- &lt;br /&gt; --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBUkfED1mfXMT5M8Qk28ANmsxcTef9TxZZGuC3Dh0W9K3Yk9TCowhzG57SZMK3eomV625vifsGmpbkHZR0qFIFiCFyQhEru-EBaJlbU-KjX20NHSPdypwekzIetxNSWSCDB5aoevd0JMOt8LwrTrsZ-n0Vg_47OPkc8OcRUOyoBQC0HRDlxYfBbjXfiwI/s642/HelloSplashScreen.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBUkfED1mfXMT5M8Qk28ANmsxcTef9TxZZGuC3Dh0W9K3Yk9TCowhzG57SZMK3eomV625vifsGmpbkHZR0qFIFiCFyQhEru-EBaJlbU-KjX20NHSPdypwekzIetxNSWSCDB5aoevd0JMOt8LwrTrsZ-n0Vg_47OPkc8OcRUOyoBQC0HRDlxYfBbjXfiwI/s600/HelloSplashScreen.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;br /&gt;  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/03-Example&quot;&gt;Example III&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello Text&lt;/i&gt;&lt;br /&gt;
Repeat previous exercise but render font text. Launch PyCharm | New Project. Setup project as previously:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example III&lt;/strong&gt; - &lt;i&gt;Hello Text&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pygame
&amp;nbsp;&amp;nbsp;pygame.init()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;screen = pygame.display.set_mode((640, 480))
&amp;nbsp;&amp;nbsp;pygame.display.set_caption(&amp;quot;Hello Text&amp;quot;)
&amp;nbsp;&amp;nbsp;sms_surface = pygame.Surface((640, 480))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;font = pygame.font.Font(&amp;quot;emulogic.ttf&amp;quot;, 20)
&amp;nbsp;&amp;nbsp;running = True
&amp;nbsp;&amp;nbsp;while running:
&amp;nbsp;&amp;nbsp;    for event in pygame.event.get():
&amp;nbsp;&amp;nbsp;        if event.type == pygame.QUIT:
&amp;nbsp;&amp;nbsp;            running = False
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    sms_surface.fill((0, 0, 0))
&amp;nbsp;&amp;nbsp;    text_surface = font.render(&amp;quot;Hello Text!&amp;quot;, False, (255, 255, 255))
&amp;nbsp;&amp;nbsp;    sms_surface.blit(text_surface, (0, 0))
&amp;nbsp;&amp;nbsp;    scaled = pygame.transform.scale(sms_surface, (640, 480))
&amp;nbsp;&amp;nbsp;    screen.blit(scaled, (220, 220))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    pygame.display.flip()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;pygame.quit()
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/04-Example&quot;&gt;Example IV&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello Sprites&lt;/i&gt;&lt;br /&gt;
Repeat previous exercise but render out sprites. Launch PyCharm | New Project. Setup project previously:
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example IV&lt;/strong&gt; - &lt;i&gt;Hello Sprites&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pygame
&amp;nbsp;&amp;nbsp;pygame.init()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;screen = pygame.display.set_mode((640, 480))
&amp;nbsp;&amp;nbsp;pygame.display.set_caption(&amp;quot;Hello Sprites&amp;quot;)
&amp;nbsp;&amp;nbsp;sms_surface = pygame.Surface((320, 240))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;spritesheet = pygame.image.load(&amp;quot;Sprites.bmp&amp;quot;).convert()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;def get_sprite(sheet, col, row, width=32, height=32):
&amp;nbsp;&amp;nbsp;    rect = pygame.Rect(col * width, row * height, width, height)
&amp;nbsp;&amp;nbsp;    return sheet.subsurface(rect)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;running = True
&amp;nbsp;&amp;nbsp;while running:
&amp;nbsp;&amp;nbsp;    for event in pygame.event.get():
&amp;nbsp;&amp;nbsp;        if event.type == pygame.QUIT:
&amp;nbsp;&amp;nbsp;            running = False
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    sms_surface.fill((0, 0, 0))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    sprite1 = get_sprite(spritesheet, col=0, row=0)
&amp;nbsp;&amp;nbsp;    sprite2 = get_sprite(spritesheet, col=0, row=1)
&amp;nbsp;&amp;nbsp;    sms_surface.blit(sprite1, (64, 64))
&amp;nbsp;&amp;nbsp;    sms_surface.blit(sprite2, (128, 64))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    scaled = pygame.transform.scale(sms_surface, (640, 480))
&amp;nbsp;&amp;nbsp;    screen.blit(scaled, (0, 0))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    pygame.display.flip()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;pygame.quit()
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/05-Example&quot;&gt;Example V&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello Input&lt;/i&gt;&lt;br /&gt;
Repeat previous exercise but with input detection. Launch PyCharm | New Project. Setup project previously:
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example V&lt;/strong&gt; - &lt;i&gt;Hello Input&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pygame
&amp;nbsp;&amp;nbsp;pygame.init()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;screen = pygame.display.set_mode((640, 480))
&amp;nbsp;&amp;nbsp;pygame.display.set_caption(&amp;quot;Hello Input&amp;quot;)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;font = pygame.font.Font(None, 48)  # Built-in default font
&amp;nbsp;&amp;nbsp;text = font.render(&amp;quot;Hello Input - Press space...&amp;quot;, True, (255, 255, 255))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;running = True
&amp;nbsp;&amp;nbsp;while running:
&amp;nbsp;&amp;nbsp;    for event in pygame.event.get():
&amp;nbsp;&amp;nbsp;        if event.type == pygame.QUIT:
&amp;nbsp;&amp;nbsp;            running = False
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    screen.fill((0, 0, 0))
&amp;nbsp;&amp;nbsp;    screen.blit(text, (100, 220))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    keys = pygame.key.get_pressed()
&amp;nbsp;&amp;nbsp;    if keys[pygame.K_SPACE]:
&amp;nbsp;&amp;nbsp;        space = font.render(&amp;quot;Space pressed!!&amp;quot;, True, (255, 255, 255))
&amp;nbsp;&amp;nbsp;        screen.blit(space, (200, 260))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    pygame.display.flip()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;pygame.quit()
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/06-Example&quot;&gt;Example VI&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello Sound&lt;/i&gt;&lt;br /&gt;
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/07-Example&quot;&gt;Example VII&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello Music&lt;/i&gt;&lt;br /&gt;
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyGameSetup/08-Example&quot;&gt;Example VIII&lt;/a&gt;&lt;/u&gt; - &lt;i&gt;Hello Audio&lt;/i&gt;&lt;br /&gt;
Repeat previous exercise but integrate all audio. Launch PyCharm | New Project. Setup project previously:
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example VIII&lt;/strong&gt; - &lt;i&gt;Hello Audio&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pygame
&amp;nbsp;&amp;nbsp;pygame.init()
&amp;nbsp;&amp;nbsp;pygame.mixer.init()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;screen = pygame.display.set_mode((640, 480))
&amp;nbsp;&amp;nbsp;pygame.display.set_caption(&amp;quot;Hello Audio&amp;quot;)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;font = pygame.font.Font(None, 48)  # Built-in default font
&amp;nbsp;&amp;nbsp;sound_01 = pygame.mixer.Sound(&amp;quot;right.wav&amp;quot;)
&amp;nbsp;&amp;nbsp;sound_02 = pygame.mixer.Sound(&amp;quot;wrong.wav&amp;quot;)
&amp;nbsp;&amp;nbsp;pygame.mixer.music.load(&amp;quot;music.mp3&amp;quot;)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;def render_text(text, color=(255, 255, 255)):
&amp;nbsp;&amp;nbsp;    return font.render(text, False, color)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;text1 = render_text(&amp;quot;Hello Audio!&amp;quot; )
&amp;nbsp;&amp;nbsp;text2 = render_text(&amp;quot;Press Left - sound #1&amp;quot;)
&amp;nbsp;&amp;nbsp;text3 = render_text(&amp;quot;Press Right - sound #2&amp;quot;)
&amp;nbsp;&amp;nbsp;text4 = render_text(&amp;quot;Press Up - play music&amp;quot;)
&amp;nbsp;&amp;nbsp;text5 = render_text(&amp;quot;Press Down - stop music&amp;quot;)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;running = True
&amp;nbsp;&amp;nbsp;while running:
&amp;nbsp;&amp;nbsp;    for event in pygame.event.get():
&amp;nbsp;&amp;nbsp;        if event.type == pygame.QUIT:
&amp;nbsp;&amp;nbsp;            running = False
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    screen.fill((0, 0, 0))
&amp;nbsp;&amp;nbsp;    screen.blit(text1, (220, 140))
&amp;nbsp;&amp;nbsp;    screen.blit(text2, (160, 180))
&amp;nbsp;&amp;nbsp;    screen.blit(text3, (160, 220))
&amp;nbsp;&amp;nbsp;    screen.blit(text4, (160, 260))
&amp;nbsp;&amp;nbsp;    screen.blit(text5, (160, 300))
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    keys = pygame.key.get_pressed()
&amp;nbsp;&amp;nbsp;    if keys[pygame.K_LEFT]:
&amp;nbsp;&amp;nbsp;        sound_01.play()
&amp;nbsp;&amp;nbsp;    if keys[pygame.K_RIGHT]:
&amp;nbsp;&amp;nbsp;        sound_02.play()
&amp;nbsp;&amp;nbsp;    if keys[pygame.K_UP]:
&amp;nbsp;&amp;nbsp;        pygame.mixer.music.play()
&amp;nbsp;&amp;nbsp;    if keys[pygame.K_DOWN]:
&amp;nbsp;&amp;nbsp;        pygame.mixer.music.stop()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    pygame.display.flip()
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;pygame.quit()
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;  
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example III&lt;/strong&gt; - &lt;i&gt;Hello Text&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example IV&lt;/strong&gt; - &lt;i&gt;Hello Sprites&lt;/i&gt;&lt;/td&gt;
&lt;/tr&gt;  
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyxLK0FV6ZjgLo9tVXDjkLcBZZCAoEM5vrpCYiTWDzazFMW4rP3Mdv9DvDhrEfOh4jvi6WThNzu_wLBQqM9NJnzWcZxBfEcfHucnCNH_8r3J7uBOFnT6ZDJADZpwsiIuy44HgChw_BMi0r1qoyQspaWX5dgQVSTBWWzP3xz9V1jH-gM6Dhha9sH0BVyaU/s642/Ex03-HelloText.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyxLK0FV6ZjgLo9tVXDjkLcBZZCAoEM5vrpCYiTWDzazFMW4rP3Mdv9DvDhrEfOh4jvi6WThNzu_wLBQqM9NJnzWcZxBfEcfHucnCNH_8r3J7uBOFnT6ZDJADZpwsiIuy44HgChw_BMi0r1qoyQspaWX5dgQVSTBWWzP3xz9V1jH-gM6Dhha9sH0BVyaU/s600/Ex03-HelloText.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHtPAmA2YhXm4oE_iewP0zJD5XwWEt8b9o8o3733tNZijGCn8SURtwPlpyEXFP9LfTGZr9VOQrX7EVv_aZVrcHZfGJctjLgZ5MhTNgp_h5ar4jduEAV4PLRqZuYUemDY6Vw3WHSiuczOh_M4W9liX8NHFEu4BZCgExFeJlDWFlOt9uZiBt7EnwelvjNR8/s642/Ex04-HelloSprites.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHtPAmA2YhXm4oE_iewP0zJD5XwWEt8b9o8o3733tNZijGCn8SURtwPlpyEXFP9LfTGZr9VOQrX7EVv_aZVrcHZfGJctjLgZ5MhTNgp_h5ar4jduEAV4PLRqZuYUemDY6Vw3WHSiuczOh_M4W9liX8NHFEu4BZCgExFeJlDWFlOt9uZiBt7EnwelvjNR8/s600/Ex04-HelloSprites.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example V&lt;/strong&gt; - &lt;i&gt;Hello Input&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example VIII&lt;/strong&gt; - &lt;i&gt;Hello Audio&lt;/i&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEUsimoLASTSxtidcGa1w0xu0lsohQcke8WA2Xa0cD1mDNCqppJsiAnkjSEgS6_KfKf2YmxU3ta7VW3iXKP40xWXPdgBcIxUsHMpB-l9cUDj6KRgj0VuKD2BpVPWI4HY2urVR8fI18yu98xM7MpU1Mkw_HPnFdrIetohdmsRU5p87D9k2Ftrxr75D-f5Y/s642/Ex05-HelloInput.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEUsimoLASTSxtidcGa1w0xu0lsohQcke8WA2Xa0cD1mDNCqppJsiAnkjSEgS6_KfKf2YmxU3ta7VW3iXKP40xWXPdgBcIxUsHMpB-l9cUDj6KRgj0VuKD2BpVPWI4HY2urVR8fI18yu98xM7MpU1Mkw_HPnFdrIetohdmsRU5p87D9k2Ftrxr75D-f5Y/s600/Ex05-HelloInput.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmkim8bLyU2I01s8nM3aOyhnH3TvjrTZkf6wgciIe-S0VcYX586_QzFc-I3jrTj_S7-SdAY6wSAm-2u-hVCeCSLraTgOpAyCK6jBRZySa4JvIDIsQKquWhbJ4Ypg-S5z5ue1vYZtqy8m4rxCscVeavyID0ZrgzQDuX_Id7k_D5mJMol7ZX12gO4zCAV6Q/s642/Ex08-HelloAudio.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmkim8bLyU2I01s8nM3aOyhnH3TvjrTZkf6wgciIe-S0VcYX586_QzFc-I3jrTj_S7-SdAY6wSAm-2u-hVCeCSLraTgOpAyCK6jBRZySa4JvIDIsQKquWhbJ4Ypg-S5z5ue1vYZtqy8m4rxCscVeavyID0ZrgzQDuX_Id7k_D5mJMol7ZX12gO4zCAV6Q/s600/Ex08-HelloAudio.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we now have the building blocks to implement PyGame APIs; we are in an excellent position to reuse existing video game content and port video game from another language to Python using PyGame!  This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2026/11/pygame-programming-sample.html&quot;&gt;post&lt;/a&gt;.
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2026/09/pygame-programming-setup.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheCshljvVjOpFiBvRjqE6X4OSEwF-ygGtY-_-Tm30VKNCP_ZAT2F1lQkq7O7aEG1SxznikR-f7PPhoZGYc1Nmx8weV5wiMquaZ7kG4GWVLkNGzxizhwDyv6ys3hsKmRrGuad6_ZI91msgPzdj3IXdnv6Dqf_mYdpaiW8qlI6Pa25syIv4Rp84JkGPJLXM/s72-c/PyGame.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-3053384654390681942</guid><pubDate>Tue, 05 May 2026 08:02:00 +0000</pubDate><atom:updated>2026-05-05T01:02:12.596-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">AI</category><title>PyTorch Setup Cheat Sheet II</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

In the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2026/04/pytorch-setup-cheat-sheet.html&quot;&gt;post&lt;/a&gt;, we checked out PyTorch Setup as an open-source machine learning framework widely used for building + training neural networks.  Here we installed and configured our nVidia driver and CUDA Toolkit to build some simple PyTorch programs.  However, we built PyTorch3d + TorchSparse packages from source each time.  Now we&#39;d like to pre-build custom wheels housed on localhost for future examples reuse.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQOvRLMCkSahj7o71INnlByMXsLthjiUzdBMTxoIlyWskK1BOd3Wc0Z3oAiwXfa5pBJG7ynepfKPGtuV4dFSx2WUExguAMyIxMYCefr8aGI7tbvPhOrqDebG5NBqnAdshg7BOKEaGnb6g1FCaFr5wQHLGFKXEZ0nunmni91dWzAibUyAtTISewcREpMfE/s636/PyTorchLogo.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQOvRLMCkSahj7o71INnlByMXsLthjiUzdBMTxoIlyWskK1BOd3Wc0Z3oAiwXfa5pBJG7ynepfKPGtuV4dFSx2WUExguAMyIxMYCefr8aGI7tbvPhOrqDebG5NBqnAdshg7BOKEaGnb6g1FCaFr5wQHLGFKXEZ0nunmni91dWzAibUyAtTISewcREpMfE/s600/PyTorchLogo.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheetII/01-Example&quot;&gt;Example I&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
All examples listed are Python 3.10.19 compatible. Launch PyCharm | New Project. Enter the following info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxgIHgV6C7wVBw29bhA6eVsYiqMyhrxdIyMELC19tG4K4oztAEOonATSLpJlsaKcAMveEyV8LC-2KA9mfJSrjKblS-VZau1XFUi00sJ3RVIKU-lWBGOyo3gkfOBDiQpeBbcJYiA2AbwLmHg9LWI3wum7CPaHFedpZtUHWVN-V2c3_ANp4Dkk2iSPlnhxg/s1000/HelloPyTorch3dWheels.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxgIHgV6C7wVBw29bhA6eVsYiqMyhrxdIyMELC19tG4K4oztAEOonATSLpJlsaKcAMveEyV8LC-2KA9mfJSrjKblS-VZau1XFUi00sJ3RVIKU-lWBGOyo3gkfOBDiQpeBbcJYiA2AbwLmHg9LWI3wum7CPaHFedpZtUHWVN-V2c3_ANp4Dkk2iSPlnhxg/s600/HelloPyTorch3dWheels.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyTorch3dWheels&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
PyCharm should setup UV virtual environment and configure Python interpreter if not then enter commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.10
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.10.19
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install packages to build custom wheels:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv pip install twine
&amp;nbsp;&amp;nbsp;uv pip install numpy==1.26.4
&amp;nbsp;&amp;nbsp;uv pip install --index-url https://download.pytorch.org/whl/cu121 \
&amp;nbsp;&amp;nbsp;    &quot;torch==2.2.0+cu121&quot; &quot;torchvision==0.17.0&quot;  &quot;torchaudio==2.2.0&quot;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create directory to house custom wheels &lt;i&gt;mkdir -p wheelhouse-cu121&lt;/i&gt;.  Write shell scripts to code wheel logic:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;  
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;PyTorch3D&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;chmod +x &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/01-Example/steveprobuild_pytorch3d_wheel.sh&quot;&gt;steveprobuild_pytorch3d_wheel.sh&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;TorchSparse&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;chmod +x &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/01-Example/steveprobuild_torchsparse_wheel.sh&quot;&gt;steveprobuild_torchsparse_wheel.sh&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Execute shell scripts to build custom wheels.  These will be the custom wheels used locally on next examples:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;  
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;COMMAND&lt;/b&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;ARTIFACT&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;bash &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/01-Example/steveprobuild_pytorch3d_wheel.sh&quot;&gt;steveprobuild_pytorch3d_wheel.sh&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;stevepropytorch3d-0.7.7-cp310-cp310-linux_x86_64.whl &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;bash &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/01-Example/steveprobuild_torchsparse_wheel.sh&quot;&gt;steveprobuild_torchsparse_wheel.sh&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;steveprotorchsparse-2.0.0b0-cp310-cp310-linux_x86_64.whl &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheetII/02-Example&quot;&gt;Example II&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise using locally built wheels.  Launch PyCharm | New Project.  Enter the following info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyTorch3dWheels&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
Copy custom wheels built from previous example: &lt;i&gt;mkdir wheelhouse-cu121&lt;/i&gt;.  Copy files into new directory:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;mkdir -p wheelhouse-cu121
&amp;nbsp;&amp;nbsp;cp -r ../01-Example/wheelhouse-cu121 .
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/02-Example/pyproject.toml&quot;&gt;dependencies&lt;/a&gt;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export MAX_JOBS=1
&amp;nbsp;&amp;nbsp;export NVCC_THREADS=1
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv lock
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following file: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/02-Example/main.py&quot;&gt;main.py&lt;/a&gt;.  Enter the command &lt;b&gt;uv run main.py&lt;/b&gt;.  Verify PyTorch packages installed!
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb79Zt0pM7bF95Bo1-iDwVK3FEJgILUGZu1qPmrIW1EaD8ydKx-6EjRHK8mhCNFKOUIjSHk0Ldty5fk7VkYHpYqRvvTNqW1DC1ypmnHsGq-ZsrBp32gHorzXEzMlqDMdfA7vRavVwEBXNvZ-CH_mPKRqczlna_KMqqzyYa9Q2TH_cHcrPuUYnyZ8xP1I0/s1027/HelloPyTorch3dOutput.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb79Zt0pM7bF95Bo1-iDwVK3FEJgILUGZu1qPmrIW1EaD8ydKx-6EjRHK8mhCNFKOUIjSHk0Ldty5fk7VkYHpYqRvvTNqW1DC1ypmnHsGq-ZsrBp32gHorzXEzMlqDMdfA7vRavVwEBXNvZ-CH_mPKRqczlna_KMqqzyYa9Q2TH_cHcrPuUYnyZ8xP1I0/s600/HelloPyTorch3dOutput.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example II&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;Hello PyTorch3d
&amp;nbsp;&amp;nbsp;torch 2.2.0+cu121
&amp;nbsp;&amp;nbsp;pytorch3d 0.7.7
&amp;nbsp;&amp;nbsp;cuda 12.1
&amp;nbsp;&amp;nbsp;cuda True
&amp;nbsp;&amp;nbsp;torch_geometric 2.7.0
&amp;nbsp;&amp;nbsp;torch_scatter 2.1.2+pt22cu121
&amp;nbsp;&amp;nbsp;torch_sparse 0.6.18+pt22cu121
&amp;nbsp;&amp;nbsp;torch_cluster 1.6.3+pt22cu121
&amp;nbsp;&amp;nbsp;torch_spline_conv 1.2.2+pt22cu121
&amp;nbsp;&amp;nbsp;torchsparse 2.0.0b
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheetII/03-Example&quot;&gt;Example III&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but upload custom wheels.  Launch PyCharm | New Project.  Enter the following info
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyTorch3dWheels&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
Copy custom wheels built from previous example: &lt;i&gt;mkdir wheelhouse-cu121&lt;/i&gt;.  Copy files into new directory:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;mkdir -p wheelhouse-cu121
&amp;nbsp;&amp;nbsp;cp -r ../01-Example/wheelhouse-cu121 .
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands to install devpi packages to upload wheels locally:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv pip install devpi-server
&amp;nbsp;&amp;nbsp;uv pip install devpi-client
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv pip install devpi-web
&amp;nbsp;&amp;nbsp;uv pip install twine
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch Terminal #1.  Initialize devpi-server on localhost port 3141 and start.  Navigate to the homepage URL
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;devpi-init					# Launch browser
&amp;nbsp;&amp;nbsp;devpi-server --host 127.0.0.1 --port 3141	# Navigate http://localhost:3141
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch Terminal #2.  Connect to the devpi-client and login.  Create custom cuda-wheels index and activate
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;devpi use http://localhost:3141
&amp;nbsp;&amp;nbsp;devpi login root --password=&#39;&#39;
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;devpi index -c cuda-wheels bases=root/pypi&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;devpi use root/cuda-wheels
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Finally upload 2x custom wheel files to devpi-web available at &lt;b&gt;http://localhost:3141/root/cuda-wheels&lt;/b&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 11px;&quot;&gt;
&amp;nbsp;&amp;nbsp;twine upload --repository-url http://localhost:3141/root/cuda-wheels/ wheelhouse-cu121/*&amp;nbsp;&amp;nbsp
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxSzpXh_G6qKBmFMc16wphQLF6_WxSCIsTOYnqQ8g4TXn-5z2nlK0A7LAsHAZs4EOYiYcHgy3gBncgSaEpUwGKVGvvxE2aQE1FUotNR61g-8A9bHwpSYiX4ZhaxFi_t1m5KkgVn_IWQfx12BGFNM7UgUGUiMAHAudhXBz_62Y4EOiqmodAzMZP0o_Y7AM/s1208/devpi-cuda-wheels.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxSzpXh_G6qKBmFMc16wphQLF6_WxSCIsTOYnqQ8g4TXn-5z2nlK0A7LAsHAZs4EOYiYcHgy3gBncgSaEpUwGKVGvvxE2aQE1FUotNR61g-8A9bHwpSYiX4ZhaxFi_t1m5KkgVn_IWQfx12BGFNM7UgUGUiMAHAudhXBz_62Y4EOiqmodAzMZP0o_Y7AM/s600/devpi-cuda-wheels.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheetII/04-Example&quot;&gt;Example IV&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise using uploaded wheels.  Launch PyCharm | New Project.  Enter the following info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyTorch3dWheels&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
In the PyCharm Terminal | Enter the following commands to install devpi packages to consume local wheels:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv pip install devpi-server
&amp;nbsp;&amp;nbsp;uv pip install devpi-client
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv pip install devpi-web
&amp;nbsp;&amp;nbsp;uv pip install twine
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch Terminal #1.  Initialize devpi-server on localhost port 3141 and start.  Navigate to the homepage URL
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;devpi-init					# Launch browser
&amp;nbsp;&amp;nbsp;devpi-server --host 127.0.0.1 --port 3141	# Navigate http://localhost:3141
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/04-Example/pyproject.toml&quot;&gt;dependencies&lt;/a&gt;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export MAX_JOBS=1
&amp;nbsp;&amp;nbsp;export NVCC_THREADS=1
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv lock
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following file: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/04-Example/main.py&quot;&gt;main.py&lt;/a&gt;.  Enter the command &lt;b&gt;uv run main.py&lt;/b&gt;.  Verify PyTorch packages installed!
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb79Zt0pM7bF95Bo1-iDwVK3FEJgILUGZu1qPmrIW1EaD8ydKx-6EjRHK8mhCNFKOUIjSHk0Ldty5fk7VkYHpYqRvvTNqW1DC1ypmnHsGq-ZsrBp32gHorzXEzMlqDMdfA7vRavVwEBXNvZ-CH_mPKRqczlna_KMqqzyYa9Q2TH_cHcrPuUYnyZ8xP1I0/s1027/HelloPyTorch3dOutput.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb79Zt0pM7bF95Bo1-iDwVK3FEJgILUGZu1qPmrIW1EaD8ydKx-6EjRHK8mhCNFKOUIjSHk0Ldty5fk7VkYHpYqRvvTNqW1DC1ypmnHsGq-ZsrBp32gHorzXEzMlqDMdfA7vRavVwEBXNvZ-CH_mPKRqczlna_KMqqzyYa9Q2TH_cHcrPuUYnyZ8xP1I0/s600/HelloPyTorch3dOutput.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example IV&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;Hello PyTorch3d
&amp;nbsp;&amp;nbsp;torch 2.2.0+cu121
&amp;nbsp;&amp;nbsp;pytorch3d 0.7.7
&amp;nbsp;&amp;nbsp;cuda 12.1
&amp;nbsp;&amp;nbsp;cuda True
&amp;nbsp;&amp;nbsp;torch_geometric 2.7.0
&amp;nbsp;&amp;nbsp;torch_scatter 2.1.2+pt22cu121
&amp;nbsp;&amp;nbsp;torch_sparse 0.6.18+pt22cu121
&amp;nbsp;&amp;nbsp;torch_cluster 1.6.3+pt22cu121
&amp;nbsp;&amp;nbsp;torch_spline_conv 1.2.2+pt22cu121
&amp;nbsp;&amp;nbsp;torchsparse 2.0.0b
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheetII/05-Example&quot;&gt;Example V&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but wrap logic as Azure ML endpoint.  Launch PyCharm | New Project.  Enter info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnRBTV2AAXc6kZ_sKalVsSlog77OMO8ierw-ZbrgQgD6cJyLMUoE0fa7j0QccEk0E6AuPNHrDgQ3IR3UGr1xNjbBhXdrTXosoo6l1BFMiNZu0DKLaCR6kuUK0QzQETgaA_lkWpKEUiGYmWWwdcQNhoJD5vg-T-otqsl-RBIbOSI1qkEUJ-UP8Pj1AhE9E/s1000/HelloAzureML.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnRBTV2AAXc6kZ_sKalVsSlog77OMO8ierw-ZbrgQgD6cJyLMUoE0fa7j0QccEk0E6AuPNHrDgQ3IR3UGr1xNjbBhXdrTXosoo6l1BFMiNZu0DKLaCR6kuUK0QzQETgaA_lkWpKEUiGYmWWwdcQNhoJD5vg-T-otqsl-RBIbOSI1qkEUJ-UP8Pj1AhE9E/s600/HelloAzureML.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloAzureML&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
PyCharm should setup UV virtual environment and configure Python interpreter if not then enter commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.10
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.10.19
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/05-Example/pyproject.toml&quot;&gt;dependencies&lt;/a&gt;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export MAX_JOBS=1
&amp;nbsp;&amp;nbsp;export NVCC_THREADS=1
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv lock
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following directories &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheetII/05-Example/app&quot;&gt;app&lt;/a&gt;&lt;/b&gt; and &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheetII/05-Example/tests&quot;&gt;tests&lt;/a&gt;&lt;/b&gt;.  Enter all code for &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/05-Example/app/scoring.py&quot;&gt;app/scoring.py&lt;/a&gt;.  Test all code using &lt;b&gt;pytest&lt;/b&gt;.
&lt;br /&gt;
Launch terminals. Enter following commands: build &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheetII/05-Example/Dockerfile&quot;&gt;Docker&lt;/a&gt; image run Docker container and submit request:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Terminal #1&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;docker build -t azml-gpu-local:latest .
&amp;nbsp;&amp;nbsp;docker run --gpus all -p 5001:5001 azml-gpu-local:latest
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Terminal #2&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;curl --location --request POST &amp;#x27;http://localhost:5001/score&amp;#x27; \
&amp;nbsp;&amp;nbsp;  --header &amp;#x27;Content-Type: application/json&amp;#x27; \
&amp;nbsp;&amp;nbsp;  --data-raw &amp;#x27;{
&amp;nbsp;&amp;nbsp;  &amp;quot;points&amp;quot;: [
&amp;nbsp;&amp;nbsp;    [0.0, 0.0, 1.0],
&amp;nbsp;&amp;nbsp;    [0.1, 0.0, 0.99],
&amp;nbsp;&amp;nbsp;    [-0.1, 0.0, 0.99],
&amp;nbsp;&amp;nbsp;    [0.0, 0.1, 0.99],
&amp;nbsp;&amp;nbsp;    [0.0, -0.1, 0.99],
&amp;nbsp;&amp;nbsp;    [0.7, 0.7, 0.0],
&amp;nbsp;&amp;nbsp;    [-0.7, 0.7, 0.0],
&amp;nbsp;&amp;nbsp;    [0.7, -0.7, 0.0],
&amp;nbsp;&amp;nbsp;    [-0.7, -0.7, 0.0],
&amp;nbsp;&amp;nbsp;    [0.0, 0.0, -1.0]
&amp;nbsp;&amp;nbsp;  ]
&amp;nbsp;&amp;nbsp;}&amp;#x27;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF9LfrZcnlP9BnXvU3V6gMThMy6lf7ISpyzORaxXgkpL9JXzDueeNNlIsUdfXdynJpB2yZVojm1zSL-20crG30ECrSSHt0dLle6TVjRbeeRG1xdCMk7LN0yntsAS5z8Nt0lro1b0pk0xFBhoBLqZ7LkD0xyKGBSRX3JJYpDrM3_a7lwxFk9RWUF6TYCEg/s1128/ScorePointCloud.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF9LfrZcnlP9BnXvU3V6gMThMy6lf7ISpyzORaxXgkpL9JXzDueeNNlIsUdfXdynJpB2yZVojm1zSL-20crG30ECrSSHt0dLle6TVjRbeeRG1xdCMk7LN0yntsAS5z8Nt0lro1b0pk0xFBhoBLqZ7LkD0xyKGBSRX3JJYpDrM3_a7lwxFk9RWUF6TYCEg/s600/ScorePointCloud.png&quot;/&gt;&lt;/a&gt;  
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example V&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;    &amp;quot;num_vertices&amp;quot;: 1524,
&amp;nbsp;&amp;nbsp;    &amp;quot;num_faces&amp;quot;: 2892,
&amp;nbsp;&amp;nbsp;    &amp;quot;mean_pixel&amp;quot;: 0.9926620125770569,
&amp;nbsp;&amp;nbsp;    &amp;quot;image_shape&amp;quot;: [
&amp;nbsp;&amp;nbsp;		128,
&amp;nbsp;&amp;nbsp;		128,
&amp;nbsp;&amp;nbsp;		3
&amp;nbsp;&amp;nbsp;	],
&amp;nbsp;&amp;nbsp;    &amp;quot;device&amp;quot;: &amp;quot;cuda:0&amp;quot;
&amp;nbsp;&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;   
Cleanup as necessary: stop and remove the docker process esp. if that process is continued to be in use:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;docker stop $(docker ps -q)
&amp;nbsp;&amp;nbsp;docker rm -f $(docker ps -q)
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have built &lt;a href=&quot;https://github.com/facebookresearch/pytorch3d&quot;&gt;PyTorch3d&lt;/a&gt; and &lt;a href=&quot;https://github.com/mit-han-lab/torchsparse&quot;&gt;TorchSparse&lt;/a&gt; packages from source, pre-built the custom wheels housed on localhost for  examples reuse.  We are now in an excellent position: drive Deep Learning education!

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2026/05/pytorch-setup-cheat-sheet-ii.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQOvRLMCkSahj7o71INnlByMXsLthjiUzdBMTxoIlyWskK1BOd3Wc0Z3oAiwXfa5pBJG7ynepfKPGtuV4dFSx2WUExguAMyIxMYCefr8aGI7tbvPhOrqDebG5NBqnAdshg7BOKEaGnb6g1FCaFr5wQHLGFKXEZ0nunmni91dWzAibUyAtTISewcREpMfE/s72-c/PyTorchLogo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-1900855150774645569</guid><pubDate>Sat, 04 Apr 2026 09:00:00 +0000</pubDate><atom:updated>2026-04-06T12:44:09.794-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">AI</category><title>PyTorch Setup Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

&lt;a href=&quot;https://en.wikipedia.org/wiki/PyTorch&quot;&gt;PyTorch&lt;/a&gt; is an open-source machine learning framework widely used for building + training neural networks.  While PyTorch provides the core building blocks for tensors, neural networks, and training loops, most real-world machine learning problems involve domain-specific data—images, audio, graphs + also 3D geometry!
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQOvRLMCkSahj7o71INnlByMXsLthjiUzdBMTxoIlyWskK1BOd3Wc0Z3oAiwXfa5pBJG7ynepfKPGtuV4dFSx2WUExguAMyIxMYCefr8aGI7tbvPhOrqDebG5NBqnAdshg7BOKEaGnb6g1FCaFr5wQHLGFKXEZ0nunmni91dWzAibUyAtTISewcREpMfE/s636/PyTorchLogo.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQOvRLMCkSahj7o71INnlByMXsLthjiUzdBMTxoIlyWskK1BOd3Wc0Z3oAiwXfa5pBJG7ynepfKPGtuV4dFSx2WUExguAMyIxMYCefr8aGI7tbvPhOrqDebG5NBqnAdshg7BOKEaGnb6g1FCaFr5wQHLGFKXEZ0nunmni91dWzAibUyAtTISewcREpMfE/s600/PyTorchLogo.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
PyTorch ecosystem extends specialized libraries for different domains [vision, audio, 3D, sparse data] go-to choice for everything from prototyping research ideas to deploying production-grade deep learning systems.
  
&lt;br /&gt;&lt;br /&gt;
PACKAGES&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;torch&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Core PyTorch library providing tensors, autograd and neural network building blocks&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;torchaudio&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Tools + datasets for audio processing, waveform transformations and speech models&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;torchvision&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Computer Vision utilities for datasets: pretrained models and image transformations&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;pytorch3d&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3D Deep Learning library for working with meshes, point clouds rendering pipelines&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;torchsparse&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;High-performance sparse tensor library for 3D geometry e.g. LiDAR and voxel grids&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Torch-scatter&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Optimized operations for scattering and aggregating neural networks tensor values&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Torch-sparse&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Sparse matrix operations for PyTorch + often used in 3D Geometric Deep Learning&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Torch-cluster&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Clustering and neighborhood learning query operations e.g. kNN and radius graphs&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Torch-spline-conv&amp;nbsp;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Spline-based convolution layers for Geometric Deep Learning on graphs and meshes&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

CUDA&lt;br /&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/CUDA&quot;&gt;CUDA&lt;/a&gt; [Compute Unified Device Architecture] is a proprietary parallel computing platform and API that allows software to use GPUs for accelerated general-purpose processing in high-performance scientific computing.
&lt;br /&gt;&lt;br /&gt;
Therefore, to leverage PyTorch computations on GPUs one must install nVidia GPU drivers that support your CUDA version, install CUDA Toolkit that includes nvcc compiler with all PyTorch compatible built packages.
&lt;br /&gt;&lt;br /&gt;  
Development setup example:
Ubuntu 20.04 | Linux kernel 5.15.0-9  | nVidia GPU Driver v535  | CUDA 12.1
&lt;br /&gt;&lt;br /&gt;

INSTALLATION&lt;br /&gt;
Complete nVidia CUDA Toolkit installation guide found &lt;a href=&quot;https://docs.nvidia.com/cuda/archive/12.1.0/cuda-installation-guide-linux&quot;&gt;here&lt;/a&gt; but can be summarized in the following steps: 
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uname -r				# 5.15.0-139-generic
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Step #1&lt;/b&gt; - &lt;i&gt;Remove partial CUDA installs&lt;/i&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;sudo apt remove -y cuda* nvidia-cuda-toolkit
&amp;nbsp;&amp;nbsp;sudo apt autoremove -y
&amp;nbsp;&amp;nbsp;sudo rm -rf /usr/local/cuda*
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Step #2&lt;/b&gt; - &lt;i&gt;Install nVidia Driver 535&lt;/i&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;sudo apt update
&amp;nbsp;&amp;nbsp;sudo apt install -y nvidia-driver-535
&amp;nbsp;&amp;nbsp;sudo reboot
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Step #3&lt;/b&gt; - &lt;i&gt;Verify nVidia Driver and CUDA version&lt;/i&gt; - nvidia-smi
&lt;br /&gt;  
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRzzCh6otxSMyclgWtpty42FAXJHWf3krd6KIFLIS7vNmf6i7yapU9Im3uk_1Fl03M50ycrNFyMGmLYnAxHKkjouk2jFkgZ-9fNq6HS67J1qLQVy1_Tzuqit6JZfwvSSiOAz1GAgGf78iwuuenJWOMFTL4t6nsCZqLgiKN9r-WQ857EW9ysYtDxgj9eI/s824/nvidia-smi.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRzzCh6otxSMyclgWtpty42FAXJHWf3krd6KIFLIS7vNmf6i7yapU9Im3uk_1Fl03M50ycrNFyMGmLYnAxHKkjouk2jFkgZ-9fNq6HS67J1qLQVy1_Tzuqit6JZfwvSSiOAz1GAgGf78iwuuenJWOMFTL4t6nsCZqLgiKN9r-WQ857EW9ysYtDxgj9eI/s600/nvidia-smi.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;  
&lt;br /&gt;  
&lt;b&gt;Step #4&lt;/b&gt; - &lt;i&gt;Install CUDA 12.1 Toolkit&lt;/i&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 10px;&quot;&gt;
&amp;nbsp;&amp;nbsp;sudo mkdir -p /etc/apt/keyrings
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub \
&amp;nbsp;&amp;nbsp; | sudo gpg --dearmor -o /etc/apt/keyrings/cuda-archive-keyring.gpg
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;echo &amp;quot;deb [signed-by=/etc/apt/keyrings/cuda-archive-keyring.gpg] \
&amp;nbsp;&amp;nbsp;https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/ /&amp;quot; \
&amp;nbsp;&amp;nbsp;| sudo tee /etc/apt/sources.list.d/cuda.list
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;sudo apt update
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Step #5&lt;/b&gt; - &lt;i&gt;Configure Environment Variables&lt;/i&gt; - source ~/.bashrc
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export CUB_HOME=~/cub
&amp;nbsp;&amp;nbsp;export CUDA_HOME=/usr/local/cuda-12.1
&amp;nbsp;&amp;nbsp;export PATH=$CUDA_HOME/bin:$PATH
&amp;nbsp;&amp;nbsp;export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
&lt;b&gt;Step #6&lt;/b&gt; - &lt;i&gt;Verify CUDA 12.1 Toolkit&lt;/i&gt; - nvcc --version
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwgtJbDb7ZOUD9R3aRUrXuYN_Ndp5vPCuPYgBtwQ9Xu0DDKY6l80Th82MTwXnrhyphenhyphenNvRrrID5-2U7aoe9nRcuxEV0atdxzJByr6nXY4k7uzxzX_dlaJStUxY0mGh27vonazz6bDW1KcvxkyGl66M3uCI6QC9pyTB6hqAMskqUMCWbV4qTiDm8JAXDDuhTs/s734/nvcc.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; 
src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwgtJbDb7ZOUD9R3aRUrXuYN_Ndp5vPCuPYgBtwQ9Xu0DDKY6l80Th82MTwXnrhyphenhyphenNvRrrID5-2U7aoe9nRcuxEV0atdxzJByr6nXY4k7uzxzX_dlaJStUxY0mGh27vonazz6bDW1KcvxkyGl66M3uCI6QC9pyTB6hqAMskqUMCWbV4qTiDm8JAXDDuhTs/s600/nvcc.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Kernel&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;5.15.0-139&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Driver&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;nvidia-driver-535&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUDA 12.1&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;/usr/local/cuda-12.1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUDA toolkit&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;/usr/local/cuda-12.1/bin/nvcc&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheet/01-Example&quot;&gt;Example I&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
All examples listed are Python 3.10.19 compatible.  Launch PyCharm | New Project.  Enter the following info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibcf5LsFgM4sBaOXeNxNhNGN7rj13ga0nagi80ZMixV97Gd5uUmfuz9bhfkvib44dEDumub94j-FCEtMF3A0BdnZpj9OcGg6qnQjOd59LaaWT6xl7YIXT9vusdoAw6K42N0nty93YsoqLYJfomWzvXXN7nPt8_xC4JPCKrtH5IXw_091AQ2pNpphAizds/s1000/HelloPyTorch3d.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibcf5LsFgM4sBaOXeNxNhNGN7rj13ga0nagi80ZMixV97Gd5uUmfuz9bhfkvib44dEDumub94j-FCEtMF3A0BdnZpj9OcGg6qnQjOd59LaaWT6xl7YIXT9vusdoAw6K42N0nty93YsoqLYJfomWzvXXN7nPt8_xC4JPCKrtH5IXw_091AQ2pNpphAizds/s600/HelloPyTorch3d.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyTorch3d&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
PyCharm should setup UV virtual environment and configure Python interpreter if not then enter commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.10
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.10.19
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheet/01-Example/pyproject.toml&quot;&gt;dependencies&lt;/a&gt;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export MAX_JOBS=1
&amp;nbsp;&amp;nbsp;export NVCC_THREADS=1
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv lock
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following file: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheet/01-Example/main.py&quot;&gt;main.py&lt;/a&gt;.  Enter the command &lt;b&gt;uv run main.py&lt;/b&gt;.  Verify PyTorch packages installed!
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb79Zt0pM7bF95Bo1-iDwVK3FEJgILUGZu1qPmrIW1EaD8ydKx-6EjRHK8mhCNFKOUIjSHk0Ldty5fk7VkYHpYqRvvTNqW1DC1ypmnHsGq-ZsrBp32gHorzXEzMlqDMdfA7vRavVwEBXNvZ-CH_mPKRqczlna_KMqqzyYa9Q2TH_cHcrPuUYnyZ8xP1I0/s1027/HelloPyTorch3dOutput.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb79Zt0pM7bF95Bo1-iDwVK3FEJgILUGZu1qPmrIW1EaD8ydKx-6EjRHK8mhCNFKOUIjSHk0Ldty5fk7VkYHpYqRvvTNqW1DC1ypmnHsGq-ZsrBp32gHorzXEzMlqDMdfA7vRavVwEBXNvZ-CH_mPKRqczlna_KMqqzyYa9Q2TH_cHcrPuUYnyZ8xP1I0/s600/HelloPyTorch3dOutput.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example I&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;Hello PyTorch3d
&amp;nbsp;&amp;nbsp;torch 2.2.0+cu121
&amp;nbsp;&amp;nbsp;pytorch3d 0.7.7
&amp;nbsp;&amp;nbsp;cuda 12.1
&amp;nbsp;&amp;nbsp;cuda True
&amp;nbsp;&amp;nbsp;torch_geometric 2.7.0
&amp;nbsp;&amp;nbsp;torch_scatter 2.1.2+pt22cu121
&amp;nbsp;&amp;nbsp;torch_sparse 0.6.18+pt22cu121
&amp;nbsp;&amp;nbsp;torch_cluster 1.6.3+pt22cu121
&amp;nbsp;&amp;nbsp;torch_spline_conv 1.2.2+pt22cu121
&amp;nbsp;&amp;nbsp;torchsparse 2.0.0b
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyTorchCheatSheet/02-Example&quot;&gt;Example II&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but wrap logic as Azure ML endpoint.  Launch PyCharm | New Project.  Enter info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnRBTV2AAXc6kZ_sKalVsSlog77OMO8ierw-ZbrgQgD6cJyLMUoE0fa7j0QccEk0E6AuPNHrDgQ3IR3UGr1xNjbBhXdrTXosoo6l1BFMiNZu0DKLaCR6kuUK0QzQETgaA_lkWpKEUiGYmWWwdcQNhoJD5vg-T-otqsl-RBIbOSI1qkEUJ-UP8Pj1AhE9E/s1000/HelloAzureML.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnRBTV2AAXc6kZ_sKalVsSlog77OMO8ierw-ZbrgQgD6cJyLMUoE0fa7j0QccEk0E6AuPNHrDgQ3IR3UGr1xNjbBhXdrTXosoo6l1BFMiNZu0DKLaCR6kuUK0QzQETgaA_lkWpKEUiGYmWWwdcQNhoJD5vg-T-otqsl-RBIbOSI1qkEUJ-UP8Pj1AhE9E/s600/HelloAzureML.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloAzureML&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
PyCharm should setup UV virtual environment and configure Python interpreter if not then enter commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.10
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.10.19
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheet/02-Example/pyproject.toml&quot;&gt;dependencies&lt;/a&gt;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export MAX_JOBS=1
&amp;nbsp;&amp;nbsp;export NVCC_THREADS=1
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv lock
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following files: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheet/02-Example/app/scoring.py&quot;&gt;app/scoring.py&lt;/a&gt; and &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyTorchCheatSheet/02-Example/.env&quot;&gt;.env&lt;/a&gt;.  Enter the command &lt;i&gt;which azmlinfsrv&lt;/i&gt;.  Edit configurations  Copy and paste the azmlinfsrv path as the script value.  Enter the following info to launch Azure ML endpoint: 
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggbq8XI9RsjUOXBgIsxoYQkV_jzi-jL7_3LgpREhaBG0gw-kkqiMHTvTKIGbIkXufN9SkauKQUp0UDO11KAdUM1O03zeeqgRtpcQcgF2fDyoem9disYjLgz25omBJ7Vu4q2yfUkCW5VMJwKLvasNN48Fw2sr2vrjzWHe_L8s5U9IGCuoZ_rj-CoNK0pgU/s880/HelloAzmlinfsrv.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggbq8XI9RsjUOXBgIsxoYQkV_jzi-jL7_3LgpREhaBG0gw-kkqiMHTvTKIGbIkXufN9SkauKQUp0UDO11KAdUM1O03zeeqgRtpcQcgF2fDyoem9disYjLgz25omBJ7Vu4q2yfUkCW5VMJwKLvasNN48Fw2sr2vrjzWHe_L8s5U9IGCuoZ_rj-CoNK0pgU/s600/HelloAzmlinfsrv.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;script value&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloAzureML/.venv/bin/azmlinfsrv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Parameters&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;--entry app/scoring.py&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Working directory&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloAzureML&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to .env files&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloAzureML/.env&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Alternatively, launch terminals.  Enter following commands to launch Azure ML endpoint and submit request:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Terminal #1&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;set -a; source .env; set +a
&amp;nbsp;&amp;nbsp;~/.venv/bin/azmlinfsrv --entry app/scoring.py
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;Terminal #2&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;curl --location --request POST &#39;http://localhost:5001/score&#39; \
&amp;nbsp;&amp;nbsp;  --header &#39;Content-Type: application/json&#39; \
&amp;nbsp;&amp;nbsp;  --data-raw &#39;{}&#39;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMk9jDOAEoq7FNEb3WrdoUBe8LkRNrFARn9BdUSVSfr1Cq5pEnY9127UXrVgIWEhih7ZQDn4jDhu9pJ9aTio3wWMGGNkylb5YS525YRilztt56B_unqmhxIkJBlLU3B3PrNbKk4crtBMtOQAhp2GpC3VLI0RDK0r7ECxJGgXoJh8YAqynuKR_X9rMyPmo/s1289/HelloAzScoring.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMk9jDOAEoq7FNEb3WrdoUBe8LkRNrFARn9BdUSVSfr1Cq5pEnY9127UXrVgIWEhih7ZQDn4jDhu9pJ9aTio3wWMGGNkylb5YS525YRilztt56B_unqmhxIkJBlLU3B3PrNbKk4crtBMtOQAhp2GpC3VLI0RDK0r7ECxJGgXoJh8YAqynuKR_X9rMyPmo/s600/HelloAzScoring.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;Example II&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;    &amp;quot;message&amp;quot;: &amp;quot;Hello PyTorch3d&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;torch_version&amp;quot;: &amp;quot;2.2.0+cu121&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;pytorch3d_version&amp;quot;: &amp;quot;0.7.7&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;cuda_version&amp;quot;: &amp;quot;12.1&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;cuda_available&amp;quot;: true,
&amp;nbsp;&amp;nbsp;    &amp;quot;torch_geometric_version&amp;quot;: &amp;quot;2.7.0&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;torch_scatter_version&amp;quot;: &amp;quot;2.1.2+pt22cu121&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;torch_sparse_version&amp;quot;: &amp;quot;0.6.18+pt22cu121&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;torch_cluster_version&amp;quot;: &amp;quot;1.6.3+pt22cu121&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;torch_spline_conv_version&amp;quot;: &amp;quot;1.2.2+pt22cu121&amp;quot;,
&amp;nbsp;&amp;nbsp;    &amp;quot;torchsparse_version&amp;quot;: &amp;quot;2.0.0b&amp;quot;
&amp;nbsp;&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Cleanup as necessary: find and kill processes using TCP port 5001 esp. if that port is continued to be in use:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;sudo fuser -k 5001/tcp		# Linux
&amp;nbsp;&amp;nbsp;sudo lsof -ti tcp:5001		# MacOS
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have installed and configured our nVidia driver and CUDA Toolkit and built some simple PyTorch programs.  However, we have built the PyTorch3d + TorchSparse packages from source each time.  Ideally, we would like to pre-build custom wheels once and house on localhost for future examples reuse!
&lt;br /&gt;
This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2026/05/pytorch-setup-cheat-sheet-ii.html&quot;&gt;post&lt;/a&gt;.

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2026/04/pytorch-setup-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQOvRLMCkSahj7o71INnlByMXsLthjiUzdBMTxoIlyWskK1BOd3Wc0Z3oAiwXfa5pBJG7ynepfKPGtuV4dFSx2WUExguAMyIxMYCefr8aGI7tbvPhOrqDebG5NBqnAdshg7BOKEaGnb6g1FCaFr5wQHLGFKXEZ0nunmni91dWzAibUyAtTISewcREpMfE/s72-c/PyTorchLogo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-794410487617885626</guid><pubDate>Tue, 17 Mar 2026 09:00:00 +0000</pubDate><atom:updated>2026-03-31T12:26:33.791-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Python</category><title>PyBind Setup Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

In 2024, we checked out &lt;a href=&quot;https://steveproxna.blogspot.com/2024/11/openai-retro-cheat-sheet.html&quot;&gt;OpenAI Retro Cheat Sheet&lt;/a&gt; as an open-source project that provides an interface to interact with various retro video games for purpose of Reinforcement Learning research.  This project: using C/C++ for high-performance but leverages &lt;a href=&quot;https://pybind11.readthedocs.io/en/stable&quot;&gt;pybind11&lt;/a&gt; to create bindings for Python client code consumption.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiGh5yxV4LJ8gBHcID6DomvBgr9iCkvM2Mm1G9UYgPF7mXiHA85U39FNTMQsKutS5KG21EPCQ-fj_coHW2NxlkSm-cDLrwzJhWc6m-TdEiF1sZjlFHchN16KvMOwpCbjkZ6GsMLiUL04YMQeyojoxvqiA9ZPPygzAdUnVnlcSfR7DFUUV-W98ZPd7eEG4/s1131/pybind11-logo.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiGh5yxV4LJ8gBHcID6DomvBgr9iCkvM2Mm1G9UYgPF7mXiHA85U39FNTMQsKutS5KG21EPCQ-fj_coHW2NxlkSm-cDLrwzJhWc6m-TdEiF1sZjlFHchN16KvMOwpCbjkZ6GsMLiUL04YMQeyojoxvqiA9ZPPygzAdUnVnlcSfR7DFUUV-W98ZPd7eEG4/s600/pybind11-logo.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;pybind11&lt;/u&gt;&lt;br /&gt;
A &lt;a href=&quot;http://pybind11.com&quot;&gt;lightweight&lt;/a&gt; header-only library that can be used to integrate C++ with Python to create bindings exposing C++ functions to Python.  Client code written in Python can be consumed to invoke the underlying C++ code.
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;Installation&lt;/u&gt;&lt;br /&gt;
All examples here are executed on Ubuntu Linux.  Therefore install &lt;a href=&quot;https://github.com/bonj4/wiki/blob/main/pybind11_installation.md&quot;&gt;pybind11&lt;/a&gt; globally to begin the examples:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;sudo apt-get update
&amp;nbsp;sudo apt-get install pybind11-dev
&amp;nbsp;sudo apt install build-essential g++
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/01-Example&quot;&gt;Example I&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Create an example that exposes &lt;a href=&quot;https://medium.com/@ahmedfgad/pybind11-tutorial-binding-c-code-to-python-337da23685dc&quot;&gt;C++ function&lt;/a&gt; to Python with pybind11.  Launch terminal | Enter commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;mkdir -p ~/HelloPyBind
&amp;nbsp;&amp;nbsp;cd HelloPyBind
&amp;nbsp;&amp;nbsp;python  -m venv .venv
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.8.10
&amp;nbsp;&amp;nbsp;pip install pybind11
&amp;nbsp;&amp;nbsp;pip install --upgrade pip
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYgMbdT4mZYG5ZA8jEL_ytuoQUWcjwTSjqRj-3IlF36atg2ikaZ4R399DK4GaqfHe0OMV4qTMOcUFKd1zRrkh8m9mJgeSaSJvPvL96WLM5teE7fJ0o4NnTF6zw4EwiVsoUHsL3qPcxKC0GsLKHpgdhoZUBHq4LKIA8TKYQFenHoAo0CGfuscaSxpt8-2c/s736/HelloPybind01a.png&quot;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYgMbdT4mZYG5ZA8jEL_ytuoQUWcjwTSjqRj-3IlF36atg2ikaZ4R399DK4GaqfHe0OMV4qTMOcUFKd1zRrkh8m9mJgeSaSJvPvL96WLM5teE7fJ0o4NnTF6zw4EwiVsoUHsL3qPcxKC0GsLKHpgdhoZUBHq4LKIA8TKYQFenHoAo0CGfuscaSxpt8-2c/s600/HelloPybind01a.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;br /&gt;
Create the following files: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/01-Example/example.cpp&quot;&gt;example.cpp&lt;/a&gt;, &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/01-Example/setup.py&quot;&gt;setup.py&lt;/a&gt;, &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/01-Example/test.py&quot;&gt;test.py&lt;/a&gt;.  Enter the following C++ and Python source code:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/01-Example/example.cpp&quot;&gt;example.cpp&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;#include &amp;lt;pybind11/pybind11.h&amp;gt;
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;int add(int x, int y)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;    return x + y;
&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;PYBIND11_MODULE(example, m)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;    // optional module docstring
&amp;nbsp;&amp;nbsp;    m.doc() = &amp;quot;pybind11 example plugin&amp;quot;;
&amp;nbsp;&amp;nbsp;    m.def(&amp;quot;add&amp;quot;, &amp;amp;add, &amp;quot;A function which adds two numbers&amp;quot;);
&amp;nbsp;&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/01-Example/setup.py&quot;&gt;setup.py&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;from setuptools import setup, Extension
&amp;nbsp;&amp;nbsp;import pybind11
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;ext_modules = [
&amp;nbsp;&amp;nbsp;    Extension(
&amp;nbsp;&amp;nbsp;        &amp;quot;example&amp;quot;,
&amp;nbsp;&amp;nbsp;        [&amp;quot;example.cpp&amp;quot;],
&amp;nbsp;&amp;nbsp;        include_dirs=[pybind11.get_include()],
&amp;nbsp;&amp;nbsp;        language=&amp;quot;c++&amp;quot;
&amp;nbsp;&amp;nbsp;    ),
&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;setup(
&amp;nbsp;&amp;nbsp;    name=&amp;quot;example&amp;quot;,
&amp;nbsp;&amp;nbsp;    version=&amp;quot;0.1&amp;quot;,
&amp;nbsp;&amp;nbsp;    ext_modules=ext_modules,
&amp;nbsp;&amp;nbsp;)
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/01-Example/test.py&quot;&gt;test.py&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import example
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;result = example.add(1, 2)
&amp;nbsp;&amp;nbsp;print(f&quot;1 + 2 = {result}&quot;)
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Build C++ code using setup.py build inplace.  Finally execute &lt;i&gt;python test.py&lt;/i&gt; for Python to execute C++ code!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;python setup.py build_ext --inplace		# example.cpython-38-x86_64-linux-gnu.so
&amp;nbsp;&amp;nbsp;python test.py				# OUTPUT	1 + 2 = 3
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglvt5e31OLhhcfJSAC_tNAIc5D4efHpDumQb-AH_3f-al8KOptjrZJORLOwT5UOvTZ3jCkFKQg_atwKudO4TcTkzE3WoldKtHg93yY8d2H3-W6JVNR4GcMyfnKLSDfN_7rC-z0DpNfaPygX-f01v_aMi1G1LMT8-Ni82_TFHYAIGSudBFV01heuU4bya0/s871/HelloPybind01b.png&quot;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglvt5e31OLhhcfJSAC_tNAIc5D4efHpDumQb-AH_3f-al8KOptjrZJORLOwT5UOvTZ3jCkFKQg_atwKudO4TcTkzE3WoldKtHg93yY8d2H3-W6JVNR4GcMyfnKLSDfN_7rC-z0DpNfaPygX-f01v_aMi1G1LMT8-Ni82_TFHYAIGSudBFV01heuU4bya0/s600/HelloPybind01b.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/02-Example&quot;&gt;Example II&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but prefer PyCharm IDE.  Launch PyCharm | New Project.  Enter the following info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiVvrWw2AjNA3i39GhyphenhyphenTNpeTkJbeIm5Ho9rKXI0xHBle1XSp3H6YRDDuIjEwzsRd-hg2LpNHabTKzqGv8IAbxO_XVrA8AubnuLlUvXnolerpV8kVzUHy4ZCZo3_t9ym3-4aDwZUwd-RS0y708SPeL6WIxb860J4Z5M3EUYX6q162ecD3EVk6ZTjpK-x74/s1000/HelloPybind02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiVvrWw2AjNA3i39GhyphenhyphenTNpeTkJbeIm5Ho9rKXI0xHBle1XSp3H6YRDDuIjEwzsRd-hg2LpNHabTKzqGv8IAbxO_XVrA8AubnuLlUvXnolerpV8kVzUHy4ZCZo3_t9ym3-4aDwZUwd-RS0y708SPeL6WIxb860J4Z5M3EUYX6q162ecD3EVk6ZTjpK-x74/s600/HelloPybind02.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyBind&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.11&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
PyCharm should setup UV virtual environment and configure Python interpreter if not then enter commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.11
&amp;nbsp;&amp;nbsp;source .venv/bin/activate           # OR .\.venv\Scripts\activate
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version            # Python 3.11.11
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;  
In the PyCharm Terminal | Enter the following commands for UV to install and sync package dependencies:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv add pybind11
&amp;nbsp;&amp;nbsp;uv add setuptools
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv lock
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following files: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/02-Example/example.cpp&quot;&gt;example.cpp&lt;/a&gt;, &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/02-Example/setup.py&quot;&gt;setup.py&lt;/a&gt;, &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/02-Example/test.py&quot;&gt;test.py&lt;/a&gt;.  Enter C++ and Python code similar to Example I.  Build C++ code using setup.py build install.  Finally execute &lt;i&gt;uv run test.py&lt;/i&gt; for Python to execute C++ code!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv run setup.py build		
&amp;nbsp;&amp;nbsp;uv run setup.py install		# example.cpython-38-x86_64-linux-gnu.so
&amp;nbsp;&amp;nbsp;uv run test.py			# OUTPUT	3 + 5 = 8	9 - 5 = 4
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/03-Example&quot;&gt;Example III&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but prefer CMake to build &lt;a href=&quot;https://medium.com/@stevechange/using-python-with-c-part1-3e894912214d&quot;&gt;C++ code&lt;/a&gt; via CMakeLists.txt.  Create PyCharm Project:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyBind&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.11&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
In the PyCharm Terminal | Enter the following commands for UV to install and sync package dependencies:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv add pybind11
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create the following files: &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/03-Example/example.cpp&quot;&gt;example.cpp&lt;/a&gt;, &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/03-Example/CMakeLists.txt&quot;&gt;CMakeLists.txt&lt;/a&gt;, &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/03-Example/test.py&quot;&gt;test.p&lt;/a&gt;y.  Enter code similar to Example II but update:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/03-Example/CMakeLists.txt&quot;&gt;CMakeLists.txt&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;cmake_minimum_required(VERSION 3.16)
&amp;nbsp;&amp;nbsp;project(example)
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;# Find the Python 3.11-specific pybind11 CONFIG from pip
&amp;nbsp;&amp;nbsp;execute_process(
&amp;nbsp;&amp;nbsp;        COMMAND ${Python3_EXECUTABLE} -m pybind11 --cmakedir
&amp;nbsp;&amp;nbsp;        OUTPUT_VARIABLE pybind11_DIR
&amp;nbsp;&amp;nbsp;        OUTPUT_STRIP_TRAILING_WHITESPACE
&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;find_package(pybind11 REQUIRED CONFIG)
&amp;nbsp;&amp;nbsp;pybind11_add_module(example example.cpp)
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Build C++ code using cmake and make.  In the PyCharm Terminal | Enter the following commands to build:
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;mkdir -p build
&amp;nbsp;&amp;nbsp;cd build
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;cmake -DPython3_EXECUTABLE=$(which python) ..
&amp;nbsp;&amp;nbsp;make -j$(grep -c ^processor /proc/cpuinfo)
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Enter commands to copy library to be used.  Finally execute &lt;i&gt;uv run test.py&lt;/i&gt; for Python to execute C++ code!
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;python -c &quot;import sysconfig, shutil, glob;		\		
&amp;nbsp;&amp;nbsp;dst = sysconfig.get_paths()[&#39;platlib&#39;];		\
&amp;nbsp;&amp;nbsp;so = glob.glob(&#39;*.so&#39;)[0];				\
&amp;nbsp;&amp;nbsp;shutil.copy2(so, dst)&quot;
&amp;nbsp;&amp;nbsp;cd ..
&amp;nbsp;&amp;nbsp;uv run test.py			# OUTPUT	Hello, World!
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
IMPORTANT&lt;br /&gt;
The first 3x examples worked but tightly coupled Python and C++ without being able to debug separately!
&lt;br /&gt;&lt;br /&gt; 
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/04-Example&quot;&gt;Example IV&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but prefer to modify the project layout to separate top level Python and C++ code:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;~/HelloPyBind/
&amp;nbsp;&amp;nbsp;├── cpp/
&amp;nbsp;&amp;nbsp;│   ├── src/
&amp;nbsp;&amp;nbsp;│   │   ├── api/
&amp;nbsp;&amp;nbsp;│   │   │   ├── my_api.h
&amp;nbsp;&amp;nbsp;│   │   │   └── my_api.cpp
&amp;nbsp;&amp;nbsp;│   │   ├── bindings/
&amp;nbsp;&amp;nbsp;│   │   │   └── pybind_module.cpp       # pybind11 bindings
&amp;nbsp;&amp;nbsp;│   │   ├── CMakeLists.txt
&amp;nbsp;&amp;nbsp;│   │   └── main.cpp                    # C++ executable entry point
&amp;nbsp;&amp;nbsp;│   ├── tests/
&amp;nbsp;&amp;nbsp;│   │   ├── CMakeLists.txt
&amp;nbsp;&amp;nbsp;│   │   └── test_api.cpp
&amp;nbsp;&amp;nbsp;│   └── CMakeLists.txt                  # top-level C++ (CLion entry point)
&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;└── python/
&amp;nbsp;&amp;nbsp;    ├── .venv/
&amp;nbsp;&amp;nbsp;    │   └── lib/
&amp;nbsp;&amp;nbsp;    │       └── python3.11/
&amp;nbsp;&amp;nbsp;    │           └── site-packages/
&amp;nbsp;&amp;nbsp;    │               └── my_api_py.cpython-311-x86_64-linux-gnu.so
&amp;nbsp;&amp;nbsp;    ├── test.py
&amp;nbsp;&amp;nbsp;    ├── pyproject.toml
&amp;nbsp;&amp;nbsp;    └── README.md
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Create PyCharm Project.  Setup virtual environment as before then create CLion project to build C++ code.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigwLXN781qw3DZh6yJcDYKnqfwle-5n6vDDVUZuioH8PbY0vaWOhEFpSJeh3q4ekSAvPVBTcuDIFNUFIC1AjbsApynIYIDRQg5tKiyvavyw9Egmo_SKqkfVk5M9nE0rCElvV3IikLbaXyLtt5Oe4jRv7eZ6ygj9ZU2-rc-nHCTaISiHk_U81iEFxbOhVU/s1000/HelloPybind04a.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigwLXN781qw3DZh6yJcDYKnqfwle-5n6vDDVUZuioH8PbY0vaWOhEFpSJeh3q4ekSAvPVBTcuDIFNUFIC1AjbsApynIYIDRQg5tKiyvavyw9Egmo_SKqkfVk5M9nE0rCElvV3IikLbaXyLtt5Oe4jRv7eZ6ygj9ZU2-rc-nHCTaISiHk_U81iEFxbOhVU/s600/HelloPybind04a.png&quot;/&gt;&lt;/a&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyBind/python&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Interpreter type: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;uv&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Python version:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;3.11&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Path to uv: &lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/.local/bin/uv&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch CLion | New Project.  Create C++ Executable using C++ 17.  Enter the following CLion information:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZuhMmNWxfw8BCpeOEBJnWoX4WxvkNDuoITgoTYXBXThPVhzh45Z0CzoSBDTVzksJYb1GD9n08sFvxb8qjL0wDNhx_P-z_sYzPkqP3ikchubE4tZgENvy92hI2zbCnUUPVSDf_i9nuK5CXTaAJOCyfFBMCZ161f6iqWFPj0dMkxU_jXmuQZunXjMhgHxY/s705/HelloPybind04b.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZuhMmNWxfw8BCpeOEBJnWoX4WxvkNDuoITgoTYXBXThPVhzh45Z0CzoSBDTVzksJYb1GD9n08sFvxb8qjL0wDNhx_P-z_sYzPkqP3ikchubE4tZgENvy92hI2zbCnUUPVSDf_i9nuK5CXTaAJOCyfFBMCZ161f6iqWFPj0dMkxU_jXmuQZunXjMhgHxY/s600/HelloPybind04b.png&quot;/&gt;&lt;/a&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C++&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C++ Executable&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;~/HelloPyBind/cpp&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Language standard:&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C++17&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Set build directory in CLion.  File menu | Settings... | Build, Execution, Deployment | CMake | Build directory
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitVgFdvzMLdRIT7Dw9GJCgMu0m52HnUsT93q23POxMdiHrriyYMhyphenhyphenKKd1LI3grFmbrzH8ndhMEIPzET590KGyly02AOEQ5PxpqDLQLzAHLfuy77aASsL_JKAJ7bMzhVyllP1944pMIVtKlbNSbRULX9soveeTbPvL20BNiRBKhxnGPQ2smn1QwEqTxRLE/s1022/HelloPybind04c.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitVgFdvzMLdRIT7Dw9GJCgMu0m52HnUsT93q23POxMdiHrriyYMhyphenhyphenKKd1LI3grFmbrzH8ndhMEIPzET590KGyly02AOEQ5PxpqDLQLzAHLfuy77aASsL_JKAJ7bMzhVyllP1944pMIVtKlbNSbRULX9soveeTbPvL20BNiRBKhxnGPQ2smn1QwEqTxRLE/s600/HelloPybind04c.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Setup folder layout as above.  Enter all C++ &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/04-Example/cpp/src&quot;&gt;source&lt;/a&gt; code and &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/04-Example/cpp/tests&quot;&gt;tests&lt;/a&gt;.  Rebuild entire solution in Debug mode.
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT&lt;br /&gt;
&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/04-Example/cpp/CMakeLists.txt&quot;&gt;CMakeLists.txt&lt;/a&gt; files are configured to copy shared object SO file into the Python .venv virtual environment
&lt;br /&gt;
&lt;br /&gt; 
Launch PyCharm | Complete the &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/04-Example/python/test.py&quot;&gt;test&lt;/a&gt; runner.  Finally execute &lt;i&gt;uv run test.py&lt;/i&gt; for Python to execute C++ code!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv run test.py				# OUTPUT	1 + 2 = 3
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/05-Example&quot;&gt;Example V&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but prefer more complexity to build &lt;a href=&quot;https://medium.com/@stevechange/using-python-with-c-part2-e1db73185c9e&quot;&gt;C++ code&lt;/a&gt; with classes as consumed by Python
&lt;br /&gt;  
&lt;br /&gt;
Create PyCharm Project. Setup virtual environment as before then create CLion project to build C++ code.  Launch CLion | New Project.  Create C++ Executable using C++ 17.  Enter the following CLion from before.
&lt;br /&gt;
&lt;br /&gt;
Set build directory in CLion.  File menu | Settings... | Build, Execution, Deployment | CMake | Build directory.  Setup folder layout as above.  Enter all C++ &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/05-Example/cpp/src&quot;&gt;source&lt;/a&gt; code and &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/05-Example/cpp/tests&quot;&gt;tests&lt;/a&gt;.  Rebuild entire solution in Debug mode.
&lt;br /&gt;
&lt;br /&gt;
Launch PyCharm | Complete the &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/05-Example/python/test.py&quot;&gt;test&lt;/a&gt; runner.  Finally execute &lt;i&gt;uv run test.py&lt;/i&gt; for Python to execute C++ code!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv run test.py		# OUTPUT	
&amp;nbsp;&amp;nbsp;# Guitar: &#39;Fender&#39; [6-string] = $1500.0
&amp;nbsp;&amp;nbsp;# Guitar: &#39;Ibanez&#39; [7-string] = $1200.0
&amp;nbsp;&amp;nbsp;# Guitar: &#39;Gibson&#39; [6-string] = $2400.0
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/06-Example&quot;&gt;Example VI&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but prefer more complexity to build &lt;a href=&quot;https://medium.com/@stevechange/using-python-with-c-part2-e1db73185c9e&quot;&gt;C++ code&lt;/a&gt; with templates consumed by Python
&lt;br /&gt;  
&lt;br /&gt;
Create PyCharm Project. Setup virtual environment as before then create CLion project to build C++ code.  Launch CLion | New Project.  Create C++ Executable using C++ 17.  Enter the following CLion from before.
&lt;br /&gt;
&lt;br /&gt;
Set build directory in CLion.  File menu | Settings... | Build, Execution, Deployment | CMake | Build directory.  Setup folder layout as above.  Enter all C++ &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/06-Example/cpp/src&quot;&gt;source&lt;/a&gt; code and &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/06-Example/cpp/tests&quot;&gt;tests&lt;/a&gt;.  Rebuild entire solution in Debug mode.
&lt;br /&gt;
&lt;br /&gt;
Launch PyCharm | Complete the &lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/06-Example/python/test.py&quot;&gt;test&lt;/a&gt; runner.  Finally execute &lt;i&gt;uv run test.py&lt;/i&gt; for Python to execute C++ code!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;# OUTPUT	
&amp;nbsp;&amp;nbsp;# Container[0] = 0.0
&amp;nbsp;&amp;nbsp;# Container[1] = 1.0
&amp;nbsp;&amp;nbsp;# Container[2] = 2.0
&amp;nbsp;&amp;nbsp;# Container[3] = 3.0
&amp;nbsp;&amp;nbsp;# Container[4] = 4.0
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;# OUTPUT	
&amp;nbsp;&amp;nbsp;# Container[5] = 5.0
&amp;nbsp;&amp;nbsp;# Container[6] = 6.0
&amp;nbsp;&amp;nbsp;# Container[7] = 7.0
&amp;nbsp;&amp;nbsp;# Container[8] = 8.0
&amp;nbsp;&amp;nbsp;# Container[9] = 9.0
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;u&gt;&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/tree/master/PyBindCheatSheet/07-Example&quot;&gt;Example VII&lt;/a&gt;&lt;/u&gt;&lt;br /&gt;
Repeat previous exercise but prefer Visual Studio 2022 on Windows to build an increasing C++ code base:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;~/HelloPyBind/
&amp;nbsp;&amp;nbsp;├── cpp/
&amp;nbsp;&amp;nbsp;│   ├── src/
&amp;nbsp;&amp;nbsp;│   │   ├── core/			  # Core API implementation
&amp;nbsp;&amp;nbsp;│   │   │   ├── *.h
&amp;nbsp;&amp;nbsp;│   │   │   └── *.cpp
&amp;nbsp;&amp;nbsp;│   │   ├── math/			  # Math-related API
&amp;nbsp;&amp;nbsp;│   │   │   ├── *.h
&amp;nbsp;&amp;nbsp;│   │   │   └── *.cpp
&amp;nbsp;&amp;nbsp;│   │   ├── mesh/			  # Mesh-related API
&amp;nbsp;&amp;nbsp;│   │   │   ├── *.h
&amp;nbsp;&amp;nbsp;│   │   │   └── *.cpp
&amp;nbsp;&amp;nbsp;│   │   ├── bindings/
&amp;nbsp;&amp;nbsp;│   │   │   └── pybind_module.cpp       # pybind11 bindings
&amp;nbsp;&amp;nbsp;│   │   ├── CMakeLists.txt
&amp;nbsp;&amp;nbsp;│   │   └── main.cpp                    # C++ executable entry point
&amp;nbsp;&amp;nbsp;│   ├── tests/
&amp;nbsp;&amp;nbsp;│   │   ├── CMakeLists.txt
&amp;nbsp;&amp;nbsp;│   │   ├── test_matrix.cpp
&amp;nbsp;&amp;nbsp;│   │   ├── test_vector.cpp
&amp;nbsp;&amp;nbsp;│   │   ├── test_mesh.cpp
&amp;nbsp;&amp;nbsp;│   │   ├── test_mesh_algorithms.cpp
&amp;nbsp;&amp;nbsp;│   │   └── test_mesh_processor.cpp
&amp;nbsp;&amp;nbsp;│   └── CMakeLists.txt                  # top-level C++ (CLion entry point)
&amp;nbsp;&amp;nbsp;└── python/
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch Visual Studio 2022 | Continue without code.  File | Open | CMake...  Navigate to cpp/&lt;a href=&quot;https://github.com/SteveProXNA/PythonSetup/blob/master/PyBindCheatSheet/07-Example/cpp/CMakeLists.txt&quot;&gt;CMakeLists.txt&lt;/a&gt;.  Build menu | Build All.  Finally, choose Test menu | Test Explorer.  Run All Tests in View or choose to Debug: 
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiGn4bGwT0Fnt6S127k02KrSCJC5SeNMW929rseqsJf0Kl7EeUlIvLiKmB_84jfgrnYIfSM9wtDs_miJMtajttlaWp6IT_mrIoKQ2fPclFc-YlWm_y4l43_WgWbCAl4ldPRNWjzpmgdTJ9KuUU0dfN3aHTxcZ3nX-MzhvmZACqrXAFkfLKFq8bbnveS3w/s1593/HelloPybind07.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiGn4bGwT0Fnt6S127k02KrSCJC5SeNMW929rseqsJf0Kl7EeUlIvLiKmB_84jfgrnYIfSM9wtDs_miJMtajttlaWp6IT_mrIoKQ2fPclFc-YlWm_y4l43_WgWbCAl4ldPRNWjzpmgdTJ9KuUU0dfN3aHTxcZ3nX-MzhvmZACqrXAFkfLKFq8bbnveS3w/s600/HelloPybind07.png&quot;/&gt;&lt;/a&gt;  
&lt;!-- --&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have demonstrated various PyBind examples in which C++ library code is consumed by a single Python API exclusively.  However, in future there may be instances in which the C++ library may need to be consumed by multiple languages.  In this case &lt;b&gt;ctypes.cdll.LoadLibrary()&lt;/b&gt; may be better that PyBind!

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2026/03/pybind-setup-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiGh5yxV4LJ8gBHcID6DomvBgr9iCkvM2Mm1G9UYgPF7mXiHA85U39FNTMQsKutS5KG21EPCQ-fj_coHW2NxlkSm-cDLrwzJhWc6m-TdEiF1sZjlFHchN16KvMOwpCbjkZ6GsMLiUL04YMQeyojoxvqiA9ZPPygzAdUnVnlcSfR7DFUUV-W98ZPd7eEG4/s72-c/pybind11-logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-5547533435299455386</guid><pubDate>Tue, 03 Feb 2026 10:00:00 +0000</pubDate><atom:updated>2026-02-03T11:57:36.040-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Python</category><title>Python Package Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

In 2020, we checked out &lt;a href=&quot;https://steveproxna.blogspot.com/2020/07/python-setup-cheat-sheet.html&quot;&gt;Python Setup Cheat Sheet&lt;/a&gt; as an interpreted high-level programming language runs on Windows, Mac OS/X and Linux using pip as the de facto standard package-management system.  However while this worked, &lt;a href=&quot;https://medium.com/@Sabrina-Carpenter/your-requirements-txt-is-a-time-bomb-2d0b30ad6a41&quot;&gt;requirements.txt&lt;/a&gt; is brittle with package dependencies + versioning.  &lt;a href=&quot;https://python-poetry.org/docs&quot;&gt;Poetry&lt;/a&gt; was introduced to resolve deterministic builds but at slower dependency resolution.  Enter &lt;a href=&quot;https://docs.astral.sh/uv&quot;&gt;uv&lt;/a&gt; for blazing speed + reliability &lt;span style=&#39;font-family:Wingdings&#39;&gt;J&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU-dJOo7nUb2oRlo-j0DwfAm3K1uuoNCSZGaeF6pkf4NDot0CbRtvPt_F1PZ1Bpi9cyY8WcUBW5BbzWchZs3f9Klj8nVjT2JNdauhLxVoptyESFUgF4WotZh2te7gOhmAbAiGT45w-HW5GFFIogFBSDLgd5DwT1FgKuX-C-3GeNN8Xf0qqiEyG_p0Whko/s685/UV.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; 
src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU-dJOo7nUb2oRlo-j0DwfAm3K1uuoNCSZGaeF6pkf4NDot0CbRtvPt_F1PZ1Bpi9cyY8WcUBW5BbzWchZs3f9Klj8nVjT2JNdauhLxVoptyESFUgF4WotZh2te7gOhmAbAiGT45w-HW5GFFIogFBSDLgd5DwT1FgKuX-C-3GeNN8Xf0qqiEyG_p0Whko/s600/UV.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;History&lt;/u&gt;&lt;br /&gt;
Python Setup Cheat Sheet detailed how to install &lt;a href=&quot;https://en.wikipedia.org/wiki/Pip_(package_manager)&quot;&gt;pip&lt;/a&gt; as the de facto standard package-management system on Windows, Mac OS/X and Linux.  However, requirements.txt does not lock down transitive dependencies + versioning which becomes brittle.  &lt;a href=&quot;https://python-poetry.org/docs&quot;&gt;Poetry&lt;/a&gt; solved this problem using &lt;a href=&quot;https://packaging.python.org/en/latest/guides/writing-pyproject-toml&quot;&gt;pyproject.toml&lt;/a&gt; configuration and lock file.
&lt;br /&gt;&lt;br /&gt;
  
&lt;b&gt;uv&lt;/b&gt;&lt;br /&gt;
Replicating Poetry with more deterministic builds using using pyproject.toml configuration and lock file, &lt;a href=&quot;https://docs.astral.sh/uv&quot;&gt;uv&lt;/a&gt; is built in Rust by Astral as a full rethinking of Python packaging designed for speed and simplicity.  uv: pitched as &quot;A single tool to replace pip, pip-tools, pipx, poetry, pyenv, twine, virtualenv and more&quot;.  &lt;a href=&quot;https://dimasyotama.medium.com/navigating-the-python-packaging-landscape-pip-vs-poetry-vs-uv-a-developers-guide-49a9c93caf9c&quot;&gt;Here&lt;/a&gt; is a detailed article comparing the Python Packaging Landscape: Pip vs. Poetry vs. UV from a developer&#39;s standpoint.
&lt;br /&gt;&lt;br /&gt;

IMPORTANT&lt;br /&gt;
First check out the &lt;a href=&quot;https://medium.com/jacklee26/uv-python-management-83d7df7cbe62&quot;&gt;traditional&lt;/a&gt; way using python and pip to compare and illustrate benefits of now using uv:
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Virtual Environment&lt;/u&gt;&lt;br /&gt;
A virtual environment isolates Python project interpreter and installed packages from the system and other Python projects which means each project should have its own environment, its version and dependencies.
&lt;br /&gt;&lt;br /&gt;
Create a virtual environment in the traditional way using python and pip then activate virtual environment:
&lt;br /&gt;
&lt;!-- --&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;
&amp;nbsp;python -m venv .venv&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;Linux OR Mac OS/X&lt;/td&gt;
&lt;td&gt;&amp;nbsp;source .venv/bin/activate&lt;/td&gt;
&lt;/tr&gt;  
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;Windows&lt;/td&gt;
&lt;td&gt;&amp;nbsp;.\.venv\Scripts\activate&lt;/td&gt;
&lt;/tr&gt; 
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Next, install packages using python, pip and requirements.txt OR poetry with pyproject.toml configuration:
&lt;br /&gt;
Brittle and/or slow [transitive] dependency resolution!
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Installation&lt;/u&gt;&lt;br /&gt;
Download and &lt;a href=&quot;https://medium.com/jacklee26/uv-python-management-83d7df7cbe62#300e&quot;&gt;install&lt;/a&gt; uv for Linux, Mac OS/X or Windows OR Launch PyCharm and install from home page:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;Linux&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;curl -LsSf https://astral.sh/uv/install.sh | sh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;Mac OS/X&lt;/b&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;brew update &amp;&amp; brew install uv&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;Windows&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&amp;nbsp;powershell -ExecutionPolicy ByPass -c &quot;irm https://astral.sh/uv/install.ps1 | iex&quot;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;b&gt;uv init&lt;/b&gt;&lt;br /&gt;
Create new directory and execute following commands to initialize Python project with an interpreter version
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim1bnRax_fbx7vfP2esAb5522UOE4yjWf5EtqnbQZT7fTYVt1_9UQkomixdFqA2dAcWVRtYBNEK5_yfbGZ3drO_urfqchbenlZnYcolywEDq0qxRn37ouECqAA3B8YYzowg8HFZxIiozrpIEocFIvgbM5dtklUE-Gukuy7p_TwIU1GGQ8adXKriZ48MSg/s664/01-uv_init.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim1bnRax_fbx7vfP2esAb5522UOE4yjWf5EtqnbQZT7fTYVt1_9UQkomixdFqA2dAcWVRtYBNEK5_yfbGZ3drO_urfqchbenlZnYcolywEDq0qxRn37ouECqAA3B8YYzowg8HFZxIiozrpIEocFIvgbM5dtklUE-Gukuy7p_TwIU1GGQ8adXKriZ48MSg/s600/01-uv_init.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch Terminal | Execute the following commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;mkdir HelloUV
&amp;nbsp;&amp;nbsp;cd HelloUV
&amp;nbsp;&amp;nbsp;uv init --python 3.11.11
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;b&gt;uv venv&lt;/b&gt;&lt;br /&gt;
Navigate into Python project and execute following commands to create the virtual environment and activate
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgww6wb03aLQFe9voHnXn38E1UHL0TTLkOlrwfEZn9T07Uf9Zl_do7k1syXVJNWETMbKtiSneTVlvIvJHhN1dZSsj_bzosYe53INtZIiVgPPx_Q3bjQ431H8BudTZyh7MZ3NLHb7x6FP4efydySggs2Cg5twCaW8dZH-uj2GXkWeuRa-fBXFC_mVBnh6WQ/s664/02-uv_venv.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgww6wb03aLQFe9voHnXn38E1UHL0TTLkOlrwfEZn9T07Uf9Zl_do7k1syXVJNWETMbKtiSneTVlvIvJHhN1dZSsj_bzosYe53INtZIiVgPPx_Q3bjQ431H8BudTZyh7MZ3NLHb7x6FP4efydySggs2Cg5twCaW8dZH-uj2GXkWeuRa-fBXFC_mVBnh6WQ/s600/02-uv_venv.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch Terminal | Execute the following commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv venv --python 3.11.11
&amp;nbsp;&amp;nbsp;source .venv/bin/activate		# Windows: .\.venv\Scripts\activate
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;b&gt;uv python&lt;/b&gt;&lt;br /&gt;
At this point you have Python project initialized with virtual environment activated.  Confirm correct version of Python interpreter installed and activate.  When using PyCharm ensure the IDE interpreter path is aligned!
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjluLpelMqzN0g17Sbc4d7n1V8CRPm35_FBGnMeP8BlEbktTWXf76atYLdU78KHfHCIEE09sYJcNbNHW2SCrJhWdvQ-sGA-pHYYtduaAdYNuTfdsHcaHV_u6LkOSnF3jW7KklFsdGN95lfgyupAuDiMtdHlvIzlTrbK7ccOntFmR6b47_9EFICZX0uBgk/s797/03-which_python.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjluLpelMqzN0g17Sbc4d7n1V8CRPm35_FBGnMeP8BlEbktTWXf76atYLdU78KHfHCIEE09sYJcNbNHW2SCrJhWdvQ-sGA-pHYYtduaAdYNuTfdsHcaHV_u6LkOSnF3jW7KklFsdGN95lfgyupAuDiMtdHlvIzlTrbK7ccOntFmR6b47_9EFICZX0uBgk/s600/03-which_python.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Inside PyCharm Terminal | Execute the following commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;which python
&amp;nbsp;&amp;nbsp;`which python` --version
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;b&gt;uv add&lt;/b&gt;&lt;br /&gt;
Install Python packages either using &lt;i&gt;uv pip install&lt;/i&gt; or &lt;i&gt;uv add&lt;/i&gt; commands.  Prefer &lt;b&gt;uv add&lt;/b&gt; because this updates pyproject.toml file automagically thus you are able to execute &lt;i&gt;uv sync&lt;/i&gt; command to install the dependencies.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0SsDA-QXu4-3zW9a1Ajy81x4-rVXPE_v4r4khCEcc1JwthGtckVVdT8k2EwA_p9KSw-vC4Qv3njtcpspZn2Xxh92X9GyYC0uorKeiRHUzGW2fPjRCkjBYAexpLHvl1SVr5TX0ihX9SO-b5lp947rkzYWF7575goCG7iO0I2d2YTht9hY5piHWszAe96M/s809/04-uv_add.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0SsDA-QXu4-3zW9a1Ajy81x4-rVXPE_v4r4khCEcc1JwthGtckVVdT8k2EwA_p9KSw-vC4Qv3njtcpspZn2Xxh92X9GyYC0uorKeiRHUzGW2fPjRCkjBYAexpLHvl1SVr5TX0ihX9SO-b5lp947rkzYWF7575goCG7iO0I2d2YTht9hY5piHWszAe96M/s600/04-uv_add.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Inside PyCharm Terminal | Execute the following commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv pip list
&amp;nbsp;&amp;nbsp;uv add requests
&amp;nbsp;&amp;nbsp;uv sync
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;b&gt;uv tree&lt;/b&gt;&lt;br /&gt;
After execute &lt;i&gt;uv add&lt;/i&gt; you can verify what is installed by checking pyproject.toml file or execute &lt;i&gt;uv pip list&lt;/i&gt; but another useful method is &lt;b&gt;uv tree&lt;/b&gt; which shows hierarchy of all your project&#39;s dependencies and relationships.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1YqvoK_gLgMcrcXbCB5ySdifJDC6hqyceAyZwODDkIZp2pjKiSNCko_XR65ewZagU8Pc8inSjbOu6YEV37UmkH2tKw9n7dLZ9yx6QB5mFisCChXB9LhVnLAJpGRMMvuKJ7IGUlu4qSanV9VD0QPuYfphap_mWuP9dVcsy3mDMqG2nvVIjvixYuPjDkWc/s809/05-uv_tree.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1YqvoK_gLgMcrcXbCB5ySdifJDC6hqyceAyZwODDkIZp2pjKiSNCko_XR65ewZagU8Pc8inSjbOu6YEV37UmkH2tKw9n7dLZ9yx6QB5mFisCChXB9LhVnLAJpGRMMvuKJ7IGUlu4qSanV9VD0QPuYfphap_mWuP9dVcsy3mDMqG2nvVIjvixYuPjDkWc/s600/05-uv_tree.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Inside PyCharm Terminal | Execute the following command: &lt;b&gt;uv tree&lt;/b&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;uv sync&lt;/b&gt;&lt;br /&gt;
Execute &lt;i&gt;uv add&lt;/i&gt; or update pyproject.toml to install dependencies.  Execute &lt;b&gt;uv sync&lt;/b&gt; to update environment.
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;uv lock&lt;/b&gt;&lt;br /&gt;
The uv.lock file records all the exact versions of all project dependencies UV figures are compatible from the pyproject.toml file to ensure constant deterministic builds with the same dependenices each time and CI/CD
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;uv tool&lt;/b&gt;&lt;br /&gt;
UV tool installs persistent tools into virtual environment that are required for that particular Python project:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3tNav_rR_TCa1u1NaeneNZtDvIugePI7DmOda7TCCvk-3fggPnnZxdB1o-IGJ5t4-yx-hsoTJUHOu1Hy62pGzlqPTaqpKzAhdaBlWU_1nsfFgf1yGTAGRMDPhQQu-Dyrty1oy42p-vgQmSLc_77yJ-TcinYDshnKXi8rcbkApDhRLyxrSJHJ5nIBzjng/s807/06-uv_tool.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3tNav_rR_TCa1u1NaeneNZtDvIugePI7DmOda7TCCvk-3fggPnnZxdB1o-IGJ5t4-yx-hsoTJUHOu1Hy62pGzlqPTaqpKzAhdaBlWU_1nsfFgf1yGTAGRMDPhQQu-Dyrty1oy42p-vgQmSLc_77yJ-TcinYDshnKXi8rcbkApDhRLyxrSJHJ5nIBzjng/s600/06-uv_tool.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Inside PyCharm Terminal | Execute the following commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv tool list
&amp;nbsp;&amp;nbsp;uv tool install ruff
&amp;nbsp;&amp;nbsp;uv tool run ruff check
&amp;nbsp;&amp;nbsp;uv tool upgrade --all
&amp;nbsp;&amp;nbsp;uv tool uninstall ruff
&amp;nbsp;&amp;nbsp;uv tool list
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;b&gt;uvx tool&lt;/b&gt;&lt;br /&gt;
Finally &lt;b&gt;uvx&lt;/b&gt; is an alias for &lt;i&gt;uv tool run&lt;/i&gt; but is designed to be run immediately without installing it persistently:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNNc_LaVn-YPidKbVbhfqTwln4RLI29vt4bQs7pCq4gwuucfrwuwC_DDZv5Cymn2Sao4VwmXW9CkvIm84W_xtLrPxVfQKh-RX5PSdbBUqDcSWoJPdAqUztL8EEvexrZBWTktT3tiKf60vJLoqK-AsohWc5r3ARhNcAaevlPnSfAhbtshNLimye16j5rM/s809/07-uvx.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; data-original-height=&quot;528&quot; data-original-width=&quot;809&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZNNc_LaVn-YPidKbVbhfqTwln4RLI29vt4bQs7pCq4gwuucfrwuwC_DDZv5Cymn2Sao4VwmXW9CkvIm84W_xtLrPxVfQKh-RX5PSdbBUqDcSWoJPdAqUztL8EEvexrZBWTktT3tiKf60vJLoqK-AsohWc5r3ARhNcAaevlPnSfAhbtshNLimye16j5rM/s600/07-uvx.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Inside PyCharm Terminal | Execute the following command: &lt;b&gt;uvx ruff check&lt;/b&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;uv cache&lt;/b&gt;&lt;br /&gt;
When you use uv all tools and dependencies are stored in cache.  These commands remove all cached data: 
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv cache clean
&amp;nbsp;&amp;nbsp;rm -r &quot;$(uv python dir)&quot;
&amp;nbsp;&amp;nbsp;rm -r &quot;$(uv tool dir)&quot;
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Commands&lt;/u&gt;&lt;br /&gt;
Here is a quick &lt;a href=&quot;https://viveksinghpathania.medium.com/from-pip-to-lightning-how-uv-opened-my-eyes-to-better-python-workflows-dfa50e8a5893&quot;&gt;summary&lt;/a&gt; of popular uv commands used during workflow.  A comprehensive list can be &lt;a href=&quot;https://medium.com/jacklee26/uv-python-management-83d7df7cbe62#7787&quot;&gt;found&lt;/a&gt;.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;uv init --app				# Scaffold project
&amp;nbsp;&amp;nbsp;uv python install 3.11		# Install Python
&amp;nbsp;&amp;nbsp;uv venv --python 3.11			# Create virtual environment
&amp;nbsp;&amp;nbsp;uv add requests			# Add dependencies
&amp;nbsp;&amp;nbsp;uv add -D pytest			# Add dev dependencies
&amp;nbsp;&amp;nbsp;uv sync --frozen			# Sync (locked)
&amp;nbsp;&amp;nbsp;uv sync				# Sync (normal)
&amp;nbsp;&amp;nbsp;uv run python main.py			# Run program
&amp;nbsp;&amp;nbsp;uv run python -V			# Show Python
&amp;nbsp;&amp;nbsp;uvx ruff check .			# Run tools ad‑hoc
&amp;nbsp;&amp;nbsp;uv lock				# Update lockfile
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Docker&lt;/u&gt;&lt;br /&gt;
A well-built uv &lt;a href=&quot;https://bury-thomas.medium.com/mastering-python-project-management-with-uv-part-3-mlops-4906965f45a2&quot;&gt;Docker image&lt;/a&gt; simplifies deployment + ensures application runs consistently in environment:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;FROM python:3.11.11-slim
&amp;nbsp;&amp;nbsp;# Install uv
&amp;nbsp;&amp;nbsp;COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
&amp;nbsp;&amp;nbsp;COPY . /app
&amp;nbsp;&amp;nbsp;WORKDIR /app
&amp;nbsp;&amp;nbsp;# Install dependencies and clear cache
&amp;nbsp;&amp;nbsp;RUN uv sync --no-dev --frozen
&amp;nbsp;&amp;nbsp;RUN rm -rf ~/.cache/uv
&amp;nbsp;&amp;nbsp;CMD [&quot;python&quot;, &quot;-c&quot;, &quot;print(&#39;Hello, World!&#39;)&quot;]
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
This is an example Dockerfile snippet how to integrate uv!  But build and run execution with the commands:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;docker build -t uv-hello .
&amp;nbsp;&amp;nbsp;docker run --rm uv-hello
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;GitHub Actions&lt;/u&gt;&lt;br /&gt;
A common &lt;a href=&quot;https://viveksinghpathania.medium.com/from-pip-to-lightning-how-uv-opened-my-eyes-to-better-python-workflows-dfa50e8a5893&quot;&gt;GitHub Actions&lt;/a&gt; pattern is to use UV to install only Prod dependencies during your build or deploy:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;name: Testing
&amp;nbsp;&amp;nbsp;on:
&amp;nbsp;&amp;nbsp;  push:
&amp;nbsp;&amp;nbsp;    branches:
&amp;nbsp;&amp;nbsp;      - &quot;main&quot;
&amp;nbsp;&amp;nbsp;jobs:
&amp;nbsp;&amp;nbsp;  build:
&amp;nbsp;&amp;nbsp;    runs-on: ubuntu-latest
&amp;nbsp;&amp;nbsp;    steps:
&amp;nbsp;&amp;nbsp;      - uses: actions/checkout@v4
&amp;nbsp;&amp;nbsp;      - name: Install UV
&amp;nbsp;&amp;nbsp;        run: curl -LsSf https://astral.sh/uv/install.sh | sh
&amp;nbsp;&amp;nbsp;      - name: Sync only prod dependencies
&amp;nbsp;&amp;nbsp;        run: uv sync --no-group dev --group prod
&amp;nbsp;&amp;nbsp;      - name: Run tests
&amp;nbsp;&amp;nbsp;        run: uv run pytest
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, uv has been &lt;a href=&quot;https://medium.com/codecodecode/uv-virtualenv-direnv-a-fast-reproducible-python-workflow-with-envrc-36da47ce1f4b&quot;&gt;pitched&lt;/a&gt; &quot;One Tool for Everything&quot; as uv &lt;b&gt;replaces&lt;/b&gt; pip, virtualenv, pip-tools, pipx, poetry, pyenv, twine and is fast at every step.  However, this has only scratched the surface as uv integrates well with other tools for fast reproducible Python workflows such as direnv, pre-commit hooks, pdm + more!
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;uv&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Handles Python installs, environment creation, and dependency resolution with locking&lt;/td&gt;  
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;direnv&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Evaluates &lt;i&gt;.envrc&lt;/i&gt; managing environment variables automatically applied to shell session&lt;/td&gt;
&lt;/tr&gt;  
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;pdm&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Orchestrate workflows + provide unified tooling to build, version, and publish pacakges&lt;/td&gt;
&lt;/tr&gt; 
&lt;/table&gt;
&lt;!-- --&gt;

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2026/02/python-package-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU-dJOo7nUb2oRlo-j0DwfAm3K1uuoNCSZGaeF6pkf4NDot0CbRtvPt_F1PZ1Bpi9cyY8WcUBW5BbzWchZs3f9Klj8nVjT2JNdauhLxVoptyESFUgF4WotZh2te7gOhmAbAiGT45w-HW5GFFIogFBSDLgd5DwT1FgKuX-C-3GeNN8Xf0qqiEyG_p0Whko/s72-c/UV.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-3332635522540810111</guid><pubDate>Thu, 01 Jan 2026 09:00:00 +0000</pubDate><atom:updated>2026-01-01T01:00:30.566-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Retrospective</category><title>Retrospective XVII</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

Last year, I conducted a simple retrospective for 2024. Therefore, here is a retrospective for year 2025.
&lt;br /&gt;&lt;br /&gt;  
&lt;u&gt;2025 Achievements&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
Document DevOps managed clusters provisioning setup E.g.: &lt;a href=&quot;https://steveproxna.blogspot.com/2025/05/cloud-setup-cheat-sheet.html&quot;&gt;Azure AKS&lt;/a&gt;, &lt;a href=&quot;https://steveproxna.blogspot.com/2025/06/cloud-setup-cheat-sheet-ii.html&quot;&gt;AWS-EKS&lt;/a&gt;, &lt;a href=&quot;https://steveproxna.blogspot.com/2025/06/cloud-setup-cheat-sheet-ii.html&quot;&gt;GCP-GKE&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Present + report The Evolution of Software Deployment Cloud CI/CD setup &lt;a href=&quot;https://steveproxna.blogspot.com/2025/07/cloud-ci-cd-cheat-sheet.html&quot;&gt;theory&lt;/a&gt; to &lt;a href=&quot;https://steveproxna.blogspot.com/2025/08/cloud-ci-cd-cheat-sheet-ii.html&quot;&gt;practical&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Consolidate &lt;a href=&quot;https://steveproxna.blogspot.com/2025/09/pytest-setup-cheat-sheet.html&quot;&gt;pytest&lt;/a&gt; unit test framework features such as fixtures, factories, mocking, patching
&lt;/li&gt;
&lt;li&gt;
Transition Python package management from &lt;a href=&quot;https://en.wikipedia.org/wiki/Pip_(package_manager)&quot;&gt;pip&lt;/a&gt; to &lt;a href=&quot;https://python-poetry.org/docs&quot;&gt;poetry&lt;/a&gt; and finally to &lt;a href=&quot;https://docs.astral.sh/uv&quot;&gt;uv&lt;/a&gt; for blazing speed    
&lt;/li&gt;    
&lt;li&gt;
Introduction to &lt;a href=&quot;https://en.wikipedia.org/wiki/MLOps&quot;&gt;MLOps&lt;/a&gt; theory learning to practical ML models and deployment implementation  
&lt;/li&gt;
&lt;li&gt;
Extend GitLab CI/CD experience to upskill to &lt;a href=&quot;https://docs.github.com/en/actions&quot;&gt;GitHub Actions&lt;/a&gt; executing on localhost using &lt;a href=&quot;https://betterstack.com/community/guides/scaling-docker/act-github-actions-tutorial&quot;&gt;ACT&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Resurrect &lt;a href=&quot;https://levelup.gitconnected.com/pybind11-a-beginners-guide-to-setting-up-c-and-python-projects-1de2f04465e9&quot;&gt;PyBind&lt;/a&gt; knowledge on &lt;a href=&quot;https://steveproxna.blogspot.com/2024/11/openai-retro-cheat-sheet.html&quot;&gt;OpenAI Retro&lt;/a&gt; to Mac on CLion for Python to C/C++ examples
&lt;/li&gt;
&lt;li&gt;
Reverse Engineer &lt;a href=&quot;https://steveproxna.blogspot.com/2025/11/simpsons-trivia-retro-achievements.html&quot;&gt;RetroAchievements&lt;/a&gt; project open source code for Simpsons Trivia integration
&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;  
Note: Reverse Engineering and setup RetroAchievements project open source code is a big achievement!
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;2026 Objectives&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
Document Python package management move from &lt;a href=&quot;https://en.wikipedia.org/wiki/Pip_(package_manager)&quot;&gt;pip&lt;/a&gt; to &lt;a href=&quot;https://python-poetry.org/docs&quot;&gt;poetry&lt;/a&gt;  to &lt;a href=&quot;https://docs.astral.sh/uv&quot;&gt;uv&lt;/a&gt; for new Python projects
&lt;/li&gt;
&lt;li&gt;
Continue MLOps integration to bridge Software Engineering to Machine Learning knowledge &lt;a href=&quot;https://medium.com/data-science/make-the-switch-from-software-engineer-to-ml-engineer-7a4948730c97&quot;&gt;gap&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Register PyBind Python to C/C++ setup cross platform and explore &lt;a href=&quot;https://nadiah.org/2020/03/01/example-debug-mixed-python-c-in-visual-studio-code&quot;&gt;debugging&lt;/a&gt; across languages
&lt;/li&gt;
&lt;li&gt;
Harness prior &lt;a href=&quot;https://steveproxna.blogspot.com/2024/11/openai-retro-cheat-sheet.html&quot;&gt;OpenAI Retro&lt;/a&gt; and &lt;a href=&quot;https://steveproxna.blogspot.com/2025/11/simpsons-trivia-retro-achievements.html&quot;&gt;RetroAchievements&lt;/a&gt; experience and apply to future AI projects!
&lt;/li&gt;  
&lt;/ul&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;!-- --&gt;
&lt;u&gt;AI Demand&lt;/u&gt;&lt;br /&gt;
According to 2025 analysis global AI and ML Engineer job openings numbering in the hundreds of thousands with employers increasingly willing to hire based on demonstrable skills rather than advanced degrees.  One market study &lt;a href=&quot;https://www.globenewswire.com/news-release/2025/03/14/3043083/28124/en/Artificial-Intelligence-Engineering-Strategic-Business-Research-Report-2025-Global-Market-to-Grow-by-Over-70-Billion-by-2030-Integration-of-AI-and-DevOps-AIOps-Sets-the-Stage-for-G.html&quot;&gt;forecasts&lt;/a&gt; AI Engineering sector could grow from $17.4 billion in 2025 to $87.5 billion by 2030 implying a sustained growth rate for the next 5yrs.
&lt;br /&gt;&lt;br /&gt;
Therefore, as a Professional Software Engineer how are some ways to transition to a more focused AI-role? 
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPh7VE_ZOxT5mz0Q0zOxByJi6QmHjAumlp5ngkAXxZJDyGB3J5lGWHFnk8rhpVmBg93MXwEA_4XbzwsSF11FCLg2QPhnm7QOyhJQwEtgS8hb10nGsXawCNFkK-Ro8kc8VgjTJJYs_IwHwN2OfyzHielNZbDGuz6G8P3SC1ghS8W9uMFqEiiIHbGioV4Es/s1000/AI.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPh7VE_ZOxT5mz0Q0zOxByJi6QmHjAumlp5ngkAXxZJDyGB3J5lGWHFnk8rhpVmBg93MXwEA_4XbzwsSF11FCLg2QPhnm7QOyhJQwEtgS8hb10nGsXawCNFkK-Ro8kc8VgjTJJYs_IwHwN2OfyzHielNZbDGuz6G8P3SC1ghS8W9uMFqEiiIHbGioV4Es/s600/AI.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;u&gt;MLOps Engineer&lt;/u&gt;&lt;br /&gt;
By expanding traditional Software Development Life Cycle skills across DevOps as modern delivery practices have evolved one next step is the progression into &lt;a href=&quot;https://en.wikipedia.org/wiki/MLOps&quot;&gt;MLOps&lt;/a&gt;: enabling the deployment monitoring and the mgt of machine learning models built by dedicated ML Engineers.  This provides immediate value to the AI-driven teams while supporting ongoing machine learning expertise.
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;AI Engineer&lt;/u&gt;&lt;br /&gt;
An &lt;a href=&quot;https://en.wikipedia.org/wiki/Artificial_intelligence_engineering&quot;&gt;AI Engineer&lt;/a&gt; specializes in building integrating deploying and optimizing machine + deep learning systems bridging the gap between research models and production-ready software.  A &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_engineering&quot;&gt;Software Engineer&lt;/a&gt; focuses on: application logic architecture performance and code quality whereas an AI Engineer works at the intersection of Software Engineering and Data Science.
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Future&lt;/u&gt;&lt;br /&gt;
In 2024 we checked out OpenAI &lt;a href=&quot;https://steveproxna.blogspot.com/2024/09/openai-farma-cheat-sheet.html&quot;&gt;Gym&lt;/a&gt; and &lt;a href=&quot;https://steveproxna.blogspot.com/2024/11/openai-retro-cheat-sheet.html&quot;&gt;Retro&lt;/a&gt; to provide early exposure to AI-centric principles integrating Reinforcement Learning environments using Python and C/C++ to upskill AI concepts such as agent training environment design reproducibility and iterative experimentation.
&lt;br /&gt;&lt;br /&gt;  
In 2025 we checked out &lt;a href=&quot;https://steveproxna.blogspot.com/2025/11/simpsons-trivia-retro-achievements.html&quot;&gt;RetroAchievements&lt;/a&gt; ecosystem to further deepen these skills dealing with emulation internals memory inspection and state tracking all highly relevant to RL and model-driven control systems.  
&lt;br /&gt;&lt;br /&gt;
Together this experience forms connection between long-standard Professional Software Engineer expertise and the emerging demands of AI Engineering.  Combining systems programming with complex environment instrumentation and practical RL-work aligns with one of the &lt;a href=&quot;https://cybernews.com/ai-news/ai-engineer-fastest-growing-job-linkedin&quot;&gt;fastest-growing&lt;/a&gt; roles in the technology sector!
&lt;!-- --&gt;

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2026/01/retrospective-xvii.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPh7VE_ZOxT5mz0Q0zOxByJi6QmHjAumlp5ngkAXxZJDyGB3J5lGWHFnk8rhpVmBg93MXwEA_4XbzwsSF11FCLg2QPhnm7QOyhJQwEtgS8hb10nGsXawCNFkK-Ro8kc8VgjTJJYs_IwHwN2OfyzHielNZbDGuz6G8P3SC1ghS8W9uMFqEiiIHbGioV4Es/s72-c/AI.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-373228980461730754</guid><pubDate>Sat, 15 Nov 2025 09:00:00 +0000</pubDate><atom:updated>2025-11-15T01:00:16.572-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Master System</category><title>Simpsons Trivia Retro Achievements</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

In 2018, &lt;a href=&quot;https://www.smspower.org/Homebrew/SimpsonsTrivia-SMS&quot;&gt;Simpsons Trivia&lt;/a&gt; built for the Sega &lt;a href=&quot;https://en.wikipedia.org/wiki/Master_System&quot;&gt;Master System&lt;/a&gt; was one entry in the annual SMS Power! &lt;a href=&quot;https://www.smspower.org/uploads/Homebrew/SimpsonsTrivia-SMS-1.02.zip&quot;&gt;Coding&lt;/a&gt; competition.  The immediate &lt;a href=&quot;https://www.smspower.org/forums/17019-CodingCompetition2018SimpsonsTriviaBySteveProXNA&quot;&gt;forum&lt;/a&gt; feedback super positive.  In 2020, member &lt;a href=&quot;https://www.smspower.org/forums/member7948&quot;&gt;FeRcHuLeS&lt;/a&gt; posted enjoyment of the game and mastered on &lt;a href=&quot;https://retroachievements.org/game/14672&quot;&gt;retroachievements.org&lt;/a&gt;.  I was unaware of this website so I had to investigate!
&lt;br /&gt;
&lt;!-- --&gt;  
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjxo7FxO7IjzPKAVZuQ2UEmxjm91aG-kGv3WgrZZxDrxboP9P_l1voo91zvvgALya_pNry1cM1bax-wTs8IeMJZAlgCjx11v-eslEYW5UwCMXv-_7xRMQzklcQz_H5uCj3QM4Noqyr9BfKAkAzUzcOda1wrmngBajD2Qi0O2KmOBL1C9A0iMY8TnAh0Lo/s1268/RetroAchievements.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjxo7FxO7IjzPKAVZuQ2UEmxjm91aG-kGv3WgrZZxDrxboP9P_l1voo91zvvgALya_pNry1cM1bax-wTs8IeMJZAlgCjx11v-eslEYW5UwCMXv-_7xRMQzklcQz_H5uCj3QM4Noqyr9BfKAkAzUzcOda1wrmngBajD2Qi0O2KmOBL1C9A0iMY8TnAh0Lo/s600/RetroAchievements.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;RetroAchievements&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://emulation.gametechwiki.com/index.php/RetroAchievements&quot;&gt;RetroAchievements&lt;/a&gt; is an online service which provides users with fan-made achievement sets for many retro gaming platforms such as the Sega Master System.  Navigate to &lt;a href=&quot;https://retroachievements.org&quot;&gt;RetroAchievements&lt;/a&gt; website.  Choose &lt;a href=&quot;https://retroachievements.org/createaccount.php&quot;&gt;Sign up&lt;/a&gt;  Create an account.  Download &lt;a href=&quot;https://retroachievements.org/bin/RALibretro-x64.zip&quot;&gt;RALibretro&lt;/a&gt; emulator which facilitates achievements integration to retro games!
&lt;br /&gt;&lt;br /&gt; 
Launch RALibretro emulator | Choose RetroAchievements menu | Login | Enter RetroAchievements site info:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhymRUNOM98VdYE4ZOBPxN-_9JWyMTxCKZerOIDVasJll4eaX6HB7FxKVsMwwuF2WPuSQ4cgNwUU5MJpSffeDcy4Fg2DTB3veAJe07kErHorc_nlSyW7blI6X5x-CdxtFRkD88Gqp0x-tjm8QzS7PqgIDqHdvcrMmm9FapyDN5WoO4BJ4jtImTbw8Lss70/s642/RALibRetroEmulator.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhymRUNOM98VdYE4ZOBPxN-_9JWyMTxCKZerOIDVasJll4eaX6HB7FxKVsMwwuF2WPuSQ4cgNwUU5MJpSffeDcy4Fg2DTB3veAJe07kErHorc_nlSyW7blI6X5x-CdxtFRkD88Gqp0x-tjm8QzS7PqgIDqHdvcrMmm9FapyDN5WoO4BJ4jtImTbw8Lss70/s600/RALibRetroEmulator.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;&lt;br /&gt;

&lt;b&gt;Cores&lt;/b&gt;&lt;br /&gt;
RetroAchievements &lt;a href=&quot;https://emulation.gametechwiki.com/index.php/Libretro#Cores&quot;&gt;cores&lt;/a&gt; are a special version of emulator cores.  Essentially a core is a plug-in or emulator that runs platform specific games.  Choose Settings menu | Manage Cores... | Master System and Download
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAieeE-SO_lpR6Aah1CCylGb6a79UFuo5p7WExi0tzKW4pGV2W9ovm4MpnW5vRio0bxWdr1IyBq6o50ohvG4WQqN7JalsQ0I-7_3d7qjoeoRo_uZw1tZ9DxblzgMV3JLhiuzKKPJ-Mbx4Q3Hm3esiX3geAjQSNRGmHTh1fo5g97_gsAhggTRHCfrn3RzU/s755/RALibRetroManageCores.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAieeE-SO_lpR6Aah1CCylGb6a79UFuo5p7WExi0tzKW4pGV2W9ovm4MpnW5vRio0bxWdr1IyBq6o50ohvG4WQqN7JalsQ0I-7_3d7qjoeoRo_uZw1tZ9DxblzgMV3JLhiuzKKPJ-Mbx4Q3Hm3esiX3geAjQSNRGmHTh1fo5g97_gsAhggTRHCfrn3RzU/s600/RALibRetroManageCores.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;    
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;Simpsons Trivia&lt;/u&gt;&lt;br /&gt;
Download &lt;a href=&quot;https://www.smspower.org/uploads/Homebrew/SimpsonsTrivia-SMS-1.02.zip&quot;&gt;Simpsons Trivia v1.02&lt;/a&gt;.  Choose RALibretro File menu | Select Core | Master System | Genesis Plus GX ensures audio support.  Choose File menu | Load Game | &lt;a href=&quot;https://github.com/SteveProXNA/SimpsonsTriviaSMS/blob/master/SimpsonsTrivia-v1.02.sms&quot;&gt;SimpsonsTrivia-v1.02.sms&lt;/a&gt;.  Game ready to play:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNDhFc_I51TMNQBk9d6sgQwlG07Z61POKio3s24Kzx7oGW4aDHavjK6sA8zP_IBYXj0Byxx5tU5TeJ0GCJ8tRtHHYxjTuhwAB3NuZ4ug9RJ4DaBDrQlJDf76yLu5BNBcDWT-WN2Q4wjy49GAMj6oN7NqMFbYI_ZBUWoEV8LVFMBq1EXs-qZP8aorkPNW8/s642/RALibRetroSimpsons.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNDhFc_I51TMNQBk9d6sgQwlG07Z61POKio3s24Kzx7oGW4aDHavjK6sA8zP_IBYXj0Byxx5tU5TeJ0GCJ8tRtHHYxjTuhwAB3NuZ4ug9RJ4DaBDrQlJDf76yLu5BNBcDWT-WN2Q4wjy49GAMj6oN7NqMFbYI_ZBUWoEV8LVFMBq1EXs-qZP8aorkPNW8/s600/RALibRetroSimpsons.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
IMPORTANT: Simpsons Trivia v1.02 &lt;b&gt;must&lt;/b&gt; be selected as this has the correct Retro Achievements game hash!  Choose arrow keys for Left, Right, Up, Down movement.  Choose Z for Fire1, X for Fire2, P or Enter to Pause.
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;Implementation&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.smspower.org/Homebrew/SimpsonsTrivia-SMS&quot;&gt;Simpsons Trivia&lt;/a&gt; game has 4x difficulty categories: Easy, Normal, Hard and Pro! plus 4x questions rounds: 5, 10, 25, and 50.  Thus 20x achievements setup: Perfect win for 4x categories * 4x rounds plus &quot;Get between 80-100%&quot; for 4x categories.  Shout out to &lt;a href=&quot;https://docs.retroachievements.org/developer-docs&quot;&gt;Bl4h8L4hBl4h&lt;/a&gt; setting up 20x achievements as per &lt;a href=&quot;https://docs.retroachievements.org/developer-docs&quot;&gt;documentation&lt;/a&gt;!
&lt;br /&gt;&lt;br /&gt;
Also, shout out to BenGhazi explaining how &lt;a href=&quot;https://retroachievements.org/downloads&quot;&gt;RALibretro&lt;/a&gt; emulator processes achievements e.g. &lt;a href=&quot;https://retroachievements.org/achievement/86807&quot;&gt;Achievement&lt;/a&gt; has 4x important pieces of data stored in RAM: Difficulty [0x00], Selected Rounds [0x05], Correct Answers [0x05] and ScreenID [0x0C].  When all values are aligned on Game Over screen then the achievement is set!
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: here is &lt;a href=&quot;https://github.com/SteveProXNA/SimpsonsTriviaSMS/releases/tag/1.02&quot;&gt; Tag 1.02&lt;/a&gt; source code excerpt which corroborates Game Over screen definition [0x0C]:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;// Screen type.
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_NONE	0
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_SPLASH	1
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_TITLE	2
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_INTRO	3
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_DIFF	4
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_LONG	5
&lt;/pre&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_READY	6
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_LEVEL	7
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_NUMBER	8
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_PLAY	9
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_QUIZ	10
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_SCORE	11
&amp;nbsp;&amp;nbsp;#define SCREEN_TYPE_OVER	12
&lt;/pre&gt;
&lt;/td&gt;  
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;u&gt;GitHub&lt;/u&gt;&lt;br /&gt;
RetroAchievements &lt;a href=&quot;https://github.com/orgs/RetroAchievements/repositories&quot;&gt;GitHub&lt;/a&gt; includes the following source code repositories for game achievement integration:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/rcheevos&quot;&gt;rcheevos&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;Library to parse and evaluate achievements and leaderboards for RetroAchievements
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/RAInterface&quot;&gt;RAInterface&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;Enables RetroAchievements emulators to interact with the server via RA_Integration.dll
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/RAIntegration&quot;&gt;RAIntegration&lt;/a&gt;&amp;nbsp;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;The DLL responsible to integrate emulators with RetroAchievements.org
&lt;/td&gt;
&lt;/tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/RALibretro&quot;&gt;RALibretro&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;RALibretro is the multi-emulator used to develop RetroAchievements
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;b&gt;Clone&lt;/b&gt;&lt;br /&gt;
On Windows, launch Terminal.  Create C:\GitHub\RetroAchievements directory.  Git clone the following repos:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;mkdir -p C:\GitHub\RetroAchievements
&amp;nbsp;cd C:\GitHub\RetroAchievements
&amp;nbsp;git clone --quiet https://github.com/RetroAchievements/rcheevos.git
&amp;nbsp;git clone --quiet https://github.com/RetroAchievements/RAInterface.git
&amp;nbsp;git clone --recursive --depth 1 -q https://github.com/RetroAchievements/RAIntegration.git&amp;nbsp;
&amp;nbsp;git clone --recursive --depth 1 -q https://github.com/RetroAchievements/RALibretro.git
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
IMPORTANT: use the &lt;b&gt;--quiet&lt;/b&gt; [or &lt;b&gt;-q&lt;/b&gt;] flag in order to suppress all the superfluous submodule logging output!
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcT2RT8ooGBAleihrvbHYB6OgvxeOiaYr9F6HXxDS1nJ6DqCHfxWePxcWJtumJnyqiQEDft2PscvWvhA9CmgvphHbj7PEvkZ8zS8VhXnTPL4sEtXaASesGmtPF1zptmKgG_ullWdrk-F7pt0ttg6AUzshZyXIbV7N5dGzvs9rZXv7jqOhrsjS3b8nmX_Q/s974/GitHubClone.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcT2RT8ooGBAleihrvbHYB6OgvxeOiaYr9F6HXxDS1nJ6DqCHfxWePxcWJtumJnyqiQEDft2PscvWvhA9CmgvphHbj7PEvkZ8zS8VhXnTPL4sEtXaASesGmtPF1zptmKgG_ullWdrk-F7pt0ttg6AUzshZyXIbV7N5dGzvs9rZXv7jqOhrsjS3b8nmX_Q/s600/GitHubClone.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;a href=&quot;https://github.com/RetroAchievements/rcheevos&quot;&gt;rcheevos&lt;/a&gt;&lt;br /&gt;
rcheevos is a C library that makes it easier to process Retro Achievements data.  Launch Visual Studio 2022.  Open rcheevos-test.sln.  Choose Debug | x64.  Rebuild Solution.  Open test/test.c.  Press F5 to Debug source:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoApZPZyYFk2aBvQvITDlNonbC3dr2-fqgQkmiKCJvp3yfrnoP5GO4nrzBswNo7h9x1xb2ygoKqPcgO0z8eRDpIHdi1HvMgnJ1BBNE0WYYMP_1fpOZxdo0OwQquqI1tZ_cH1UQOlHwRzpq9vAPeELYKZAa4TjWT1_fmcmFSsZ1DHf_J-zti6XBjjw3mMk/s1008/rcheevos.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoApZPZyYFk2aBvQvITDlNonbC3dr2-fqgQkmiKCJvp3yfrnoP5GO4nrzBswNo7h9x1xb2ygoKqPcgO0z8eRDpIHdi1HvMgnJ1BBNE0WYYMP_1fpOZxdo0OwQquqI1tZ_cH1UQOlHwRzpq9vAPeELYKZAa4TjWT1_fmcmFSsZ1DHf_J-zti6XBjjw3mMk/s600/rcheevos.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;a href=&quot;https://github.com/RetroAchievements/RAInterface&quot;&gt;RAInterface&lt;/a&gt;&lt;br /&gt;
RAInterface is a submodule which provides emulator hooks to integrate with RA server via RA_Integration.dll
&lt;br /&gt;&lt;br /&gt;
  
&lt;a href=&quot;https://github.com/RetroAchievements/RAIntegration&quot;&gt;RAIntegration&lt;/a&gt;&lt;br /&gt;
RAIntegration is the main DLL used for interfacing with &lt;a href=&quot;https://retroachievements.org/game/14672&quot;&gt;retroachievements.org&lt;/a&gt;.  Launch Visual Studio 2022.  Open RA_Integration.sln.  Choose Debug | x64.  Rebuild Solution.  Install CppUnitTest &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=drleq.CppUnitTestFrameworkAdaptor&quot;&gt;Test Adapter&lt;/a&gt; to run all Interface + Integration tests: Extensions menu | Manage Extensions | Test Adapter CppUnitTest Framework
&lt;br /&gt;
&lt;br /&gt;
Launch Test Explorer | Test menu | Test Explorer | Right click specific test e.g. RA_Interface.Tests | Debug:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSxqhFgTfQpp2tGTV7UuCxCRaAGAgPCDfDMS1UvmZjstCfbYyxH9apdLYvSHoqyLaTGJfj0gyxiv5oP84A9cl68X8Tc35g5AS_tCwIzP7C_AfA2-bpOTRXz7BkxJF5vFOh9wVkpoUGgKo8IkPkmIAtpAgtnDdcvgTnPmdOZy8dnakFYZwi6gwRZkrjZCw/s1008/RAIntegration.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot;width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSxqhFgTfQpp2tGTV7UuCxCRaAGAgPCDfDMS1UvmZjstCfbYyxH9apdLYvSHoqyLaTGJfj0gyxiv5oP84A9cl68X8Tc35g5AS_tCwIzP7C_AfA2-bpOTRXz7BkxJF5vFOh9wVkpoUGgKo8IkPkmIAtpAgtnDdcvgTnPmdOZy8dnakFYZwi6gwRZkrjZCw/s600/RAIntegration.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;
  
&lt;a href=&quot;https://github.com/RetroAchievements/RALibretro&quot;&gt;RALibretro&lt;/a&gt;&lt;br /&gt;
RALibretro is the multi-emulator used to develop RetroAchievements and earn them.  RALibretro uses &lt;a href=&quot;https://github.com/libretro&quot;&gt;libretro&lt;/a&gt; cores to do the actual emulation with RAIntegration DLL to connect with the site.  Launch Visual Studio 2022.  Open RALibretro.sln.  Choose Debug | x64.  Rebuild Solution.  Open src/main.cpp.  Press F5 to Debug source:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXmztKReb3dAp5Mu1_n-Mg4uE38sDZdG8xEuyAFyyam89nSGWPueRniQtPVpuJrMQ3LBvH-Nw_5ScTkNknWQYBRIiKfuWYFEiAlbEK9C393doF3bj3w8aDidfH2PPaqN0TLn9qhBG4K82mB8kLeT9oA-BMEDtbgHo8vbOYklQoDTzjMH3wl4K757qpJoQ/s1008/RALibRetro.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXmztKReb3dAp5Mu1_n-Mg4uE38sDZdG8xEuyAFyyam89nSGWPueRniQtPVpuJrMQ3LBvH-Nw_5ScTkNknWQYBRIiKfuWYFEiAlbEK9C393doF3bj3w8aDidfH2PPaqN0TLn9qhBG4K82mB8kLeT9oA-BMEDtbgHo8vbOYklQoDTzjMH3wl4K757qpJoQ/s600/RALibRetro.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
 &lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Overview&lt;/u&gt;&lt;br /&gt;
Here is an overview of the 1x C project rcheevos and 3x C++ projects to interface + integrate + emulate:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Project&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Role&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Dependencies&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/rcheevos&quot;&gt;rcheevos&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;Core engine: parse + evaluate achievements / leaderboards
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;None
&lt;/td&gt;  
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/RAInterface&quot;&gt;RAInterface&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;Interface library for emulators to interact with the RA stack
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;rcheevos
&lt;/td&gt;  
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/RAIntegration&quot;&gt;RAIntegration&lt;/a&gt;&amp;nbsp;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;Full DLL integration [login/server/achievement submission]
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;RAInterface + rcheevos&amp;nbsp;
&lt;/td&gt;  
&lt;/tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://github.com/RetroAchievements/RALibretro&quot;&gt;RALibretro&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;Multi-emulator that uses RA stack to support achievements
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;RAIntegration
&lt;/td&gt;  
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
  
libretro&lt;br /&gt;
&lt;a href=&quot;https://emulation.gametechwiki.com/index.php/Libretro&quot;&gt;libretro&lt;/a&gt; is an API designed for retro games and emulators to be compiled as &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic-link_library&quot;&gt;DLLs&lt;/a&gt; which can be used in front ends like RALibretro that implement the libretro API.  This is reminiscent of the OpenAI Retro work we did in &lt;a href=&quot;https://steveproxna.blogspot.com/2024/11&quot;&gt;2024&lt;/a&gt; which also uses libretro cores but exposes them in Python with Reinforcement Learning environments.
&lt;br /&gt;&lt;br /&gt;
Similar to RetroAchievements OpenAI Retro uses its own Game Integration tool to inspect memory for points of interest e.g. starting state, reward function + done condition whereas RALibretro uses Memory Inspector:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXtUbvOyapUR10MD4gKS8GreyihNKtskWrvQek4YFLoj3XAK31e_qETB-PbYwN13J9EPGUy5HfwPjSWctINhMa1gLficATXD8q8RFnEUzWm1lTsVHlUNufdhQk7lL26hV543M5Ke6ElMnIHie71SMw1kZdDrfDTpW39RASi5LnaWIvm0-yFDdtWPJCREI/s530/MemoryInspector.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXtUbvOyapUR10MD4gKS8GreyihNKtskWrvQek4YFLoj3XAK31e_qETB-PbYwN13J9EPGUy5HfwPjSWctINhMa1gLficATXD8q8RFnEUzWm1lTsVHlUNufdhQk7lL26hV543M5Ke6ElMnIHie71SMw1kZdDrfDTpW39RASi5LnaWIvm0-yFDdtWPJCREI/s600/MemoryInspector.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, the RetroAchievements integration into Simpsons Trivia game has been awesome as gamers continue to play this game and top the achievements more than seven years after it was published!  In fact, many hard core gamers have published YouTube &lt;a href=&quot;https://www.youtube.com/watch?v=h1DcCFx0_Ss&quot;&gt;videos&lt;/a&gt; showcasing their achievements for others to follow:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;iframe width=&quot;98%&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/jJ0xRMU2kv0&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;!-- --&gt;
&lt;br /&gt;
The next step would be reseach the documentation fully and create some RetroAchievements sets myself &lt;span style=&#39;font-family:Wingdings&#39;&gt;J&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;
  
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2025/11/simpsons-trivia-retro-achievements.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjxo7FxO7IjzPKAVZuQ2UEmxjm91aG-kGv3WgrZZxDrxboP9P_l1voo91zvvgALya_pNry1cM1bax-wTs8IeMJZAlgCjx11v-eslEYW5UwCMXv-_7xRMQzklcQz_H5uCj3QM4Noqyr9BfKAkAzUzcOda1wrmngBajD2Qi0O2KmOBL1C9A0iMY8TnAh0Lo/s72-c/RetroAchievements.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-7461536414304992499</guid><pubDate>Mon, 15 Sep 2025 08:00:00 +0000</pubDate><atom:updated>2025-09-15T01:00:07.781-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Python</category><title>Pytest Setup Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

In 2020, we checked out &lt;a href=&quot;https://steveproxna.blogspot.com/2020/07/python-setup-cheat-sheet.html&quot;&gt;Python Setup Cheat Sheet&lt;/a&gt; as an interpreted high-level programming language with all code samples&#39; unit tests using unittest package TestCase class.  However, since then we have learned that &lt;a href=&quot;https://pytest-with-eric.com&quot;&gt;pytest&lt;/a&gt; allows writing shorter more readable tests with less boilerplate.  Plus we would like to include mocks!!  
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5SeutLv2xN_orl-llnhD8H58gAtNhBFoIXsyAywK3-tcb0Ov_I4igsZhlk-1QHT2eMPOzY6nn8vQMx_HNHamjKR9eRKRshTajA5xZ-Jekpr-FIAMGht4ayQeF0Vd_2WYAXfuGGQh6winK76XYjsvvYEC2JIA5F2_iuXlobGn7PzMwq2LMPjUjUExW7nc/s2360/PythonPytest.jpg&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5SeutLv2xN_orl-llnhD8H58gAtNhBFoIXsyAywK3-tcb0Ov_I4igsZhlk-1QHT2eMPOzY6nn8vQMx_HNHamjKR9eRKRshTajA5xZ-Jekpr-FIAMGht4ayQeF0Vd_2WYAXfuGGQh6winK76XYjsvvYEC2JIA5F2_iuXlobGn7PzMwq2LMPjUjUExW7nc/s600/PythonPytest.jpg&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Frameworks&lt;/u&gt;&lt;br /&gt;
When developing code in Python there are typically five Top Python Testing &lt;a href=&quot;https://pytest-with-eric.com/comparisons/python-testing-frameworks&quot;&gt;Frameworks&lt;/a&gt; that are favorable:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;NAME&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;MONIKER &lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;DESCRIPTION&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;unittest&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;PyUnit&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;The default Python testing framework built-in with the Python Standard Library&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;pytest&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Pytest&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Popular testing frameworks known for simplicity, flexibility + powerful features&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;noseTest&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Nose2&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Enhanced unittest version offering additional plugins to support test execution&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;DocTest&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;DocTest&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Python Standard Library module generates tests within source code DocString&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Robot&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Robot&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Acceptance testing keyword-driven module that simplifies testcase automation&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Here are some reasons why &lt;a href=&quot;https://docs.pytest.org/en/stable&quot;&gt;pytest&lt;/a&gt; currently seems to be the most popular Python unit test framework out:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;1. Simple and Readable Syntax
&amp;nbsp;&amp;nbsp;   You write plain Python functions instead of creating large verbose classes
&amp;nbsp;&amp;nbsp;   Assertions use plain assert statements which provide more detailed output
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;  
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;2. Rich Plugin Ecosystem
&amp;nbsp;&amp;nbsp;   Plugins like pytest-mock, pytest-asyncio, pytest-cov, and more
&amp;nbsp;&amp;nbsp;   Easy to extend pytest plugins or write your own custom plugins
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;  
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;3. Powerful Fixtures
&amp;nbsp;&amp;nbsp;   Allows for clean and re-usable setup and teardown using fixtures
&amp;nbsp;&amp;nbsp;   Supports various test level scopes, autouse, and parametrization
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;  
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;4. Test Discovery
&amp;nbsp;&amp;nbsp;   Automatically discovers tests in files named test_*.py
&amp;nbsp;&amp;nbsp;   No need to manually register tests or use loader classes
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;  
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;5. Great Reporting
&amp;nbsp;&amp;nbsp;   Colored output, diffs for failing assertions, and optional verbosity
&amp;nbsp;&amp;nbsp;   Integrates easily with tools like coverage, tox, and CI/CD systems
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;  
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;6. Supports Complex Testing Needs
&amp;nbsp;&amp;nbsp;   Parameterized tests (@pytest.mark.parametrize)
&amp;nbsp;&amp;nbsp;   parallel test execution (pytest-xdist) + hooks
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;pytest&lt;/u&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;pip install pytest
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  

&lt;u&gt;Setup&lt;/u&gt;&lt;br /&gt;
Depending on your stack here is some great documentation to setup pytest on &lt;a href=&quot;https://pytest-with-eric.com/integrations/pytest-pycharm-integration&quot;&gt;PyCharm&lt;/a&gt;, &lt;a href=&quot;https://pytest-with-eric.com/introduction/how-to-run-pytest-in-vscode&quot;&gt;VS Code&lt;/a&gt; or &lt;a href=&quot;https://pytest-with-eric.com/getting-started/poetry-run-pytest&quot;&gt;Poetry&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Configuration&lt;/u&gt;&lt;br /&gt;
In pytest, &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-ini&quot;&gt;pytest.ini&lt;/a&gt; is the main configuration file used to customize and control pytest behavior across the unit test suite.  pytest.ini hosts pytest options, test paths, plugin settings and markers to attach to the test functions to categorize, filter or modify their behavior.  Here is a sample pytest.ini configuration file as base: 
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;[pytest]  
&amp;nbsp;&amp;nbsp;addopts = -ra -q
&amp;nbsp;&amp;nbsp;testpaths = tests
&amp;nbsp;&amp;nbsp;markers =
&amp;nbsp;&amp;nbsp;    slow: marks tests as slow (deselect with &#39;-m &quot;not slow&quot;&#39;)
&amp;nbsp;&amp;nbsp;    db: marks tests requiring database
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Fixtures&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://pytest-with-eric.com/fixtures/pytest-fixtures&quot;&gt;Fixtures&lt;/a&gt; are methods in pytest that provide fixed baseline for tests to run.  Fixtures can be used to &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-setup-teardown/#What-is-Setup-and-Teardown&quot;&gt;setup&lt;/a&gt; all preconditions for tests, provide data, or perform &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-setup-teardown/#Importance-of-Test-Setup-and-Teardown&quot;&gt;teardown&lt;/a&gt; after tests finished via @pytest.fixture decorator.
&lt;br /&gt;&lt;br /&gt; 
&lt;i&gt;Scope&lt;/i&gt;&lt;br /&gt;
Fixtures have scope: Function, Class, Module + Session which define how long fixture available during test:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;SCOPE&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;DESCRIPTION&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Function&lt;/td&gt;&lt;td&gt;&amp;nbsp;Fixture created once per test function and destroyed at end of test function&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Class&lt;/td&gt;&lt;td&gt;&amp;nbsp;Fixture created once per test class and destroyed at the end of test class&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Module&lt;/td&gt;&lt;td&gt;&amp;nbsp;Fixture created once per test module and destroyed at end of test module&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Session&lt;/td&gt;&lt;td&gt;&amp;nbsp;Fixture created once per test session and destroyed at end of test session&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;i&gt;conftest&lt;/i&gt;&lt;br /&gt;
In pytest, &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-conftest&quot;&gt;conftest.py&lt;/a&gt; file is used to share fixtures across multiple tests.  All the fixtures in conftest.py will be automagically detected without needing to import.  conftest: typically scoped at test root directory structure.
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;Dependencies&lt;/i&gt;&lt;br /&gt;
Dependency Injection: when fixtures are requested by other fixtures although this adds complexity to tests!
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;autouse&lt;/i&gt;&lt;br /&gt;
Simple trick to avoid defining fixture in each test: use the &lt;b&gt;&lt;a href=&quot;https://pytest-with-eric.com/fixtures/pytest-fixture-autouse&quot;&gt;autouse&lt;/a&gt;=True&lt;/b&gt; flag to apply fixture to all tests.
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;yield&lt;/i&gt;&lt;br /&gt;
When you use &lt;a href=&quot;https://pytest-with-eric.com/fixtures/pytest-fixtures/#Yield-vs-Return-in-Fixtures&quot;&gt;yield&lt;/a&gt; in fixture function setup code executes before yield and teardown executes after yield: 
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pytest  
&amp;nbsp;&amp;nbsp;@pytest.fixture
&amp;nbsp;&amp;nbsp;def my_fixture(): 
&amp;nbsp;&amp;nbsp;    # setup code
&amp;nbsp;&amp;nbsp;    yield &quot;fixture value&quot;
&amp;nbsp;&amp;nbsp;    # teardown code
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;i&gt;Arguments&lt;/i&gt;&lt;br /&gt;
Use pytest fixtures with &lt;a href=&quot;https://pytest-with-eric.com/fixtures/pytest-fixture-with-arguments&quot;&gt;arguments&lt;/a&gt; to write re-usable fixtures that can easily share across tests also known as Parameterized fixtures using &lt;i&gt;@pytest.fixture(params=[0, 1, 2])&lt;/i&gt; syntax.  Note: these fixtures should not be confused with the &lt;i&gt;@pytest.mark.parametrize&lt;/i&gt; &lt;a href=&quot;https://pytest-with-eric.com/introduction/pytest-parameterized-tests/#What-Are-Pytest-Parameters&quot;&gt;decorator&lt;/a&gt; which can be used to specify inputs and outputs!
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;Factories&lt;/i&gt;&lt;br /&gt;
&lt;a href=&quot;https://pytest-with-eric.com/fixtures/pytest-fixture-with-arguments/#Factories-As-Fixtures&quot;&gt;Factories&lt;/a&gt;, in the context of pytest fixtures, are functions that are used to create and return instances of objects that are needed to generate test data or objects with specific configuration in re-usable manner:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;conftest.py&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;unittest.py&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;@pytest.fixture
&amp;nbsp;def user_creds(): 
&amp;nbsp;  def _user_creds(name: str, email: str):
&amp;nbsp;    return {&quot;name&quot;: name, &quot;email&quot;: email}  
&amp;nbsp;  return _user_creds
&lt;/pre&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;def test_user_creds(user_creds):
&amp;nbsp;  assert user_creds(&quot;John&quot;, &quot;x@abc.com&quot;)=={  
&amp;nbsp;    &quot;name&quot;: &quot;John&quot;,  
&amp;nbsp;    &quot;email&quot;: &quot;x@abc.com&quot;,
&amp;nbsp;  }
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Best &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-organize-tests&quot;&gt;practices&lt;/a&gt; for organizing tests include: Organizing Tests by Testing &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-organize-tests/#Best-Practice-1-%E2%80%94-Organizing-Tests-by-Testing-Pyramid&quot;&gt;Pyramid&lt;/a&gt;, Structure Should &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-organize-tests/#Best-Practice-2-Test-Structure-Should-Mirror-Application-Code&quot;&gt;Mirror&lt;/a&gt; Application Code, &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-organize-tests/#Best-Practice-3-%E2%80%94-How-to-Group-or-Organize-Fixtures&quot;&gt;Group&lt;/a&gt; or Organize Fixtures and Organize Tests &lt;a href=&quot;https://pytest-with-eric.com/pytest-best-practices/pytest-organize-tests/#Tests-Outside-Application-Code&quot;&gt;Outside&lt;/a&gt; Application Code for scalability.
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Mocking&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-mocking&quot;&gt;Mocking&lt;/a&gt; is technique that allows you to isolate pieces of code being tested from its dependencies so the test can focus on the code under test in isolation.  The &lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html&quot;&gt;unittest.mock&lt;/a&gt; package offers Mock and MagicMock objects:
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;&lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html#the-mock-class&quot;&gt;Mock&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;
A mock object simulates the behavior of the object it replaces by creating attributes and methods on-the-fly.
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;&lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html#magic-mock&quot;&gt;MagicMock&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;
Subclass of Mock with default implementations for most magic methods (__len__, __getitem__, etc.).  Useful when mocking objects that interact with Python&#39;s dunder methods that enable custom behaviors for common operations.
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;Patching&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-common-mocking-problems/#Mock-and-Patch-%E2%80%94-A-Brief-Recap&quot;&gt;Patching&lt;/a&gt; is technique that temporarily replaces real objects in code with mock objects during test execution.  &lt;a href=&quot;https://pytest-with-eric.com/mocking/mocking-vs-patching/#Understanding-Patching-How-It-Works&quot;&gt;Patching&lt;/a&gt; helps ensure external systems do not affect test outcomes thus tests are consistent and repeatable.
&lt;br /&gt;&lt;br /&gt;
IMPORTANT - Mocks are &lt;b&gt;NOT&lt;/b&gt; stubs!&lt;br /&gt;
When we combine &lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch&quot;&gt;@patch&lt;/a&gt; decorator with &lt;i&gt;return_value&lt;/i&gt; or &lt;i&gt;side_effect&lt;/i&gt; it is a stub but from the &lt;a href=&quot;https://docs.python.org/3/library/unittest.mock.html&quot;&gt;mock&lt;/a&gt; package!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;METHOD&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;DESCRIPTION&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-mock-multiple-return-values/#Single-Return-Value-Mocking&quot;&gt;return_value&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Specify the single value of Mock object to be returned when method called&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-mock-multiple-return-values/#Multiple-Return-Values-with-%E2%80%98side-effect%E2%80%99&quot;&gt;side_effect&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Specify multiple values of Mock object to be returned when method called&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;u&gt;Difference&lt;/u&gt;&lt;br /&gt;
In pytest, Mock and patch are both &lt;a href=&quot;https://pytest-with-eric.com/mocking/python-magicmock-raise-exception/#What-is-the-Difference-Between-Mock-and-Patch&quot;&gt;tools&lt;/a&gt; for simulating or replacing parts of your code during testing.  Mock creates mock objects while patch temporarily replaces real objects with mocks during tests to isolate code:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;Mock&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;patch&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;from unittest.mock import Mock  
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;mock_obj = Mock()
&amp;nbsp;&amp;nbsp;mock_obj.some_method.return_value = 42 
&amp;nbsp;&amp;nbsp;result = mock_obj.some_method()  
&amp;nbsp;&amp;nbsp;assert result == 42
&lt;/pre&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;from unittest.mock import patch
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;def external_function(): 
&amp;nbsp;&amp;nbsp;    pass
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;@patch(&#39;module_name.external_function&#39;)  
&amp;nbsp;&amp;nbsp;def test_function(mock_external): 
&amp;nbsp;&amp;nbsp;    mock_external.return_value = &quot;Mock data&quot;
&amp;nbsp;&amp;nbsp;    result = external_function() 
&amp;nbsp;&amp;nbsp;    assert result == &quot;Mock data&quot;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!--&lt;br /&gt;--&gt;
  
IMPORTANT&lt;br /&gt;
When creating mocks it is critical to ensure mock objects accurately reflect objects they are replacing.  Thus, it is best practice to use &lt;b&gt;&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-common-mocking-problems/#Mocks-Fail-To-Respect-Method-Signature&quot;&gt;autospec&lt;/a&gt;=True&lt;/b&gt; to ensure mock objects respect function signatures being replaced!
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Assertions&lt;/u&gt;&lt;br /&gt;
For completeness, here is list of &lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-mock-assert-called/#Pytest-Mock-Assert-Call-The-Key-Concepts&quot;&gt;assertion&lt;/a&gt; methods to verify method on mock object was called during tests:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;METHOD&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;DESCRIPTION&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;assert_called&lt;/td&gt;&lt;td&gt;&amp;nbsp;verify specific method on mock object has been called during a test&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;assert_called_once&lt;/td&gt;&lt;td&gt;&amp;nbsp;verify specific method on mock object has been called only one time&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;assert_called_once_with&lt;/td&gt;&lt;td&gt;&amp;nbsp;verify specific method on mock object called once with specific args&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;assert_called_with&lt;/td&gt;&lt;td&gt;&amp;nbsp;verify every time method on mock object called with fixed arguments&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;assert_not_called&lt;/td&gt;&lt;td&gt;&amp;nbsp;verify specific method on mock object was not called during the test&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;assert_has_calls&lt;/td&gt;&lt;td&gt;&amp;nbsp;verify the order in which specific method on mock object was called&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;assert_any_call&lt;/td&gt;&lt;td&gt;&amp;nbsp;verify specific method on mock object has been called at least once&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Monkeypatch&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-monkeypatch&quot;&gt;Monkeypatching&lt;/a&gt; is technique used to modify code behavior at runtime especially where certain dependencies or settings make it challenging to isolate functionality for example &lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-monkeypatch/#Monkeypatching-Environment-Variables&quot;&gt;environment variables&lt;/a&gt; or &lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-monkeypatch/#Monkeypatching-Functions&quot;&gt;system paths&lt;/a&gt;:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;app.py&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;test_app.py&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;  
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import os
&amp;nbsp;&amp;nbsp;def get_app_mode() -&gt; str:
&amp;nbsp;&amp;nbsp;    app_mode = os.getenv(&quot;APP_MODE&quot;)&amp;nbsp;
&amp;nbsp;&amp;nbsp;    return app_mode.lower()
&lt;/pre&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;def test_get_app_mode(monkeypatch):
&amp;nbsp;&amp;nbsp;    &quot;&quot;&quot;Test behavior when APP_MODE is set.&quot;&quot;&quot;
&amp;nbsp;&amp;nbsp;    monkeypatch.setenv(&quot;APP_MODE&quot;, &quot;Testing&quot;)&amp;nbsp;
&amp;nbsp;&amp;nbsp;    assert get_app_mode() == &quot;testing&quot;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;u&gt;pytest-mock&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-mocking&quot;&gt;pytest-mock&lt;/a&gt; is pytest &lt;a href=&quot;https://pypi.org/project/pytest-mock&quot;&gt;plugin&lt;/a&gt; built on top of unittest.mock that provides an easy-to-use &lt;b&gt;&lt;a href=&quot;https://pytest-with-eric.com/mocking/pytest-mocking/#mocker-Fixture&quot;&gt;mocker&lt;/a&gt;&lt;/b&gt; fixture that can be used to create mock objects and patch functions.  When you use &lt;i&gt;mocker.patch()&lt;/i&gt; method provided by pytest-mock default behavior is to replace the object with &lt;i&gt;MagicMock()&lt;/i&gt; so pytest-mock uses &lt;i&gt;MagicMock()&lt;/i&gt;.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;pip install pytest-mock
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;app.py&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import requests
&amp;nbsp;&amp;nbsp;from http import HTTPStatus
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;def get_user_name(user_id: int) -&gt; str:
&amp;nbsp;&amp;nbsp;    response = requests.get(f&quot;https://api.example.com/users/{user_id}&quot;)
&amp;nbsp;&amp;nbsp;    return response.json()[&#39;name&#39;] if response.status_code == HTTPStatus.OK else None
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt; 
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;test_app.py&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;from http import HTTPStatus
&amp;nbsp;&amp;nbsp;from app import get_user_name
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;def test_get_user_name(mocker):
&amp;nbsp;&amp;nbsp;    mock_response = mocker.Mock()
&amp;nbsp;&amp;nbsp;    mock_response.status_code = http.HTTPStatus.OK
&amp;nbsp;&amp;nbsp;    mock_response.json.return_value = {&#39;name&#39;: &#39;Test&#39;}
&amp;nbsp;&amp;nbsp;    mocker.patch(&#39;app.requests.get&#39;, return_value=mock_response)
&amp;nbsp;&amp;nbsp;    result = get_user_name(1)
&amp;nbsp;&amp;nbsp;    assert result == &#39;Test&#39;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;   
&lt;!-- --&gt;
&lt;u&gt;Legacy&lt;/u&gt;&lt;br /&gt;
In many legacy Python codebases you may detect references to &lt;i&gt;Mock()&lt;/i&gt;, &lt;i&gt;MagicMock()&lt;/i&gt; and &lt;i&gt;@patch&lt;/i&gt; decorator from unittest.mock with pytest.  Teams often keep the old style unless there compelling reason to refactor it.
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Recommendation&lt;/u&gt;&lt;br /&gt;
However, here are some recommendations to prefer pytest-mock and mocker fixture for future unit testing:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;1. Prefer pytest-mock and the mocker fixture
&amp;nbsp;&amp;nbsp;   Cleaner syntax than unittest.mock.patch
&amp;nbsp;&amp;nbsp;   Automatically cleaned up after each test
&amp;nbsp;&amp;nbsp;   Plays well with other pytest fixtures
&amp;nbsp;&amp;nbsp;   Centralizes all patching into one fixture (mocker)
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;2. Use monkeypatch for patching env vars, system paths and etc.
&amp;nbsp;&amp;nbsp;   Prefer monkeypatch for clarity and idiomatic pytest style
&amp;nbsp;&amp;nbsp;   e.g. os.environ, system paths, or patching open()
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;3. Avoid @patch decorators unless migrating old tests
&amp;nbsp;&amp;nbsp;   Can be harder to read or stack with multiple patches
&amp;nbsp;&amp;nbsp;   Better to use mocker.patch() inline as cleaner syntax
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;4. Use autospec=True when mocking complex or external APIs
&amp;nbsp;&amp;nbsp;   Ensure mocks behave like the real objects (catch bad call signatures)
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;5. Use fixtures to share mocks across tests
&amp;nbsp;&amp;nbsp;   When you have mock used by multiple tests then define it as a fixture
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;b&gt;tl;dr&lt;/b&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Prefer pytest-mock (mocker fixture) for readability and less boilerplate.  Import tools like MagicMock, Mock, call, ANY from unittest.mock when needed.  Avoid @patch unless needed — inline mocker.patch() is usually cleaner.  Keep everything in one style within a test module for consistency.
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;pytest-asyncio&lt;/u&gt;&lt;br /&gt;
Concurrency allows a program to efficiently execute its tasks asynchronously i.e. executing tasks while other tasks are waiting.  &lt;i&gt;&lt;a href=&quot;https://pytest-with-eric.com/pytest-advanced/pytest-asyncio&quot;&gt;pytest-asyncio&lt;/a&gt;&lt;/i&gt; simplifies handling event loops + managing async fixtures thru unit testing.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;pip install pytest-asyncio
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;app.py&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;test_app.py&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt; 
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import asyncio
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;async def fetch_data():
&amp;nbsp;&amp;nbsp;    # Simulate I/O operation.
&amp;nbsp;&amp;nbsp;    await asyncio.sleep(1)
&amp;nbsp;&amp;nbsp;    return {&quot;status&quot;: &quot;OK&quot;, &quot;data&quot;: [42]}&amp;nbsp;
&lt;/pre&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;import pytest
&amp;nbsp;&amp;nbsp;from app import fetch_data
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;@pytest.mark.asyncio
&amp;nbsp;&amp;nbsp;async def test_fetch_data():
&amp;nbsp;&amp;nbsp;    result = await fetch_data()
&amp;nbsp;&amp;nbsp;    assert result[&quot;status&quot;] == &quot;OK&quot;&amp;nbsp;
&amp;nbsp;&amp;nbsp;    assert result[&quot;data&quot;] == [42]
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!--&lt;br /&gt;--&gt;
Consequently &lt;i&gt;&lt;a href=&quot;https://pytest-with-eric.com/pytest-advanced/pytest-asyncio/#Async-Mocking-Using-AsyncMock&quot;&gt;AsyncMock&lt;/a&gt;&lt;/i&gt; from unittest.mock allows you to mock asynchronous functions and/or coroutines.
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;CI/CD&lt;/u&gt;&lt;br /&gt;
GitHub &lt;a href=&quot;https://pytest-with-eric.com/integrations/pytest-github-actions&quot;&gt;Actions&lt;/a&gt; is feature-rich &lt;a href=&quot;https://en.wikipedia.org/wiki/CI/CD&quot;&gt;CI/CD&lt;/a&gt; platform and offers an easy and flexible way to automate your testing processes.  GitHub Actions mainly consist of files called workflows.  The workflow file contains job or several jobs that consist of sequence of steps.  Here is sample YAML file that will trigger the workflow on git push:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;~/.github/workflows/run_test.yml&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;name: Run Unit Test via Pytest
&amp;nbsp;&amp;nbsp;on: [push]
&amp;nbsp;&amp;nbsp;jobs:
&amp;nbsp;&amp;nbsp;  build:
&amp;nbsp;&amp;nbsp;    runs-on: ubuntu-latest
&amp;nbsp;&amp;nbsp;    strategy:
&amp;nbsp;&amp;nbsp;      matrix:
&amp;nbsp;&amp;nbsp;        python-version: [&quot;3.10&quot;]
&amp;nbsp;&amp;nbsp;    steps:
&amp;nbsp;&amp;nbsp;      - uses: actions/checkout@v3
&amp;nbsp;&amp;nbsp;      - name: Set up Python ${{ matrix.python-version }}
&amp;nbsp;&amp;nbsp;        uses: actions/setup-python@v4
&amp;nbsp;&amp;nbsp;        with:
&amp;nbsp;&amp;nbsp;          python-version: ${{ matrix.python-version }}
&amp;nbsp;&amp;nbsp;      - name: Install dependencies
&amp;nbsp;&amp;nbsp;        run: |
&amp;nbsp;&amp;nbsp;          python -m pip install --upgrade pip
&amp;nbsp;&amp;nbsp;          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
&amp;nbsp;&amp;nbsp;      - name: Lint with Ruff
&amp;nbsp;&amp;nbsp;        run: |
&amp;nbsp;&amp;nbsp;          pip install ruff
&amp;nbsp;&amp;nbsp;          ruff --format=github --target-version=py310 .
&amp;nbsp;&amp;nbsp;        continue-on-error: true
&amp;nbsp;&amp;nbsp;      - name: Test with pytest
&amp;nbsp;&amp;nbsp;        run: |
&amp;nbsp;&amp;nbsp;          coverage run -m pytest  -v -s
&amp;nbsp;&amp;nbsp;      - name: Generate Coverage Report
&amp;nbsp;&amp;nbsp;        run: |
&amp;nbsp;&amp;nbsp;          coverage report -m
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have setup pytest for more robust unit testing with mocks and stubs via patching.  Looking forward there are additional ways to &lt;a href=&quot;https://pytest-with-eric.com/pytest-advanced/pytest-improve-runtime&quot;&gt;improve&lt;/a&gt; unit test development experience with pytest as per the article:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;1. Use &lt;a href=&quot;https://pytest-with-eric.com/pytest-advanced/pytest-improve-runtime/#Use-Markers-To-Prioritise-Tests&quot;&gt;Markers&lt;/a&gt; To Prioritise Tests
&amp;nbsp;&amp;nbsp;   Organize tests in such a way that prioritizes key functionalities first
&amp;nbsp;&amp;nbsp;   Running tests with critical functionality first provide faster feedback
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;2. Do More With Less (&lt;a href=&quot;https://pytest-with-eric.com/pytest-advanced/pytest-improve-runtime/#Do-More-With-Less-Parametrized-Testing&quot;&gt;Parametrized&lt;/a&gt; Testing)
&amp;nbsp;&amp;nbsp;   Parametrized Testing allows you to test multiple scenarios in single test function
&amp;nbsp;&amp;nbsp;   Feed different parameters into same test logic covering more scenarios + less code
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;3. &lt;a href=&quot;https://pytest-with-eric.com/pytest-advanced/pytest-improve-runtime/#Profiling-Tests&quot;&gt;Profiling&lt;/a&gt; Tests
&amp;nbsp;&amp;nbsp;   Identify the slow-running unit tests using the --durations=XXX flag
&amp;nbsp;&amp;nbsp;   Use the pytest-profiling plugin to generate tabular and heat graphs
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;4. Run Tests In Parallel (Use &lt;a href=&quot;https://pytest-with-eric.com/pytest-advanced/pytest-improve-runtime/#Run-Tests-In-Parallel-Use-pytest-xdist&quot;&gt;pytest-xdist&lt;/a&gt;)
&amp;nbsp;&amp;nbsp;   Use the pytest-xdist plugin to distribute tests across multiple CPUs
&amp;nbsp;&amp;nbsp;   Tests run in parallel, use resources better, provide faster feedback!
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
  
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2025/09/pytest-setup-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5SeutLv2xN_orl-llnhD8H58gAtNhBFoIXsyAywK3-tcb0Ov_I4igsZhlk-1QHT2eMPOzY6nn8vQMx_HNHamjKR9eRKRshTajA5xZ-Jekpr-FIAMGht4ayQeF0Vd_2WYAXfuGGQh6winK76XYjsvvYEC2JIA5F2_iuXlobGn7PzMwq2LMPjUjUExW7nc/s72-c/PythonPytest.jpg" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-3969117985250441702</guid><pubDate>Sun, 31 Aug 2025 08:00:00 +0000</pubDate><atom:updated>2025-08-31T01:00:13.191-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Cloud</category><title>Cloud CI-CD Cheat Sheet II</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
  
In the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2025/07/cloud-ci-cd-cheat-sheet.html&quot;&gt;post&lt;/a&gt;, we checked out Cloud CI/CD Cheat Sheet to transition from the 1990s to modern day CI/CD.  Now lets integrate GitLab with GitFlow SDLC to demonstrate the Kubernetes CI/CD pipeline benefits.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfdryn90ILEQjxlge0UqwMW56nzSHXLsRAkYD0iz3Kr0e3PbwLmRbdkn_FUgSn_pX43Y0SViVk1BDpb_bN9TYxrbtWENbO_A4uAHJLAqwrQ4z6hohhScg4NRV_ZCWZZBMS1AkFFY0Qlv7E9L7uQJr_9dFml5CaoXCwENAeF7My9r9k0mn7jW9Qc4l9Ovg/s713/GitLab.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfdryn90ILEQjxlge0UqwMW56nzSHXLsRAkYD0iz3Kr0e3PbwLmRbdkn_FUgSn_pX43Y0SViVk1BDpb_bN9TYxrbtWENbO_A4uAHJLAqwrQ4z6hohhScg4NRV_ZCWZZBMS1AkFFY0Qlv7E9L7uQJr_9dFml5CaoXCwENAeF7My9r9k0mn7jW9Qc4l9Ovg/s600/GitLab.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
  
&lt;b&gt;GitLab CI/CD&lt;/b&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Create &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/.gitlab-ci.yml&quot;&gt;.gitlab-ci.yml&lt;/a&gt; at the root of project
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
this is the driver file that co-ordinates stages:
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Build / Lint / Deploy
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;i&gt;gitlab-ci.yml&lt;/i&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_eMSneyUfkzf1Mi3wKJXltnC9vcZ2kfPhCLPI76I726T81Nmbeq8fOmuF_R6R3Feh1kUrGxk76xIuioLHNSGDvaOG36YLPSwKNqOYb062MtAt5zqOQI1gjeKTSvJ84VTAF8lgLrZsasCAUHvtionukb-yni5kvW1BSI4feplXSAHGugy9f-T7MsIB5z0/s441/05-gitlab-ci.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_eMSneyUfkzf1Mi3wKJXltnC9vcZ2kfPhCLPI76I726T81Nmbeq8fOmuF_R6R3Feh1kUrGxk76xIuioLHNSGDvaOG36YLPSwKNqOYb062MtAt5zqOQI1gjeKTSvJ84VTAF8lgLrZsasCAUHvtionukb-yni5kvW1BSI4feplXSAHGugy9f-T7MsIB5z0/s600/05-gitlab-ci.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;i&gt;Variables&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Generic Variables used in all environments and environment specific variables to build software
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Rules that can be used to automate deployments to &quot;lower&quot; environments vs. Manual deployments
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
YAML that builds the Docker image and push image to container registry of the developer&#39;s choice
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
YAML that has instructions on how to deploy latest built Docker image to Kubernetes cluster
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/cicd/deploy/environments.yml&quot;&gt;environments.yml&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/cicd/templates/deployment-rules.yml&quot;&gt;deployment-rules.yml&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1vsDlaM52GnLHCHM6tmreKRAzvLTZB12aWlMJnZK-eC1vhQ-8TSt8QRU7o9QWXEATw1StKSZ2LguMjVNbD9p6lec48nahCxoX6Dl30KPSe7zpiI4GP8SIraj7mzHDZ9krLlct9x2oWpXT1hiRaida8nMye5UL-Rv6V-vun_KVhWfzdMsSafiUoiHiJbo/s689/06-environments.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1vsDlaM52GnLHCHM6tmreKRAzvLTZB12aWlMJnZK-eC1vhQ-8TSt8QRU7o9QWXEATw1StKSZ2LguMjVNbD9p6lec48nahCxoX6Dl30KPSe7zpiI4GP8SIraj7mzHDZ9krLlct9x2oWpXT1hiRaida8nMye5UL-Rv6V-vun_KVhWfzdMsSafiUoiHiJbo/s600/06-environments.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggNvWP1hSwIDkLlhSBdGanDlEF3ewbjay4Irz0wifIYRoUHS4R2spksccRjIJishN0q77DGLaBk5zVJmdJvCd79Z5RAl-6c_tRuMWul2dJ0J50hQg2JvtecF__tSPuvR8rNo5a0kl9j2rt7YDUj3nVa5dsAx9RcXmRuShIfmH0l9pV9Cl4_pDUP0AiKQs/s483/07-deployment-rules.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggNvWP1hSwIDkLlhSBdGanDlEF3ewbjay4Irz0wifIYRoUHS4R2spksccRjIJishN0q77DGLaBk5zVJmdJvCd79Z5RAl-6c_tRuMWul2dJ0J50hQg2JvtecF__tSPuvR8rNo5a0kl9j2rt7YDUj3nVa5dsAx9RcXmRuShIfmH0l9pV9Cl4_pDUP0AiKQs/s600/07-deployment-rules.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;i&gt;Artefacts&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
YAML files that contain Helm chart artefacts used like Deployment and Service YAML
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
YAML files that contain Values to be injected including environment specific variables
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/helm/templates/deployment.yaml&quot;&gt;deployment.yaml&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/helm/templates/service.yaml&quot;&gt;service.yaml&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj52aJLK_aTvke-VFYnD47_2mfGIRumEs0Y0uW3f_QaI2N5_3XGeyTnx_iFGNFkmlJF1IdkwVhNU-7SQTVt6wx4Nnf9a-9mfNh5fG-zZl9vAWVjctkUkPTSoxsA1Y-tfIuUJI-J06DlpuWmpPFynwM4Yre2Gwi0FvFKvTKEJvA4109K3ARPziN2WzN2_hE/s777/08-deployment.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; 
src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj52aJLK_aTvke-VFYnD47_2mfGIRumEs0Y0uW3f_QaI2N5_3XGeyTnx_iFGNFkmlJF1IdkwVhNU-7SQTVt6wx4Nnf9a-9mfNh5fG-zZl9vAWVjctkUkPTSoxsA1Y-tfIuUJI-J06DlpuWmpPFynwM4Yre2Gwi0FvFKvTKEJvA4109K3ARPziN2WzN2_hE/s600/08-deployment.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWmleL0XwjN_gJnA94UuuSlTPYozFce-zXdCD01E2PIwlUMRd5PsXRmR1AYIfUBf476d5AEaWHrVpHA81G47l8wcZ10YhyowISW5wlBmg1RHkWzA_P4dd0nqMUdCa9P8S18nBF3EyfdGucEFeQfVNizioySnhQS9I2-OBmvl14qCGsywBfkjzpFmxZ_Kc/s785/09-service.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWmleL0XwjN_gJnA94UuuSlTPYozFce-zXdCD01E2PIwlUMRd5PsXRmR1AYIfUBf476d5AEaWHrVpHA81G47l8wcZ10YhyowISW5wlBmg1RHkWzA_P4dd0nqMUdCa9P8S18nBF3EyfdGucEFeQfVNizioySnhQS9I2-OBmvl14qCGsywBfkjzpFmxZ_Kc/s600/09-service.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
NOTE: Hardcoded non-sensitive variables stored in &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/helm/values.yaml&quot;&gt;Values YAML&lt;/a&gt; files including all environment variables:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH1u2tCLZJiuzoVwLjYzRXniQbFjfwIatFPYi_-Yh0u22yECcsKkn46C8dfk4_zEhF0AWNAMSxIB1HerIaAOdR8VuxICndcxI9W06tfs8Ebqb1E3OVqcczOcoiUL3uKOwe6WQqPTBBLHXVRPcy21vHHnKZWp5EKKg6dWA3ObX21p6nr081pKDLWKNGvBE/s437/10-values.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH1u2tCLZJiuzoVwLjYzRXniQbFjfwIatFPYi_-Yh0u22yECcsKkn46C8dfk4_zEhF0AWNAMSxIB1HerIaAOdR8VuxICndcxI9W06tfs8Ebqb1E3OVqcczOcoiUL3uKOwe6WQqPTBBLHXVRPcy21vHHnKZWp5EKKg6dWA3ObX21p6nr081pKDLWKNGvBE/s600/10-values.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Whereas sensitive information is stored in Kubernetes secret resources and injected at deployment time.
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;GitFlow SDLC&lt;/b&gt;
&lt;br /&gt;
&lt;i&gt;Development&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
GitLab source code repo has main branch for all the Prod deployments
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
GitLab source code repo has develop branch as the integration branch
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
develop branch for feature development and deployment to DEV / UAT
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
GitFlow: ensure develop branch is stable: cut feature branch off develop
&lt;br /&gt;	
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
&lt;i&gt;Deployment&lt;/i&gt;  
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Submit Pull Request | Merge to develop branch | Trigger build
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Auto-deploy to DEV | Manual deploy to UAT [when QA ready]
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;i&gt;Testing&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Feature completed on DEV / preliminary testing on UAT cut release branch off develop
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Deploy release branch to UAT - complete feature testing and regression testing
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Any bugs on UAT in release candidate then cut bugfix branch off release branch
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Fix bug | Submit Pull Request | Merge to release branch | Re-deploy to UAT [manually]
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;i&gt;Release&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Once release candidate is stable / all bugs fixed: then submit Pull Request release branch to main
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
This action will build pipeline but NOT deploy!! Manually deploy to Prod when stakeholders agree!!
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1nb1mRvjWBSSpZzRVSDreAmIQ8HlJAcjJSTw5QBaS9VMgbRXl3VU7xEZ6WIbcvHbonF_-oRCGdrPuWdtnK3B36ld2rExt7bTBaffpVANldhWH_VSPXhMhhjgyGHBb_H3h6FoIZQKrZD0JGeem6r3mKXUrSBtNgsWigp0lWdTfivNkES9jydfuxcPNBWQ/s770/BuildPipelines.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1nb1mRvjWBSSpZzRVSDreAmIQ8HlJAcjJSTw5QBaS9VMgbRXl3VU7xEZ6WIbcvHbonF_-oRCGdrPuWdtnK3B36ld2rExt7bTBaffpVANldhWH_VSPXhMhhjgyGHBb_H3h6FoIZQKrZD0JGeem6r3mKXUrSBtNgsWigp0lWdTfivNkES9jydfuxcPNBWQ/s600/BuildPipelines.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Alignment&lt;/i&gt;  
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Finally, after deploy to Prod from main submit PR from main to develop for alignment
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Hotfixes available similar to bugfix | Cut hotfix branch from main and submit PR deploy to Prod
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
After hotfix merged to main and deployed to Prod submit PR from main to develop for alignment
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  

&lt;b&gt;Kubernetes Management: Rancher&lt;/b&gt;
&lt;br /&gt;
Q. What is Rancher?
&lt;br /&gt;
Open source platform that simplifies the deployment, scaling and management of your Kubernetes clusters:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Kubernetes: open source orchestration platform that automates management of containerized apps
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Rancher: open source container platform built on top of Kubernetes to simplify cluster management
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Download Kubernetes cluster configuration kubeconfig files from Rancher to connect to your clusters
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;b&gt;Kubernetes kubeconfig&lt;/b&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
kubeconfig file is YAML configuration used to connect to Kubernetes clusters, users and contexts
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Download DEV kubeconfig file from Rancher to localhost ~/.kube/dev-config
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Download UAT kubeconfig file from Rancher to localhost ~/.kube/uat-config
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
SETUP
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;# Setup the global KUBECONFIG environment variable
&amp;nbsp;&amp;nbsp;export KUBECONFIG=~/.kube/config:~/.kube/dev-config:~/.kube/uat-config
&amp;nbsp;&amp;nbsp;# Flatten multiple kubeconfig files into one &quot;master&quot; kubeconfig file
&amp;nbsp;&amp;nbsp;kubectl config view --flatten &gt; one-config.yaml
&amp;nbsp;&amp;nbsp;# Rename accordingly
&amp;nbsp;&amp;nbsp;mv one-config.yaml ~/.kube/config
&amp;nbsp;&amp;nbsp;# Confirm cluster configuration update
&amp;nbsp;&amp;nbsp;kubectl config get-contexts
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;b&gt;Deployment Verification&lt;/b&gt;
&lt;br /&gt;
Monitor cluster - What is &lt;a href=&quot;https://www.armosec.io/glossary/kubectl&quot;&gt;kubectl&lt;/a&gt;?
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Command line tool run commands against Kubernetes clusters - communicate using Kubernetes API
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Post-deployment use kubectl commands to verify the health of cluster ensuring all pods re-spawned
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;b&gt;TEST Deployment&lt;/b&gt;
&lt;br /&gt;
Finally, test endpoint(s) via curl or in Postman:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;# Test endpoint
&amp;nbsp;&amp;nbsp;kubectl port-forward service/flask-api-service 8080:80
&amp;nbsp;&amp;nbsp;curl http://localhost:8080/api/v1 --header &quot;Content-Type: application/json&quot;
&amp;nbsp;&amp;nbsp;# RESPONSE
&amp;nbsp;&amp;nbsp;{&quot;message&quot;: &quot;Hello World (Python)!&quot;}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;b&gt;CI/CD Pipeline Benefits&lt;/b&gt;
&lt;br /&gt;
&lt;a href=&quot;https://about.gitlab.com/blog/positive-outcomes-ci-cd&quot;&gt;Four Benefits of CI/CD&lt;/a&gt; - successful pipeline strategy helps your team deliver higher quality Software faster!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Increased speed of innovation + automation = deployments that are faster and more regular
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Code in Production adds immediate value instead of sat waiting in a deployment queue!
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Engineers become more productive instead of focus on boring / mundane manual tasks
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Higher code quality due to continuous automated build, test, deploy rinse + repeat cycles &lt;span style=&#39;font-family:Wingdings&#39;&gt;J&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have now highlighted the back story transitioning from the 1990s to modern day CI/CD and outlined the integration process with GitFlow SDLC to demonstrate Kubernetes CI/CD pipeline benefits!
&lt;br /&gt;&lt;br /&gt;

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2025/08/cloud-ci-cd-cheat-sheet-ii.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfdryn90ILEQjxlge0UqwMW56nzSHXLsRAkYD0iz3Kr0e3PbwLmRbdkn_FUgSn_pX43Y0SViVk1BDpb_bN9TYxrbtWENbO_A4uAHJLAqwrQ4z6hohhScg4NRV_ZCWZZBMS1AkFFY0Qlv7E9L7uQJr_9dFml5CaoXCwENAeF7My9r9k0mn7jW9Qc4l9Ovg/s72-c/GitLab.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-184175671522196856</guid><pubDate>Thu, 31 Jul 2025 08:00:00 +0000</pubDate><atom:updated>2025-07-31T01:00:18.155-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Cloud</category><title>Cloud CI-CD Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

In 2024, we checked out &lt;a href=&quot;https://steveproxna.blogspot.com/2024/07/gitlab-cheat-sheet.html&quot;&gt;GitLab Cheat Sheet&lt;/a&gt; to streamline collaborative workflow and then leverage CI/CD pipelines.  However, it is interesting to tell the back story how we got from the 1990s to modern day CI/CD.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiCj481fVWFMoyO-kJkFBrGdOjK9cBzwTv4jHVtJbYgpy4KzOh0Hidn576NTY2osFPoCGxU96leIaS1c23MdpIZxqxK4fJspudZa3g_zU9tQa_v31dotCWdBjC7t9VafujVUPF0zsQJpkNyMNfetqOz5ETqmxE6so8hqD7qpYMbINxw7uzi4Td9rsDP=s364&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiCj481fVWFMoyO-kJkFBrGdOjK9cBzwTv4jHVtJbYgpy4KzOh0Hidn576NTY2osFPoCGxU96leIaS1c23MdpIZxqxK4fJspudZa3g_zU9tQa_v31dotCWdBjC7t9VafujVUPF0zsQJpkNyMNfetqOz5ETqmxE6so8hqD7qpYMbINxw7uzi4Td9rsDP=s600&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out! 
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;Evolution of SoftwareDeployment: Physical Servers to Container Orchestration&lt;/u&gt;
&lt;br /&gt;&lt;br /&gt;

&lt;b&gt;Era of Physical Servers: 1990s and Before&lt;/b&gt;
&lt;br /&gt;
Back in the 1990s Software was predominantly deployed directly onto physical servers, many often housed in on-premises data centers.  Each server typically dedicated to specific application [or set of applications].
&lt;br /&gt;&lt;br /&gt;
  
Challenges: Scalability, Isolation, Resource Utilization
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;involved procuring, setting up, deploying to additional physical servers = time consuming + expensive
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;multiple apps could interfer with one another leading to system crashes or other performance issues
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;some servers underutilized while others overwhelmed which meant inefficient resource distribution
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Dawn of Virtualization: 2000s&lt;/b&gt;
&lt;br /&gt;
  
Introduction of virtualization technologies like those provided by VMware allowed Virtual Machines [VMs] to each run a physical server which meant each VM operating as though it were on own dedicated hardware.
  
&lt;br /&gt;&lt;br /&gt;
Benefits: Resource Efficiency, Isolation, Snapshot + Cloning
&lt;br /&gt;
  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
multiple VMs could share resources of single server leading to better resource utilization
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
VMs provide new level of isolation btwn apps = failure of one VM did not affect other VM
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
VM state could be saved + cloned making it easier to replicate environments for scaling
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Containerization: Rise of Docker&lt;/b&gt;
&lt;br /&gt;
  
Next significant shift was containerization with Docker at the forefront.  Unlike VMs, containers share host OS running in isolated User space which is lightweight and portable and can startup / shutdown more rapidly.
  
&lt;br /&gt;&lt;br /&gt;
Advantages: Speed, Portability, Density
&lt;br /&gt;
  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
containers start almost instantly i.e. applications launched and scaled in only a matter of seconds
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
container images are consistent across environments = it works on my machine issues minimized
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
lightweight nature = many containers run on host machine = better resource utilization than VMs
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
  
&lt;b&gt;Container Orchestration: Enter Kubernetes&lt;/b&gt;
&lt;br /&gt;
  
Increased container adoption prompted the need for container orchestration technologies like Kubernetes to
manage scale and monitor containerized applications especially those hosted by managed Cloud providers.
  
&lt;br /&gt;&lt;br /&gt;
Functions: Auto-scaling, Self-healing, Load Balancing, Service Discovery
&lt;br /&gt;
  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
orchestration systems can automatically scale apps based on denamd or sudden traffic spikes
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
if container or node fails then the orchestrator can restart or replace it = increased reliability!
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
incoming requests are automatically distributed across containers ensure optimal performance  
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
as containers move across nodes, services can be discovered without any manual intervention
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Summary of Definitions&lt;/b&gt;
&lt;br /&gt;
  
&lt;i&gt;Docker&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Platform as a Service product that uses OS-level virtualization Software in packages as containers
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Containers are isolated from one another bundle their own software, libraries, and configurations
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
All containers share signle OS kernel on host thus use fewer resources than Virtual Machines
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;i&gt;Kubernetes&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Open-source container orchestration system automating app deployment, scaling and management
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Runs containerized applications in cluster host machines from containers typically built using Docker
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
  
&lt;i&gt;Helm&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Kubernetes package manager simplifies managing and deploying applications to clusters via &quot;Charts&quot;
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Helm facilitates configuration separated out in Values files and scaled out across all environments
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Summary of Technology&lt;/b&gt;
&lt;br /&gt;
  
&lt;i&gt;Docker&lt;/i&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Dockerfile
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Image
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Container

&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;text file that contains all commands used to assemble a Docker image template
&lt;br /&gt;
&amp;nbsp;executable package that includes code, runtime, environment variables and config
&lt;br /&gt;
&amp;nbsp;running instance of a Docker image isolated from other processes running on host
&lt;/td&gt;
  
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;i&gt;Kubernetes&lt;/i&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Namespace
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Workload
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Pod
&lt;br /&gt;  
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Node
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Replicaset
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Deployment
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Service
&lt;br /&gt;
  
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;scope cluster resources and a way to isolate Kubernetes objects
&lt;br /&gt;
&amp;nbsp;containerized application running within the Kubernetes cluster
&lt;br /&gt;
&amp;nbsp;smallest deployable unit as created and managed in Kubernetes
&lt;br /&gt;
&amp;nbsp;workloads are placed in Containers on Pods to be run on Nodes
&lt;br /&gt;
&amp;nbsp;maintains a stable set of replica pods available running any time
&lt;br /&gt;
&amp;nbsp;provide a declarative way to update all Pods and Replicasets
&lt;br /&gt;
&amp;nbsp;abstract way to expose an application running on a set of Pods
&lt;br /&gt; 
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;DEMO Hello World&lt;/b&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Execute code on localhost [IDE]
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Build Docker image and locally
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Provision local Kubernetes cluster
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;TEST after deployment
&lt;br /&gt;
&amp;nbsp;curl http://localhost:8080
&lt;br /&gt;
&amp;nbsp;Hello World
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Python &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/main.py&quot;&gt;Flask API&lt;/a&gt; application:
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMs6w7krE1IcMTs3R-WJf-cBhoLiewJ1vO4ceQ8n8xOgiSSoiHdNWKm79t5aq3F4es0Z4TLaGdMs0PZNU6AT_z0f8alN_qRmQwMGOGYBEBZpR7A5Tx2u6ZblvTcoGKr9oFlw6EscT5pwika3j5SoOn7EiOMwDnUcPNqYgMUQYixdpVvJkhR53j6mpNkH0/s788/01-wsgi.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMs6w7krE1IcMTs3R-WJf-cBhoLiewJ1vO4ceQ8n8xOgiSSoiHdNWKm79t5aq3F4es0Z4TLaGdMs0PZNU6AT_z0f8alN_qRmQwMGOGYBEBZpR7A5Tx2u6ZblvTcoGKr9oFlw6EscT5pwika3j5SoOn7EiOMwDnUcPNqYgMUQYixdpVvJkhR53j6mpNkH0/s600/01-wsgi.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;DEMO Docker Commands&lt;/b&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;# Create KinD cluster
&amp;nbsp;&amp;nbsp;kind create cluster --name flask-cluster
&amp;nbsp;&amp;nbsp;# Create Dockerfile | Build Docker image
&amp;nbsp;&amp;nbsp;docker buiild --pull -rm -f &quot;Dockerfile&quot; -t flask-api:latest &quot;.&quot;
&amp;nbsp;&amp;nbsp;# Execute Docker container
&amp;nbsp;&amp;nbsp;docker run --rm -d -p 8080:8080/tcp flask-api:latest
&amp;nbsp;&amp;nbsp;# Test endpoint
&amp;nbsp;&amp;nbsp;curl http://localhost:8080
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/Dockerfile&quot;&gt;Dockerfile&lt;/a&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjakeZFuu4lA7D_aUMew50WNgv2cweAq7OZ1TNsgY2H_gDQQbz94Xt3btADcDMl1Lu3jUCBZ837DffBeWKnY3KAp2jHN7TY3DW9EakCtUpBpKBg-qJnLjkFdyYKHyTL1ZcPzW7R4MuiT0DjSFbB4_TF9sDt4QpwDsGfkQtNH_3y8vlBxAwk0WBoHlgmhj0/s619/02-Dockerfile.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; 
src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjakeZFuu4lA7D_aUMew50WNgv2cweAq7OZ1TNsgY2H_gDQQbz94Xt3btADcDMl1Lu3jUCBZ837DffBeWKnY3KAp2jHN7TY3DW9EakCtUpBpKBg-qJnLjkFdyYKHyTL1ZcPzW7R4MuiT0DjSFbB4_TF9sDt4QpwDsGfkQtNH_3y8vlBxAwk0WBoHlgmhj0/s600/02-Dockerfile.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
KinD = Kubernetes in Docker is a tool for running local Kubernetes cluster using Docker container &quot;nodes&quot;.
&lt;br /&gt;
&lt;br /&gt;  

&lt;b&gt;DEMO Kubernetes Commands&lt;/b&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;# Load image into KinD cluster
&amp;nbsp;&amp;nbsp;kind load docker-image flask-api:latest --name flask-cluster
&amp;nbsp;&amp;nbsp;# Setup KinD cluster
&amp;nbsp;&amp;nbsp;kubectl create ns test-ns
&amp;nbsp;&amp;nbsp;kubectl config set-context --current --namespace=test-ns
&amp;nbsp;&amp;nbsp;# Rollout Kubernetes Deployment and Service resources
&amp;nbsp;&amp;nbsp;kubectl apply -f Kubernetes.yaml
&amp;nbsp;&amp;nbsp;# Test endpoint
&amp;nbsp;&amp;nbsp;curl http://localhost:8080
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/Kubernetes.yaml&quot;&gt;Kubernetes.yaml&lt;/a&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxjgxrXiMc5mPxGRMJqvLAcDQZ_yvYa-snzbVENPze51HOjUem8oznnuv5zq3UZprfqUF42-PeFjKGV_SMkyYEqqqc5xSWhZoDF2tT6hWxYMLgp6yEJHNyoTcwObPNXR_T3LYcOmL_bD3xKsVz9vQZHS4BXj7LzMffLp3QqLwVv9Ilb6T_6dguEP_4Oy0/s589/03-deployment.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;100%&quot; width=&quot;98%&quot;
src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxjgxrXiMc5mPxGRMJqvLAcDQZ_yvYa-snzbVENPze51HOjUem8oznnuv5zq3UZprfqUF42-PeFjKGV_SMkyYEqqqc5xSWhZoDF2tT6hWxYMLgp6yEJHNyoTcwObPNXR_T3LYcOmL_bD3xKsVz9vQZHS4BXj7LzMffLp3QqLwVv9Ilb6T_6dguEP_4Oy0/s600/03-deployment.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhgjWwOGYUsKDIjFiirZ9OLOfSLtPbPvmkYrh2usBSVcdzam_ZkzAbsOelvPqVCUXxNhKSRc9fEkND1g2dMY31V6ONub8g5ZywqO7zaFPJvbPju4mFo_BT493hIpu9yPcw40nGieInn8f5-1TFUvY_K6nyus46ksf9RCAn7_OCFIvZUlrXtEVyMfXRI2E/s346/04-service.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;100%&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhgjWwOGYUsKDIjFiirZ9OLOfSLtPbPvmkYrh2usBSVcdzam_ZkzAbsOelvPqVCUXxNhKSRc9fEkND1g2dMY31V6ONub8g5ZywqO7zaFPJvbPju4mFo_BT493hIpu9yPcw40nGieInn8f5-1TFUvY_K6nyus46ksf9RCAn7_OCFIvZUlrXtEVyMfXRI2E/s600/04-service.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;b&gt;LIMITATIONS&lt;/b&gt;
&lt;br /&gt;
DEMO Hello World is sufficient to demonstrate the process on localhost but has many real world limitations!
&lt;br /&gt;&lt;br /&gt;

&lt;i&gt;Limitations&lt;/i&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Everything is on localhost - Cloud Computing typically requires Kubernetes cluster(s)
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Manually build Docker image from the Dockerfile
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Manually push Docker image to container registry
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Manually deploy running Docker container into Kubernetes cluster [Deployment exposed as Service]
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
All Kubernetes resource values are hardcoded into declarative YAML file [Deployment and a Service]
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
No facility to scale deployment across multiple environments: DEV, IQA, UAT, Prod
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
Environment variables can be injected but is very brittle and cumbersome process
&lt;br /&gt;
&amp;nbsp;&lt;span style=&quot;font-family: &#39;Wingdings&#39;;&quot;&gt;•&lt;/span&gt;&amp;nbsp;
No real immediate and secure way to inject secret information into deployment [secret password]
&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
  
&lt;i&gt;Solution&lt;/i&gt;
&lt;br /&gt;
Next step is to integrate GitLab CI/CD pipeline to solve these issues and automate build deployment process!
  
&lt;br /&gt;
This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2025/08/cloud-ci-cd-cheat-sheet-ii.html&quot;&gt;post&lt;/a&gt;.

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2025/07/cloud-ci-cd-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEiCj481fVWFMoyO-kJkFBrGdOjK9cBzwTv4jHVtJbYgpy4KzOh0Hidn576NTY2osFPoCGxU96leIaS1c23MdpIZxqxK4fJspudZa3g_zU9tQa_v31dotCWdBjC7t9VafujVUPF0zsQJpkNyMNfetqOz5ETqmxE6so8hqD7qpYMbINxw7uzi4Td9rsDP=s72-c" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-5846049652941068976</guid><pubDate>Mon, 02 Jun 2025 08:30:00 +0000</pubDate><atom:updated>2025-06-02T09:16:07.623-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Cloud</category><title>Cloud Setup Cheat Sheet II</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
  
In the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2025/05/cloud-setup-cheat-sheet.html&quot;&gt;post&lt;/a&gt;, we checked out Cloud Cheat Sheet to explain cluster provisioning process for managed cloud providers such as &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/aks&quot;&gt;Azure AKS&lt;/a&gt;.  Now we will resume to provision clusters: &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html&quot;&gt;Amazon EKS&lt;/a&gt; and &lt;a href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview&quot;&gt;Google GKE&lt;/a&gt;.
&lt;br /&gt;

&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUI-Hum7q-EyAT3L3whtJaWaGNSvQ3qf5PqgxKaqUBJz4pZEB8sKgRI2pt5cdm6lL02V7x2VEndOXpLOuxrEk2RVl6WridZfmrbme58oiKCY9zlTQE7dkweQn7LPeF5Bin5r45mdPfaInFicH27SAlEIsU-kXNMbFegcUCCpD8iQDlgnZUD3A56HVKvPA/s1280/Azure.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUI-Hum7q-EyAT3L3whtJaWaGNSvQ3qf5PqgxKaqUBJz4pZEB8sKgRI2pt5cdm6lL02V7x2VEndOXpLOuxrEk2RVl6WridZfmrbme58oiKCY9zlTQE7dkweQn7LPeF5Bin5r45mdPfaInFicH27SAlEIsU-kXNMbFegcUCCpD8iQDlgnZUD3A56HVKvPA/s600/Azure.png&quot;/&gt;&lt;/a&gt;         
&lt;/td&gt;  
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqDmLhoOxuMdAnFLK9eik1f36eOoDYnl4wp7kzZlVeOCD5_5cbEaUCewRcsUObBQ5JZ1rpes4JsHnOLYw-_g6J1hdLPUbU8IzLC56jPyN-po_FL1qQq-lzDFzv2h5d_cWen-Q4e7ZUyRLZurjuqyJagWlupWX5hcqU4W7z6k-hIqQhZ2F2JwZpI6TJEKE/s1280/AWS_org.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqDmLhoOxuMdAnFLK9eik1f36eOoDYnl4wp7kzZlVeOCD5_5cbEaUCewRcsUObBQ5JZ1rpes4JsHnOLYw-_g6J1hdLPUbU8IzLC56jPyN-po_FL1qQq-lzDFzv2h5d_cWen-Q4e7ZUyRLZurjuqyJagWlupWX5hcqU4W7z6k-hIqQhZ2F2JwZpI6TJEKE/s600/AWS_org.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLxxk1qQND-5_PHqUZY5uHTzic9Tefp3d6FJO5vOmYnbLP0xTXG0zujtNUMryHyiwEe6QJp4NLhKyrgy4KjkGa6KBLcLFw4b8cim2ip_Blm_ayiN-tO2CcinheHDNt3pEFNIjOfajAzeQCqe6PXLC-NOdFvsulPJ7dLdVstTUKiZmyhDCCZlul37sa9DY/s1280/GCP_org.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLxxk1qQND-5_PHqUZY5uHTzic9Tefp3d6FJO5vOmYnbLP0xTXG0zujtNUMryHyiwEe6QJp4NLhKyrgy4KjkGa6KBLcLFw4b8cim2ip_Blm_ayiN-tO2CcinheHDNt3pEFNIjOfajAzeQCqe6PXLC-NOdFvsulPJ7dLdVstTUKiZmyhDCCZlul37sa9DY/s600/GCP_org.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

Let&#39;s check it out!  
&lt;br /&gt;
&lt;br /&gt;

&lt;u&gt;Pre-Requisites&lt;/u&gt;&lt;br /&gt;
This blog post assumes an &lt;a href=&quot;https://portal.azure.com&quot;&gt;Azure&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com&quot;&gt;AWS&lt;/a&gt;, &lt;a href=&quot;https://console.cloud.google.com&quot;&gt;GCP&lt;/a&gt; account is &lt;a href=&quot;https://steveproxna.blogspot.com/2025/05/cloud-setup-cheat-sheet.html&quot;&gt;setup&lt;/a&gt; plus all the corresponding &lt;a href=&quot;https://seroter.com/2020/09/15/lets-compare-the-cli-experiences-offered-by-aws-microsoft-azure-and-google-cloud-platform&quot;&gt;CLIs&lt;/a&gt; are configured!

&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;AWS Login&lt;/u&gt;&lt;br /&gt;
Navigate to &lt;a href=&quot;https://aws.amazon.com&quot;&gt;https://aws.amazon.com&lt;/a&gt; | Sign In | Sign in using root user email.  Root user | Root user email address e.g.
steven_boland@hotmail.com | Next | Enter password.  Setup AWS Multi-Factor &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa.html&quot;&gt;Authentication&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
  
&lt;u&gt;AWS Single Sign On&lt;/u&gt;&lt;br /&gt;
Accessing AWS clusters programmatically is recommened to &lt;a href=&quot;https://pushkar-sre.medium.com/how-to-set-up-aws-cli-with-aws-single-sign-on-sso-acf4dd88e056&quot;&gt;setup&lt;/a&gt; and configure AWS SSO.  Example config:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;sso_start_url = https://stevepro.awsapps.com/start
&amp;nbsp;&amp;nbsp;sso_region = eu-west-1
&amp;nbsp;&amp;nbsp;sso_account_id = 4xxxxxxxxxx8
&amp;nbsp;&amp;nbsp;sso_role_name = AdministratorAccess
&amp;nbsp;&amp;nbsp;region = eu-west-1
&amp;nbsp;&amp;nbsp;output = json
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
  
&lt;a href=&quot;https://eksctl.io&quot;&gt;eksctl&lt;/a&gt;&lt;br /&gt;
Command-line tool that abstracts complexity involved in setting up AWS EKS clusters.  Here is how to install:
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Linux&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;curl --silent --location &quot;https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$(uname &lt;br /&gt;&amp;nbsp;-s)_amd64.tar.gz&quot; | tar xz -C /tmp&lt;br /&gt;
&amp;nbsp;sudo mv /tmp/eksctl /usr/local/bin&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Mac OS/X&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;brew tap eksctl-io/eksctl&lt;/td&gt;
&lt;td&gt;&amp;nbsp;brew install eksctl&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Windows&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;Launch Powershell&lt;/td&gt;
&lt;td&gt;&amp;nbsp;choco install eksctl&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;u&gt;Master Key&lt;/u&gt;&lt;br /&gt;
Next, create master SSH key for secure, automated and controlled access to your Kubernetes infrastructure:
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;60%&quot;&gt;
&amp;nbsp;cd ~/.ssh&lt;br /&gt;
&amp;nbsp;ssh-keygen -t rsa -b 4096 -N &#39;&#39; -f master_ssh_key&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;eval $(ssh-agent -s)&lt;br /&gt;
&amp;nbsp;ssh-add master_ssh_key&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html&quot;&gt;Amazon EKS&lt;/a&gt;&lt;br /&gt;
Amazon provides Elastic Kubernetes Service as a fully managed Kubernetes container orchestration service.  Follow all instructions below in order to provision a Kubernetes cluster and test its functionality end-to-end.
Download code sample &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/CloudTesting/tree/main/CloudSetupCheatSheetII/stevepro-awseks&quot;&gt;here&lt;/a&gt;&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;

Pre-Requisites
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;aws sso login
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Check Resources&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&amp;nbsp;aws ec2 describe-instances --query &#39;Reservations[*].Instances[*].InstanceId&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws ec2 describe-addresses --query &#39;Addresses[*].PublicIp&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws ec2 describe-key-pairs --query &#39;KeyPairs[*].KeyName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws ec2 describe-volumes --query &#39;Volumes[*].VolumeId&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws ec2 describe-vpcs --query &#39;Vpcs[*].VpcId&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws cloudformation list-stacks --query &#39;StackSummaries[*].StackName&#39; --output table&lt;br /&gt;  
&amp;nbsp;&amp;nbsp;aws cloudwatch describe-alarms --query &#39;MetricAlarms[*].AlarmName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws ecr describe-repositories --query &#39;repositories[*].repositoryName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws ecs list-clusters --query &#39;clusterArns&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws eks list-clusters --query &#39;clusters&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws elasticbeanstalk describe-environments --query &#39;Environments[*].EnvironmentName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws elb describe-load-balancers --query &#39;LoadBalancerDescriptions[*].LoadBalancerName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws elbv2 describe-load-balancers --query &#39;LoadBalancers[*].LoadBalancerName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws iam list-roles --query &#39;Roles[*].RoleName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws iam list-users --query &#39;Users[*].UserName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws lambda list-functions --query &#39;Functions[*].FunctionName&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws rds describe-db-instances --query &#39;DBInstances[*].DBInstanceIdentifier&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws route53 list-hosted-zones --query &#39;HostedZones[*].Name&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws s3 ls&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws sns list-topics --query &#39;Topics[*].TopicArn&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws sqs list-queues --query &#39;QueueUrls&#39; --output table&lt;br /&gt;
&amp;nbsp;&amp;nbsp;aws ssm describe-parameters --query &#39;Parameters[*].Name&#39; --output table&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Cluster YAML&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kind: ClusterConfig
&amp;nbsp;&amp;nbsp;apiVersion: eksctl.io/v1alpha5
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;metadata:
&amp;nbsp;&amp;nbsp;  name: stevepro-aws-eks
&amp;nbsp;&amp;nbsp;  region: eu-west-1
&amp;nbsp;&amp;nbsp;  version: &quot;1.27&quot;
&amp;nbsp;&amp;nbsp;  tags:
&amp;nbsp;&amp;nbsp;    createdBy: stevepro
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;kubernetesNetworkConfig:
&amp;nbsp;&amp;nbsp;  ipFamily: IPv4
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;iam:
&amp;nbsp;&amp;nbsp;  withOIDC: true
&amp;nbsp;&amp;nbsp;  serviceAccounts:
&amp;nbsp;&amp;nbsp;  - metadata:
&amp;nbsp;&amp;nbsp;      name: ebs-csi-controller-sa
&amp;nbsp;&amp;nbsp;      namespace: kube-system
&amp;nbsp;&amp;nbsp;    attachPolicyARNs:
&amp;nbsp;&amp;nbsp;    - &quot;arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy&quot;
&amp;nbsp;&amp;nbsp;    roleOnly: true
&amp;nbsp;&amp;nbsp;    roleName: stevepro-aws-eks-AmazonEKS_EBS_CSI_DriverRole
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;addons:
&amp;nbsp;&amp;nbsp;- name: aws-ebs-csi-driver
&amp;nbsp;&amp;nbsp;  version: v1.38.1-eksbuild.2
&amp;nbsp;&amp;nbsp;  serviceAccountRoleARN: \
&amp;nbsp;&amp;nbsp;	arn:aws:iam::4xxxxxxxxxx8:role/stevepro-aws-eks-AmazonEKS_EBS_CSI_DriverRole
&amp;nbsp;&amp;nbsp;- name: vpc-cni
&amp;nbsp;&amp;nbsp;  version: v1.19.2-eksbuild.1
&amp;nbsp;&amp;nbsp;- name: coredns
&amp;nbsp;&amp;nbsp;  version: v1.10.1-eksbuild.18
&amp;nbsp;&amp;nbsp;- name: kube-proxy
&amp;nbsp;&amp;nbsp;  version: v1.27.16-eksbuild.14
&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;nodeGroups:
&amp;nbsp;&amp;nbsp;  - name: stevepro-aws-eks
&amp;nbsp;&amp;nbsp;    instanceType: m5.large
&amp;nbsp;&amp;nbsp;    desiredCapacity: 0
&amp;nbsp;&amp;nbsp;    minSize: 0
&amp;nbsp;&amp;nbsp;    maxSize: 3
&amp;nbsp;&amp;nbsp;    ssh:
&amp;nbsp;&amp;nbsp;      allow: true
&amp;nbsp;&amp;nbsp;      publicKeyPath: ~/.ssh/master_ssh_key.pub
&amp;nbsp;&amp;nbsp;    preBootstrapCommands:
&amp;nbsp;&amp;nbsp;      - &quot;true&quot;
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Create Cluster&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;eksctl create cluster -f ~/stevepro-awseks/cluster.yaml          \
&amp;nbsp;    --kubeconfig ~/stevepro-awseks/kubeconfig                     \
&amp;nbsp;    --verbose 5
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Scale Nodegroup&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;eksctl scale nodegroup                                           \
&amp;nbsp;    --cluster=stevepro-aws-eks                                    \
&amp;nbsp;    --name=stevepro-aws-eks                                       \
&amp;nbsp;    --nodes=3                                                     \
&amp;nbsp;    --nodes-min=0                                                 \
&amp;nbsp;    --nodes-max=3                                                 \
&amp;nbsp;    --verbose 5
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Deploy Test&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kubectl create ns test-ns
&amp;nbsp;&amp;nbsp;kubectl config set-context --current --namespace=test-ns
&amp;nbsp;&amp;nbsp;kubectl apply -f Kubernetes.yaml
&amp;nbsp;&amp;nbsp;kubectl port-forward service/flask-api-service 8080:80
&amp;nbsp;&amp;nbsp;curl http://localhost:8080
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Output&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;Hello World (Python)!
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Shell into Node&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kubectl get po -o wide
&amp;nbsp;&amp;nbsp;cd ~/.ssh
&amp;nbsp;&amp;nbsp;ssh -i master_ssh_key ec2-user@node-ip-address
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Cleanup&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kubectl delete -f Kubernetes.yaml
&amp;nbsp;&amp;nbsp;kubectl delete ns test-ns
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Delete Cluster&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;eksctl delete cluster                                            \
&amp;nbsp;    --name=stevepro-aws-eks                                       \
&amp;nbsp;    --region eu-west-1                                            \
&amp;nbsp;    --force
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;ERRORS&lt;/b&gt;&lt;br /&gt;
&lt;i&gt;Error: getting availability zones for region operation error EC2: DescribeAvailabilityZones, StatusCode: 403&lt;/i&gt;
&lt;br /&gt;
&lt;a href=&quot;https://stackoverflow.com/questions/60438285/error-getting-availability-zones-when-trying-to-create-eks-cluster&quot;&gt;Reference&lt;/a&gt;: Dashboard | IAM | Users | SteveProXNA | Permissions | Add Permission | AdministratorAccess:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;    &quot;Version&quot;: &quot;2012-10-17&quot;,
&amp;nbsp;    &quot;Statement&quot;: [
&amp;nbsp;        {
&amp;nbsp;            &quot;Effect&quot;: &quot;Allow&quot;,
&amp;nbsp;            &quot;Action&quot;: &quot;*&quot;,
&amp;nbsp;            &quot;Resource&quot;: &quot;*&quot;
&amp;nbsp;        }
&amp;nbsp;    ]
&amp;nbsp;&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;i&gt;Error:  unable to determine AMI from SSM Parameter Store: operation SSM: GetParameter, StatusCode: 400&lt;/i&gt;
&lt;br /&gt;
AWS Dashboard | IAM | Users | SteveProXNA | Create new group | Permission | AdministratorAccess-Amplify
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;    &quot;Version&quot;: &quot;2012-10-17&quot;,
&amp;nbsp;    &quot;Statement&quot;: [
&amp;nbsp;        {
&amp;nbsp;            &quot;Effect&quot;: &quot;Allow&quot;,
&amp;nbsp;            &quot;Action&quot;: ],
&amp;nbsp;                &quot;ssm:GetParameter&quot;,
&amp;nbsp;                &quot;ssm:GetParameters&quot;
&amp;nbsp;            ],
&amp;nbsp;            &quot;Resource&quot;: &quot;arn:aws:ssm:*:*:parameter/aws/service/eks/optimized-ami/*&quot;
&amp;nbsp;        },
&amp;nbsp;        {
&amp;nbsp;            &quot;Effect&quot;: &quot;Allow&quot;,
&amp;nbsp;            &quot;Action&quot;: &quot;ec2:DescribeImages&quot;,
&amp;nbsp;            &quot;Resource&quot;: &quot;*&quot;
&amp;nbsp;        }
&amp;nbsp;    ]
&amp;nbsp;&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;a href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview&quot;&gt;Google GKE&lt;/a&gt;&lt;br /&gt;
Google provides the Google Kubernetes Engine as fully managed Kubernetes container orchestration service.  Follow all instructions below in order to provision a Kubernetes cluster and test its functionality end-to-end.
&lt;br /&gt;
Download code sample &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/CloudTesting/tree/main/CloudSetupCheatSheetII/stevepro-gcpgke&quot;&gt;here&lt;/a&gt;&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;Pre-Requisites&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&amp;nbsp;gcloud auth login&lt;br /&gt;
&amp;nbsp;&amp;nbsp;gcloud auth application-default login&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&amp;nbsp;gcloud auth configure-docker&lt;br /&gt;
&amp;nbsp;&amp;nbsp;gcloud config set project SteveProProject&lt;br /&gt;
&lt;/td&gt;  
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Check Resources&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&amp;nbsp;gcloud compute instances list&lt;br /&gt;
&amp;nbsp;&amp;nbsp;gcloud compute disks list&lt;br /&gt;
&amp;nbsp;&amp;nbsp;gcloud compute forwarding-rules list&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;&amp;nbsp;gcloud compute firewall-rules list&lt;br /&gt;
&amp;nbsp;&amp;nbsp;gcloud compute addresses list&lt;br /&gt;
&amp;nbsp;&amp;nbsp;gcloud container clusters list&lt;br /&gt;
&lt;/td&gt;  
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Create Cluster&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;gcloud container clusters create stevepro-gcp-gke               \
&amp;nbsp;    --project=steveproproject                                     \
&amp;nbsp;    --zone europe-west1-b                                         \
&amp;nbsp;    --machine-type=e2-standard-2                                  \
&amp;nbsp;    --disk-type pd-standard                                       \
&amp;nbsp;    --cluster-version=1.30.10-gke.1070000                         \
&amp;nbsp;    --num-nodes 3                                                 \
&amp;nbsp;    --network=default                                             \
&amp;nbsp;    --create-subnetwork=name=stevepro-gcp-gke-subnet,range=/28    \
&amp;nbsp;    --enable-ip-alias                                             \
&amp;nbsp;    --enable-intra-node-visibility                                \
&amp;nbsp;    --logging=NONE                                                \
&amp;nbsp;    --monitoring=NONE                                             \
&amp;nbsp;    --enable-network-policy                                       \
&amp;nbsp;    --labels=prefix=stevepro-gcp-gke,created-by=${USER}           \
&amp;nbsp;    --no-enable-managed-prometheus                                \
&amp;nbsp;    --quiet --verbosity debug
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Get Credentials&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;gcloud container clusters get-credentials stevepro-gcp-gke       \
&amp;nbsp;    --zone=europe-west1-b                                         \
&amp;nbsp;    --quiet --verbosity debug
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

IMPORTANT - if you do not have the following &lt;i&gt;gke gcloud auth plugin&lt;/i&gt; then execute the following commands:
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;gcloud components install gke-gcloud-auth-plugin
&amp;nbsp;&amp;nbsp;gke-gcloud-auth-plugin --version
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Deploy Test&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kubectl create ns test-ns
&amp;nbsp;&amp;nbsp;kubectl config set-context --current --namespace=test-ns
&amp;nbsp;&amp;nbsp;kubectl apply -f Kubernetes.yaml
&amp;nbsp;&amp;nbsp;kubectl port-forward service/flask-api-service 8080:80
&amp;nbsp;&amp;nbsp;curl http://localhost:8080
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Output&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;Hello World (Python)!
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Shell into Node&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;mkdir -p ~/GitHub/luksa
&amp;nbsp;&amp;nbsp;cd ~/GitHub/luksa
&amp;nbsp;&amp;nbsp;git clone https://github.com/luksa/kubectl-plugins.git
&amp;nbsp;&amp;nbsp;cd kubectl-plugins
&amp;nbsp;&amp;nbsp;chmod +x kubectl-ssh
&amp;nbsp;&amp;nbsp;kubectl get nodes
&amp;nbsp;&amp;nbsp;./kubectl-ssh node gke-stevepro-gcp-gke-default-pool-0b4ca8ca-sjpj
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Cleanup&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kubectl delete -f Kubernetes.yaml
&amp;nbsp;&amp;nbsp;kubectl delete ns test-ns
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Delete Cluster&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;gcloud container clusters delete stevepro-gcp-gke                \
&amp;nbsp;    --zone europe-west1-border                                    \
&amp;nbsp;    --quiet --verbosity debug
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have now setup and provisioned &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/aks&quot;&gt;Azure AKS&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html&quot;&gt;Amazon EKS&lt;/a&gt; and &lt;a href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview&quot;&gt;Google GKE&lt;/a&gt; clusters with end-to-end tests.  In future we could explore provisioning AWS and GCP &lt;a href=&quot;https://kubernetes.io/docs/reference/setup-tools/kubeadm&quot;&gt;Kubeadm&lt;/a&gt; clusters using &lt;a href=&quot;https://rangapv.medium.com/terraform-scripts-to-create-a-k8s-cluster-using-kubeadm-in-aws-from-scratch-72fba6133797&quot;&gt;Terraform&lt;/a&gt;!

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2025/06/cloud-setup-cheat-sheet-ii.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUI-Hum7q-EyAT3L3whtJaWaGNSvQ3qf5PqgxKaqUBJz4pZEB8sKgRI2pt5cdm6lL02V7x2VEndOXpLOuxrEk2RVl6WridZfmrbme58oiKCY9zlTQE7dkweQn7LPeF5Bin5r45mdPfaInFicH27SAlEIsU-kXNMbFegcUCCpD8iQDlgnZUD3A56HVKvPA/s72-c/Azure.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-3477814433471183346</guid><pubDate>Mon, 05 May 2025 08:30:00 +0000</pubDate><atom:updated>2025-05-05T01:30:36.140-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Cloud</category><title>Cloud Setup Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
  
In 2024, we checked out &lt;a href=&quot;https://steveproxna.blogspot.com/2024/07/gitlab-cheat-sheet.html&quot;&gt;GitLab Cheat Sheet&lt;/a&gt; to streamline collaborative team workflows that leverage CI/CD pipelines.  Now, we will explain cluster provisioning process for managed cloud providers: &lt;a href=&quot;https://portal.azure.com&quot;&gt;Azure&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com&quot;&gt;AWS&lt;/a&gt; + &lt;a href=&quot;https://console.cloud.google.com&quot;&gt;GCP&lt;/a&gt;.
&lt;br /&gt;

&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUI-Hum7q-EyAT3L3whtJaWaGNSvQ3qf5PqgxKaqUBJz4pZEB8sKgRI2pt5cdm6lL02V7x2VEndOXpLOuxrEk2RVl6WridZfmrbme58oiKCY9zlTQE7dkweQn7LPeF5Bin5r45mdPfaInFicH27SAlEIsU-kXNMbFegcUCCpD8iQDlgnZUD3A56HVKvPA/s1280/Azure.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUI-Hum7q-EyAT3L3whtJaWaGNSvQ3qf5PqgxKaqUBJz4pZEB8sKgRI2pt5cdm6lL02V7x2VEndOXpLOuxrEk2RVl6WridZfmrbme58oiKCY9zlTQE7dkweQn7LPeF5Bin5r45mdPfaInFicH27SAlEIsU-kXNMbFegcUCCpD8iQDlgnZUD3A56HVKvPA/s600/Azure.png&quot;/&gt;&lt;/a&gt;         
&lt;/td&gt;  
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqDmLhoOxuMdAnFLK9eik1f36eOoDYnl4wp7kzZlVeOCD5_5cbEaUCewRcsUObBQ5JZ1rpes4JsHnOLYw-_g6J1hdLPUbU8IzLC56jPyN-po_FL1qQq-lzDFzv2h5d_cWen-Q4e7ZUyRLZurjuqyJagWlupWX5hcqU4W7z6k-hIqQhZ2F2JwZpI6TJEKE/s1280/AWS_org.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqDmLhoOxuMdAnFLK9eik1f36eOoDYnl4wp7kzZlVeOCD5_5cbEaUCewRcsUObBQ5JZ1rpes4JsHnOLYw-_g6J1hdLPUbU8IzLC56jPyN-po_FL1qQq-lzDFzv2h5d_cWen-Q4e7ZUyRLZurjuqyJagWlupWX5hcqU4W7z6k-hIqQhZ2F2JwZpI6TJEKE/s600/AWS_org.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLxxk1qQND-5_PHqUZY5uHTzic9Tefp3d6FJO5vOmYnbLP0xTXG0zujtNUMryHyiwEe6QJp4NLhKyrgy4KjkGa6KBLcLFw4b8cim2ip_Blm_ayiN-tO2CcinheHDNt3pEFNIjOfajAzeQCqe6PXLC-NOdFvsulPJ7dLdVstTUKiZmyhDCCZlul37sa9DY/s1280/GCP_org.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLxxk1qQND-5_PHqUZY5uHTzic9Tefp3d6FJO5vOmYnbLP0xTXG0zujtNUMryHyiwEe6QJp4NLhKyrgy4KjkGa6KBLcLFw4b8cim2ip_Blm_ayiN-tO2CcinheHDNt3pEFNIjOfajAzeQCqe6PXLC-NOdFvsulPJ7dLdVstTUKiZmyhDCCZlul37sa9DY/s600/GCP_org.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
Let&#39;s check it out!  
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Pre-Requisites&lt;/u&gt;&lt;br /&gt;
This blog post assumes an &lt;a href=&quot;https://portal.azure.com&quot;&gt;Azure&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com&quot;&gt;AWS&lt;/a&gt;, &lt;a href=&quot;https://console.cloud.google.com&quot;&gt;GCP&lt;/a&gt; account is setup.  The following links document paid or free tier:
&lt;br /&gt;

&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;Azure [Microsoft]&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;AZ&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://www.datacamp.com/tutorial/how-to-set-up-and-configure-azure&quot;&gt;PAID&lt;/a&gt; Tier Account&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://k21academy.com/microsoft-azure/create-free-microsoft-azure-trial-account&quot;&gt;FREE&lt;/a&gt; Tier Account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;Amazon Web Services&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;AWS&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://www.geeksforgeeks.org/amazon-web-services-setting-up-an-aws-account&quot;&gt;PAID&lt;/a&gt; Tier Account&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://k21academy.com/amazon-web-services/aws-solutions-architect/create-aws-free-tier-account&quot;&gt;FREE&lt;/a&gt; Tier Account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;Google Cloud Platform&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;GCP&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://www.optimizesmart.com/how-to-create-a-new-google-cloud-platform-account&quot;&gt;PAID&lt;/a&gt; Tier Account&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://k21academy.com/google-cloud/create-google-cloud-free-tier-account&quot;&gt;FREE&lt;/a&gt; Tier Account&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure&quot;&gt;Azure CLI&lt;/a&gt;&lt;br /&gt;
The Azure Command Line Interface is a set of commands used to create and manage Azure resources.  The CLI is available across services designed to get working with Azure quickly with an emphasis on automation.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Linux&lt;/b&gt;&lt;br /&gt;
Install the &lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux&quot;&gt;Azure CLI&lt;/a&gt; on Linux | Choose an installation method e.g. apt (Ubunuty, Debian) | Launch Terminal
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Mac OS/X&lt;/b&gt;&lt;br /&gt;
Install &lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-macos&quot;&gt;Azure CLI&lt;/a&gt; on Mac OS/X | Install with Homebrew | Install &lt;a href=&quot;https://docs.brew.sh/Installation.html&quot;&gt;Homebrew&lt;/a&gt; manager if you haven&#39;t already!
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;brew update &amp;&amp; brew install azure-cli&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Windows&lt;/b&gt;&lt;br /&gt;
Install &lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-windows&quot;&gt;Azure CLI&lt;/a&gt; on Windows | Microsoft Install (MSI) | Download the Latest MSI of the &lt;a href=&quot;https://aka.ms/installazurecliwindowsx64&quot;&gt;Azure CLI&lt;/a&gt; (64-bit)
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;Download and install https://aka.ms/installazurecliwindowsx64&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
After installing the Azure CLI on Linux, Mac OS/X, Windows confirm the current working version of the CLI:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;az version&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
  
&lt;a href=&quot;https://aws.amazon.com/cli&quot;&gt;AWS CLI&lt;/a&gt;&lt;br /&gt;
The AWS Command Line Interface is a unified tool used to manage your AWS services.  Use the AWS CLI tool to download configure and control AWS services from the command line and automate them through scripts.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Linux&lt;/b&gt;&lt;br /&gt;
Install the &lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&quot;&gt;AWS CLI&lt;/a&gt; on Linux | Linux tab | Command line installer - Linux x86 (64-bit) | Launch the Terminal
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;curl &quot;https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip&quot; -o &quot;awscliv2.zip&quot;&lt;br /&gt;
&amp;nbsp;unzip awscliv2.zip&lt;br /&gt;
&amp;nbsp;sudo ./aws/install&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Mac OS/X&lt;/b&gt;&lt;br /&gt;
Install the &lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&quot;&gt;AWS CLI&lt;/a&gt; on MacOS/X | macOS tab | GUI installer | Download the macOS pkg file &lt;a href=&quot;https://awscli.amazonaws.com/AWSCLIV2.pkg&quot;&gt;AWSCLIV2.pkg&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;Download and install https://awscli.amazonaws.com/AWSCLIV2.pkg&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Windows&lt;/b&gt;&lt;br /&gt;
Install the &lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&quot;&gt;AWS CLI&lt;/a&gt; on Windows | Windows tab | Download MSI | Download Windows (64-bit) &lt;a href=&quot;https://awscli.amazonaws.com/AWSCLIV2.msi&quot;&gt;AWSCLIV2.msi&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;Download and install https://awscli.amazonaws.com/AWSCLIV2.msi&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
After installing the AWS  CLI on Linux, Mac OS/X, Windows confirm the current working version of the CLI:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;aws --version&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;  
  
&lt;a href=&quot;https://cloud.google.com/cli&quot;&gt;GCP CLI&lt;/a&gt;&lt;br /&gt;
The GCP Command Line Interface is used to create and manage Google Cloud resources + services directly from the command line and to perform common platform tasks faster by controlling cloud resources at scale.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Linux&lt;/b&gt;&lt;br /&gt;
Install the &lt;a href=&quot;https://cloud.google.com/sdk/docs/install#linux&quot;&gt;gcloud CLI&lt;/a&gt; | Linux tab | Platform Linux 64-bit (x86_64) | Launch Terminal + execute commands:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;
&amp;nbsp;curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86_64.tar.gz&lt;br /&gt;
&amp;nbsp;tar -xf google-cloud-cli-linux-x86_64.tar.gz&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;cd google-cloud-sdk&lt;/td&gt;
&lt;td&gt;&amp;nbsp;./install.sh&lt;/td&gt;
&lt;/tr&gt;  
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Mac OS/X&lt;/b&gt;&lt;br /&gt;
Install the &lt;a href=&quot;https://cloud.google.com/sdk/docs/install#mac&quot;&gt;gcloud CLI&lt;/a&gt; | macOS tab | Platform macOS macOS 64-bit (ARM64, Apple silicon) | Launch Terminal
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;
&amp;nbsp;curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-darwin-arm.tar.gz&lt;br /&gt;
&amp;nbsp;tar -xf google-cloud-cli-darwin-arm.tar.gz&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;cd google-cloud-sdk&lt;/td&gt;
&lt;td&gt;&amp;nbsp;./install.sh&lt;/td&gt;
&lt;/tr&gt;  
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Windows&lt;/b&gt;&lt;br /&gt;
Install the &lt;a href=&quot;https://cloud.google.com/sdk/docs/install#windows&quot;&gt;gcloud CLI&lt;/a&gt; | Windows tab | Download the Google Cloud CLI installer &lt;a href=&quot;https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe&quot;&gt;GoogleCloudSDKInstaller.exe&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;Download and install https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
After installing the gcloud CLI on Linux, Mac OS/X, Windows confirm the current working version of the CLI:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;gcloud init&lt;/td&gt;
&lt;td&gt;&amp;nbsp;gcloud version&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;u&gt;Master Key&lt;/u&gt;&lt;br /&gt;
Next, create master SSH key for secure, automated and controlled access to your Kubernetes infrastructure:
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;60%&quot;&gt;
&amp;nbsp;cd ~/.ssh&lt;br /&gt;
&amp;nbsp;ssh-keygen -t rsa -b 4096 -N &#39;&#39; -f master_ssh_key&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;eval $(ssh-agent -s)&lt;br /&gt;
&amp;nbsp;ssh-add master_ssh_key&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;

&lt;a href=&quot;https://learn.microsoft.com/en-us/azure/aks&quot;&gt;Azure AKS&lt;/a&gt;&lt;br /&gt;
Microsoft provides Azure Kubernetes Services as fully managed Kubernetes container orchestration service.  Follow all instructions below in order to provision a Kubernetes cluster and end-to-end test its functionality. 
&lt;br /&gt;
Download code sample &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/CloudTesting/tree/main/CloudSetupCheatSheet/stevepro-azraks&quot;&gt;here&lt;/a&gt;&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;Pre-Requisites&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;az login
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Check Resources&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;az account list --output table
&amp;nbsp;&amp;nbsp;az group list --output table
&amp;nbsp;&amp;nbsp;az resource list --output table
&amp;nbsp;&amp;nbsp;az resource list --query &quot;[?location==&#39;northeurope&#39;]&quot; --output table
&amp;nbsp;&amp;nbsp;az vm list --output table
&amp;nbsp;&amp;nbsp;az aks list --output table
&amp;nbsp;&amp;nbsp;az container list --output table
&amp;nbsp;&amp;nbsp;az storage account list --output table
&amp;nbsp;&amp;nbsp;az network public-ip list --output table
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Create Group&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;az group create --name stevepro-azraks-rg --location northeurope --debug
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Security Principal&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;az ad sp create-for-rbac --name ${USER}-sp --skip-assignment
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Output&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;    &quot;appId&quot;: &quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&quot;,
&amp;nbsp;    &quot;displayName&quot;: &quot;stevepro-sp&quot;,
&amp;nbsp;    &quot;password&quot;: &quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&quot;,
&amp;nbsp;    &quot;tenant&quot;: &quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&quot;,
&amp;nbsp;&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Export&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export AZ_SP_ID=&amp;lt;value_from_appId&amp;gt;
&amp;nbsp;&amp;nbsp;export AZ_SP_PASSWORD=&amp;lt;value_from_password&amp;gt;
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Create Cluster&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;az aks create --name stevepro-azraks                 \
&amp;nbsp;    --resource-group stevepro-azraks-rg               \
&amp;nbsp;    --dns-name-prefix stevepro-azraks                 \
&amp;nbsp;    --node-count 3                                    \
&amp;nbsp;    --node-vm-size Standard_D2s_v3                    \
&amp;nbsp;    --kubernetes-version 1.31                         \
&amp;nbsp;    --ssh-key-value ~/.ssh/master_ssh_key.pub         \
&amp;nbsp;    --service-principal ${AZ_SP_ID}                   \
&amp;nbsp;    --client-secret ${AZ_SP_PASSWORD}                 \
&amp;nbsp;    --load-balancer-sku standard                      \
&amp;nbsp;    --network-plugin azure --debug
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Get Credentials&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;export KUBECONFIG=~/.kube/config
&amp;nbsp;&amp;nbsp;az aks get-credentials --name stevepro-azraks        \
&amp;nbsp;    --resource-group stevepro-azraks-rg --file ~/.kube/config
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Deploy Test&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kubectl create ns test-ns
&amp;nbsp;&amp;nbsp;kubectl config set-context --current --namespace=test-ns
&amp;nbsp;&amp;nbsp;kubectl apply -f Kubernetes.yaml
&amp;nbsp;&amp;nbsp;kubectl port-forward service/flask-api-service 8080:80
&amp;nbsp;&amp;nbsp;curl http://localhost:8080
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Output&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;Hello World (Python)!
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Shell into Node&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;mkdir -p ~/GitHub/luksa
&amp;nbsp;&amp;nbsp;cd ~/GitHub/luksa
&amp;nbsp;&amp;nbsp;git clone https://github.com/luksa/kubectl-plugins.git
&amp;nbsp;&amp;nbsp;cd kubectl-plugins
&amp;nbsp;&amp;nbsp;chmod +x kubectl-ssh
&amp;nbsp;&amp;nbsp;kubectl get nodes
&amp;nbsp;&amp;nbsp;./kubectl-ssh node aks-nodepool1-20972701-vmss000000
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Cleanup&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;kubectl delete -f Kubernetes.yaml
&amp;nbsp;&amp;nbsp;kubectl delete ns test-ns
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
  
&lt;b&gt;Delete Cluster&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;az aks delete --name stevepro-azraks                 \
&amp;nbsp;    --resource-group stevepro-azraks-rg
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Delete Group&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;pre style=&quot;font-size: 12px;&quot;&gt;
&amp;nbsp;&amp;nbsp;az group delete --name stevepro-azraks-rg --yes --no-wait
&amp;nbsp;&amp;nbsp;az group delete --name NetworkWatcherRG --yes --no-wait
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have setup CLIs for Azure, Amazon and Google and provisioned an &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/aks&quot;&gt;Azure AKS&lt;/a&gt; Kubernetes cluster with end-to-end testing.  Next, we will resume to provision clusters for &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html&quot;&gt;Amazon EKS&lt;/a&gt; and &lt;a href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview&quot;&gt;Google GKE&lt;/a&gt;.  This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2025/06/cloud-setup-cheat-sheet-ii.html&quot;&gt;post&lt;/a&gt;.

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2025/05/cloud-setup-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUI-Hum7q-EyAT3L3whtJaWaGNSvQ3qf5PqgxKaqUBJz4pZEB8sKgRI2pt5cdm6lL02V7x2VEndOXpLOuxrEk2RVl6WridZfmrbme58oiKCY9zlTQE7dkweQn7LPeF5Bin5r45mdPfaInFicH27SAlEIsU-kXNMbFegcUCCpD8iQDlgnZUD3A56HVKvPA/s72-c/Azure.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-3053315248007424658</guid><pubDate>Wed, 01 Jan 2025 10:00:00 +0000</pubDate><atom:updated>2025-01-01T02:00:07.352-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Retrospective</category><title>Retrospective XVI</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;

Last year, I conducted a simple retrospective for 2023. Therefore, here is a retrospective for year 2024.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;2024 Achievements&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
Transfer all Windows and Linux keyboard &lt;a href=&quot;https://steveproxna.blogspot.com/2024/05/macos-setup-cheat-sheet.html&quot;&gt;shortcuts&lt;/a&gt; and muscle memory to new Mac Book Pro
&lt;/li&gt;
&lt;li&gt;
Transfer all important Windows and Linux applications &lt;a href=&quot;https://steveproxna.blogspot.com/2024/06/macos-setup-cheat-sheet-ii.html&quot;&gt;navigations&lt;/a&gt; for M1-powered MacBooks
&lt;/li&gt;
&lt;li&gt;
Build &lt;a href=&quot;https://steveproxna.blogspot.com/2024/07/gitlab-cheat-sheet.html&quot;&gt;GitLab CI/CD&lt;/a&gt; pipelines extending DevOps skillset and streamline collaborative workflow
&lt;/li&gt;
&lt;li&gt;
Provision Kubernetes clusters for GitLab CI/CD pipelines e.g. Azure AKS, AWS-EKS, GCP-GKE
&lt;/li&gt;
&lt;li&gt;
Configure &lt;a href=&quot;https://steveproxna.blogspot.com/2024/08/doom-code-walkthru.html&quot;&gt;Doom&lt;/a&gt; open source port for Windows and Linux to debug step thru the source code
&lt;/li&gt;
&lt;li&gt;
Launch fulltime Python coding experience to learn AI focusing on RL Reinforcement Learning
&lt;/li&gt;
&lt;li&gt;
Experiment with &lt;a href=&quot;https://steveproxna.blogspot.com/2024/09/openai-farma-cheat-sheet.html&quot;&gt;OpenAI Gym&lt;/a&gt; project for RL research and build Atari available environments
&lt;/li&gt;
&lt;li&gt;
Investigate &lt;a href=&quot;https://steveproxna.blogspot.com/2024/11/openai-retro-cheat-sheet.html&quot;&gt;OpenAI Retro&lt;/a&gt; project for RL research on classic Sega 8-bit + 16-bit video games
&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
Note: building OpenAI projects for classic Sega 8/16-bit video games integration is a big achievement!
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;2025 Objectives&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
Document DevOps managed clusters provisioning experience with &lt;a href=&quot;https://en.wikipedia.org/wiki/Amazon_Web_Services&quot;&gt;AWS&lt;/a&gt; / &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Azure&quot;&gt;Azure&lt;/a&gt; / &lt;a href=&quot;https://en.wikipedia.org/wiki/Google_Cloud_Platform&quot;&gt;GCP&lt;/a&gt; providers
&lt;/li&gt;
&lt;li&gt;
Channel cloud computing knowledge toward software architecture or infrastructure certification
&lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;https://levelup.gitconnected.com/pybind11-a-beginners-guide-to-setting-up-c-and-python-projects-1de2f04465e9&quot;&gt;Harness&lt;/a&gt; Python potential power invoking C/C++ [PyBind11] with code magnitudes times faster
&lt;/li&gt;
&lt;li&gt;
Extend OpenAI Gym and Retro projects for more Indie &lt;a href=&quot;https://www.smspower.org/Homebrew&quot;&gt;video games&lt;/a&gt; + Reinforcement Learning!
&lt;/li&gt;
&lt;/ul&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Artificial Intelligence&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
Artificial Intelligence refers to capability of machines to imitate human intelligence.  AI empowers machines to acquire knowledge, adapt and independently make decisions like teaching a computer to act human like.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Machine Learning&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
AI involves a crucial element known as Machine Learning.  ML is akin to training computers to improve tasks without providing detailed instructions.  Machines utilize data to learn and enhance the performance without explicit programming and concentrates on creating algorithms for computers to learn from data to improve.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Deep Learning&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
Deep Learning involves artificial neural networks inspired by the human brain: mimicking how human brains work.   DL excels at handling complex tasks and large datasets efficiently and achieves remarkable success in areas like natural language processing and computer vision despite complexity and interpretation challenges.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;u&gt;Generative AI&lt;/u&gt;&lt;br /&gt;
&lt;!-- --&gt;
Generative AI is the latest innovation in the AI field.  Instead of just identifying patterns GenAI goes one step further by actually attempting to produce new content that closely resembles what humans might create.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;

&lt;i&gt;Outline&lt;/i&gt;&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Artificial Intelligence&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Artificial Intelligence is the &quot;big brain&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Machine Learning&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Machine Learning is its learning process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Deep Learning&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Deep Learning is its intricate wiring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Generative AI&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Generative AI is the creative spark&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiysHgBElTTh-Ns_UDxSQnhGITpUxBrpdS1kC9ffq6H2xMUd_xRGh08gQKtNcBP0E790nwh5cmtqMFKQTY9V3bpR8wRbEKrF8os6xTNwV75_jqIaBseszw42g7TVXdflWNULUzmsrr9sGgK2fPr96Xcc8pKi5diCDeJhvqY5mY1Fthv45STAKY_4ViTKk/s1080/genai.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiysHgBElTTh-Ns_UDxSQnhGITpUxBrpdS1kC9ffq6H2xMUd_xRGh08gQKtNcBP0E790nwh5cmtqMFKQTY9V3bpR8wRbEKrF8os6xTNwV75_jqIaBseszw42g7TVXdflWNULUzmsrr9sGgK2fPr96Xcc8pKi5diCDeJhvqY5mY1Fthv45STAKY_4ViTKk/s600/genai.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://www.snowflake.com/resource/generative-ai-and-llms-for-dummies&quot;&gt;Gen AI and LLMs&lt;/a&gt; are revolutionizing our personal and professional lives From supercharged digital assistants to seemingly omniscient chatbots these &lt;a href=&quot;https://writer.com/guides/generative-ai-survey&quot;&gt;technologies&lt;/a&gt; are driving a new era of convenience, productivity, and connectivity.
&lt;br /&gt;&lt;br /&gt;
Traditional AI uses predictive models to classify data, recognize patterns, + predict outcomes within specific context whereas Gen AI models generate entirely new outputs rather than simply making predictions based on prior experience.
&lt;br /&gt;&lt;br /&gt;
This shift from prediction to creation opens up new realms of innovation: in healthcare traditional predictive model can spot suspicious lesion in lung tissue &lt;a href=&quot;https://en.wikipedia.org/wiki/Magnetic_resonance_imaging&quot;&gt;MRI&lt;/a&gt; whereas GenAI could also determine the likelihood that patient will develop pneumonia or other lung diseases and offer treatment recommendations based on best practices gleaned from thousands of similar cases.
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;Example&lt;/i&gt;&lt;br /&gt;
GenAI powered healthcare chatbots can assist patients and healthcare providers and medical administrators:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr valign=&quot;top&quot;&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;01.&lt;/b&gt;&amp;nbsp;Symptom Checker&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;07.&lt;/b&gt;&amp;nbsp;Mental Health Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr valign=&quot;top&quot;&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;02.&lt;/b&gt;&amp;nbsp;Appointment Scheduling&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;08.&lt;/b&gt;&amp;nbsp;Insurance and Billing Assistance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr valign=&quot;top&quot;&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;03.&lt;/b&gt;&amp;nbsp;Medication Reminders&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;09.&lt;/b&gt;&amp;nbsp;Virtual Consultations and Telemedicine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr valign=&quot;top&quot;&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;04.&lt;/b&gt;&amp;nbsp;Health Tips and Preventive Care&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;10.&lt;/b&gt;&amp;nbsp;Health Records Access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr valign=&quot;top&quot;&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;05.&lt;/b&gt;&amp;nbsp;Lab Results Interpretation&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;11.&lt;/b&gt;&amp;nbsp;Emergency Triage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr valign=&quot;top&quot;&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;06.&lt;/b&gt;&amp;nbsp;Chronic Disease Management&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
By leveraging conversational AI healthcare chatbot can improve patient engagement and provide real-time support and optimize the workflow for healthcare providers.  Finally, Reinforcement Learning From Human Feedback RLHF can be integrated to further improve model performance over original pre-trained version!
&lt;br /&gt;&lt;br /&gt;

&lt;u&gt;Future&lt;/u&gt;&lt;br /&gt;
Artificial Intelligence is changing industries across the globe from healthcare and finance to marketing and logistics.  As we enter 2025, the demand for &lt;a href=&quot;https://www.linkedin.com/pulse/top-10-ai-skills-learn-get-job-2025-zummit-africa-wabjc&quot;&gt;skilled&lt;/a&gt; AI professionals continues to soar.  Start out by building strong foundations in Python and understand key concepts such as machine learning and neural networks.
&lt;br /&gt;&lt;br /&gt;
Therefore, whether an AI beginner or seasoned tech professional, here are the top 10 AI skills for success:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;No.&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;AI Skill&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Key Tools&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;01&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Machine Learning (ML)&lt;/td&gt;&lt;td&gt;&amp;nbsp;Scikit-learn, TensorFlow, PyTorch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;02&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Deep Learning&lt;/td&gt;&lt;td&gt;&amp;nbsp;Keras, PyTorch, Google Colab&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;03&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Natural Language Processing (NLP)&lt;/td&gt;&lt;td&gt;&amp;nbsp;NLTK, SpaCy, GPT-based models (e.g., GPT-4)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;04&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Data Science and Analytics&lt;/td&gt;&lt;td&gt;&amp;nbsp;NumPy, Pandas, Jupyter Notebooks&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;05&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Computer Vision&lt;/td&gt;&lt;td&gt;&amp;nbsp;OpenCV, YOLO (You Only Look Once), TensorFlow&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;06&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;AI Ethics and Bias Mitigation&lt;/td&gt;&lt;td&gt;&amp;nbsp;AI Ethics Courses, Fairness Indicators (Google)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;07&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;AI Infrastructure and Cloud Computing&lt;/td&gt;&lt;td&gt;&amp;nbsp;Amazon Web Services, Microsoft Azure, Google Cloud AI&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;08&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Reinforcement Learning&lt;/td&gt;&lt;td&gt;&amp;nbsp;OpenAI Gym, TensorFlow Agents, Stable Baselines3&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;09&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;AI Operations (MLOps)&lt;/td&gt;&lt;td&gt;&amp;nbsp;Docker, Kubernetes, Kubeflow, MLflow&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;10&lt;/b&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Generative AI&lt;/td&gt;&lt;td&gt;&amp;nbsp;Generative Adversarial Networks, DALL-E, GPT models&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Finally, the GenAI market is poised to explode, growing to $1.3 trillion over the next 10 years from market size of just $40 billion in 2022.  Therefore, it would be extraordinary to integrate GenAI to build content for OpenAI-based retro video games only to be trained by Reinforcement Learning algorithms to beat them &lt;span style=&#39;font-family:Wingdings&#39;&gt;J&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2025/01/retrospective-xvi.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiysHgBElTTh-Ns_UDxSQnhGITpUxBrpdS1kC9ffq6H2xMUd_xRGh08gQKtNcBP0E790nwh5cmtqMFKQTY9V3bpR8wRbEKrF8os6xTNwV75_jqIaBseszw42g7TVXdflWNULUzmsrr9sGgK2fPr96Xcc8pKi5diCDeJhvqY5mY1Fthv45STAKY_4ViTKk/s72-c/genai.png" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-839135788501844274</guid><pubDate>Fri, 15 Nov 2024 09:00:00 +0000</pubDate><atom:updated>2024-11-18T12:17:40.446-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">OpenAI</category><title>OpenAI Retro Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2024/09/openai-farma-cheat-sheet.html&quot;&gt;post&lt;/a&gt;, we checked out &lt;a href=&quot;https://github.com/openai/gym&quot;&gt;OpenAI Gym&lt;/a&gt;: an open source library in Python used for reinforcement learning algorithms development to communicate between environments such as classic Atari video games.
&lt;br /&gt;&lt;br /&gt;
In the this post, we check out &lt;a href=&quot;https://github.com/openai/retro&quot;&gt;OpenAI Retro&lt;/a&gt;: source code repository which lets you turn classic video games into Gym environments for reinforcement learning with classic Atari video games and many other Emulated Systems including: &lt;a href=&quot;https://steveproxna.blogspot.com/2023/11/gbdk-programming-sample.html&quot;&gt;Nintendo&lt;/a&gt; GameBoy / GameBoy Color, the Sega &lt;a href=&quot;https://steveproxna.blogspot.com/2020/11/sgdk-programming-sample.html&quot;&gt;MegaDrive&lt;/a&gt; and the Sega &lt;a href=&quot;https://steveproxna.blogspot.com/2022/07/devkitsms-programming-sample-v.html&quot;&gt;Master System&lt;/a&gt;.
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPg5lDn5BIDcj0-l8C-P-tTwHoFTFbPHaOFt0LcF-7Oc7-5teLiMO0y9Od48m4ZJRZ5IXWBQczz1YQ-V4DhZ-I3Xg6kkxdhj6qv52OWb1IALk1TXgRYu24MELKHgpGyj_b4NVMJ9nd-bLnHD2U8NwvhyphenhyphenUrB7K3OKx6kFoSXBNTSQk-H3KSjfllSXJmGVE/s1856/Strider-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPg5lDn5BIDcj0-l8C-P-tTwHoFTFbPHaOFt0LcF-7Oc7-5teLiMO0y9Od48m4ZJRZ5IXWBQczz1YQ-V4DhZ-I3Xg6kkxdhj6qv52OWb1IALk1TXgRYu24MELKHgpGyj_b4NVMJ9nd-bLnHD2U8NwvhyphenhyphenUrB7K3OKx6kFoSXBNTSQk-H3KSjfllSXJmGVE/s600/Strider-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Gym Retro&lt;/u&gt;&lt;/br /&gt;
In May 2018, Open AI announce &lt;a href=&quot;https://openai.com/index/gym-retro&quot;&gt;Gym Retro&lt;/a&gt;: a platform for reinforcement learning research on classic 8-bit and 16-bit video games.  The release includes games from the Sega Genesis and Sega Master System, and Nintendo’s NES, SNES, and Game Boy consoles.  The release also includes an &lt;a href=&quot;https://retro.readthedocs.io/en/latest/integration.html&quot;&gt;Integration Tool&lt;/a&gt; that lets you create save states, find memory locations + design scenarios that reinforcement learning agents can solve.   
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Hello Gym Retro&lt;/b&gt;&lt;br /&gt;
Create new Hello Gym Retro type environment.  Launch PyCharm | New Project | Name: HelloGymRetro [~/]
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdSdgYzbDsRlAkMUCrUAVg_wlqmeoK_DWAX9dbwPzMzWBPVWNTpsGYGyYMYdC_53SeQNYXG1DOdjOBnR9gBmXfMzh3AqhPgKR8fK_GxmxOqPyi4WxXXb1hOGRw8T4gqJNXknJJbZGymne8fOA85SzjXxC0QKfZbUlwn5uN-B4BJZ5ao05OUJsIApV_sZY/s800/HelloGymRetro.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdSdgYzbDsRlAkMUCrUAVg_wlqmeoK_DWAX9dbwPzMzWBPVWNTpsGYGyYMYdC_53SeQNYXG1DOdjOBnR9gBmXfMzh3AqhPgKR8fK_GxmxOqPyi4WxXXb1hOGRw8T4gqJNXknJJbZGymne8fOA85SzjXxC0QKfZbUlwn5uN-B4BJZ5ao05OUJsIApV_sZY/s600/HelloGymRetro.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;python -m venv .venv&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install gym-retro&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;source .venv/bin/activate&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install --upgrade pip&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
CODE
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;import retro&lt;br /&gt;
&amp;nbsp;env = retro.make(game=&quot;Airstriker-Genesis&quot;)&lt;br /&gt;
&amp;nbsp;observation = env.reset()&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;while True:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action = env.action_space.sample()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation, reward, done, info = env.step(action)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;env.render()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if done:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation = env.reset()&lt;br /&gt;
&amp;nbsp;env.close()&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
IPMORTANT
&lt;br /&gt;
At the time of this writing you may experience the following errors.  Here are errors encountered + solutions:  
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;ERROR #1&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;
&amp;nbsp;AttributeError: module &#39;gym.utils.seeding&#39; has no attribute &#39;hash_seed&#39;&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://stackoverflow.com/questions/73710249/openai-gym-retro-error-attributeerror-module-gym-utils-seeding-has-no-attri&quot;&gt;Solution&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;pip uninstall -y gym&lt;/td&gt;
&lt;td&gt;&amp;nbsp;pip install gym==0.25.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;ERROR #2&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;
&amp;nbsp;ModuleNotFoundError: No module named &#39;gym.envs.classic_control.rendering&#39;&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://www.reddit.com/r/reinforcementlearning/comments/uklf29/no_module_named_gymenvsclassic_controlrendering&quot;&gt;Solution&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;pip uninstall -y gym&lt;/td&gt;
&lt;td&gt;&amp;nbsp;pip install gym==0.21.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;ERROR #3&amp;nbsp&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;ERROR: Could not find a version that satisfies the requirement gym==0.21.0 &lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/openai/gym/issues/3202&quot;&gt;Solution&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;pip install&lt;br /&gt;&amp;nbsp;git+https://github.com/openai/gym.git@9180d12e1b66e7e2a1a622614f787a6ec147ac40&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;Stable Retro&lt;/u&gt;&lt;/br /&gt;
As per previous &lt;a href=&quot;https://steveproxna.blogspot.com/2024/09/openai-farma-cheat-sheet.html&quot;&gt;post&lt;/a&gt;, we learned that the lack of maintenance for OpenAI Gym prompted &lt;a href=&quot;https://gymnasium.farama.org/index.html&quot;&gt;Gymnasium&lt;/a&gt;: which is an open source fork of the OpenAI Gym library maintained by The &lt;a href=&quot;https://farama.org&quot;&gt;Farama Foundation&lt;/a&gt;.  As Gym Retro built upon an unmaintained version of the OpenAI Gym library then this may explain errors encountered above &lt;span style=&#39;font-family:Wingdings&#39;&gt;J&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;
&lt;br /&gt;&lt;br /&gt;
Similarly, like Gym Retro built upon OpenAI Gym, &lt;a href=&quot;https://stable-retro.farama.org&quot;&gt;Stable Retro&lt;/a&gt; is built upon Farama Foundation Gymnasium.  &lt;a href=&quot;https://github.com/Farama-Foundation/stable-retro&quot;&gt;Stable Retro&lt;/a&gt; lets you convert classic video games into Gymnasium environments for Reinforcement Learning!
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Hello Stable Retro&lt;/b&gt;&lt;br /&gt;
Create Hello Stable Retro type environment.  Launch PyCharm | New Project | Name: HelloStableRetro [~/]
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiar5WXrKel7pqEC7XB0eoD7QrWZUJiMPLqo2o1oDNkm1wy7deRL0mdwjOCrXuAPfM_38VXT6Y5jepRZYrsmamfHVtU5pxpvQcqdm_MeIDTJYBr-M-3drN3XsPF8XqUREW3xMx-mtIPzs_mtgOM5nyJiaFD0BgmrRkMVTvJn8oPSFxt2R_VF7HiaI_Vk5s/s800/HelloStableRetro.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiar5WXrKel7pqEC7XB0eoD7QrWZUJiMPLqo2o1oDNkm1wy7deRL0mdwjOCrXuAPfM_38VXT6Y5jepRZYrsmamfHVtU5pxpvQcqdm_MeIDTJYBr-M-3drN3XsPF8XqUREW3xMx-mtIPzs_mtgOM5nyJiaFD0BgmrRkMVTvJn8oPSFxt2R_VF7HiaI_Vk5s/s600/HelloStableRetro.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;python -m venv .venv&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install stable-retro&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;source .venv/bin/activate&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install --upgrade pip&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
 &lt;!-- --&gt;
CODE
&lt;!-- --&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;import retro&lt;br /&gt;
&amp;nbsp;env = retro.make(game=&quot;Airstriker-Genesis&quot;)&lt;br /&gt;
&amp;nbsp;observation, info = env.reset()&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;while True:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action = env.action_space.sample()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation, reward, terminated, truncated, info = env.step(action)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if terminated or truncated:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation, info = env.reset()&lt;br /&gt;
&amp;nbsp;env.close()&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;Retro Examples&lt;/u&gt;&lt;br /&gt;
Complete all Retro examples!  Extend &lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting&quot;&gt;OpenAI Test&lt;/a&gt; repo.  Launch PyCharm | New Project | RetroCheatSheet
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJS05ETesbaDzt487QaxDfZk80VjSM9xEBXfX9E5P9o_i1Ur5pYgomk3hnaScMRHCkd1RQaooCw_hjsSwCfUwnW1PKS-fg-iP7fuQZX9IIdcXX0q4d4_ug8Q-9NEcRI9qtuR1eFfY97WErQQi8jgJEQCpROFyGoAiua3c7BiqiRgSE8FDliT2OvzlKLe4/s800/RetroCheatSheetProject.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJS05ETesbaDzt487QaxDfZk80VjSM9xEBXfX9E5P9o_i1Ur5pYgomk3hnaScMRHCkd1RQaooCw_hjsSwCfUwnW1PKS-fg-iP7fuQZX9IIdcXX0q4d4_ug8Q-9NEcRI9qtuR1eFfY97WErQQi8jgJEQCpROFyGoAiua3c7BiqiRgSE8FDliT2OvzlKLe4/s600/RetroCheatSheetProject.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;  
&lt;br /&gt;&lt;br /&gt;
IMPORTANT&lt;br /&gt;
If Python Interpreter not set and/or Virtual Environment not available then choose File | Settings... | Project: Python Interpreter | Add Interpreter | Add Local Interpreter.  Launch terminal: &lt;b&gt;source .venv/bin/activate&lt;/b&gt;.  
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTp3AM9KZWRI1YqTljzJvp04S-jdJ0DPRCQSMcTlv3IJPLcnDjcfIybol_nl-cLyr6Y_YoaHW685dtNPCkPveOpZSPiDCymQXZ5OiurykWpKOzZqJ5ImiBJo4Jk230Mn_4wfexA9P43PhWvTEyb0Tv-TYCt70gfHshZt7KrmYA0S46SLUWDXd9Z30-3Fo/s1028/RetroCheatSheetVenv.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTp3AM9KZWRI1YqTljzJvp04S-jdJ0DPRCQSMcTlv3IJPLcnDjcfIybol_nl-cLyr6Y_YoaHW685dtNPCkPveOpZSPiDCymQXZ5OiurykWpKOzZqJ5ImiBJo4Jk230Mn_4wfexA9P43PhWvTEyb0Tv-TYCt70gfHshZt7KrmYA0S46SLUWDXd9Z30-3Fo/s600/RetroCheatSheetVenv.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Setup ROMs: copy Sega ROM files from the &lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/tree/main/RetroCheatSheet/data&quot;&gt;data&lt;/a&gt; directory to Virtual Environment via the &lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/copy_files.py&quot;&gt;copy_files.py&lt;/a&gt; script
&lt;br /&gt;
&lt;!-- --&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&amp;nbsp;mkdir data&lt;br /&gt;
&amp;nbsp;mkdir examples&lt;br /&gt;
&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;
&amp;nbsp;cd examples&lt;br /&gt;
&amp;nbsp;python copy_files.py&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;  
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Sega Master System&lt;/b&gt;&lt;br /&gt;
Launch retro games for the Sega Master System 8-bit video game console with &lt;b&gt;.sms&lt;/b&gt; supported ROM types:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install stable-retro&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install --upgrade pip&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/AlienSyndrome-Sms.py&quot;&gt;AlienSyndrome-Sms&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/RType-Sms.py&quot;&gt;RType-Sms&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/BladeEagle-Sms.py&quot;&gt;BladeEagle-Sms&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/Shinobi-Sms.py&quot;&gt;Shinobi-Sms&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/DickTracy-Sms.py&quot;&gt;DickTracy-Sms&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/SonicTheHedgehog-Sms.py&quot;&gt;SonicTheHedgehog-Sms&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/JamesPond2CodenameRoboCod-Sms.py&quot;&gt;JamesPond2CodenameRoboCod-Sms&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Sms/TransBot-Sms.py&quot;&gt;TransBot-Sms&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;!--&lt;br /&gt;--&gt;
&lt;!-- --&gt;  
&lt;table width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguIvwlj2n5mlq54oUl7_894BwFf6lNalVFf-6QvgmAwICjoKXkgythmIygAzI0_6nqh5UIkG2rxyyaF_o61LaW8VkbcuoTVDrVlRuXLFZJtx8HxCY7_34XqVhhpzDbwEtdiSPg7n2DbRNdI79VtI0XwHLwpceC-AtMGkzRc2gvAeHXWWcxVtxBqeGD60A/s256/AlienSyndrome-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguIvwlj2n5mlq54oUl7_894BwFf6lNalVFf-6QvgmAwICjoKXkgythmIygAzI0_6nqh5UIkG2rxyyaF_o61LaW8VkbcuoTVDrVlRuXLFZJtx8HxCY7_34XqVhhpzDbwEtdiSPg7n2DbRNdI79VtI0XwHLwpceC-AtMGkzRc2gvAeHXWWcxVtxBqeGD60A/s600/AlienSyndrome-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9Vo6N4oeGeCucDq8WT3tSEDXC-RmxWeYz1M3uG5EmOtaQ6mkxftG-UqRk_IW6oVg5l2vbzR3-4mrybJ4CnqdMbAGtLaEqNTCz-SqbzqzUNHYWuhONCgzOci2sLNisIFxDVgF8-V3Kw7eJiTczL0LeCt3BrJhGRHDBt6vwlDQ17Y2Yo_E0uJsjmZsEIUo/s256/BladeEagle-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9Vo6N4oeGeCucDq8WT3tSEDXC-RmxWeYz1M3uG5EmOtaQ6mkxftG-UqRk_IW6oVg5l2vbzR3-4mrybJ4CnqdMbAGtLaEqNTCz-SqbzqzUNHYWuhONCgzOci2sLNisIFxDVgF8-V3Kw7eJiTczL0LeCt3BrJhGRHDBt6vwlDQ17Y2Yo_E0uJsjmZsEIUo/s600/BladeEagle-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5XSKyV1fpr1xFqFfvbRUHYXRSMuKhgqP4NhB1qkHUBmtpLEcN5HEYRvOvQBy7Ug1UgPGDSzpwXWghoVaBKGJ_L6rKaxzNybKYb03jLJlEU5V963Ah_PGKM5SkfKgexfmy0gXre5DbbBndISGJ73_hobDfjRKcZUMBfH9GCrhwChXkjP9ac632NkZfUC4/s256/DickTracy-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5XSKyV1fpr1xFqFfvbRUHYXRSMuKhgqP4NhB1qkHUBmtpLEcN5HEYRvOvQBy7Ug1UgPGDSzpwXWghoVaBKGJ_L6rKaxzNybKYb03jLJlEU5V963Ah_PGKM5SkfKgexfmy0gXre5DbbBndISGJ73_hobDfjRKcZUMBfH9GCrhwChXkjP9ac632NkZfUC4/s600/DickTracy-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxqdzjDOVxdcZxmaVqmo44sfoROGHdVV5BHY9C5dKtI2NGi_XmNqp_QGrnGWW0PSYP3IFOzOVAUnp7mObRsh98PYCD0yPYoxo1HDOm8hcNlat9xwla0Wuafu4YENDVBGDxw1t21O0GjYuoufytc0HnbGV3B_wNd1F09NR9KriMKUNrAG2UJ36Ad_Hr4Ow/s256/JamesPond2CodenameRoboCod-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxqdzjDOVxdcZxmaVqmo44sfoROGHdVV5BHY9C5dKtI2NGi_XmNqp_QGrnGWW0PSYP3IFOzOVAUnp7mObRsh98PYCD0yPYoxo1HDOm8hcNlat9xwla0Wuafu4YENDVBGDxw1t21O0GjYuoufytc0HnbGV3B_wNd1F09NR9KriMKUNrAG2UJ36Ad_Hr4Ow/s600/JamesPond2CodenameRoboCod-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbHXtPtOjAdZRoJR6uMT80aRpW9uB5J6-lN2ue4cyll-AOeoz3Pv3zf8NVk9angEc-YhC9p3W1IomGiui4coe8BQk3R74QG0mKq9ljzCWDU2cwa5eBcfADm28db9CXKMghZ9un9qKeWDJt1wzoOp8dV8AfCd_pOGInQUOfBsxNvr964y84U-7yNN5V_UE/s256/RType-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbHXtPtOjAdZRoJR6uMT80aRpW9uB5J6-lN2ue4cyll-AOeoz3Pv3zf8NVk9angEc-YhC9p3W1IomGiui4coe8BQk3R74QG0mKq9ljzCWDU2cwa5eBcfADm28db9CXKMghZ9un9qKeWDJt1wzoOp8dV8AfCd_pOGInQUOfBsxNvr964y84U-7yNN5V_UE/s600/RType-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBq8cEj8S1Dl5GeSjZWmLsCN-pjErT9wqUCp_pOYx8XXDTvISNtVD80-viO-QrjQZrgh_tyUeP_qI_syKa0QjUbX4ueMhs5F6VdrotpxdgPTzeEccPofk4u4kTzqxJDL4yj70jMvCiz4afjAOQZ5-HKgeRwjs9rqV_WXKkrIImBmYZUeoRAB8-bAyxHr0/s256/Shinobi-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBq8cEj8S1Dl5GeSjZWmLsCN-pjErT9wqUCp_pOYx8XXDTvISNtVD80-viO-QrjQZrgh_tyUeP_qI_syKa0QjUbX4ueMhs5F6VdrotpxdgPTzeEccPofk4u4kTzqxJDL4yj70jMvCiz4afjAOQZ5-HKgeRwjs9rqV_WXKkrIImBmYZUeoRAB8-bAyxHr0/s600/Shinobi-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgco_IrLnOlBMLfbde-0uOBCZn4nMw64c_FPNRIQmSPncNRjVxIq6BvIYU-YW3F_Nfj-ByOXYC6t0ZcnBDHqCOPVV1nhU2PxSjjXt3L43Leq_s8_ZqOcI5yQ812XUV6PL56ghY69GGPt8Rk-DMFEBULYSMik_KpX0pwaQkpTVNPiAY6COUHIZVrEys0VlA/s256/SonicTheHedgehog-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgco_IrLnOlBMLfbde-0uOBCZn4nMw64c_FPNRIQmSPncNRjVxIq6BvIYU-YW3F_Nfj-ByOXYC6t0ZcnBDHqCOPVV1nhU2PxSjjXt3L43Leq_s8_ZqOcI5yQ812XUV6PL56ghY69GGPt8Rk-DMFEBULYSMik_KpX0pwaQkpTVNPiAY6COUHIZVrEys0VlA/s600/SonicTheHedgehog-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi19HvgCH9d07DfOVGHWtMRnW31CaI3IxxM_7M1z6ori7OrX-dPQoT8YKpNDcWO7KXk2CvrQXdXMlBItohhPyZhgJqlpTCsTBFq1gQaBMuqSIcT3iO9S1JHNRhqHnFLbuFx5DmMhgDsd6-Y-QhTu3FIxuPo9XzGwW7RvBgVJcMUJgXDg88PGJQs27NUYQ0/s256/Transbot-Sms.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi19HvgCH9d07DfOVGHWtMRnW31CaI3IxxM_7M1z6ori7OrX-dPQoT8YKpNDcWO7KXk2CvrQXdXMlBItohhPyZhgJqlpTCsTBFq1gQaBMuqSIcT3iO9S1JHNRhqHnFLbuFx5DmMhgDsd6-Y-QhTu3FIxuPo9XzGwW7RvBgVJcMUJgXDg88PGJQs27NUYQ0/s600/Transbot-Sms.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Sega Genesis&lt;/b&gt;&lt;br /&gt;
Launch retro games for the Sega Genesis [MD] 16-bit video game console with &lt;b&gt;.md&lt;/b&gt; supported ROM types:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install stable-retro&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install --upgrade pip&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/AlteredBeast-Genesis.py&quot;&gt;AlteredBeast-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/SonicTheHedgehog2-Genesis.py&quot;&gt;SonicTheHedgehog2-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/Flicky-Genesis.py&quot;&gt;Flicky-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/SonicTheHedgehog3-Genesis.py&quot;&gt;SonicTheHedgehog3-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/GhoulsnGhosts-Genesis.py&quot;&gt;GhoulsnGhosts-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/StreetsOfRage2-Genesis.py&quot;&gt;StreetsOfRage2-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/RevengeOfShinobi-Genesis.py&quot;&gt;RevengeOfShinobi-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting/blob/main/RetroCheatSheet/examples/Genesis/Strider-Genesis.py&quot;&gt;Strider-Genesis&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;!--&lt;br /&gt;--&gt;
&lt;!-- --&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiq_sCV31P7J5ePExSbnVkbowOWbTv29s7ZXtiN9-RwbHtAxN68J9Y13tiNDrXS2eP9wu4LTh_uH4O4bnGt3YS8v7qPB0arat1eSPilg7xilXjOhXmnZuh-ImBtBYysMeJaC2hGdoSOSQ7XxyKzHAXt0CKsrJ93A_XZYXHxk6ppRM9cpqiVFHdnhjvnmY/s320/AlteredBeast-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiq_sCV31P7J5ePExSbnVkbowOWbTv29s7ZXtiN9-RwbHtAxN68J9Y13tiNDrXS2eP9wu4LTh_uH4O4bnGt3YS8v7qPB0arat1eSPilg7xilXjOhXmnZuh-ImBtBYysMeJaC2hGdoSOSQ7XxyKzHAXt0CKsrJ93A_XZYXHxk6ppRM9cpqiVFHdnhjvnmY/s600/AlteredBeast-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD9K0Pu4cfhWmN95VNIAGz6tHVeFv8ENeOz9D-V4M2KamWaqNvVh_d4WqfPOh5jBiSMB6VdC7fBTIHtMx9jOiZs3oBlG30qFL-aDPsh51xRQC0sqVIaeNVPp5R88NmReubvwVR6t5x_injzXw2sb3e71CcMbiexqgFfG2xf4wdjnYxX5doGTVzCTtHIqc/s320/Flicky-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD9K0Pu4cfhWmN95VNIAGz6tHVeFv8ENeOz9D-V4M2KamWaqNvVh_d4WqfPOh5jBiSMB6VdC7fBTIHtMx9jOiZs3oBlG30qFL-aDPsh51xRQC0sqVIaeNVPp5R88NmReubvwVR6t5x_injzXw2sb3e71CcMbiexqgFfG2xf4wdjnYxX5doGTVzCTtHIqc/s600/Flicky-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv750Y48-_VMNmVtbUM-CT135MqHzncBZpmBlSrtKVuzoNpmJi39Awh5qoVBgwOOHN3xwMAY3Oa-OwZLbM9Mh9xf31XmynEMQ4xs96c1cPoStB9PYhIQbeNm6KgA5I8ayPbBh_8tQYGYzsV-4OZ8qA4HZOzx87vhkF0QLWtC8ap4Xe-_A18hdawtE-dzU/s320/GhoulsnGhosts-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv750Y48-_VMNmVtbUM-CT135MqHzncBZpmBlSrtKVuzoNpmJi39Awh5qoVBgwOOHN3xwMAY3Oa-OwZLbM9Mh9xf31XmynEMQ4xs96c1cPoStB9PYhIQbeNm6KgA5I8ayPbBh_8tQYGYzsV-4OZ8qA4HZOzx87vhkF0QLWtC8ap4Xe-_A18hdawtE-dzU/s600/GhoulsnGhosts-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmTF9zOFbhF1wGIBM1vjj3NZY4YfUVQdUkMEwhajfy-VRNbUGnYpn64I9xn_d3Y34eVaqTIqAHZGylcmbm8XAWF5FWZNMbjl_zrZ5ERjyy7dTGtXuh7Xtpwhv-j1pnextyT8VlkGrMA3F_f3vq3j8onD4hSH9XiZiSrdQtNOm99zIGUezAREUKY7sKOzg/s320/RevengeOfShinobi-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmTF9zOFbhF1wGIBM1vjj3NZY4YfUVQdUkMEwhajfy-VRNbUGnYpn64I9xn_d3Y34eVaqTIqAHZGylcmbm8XAWF5FWZNMbjl_zrZ5ERjyy7dTGtXuh7Xtpwhv-j1pnextyT8VlkGrMA3F_f3vq3j8onD4hSH9XiZiSrdQtNOm99zIGUezAREUKY7sKOzg/s600/RevengeOfShinobi-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimMC2BTDo7xYUIRM00tdghsxUpM5wrByYsLSGLnh1Xu6KjzCuz8MuKJH5RhoBCp10Jjm7Gpg2nIq06dSK5jadev-2TYH1OiVFRdkjP8FFQRLgBkUxmrPoifT1Gz7qB9scgGSu8NNVWx7Pu7qsgjllUZwTKZ-HEs7Ta5jom6zE1g6QNLcNYUmfhhAMMrPY/s320/SonicTheHedgehog2-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimMC2BTDo7xYUIRM00tdghsxUpM5wrByYsLSGLnh1Xu6KjzCuz8MuKJH5RhoBCp10Jjm7Gpg2nIq06dSK5jadev-2TYH1OiVFRdkjP8FFQRLgBkUxmrPoifT1Gz7qB9scgGSu8NNVWx7Pu7qsgjllUZwTKZ-HEs7Ta5jom6zE1g6QNLcNYUmfhhAMMrPY/s600/SonicTheHedgehog2-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPIIjFczf4pmMckshYcr_8wlJ0Q6lRQe-LmXzPetlYMNPhB_LGkl68T-W2Ak-k8Jw-ma3aiJOnlp16fNA0zxOPP26F0D9t8SRF2Pg7QOMsCazDDUpP3E1VKeV8LMwM26b1FNLlvbCVmXLt2hyLbtizXPXOUpDlE6oUDBpTjHMmakxCqP-k2V12Q13WGGo/s320/SonicTheHedgehog3-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPIIjFczf4pmMckshYcr_8wlJ0Q6lRQe-LmXzPetlYMNPhB_LGkl68T-W2Ak-k8Jw-ma3aiJOnlp16fNA0zxOPP26F0D9t8SRF2Pg7QOMsCazDDUpP3E1VKeV8LMwM26b1FNLlvbCVmXLt2hyLbtizXPXOUpDlE6oUDBpTjHMmakxCqP-k2V12Q13WGGo/s600/SonicTheHedgehog3-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim1BH-74ntg6Ma6s9Ap1HsOlXW4G5f1Ek7c2rYTH7vVjHszpBnumxUVwYDGqagNgIuzopyqJNYXow7Mj_ZDa7J_MUtk62XVJAMoEi58lqsVdYs-zHZKa7sE-CBe6aXFm6FzIGHQZ1LZodro8ut1DSfNTfCINHUctjTRHS58HYFr2khF3ocwOnH2VuTDRM/s320/StreetsOfRage2-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim1BH-74ntg6Ma6s9Ap1HsOlXW4G5f1Ek7c2rYTH7vVjHszpBnumxUVwYDGqagNgIuzopyqJNYXow7Mj_ZDa7J_MUtk62XVJAMoEi58lqsVdYs-zHZKa7sE-CBe6aXFm6FzIGHQZ1LZodro8ut1DSfNTfCINHUctjTRHS58HYFr2khF3ocwOnH2VuTDRM/s600/StreetsOfRage2-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbNPv0UBNMtyZcSXLe9DQvZdEY4LmXRIfqIKxt_hCeWKspSQFH0rpS30_xSLhBpv6RCzyAXyUDC1piy4Eaf-LqBqIUWg1ya7DAeCqRM6D_da-tGPT8LJZjM1nswUSS4YVBIuj__mwUc6By0cB5j3fvKctPKN7i8d1gkQQ9cFj1o1km2ncMr9HBhqbaGps/s320/Strider-Genesis.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbNPv0UBNMtyZcSXLe9DQvZdEY4LmXRIfqIKxt_hCeWKspSQFH0rpS30_xSLhBpv6RCzyAXyUDC1piy4Eaf-LqBqIUWg1ya7DAeCqRM6D_da-tGPT8LJZjM1nswUSS4YVBIuj__mwUc6By0cB5j3fvKctPKN7i8d1gkQQ9cFj1o1km2ncMr9HBhqbaGps/s600/Strider-Genesis.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;i&gt;YouTube&lt;/i&gt;&lt;br /&gt;
&lt;iframe width=&quot;98%&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/A-Ey1Ss1tF8&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Pull Request&lt;/u&gt;&lt;br /&gt;
Finally, setup Pull Request for future contributions.  Navigate to &lt;a href=&quot;https://github.com/Farama-Foundation/stable-retro&quot;&gt;stable-retro&lt;/a&gt; source repo and Create new fork
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8VxWO4o0fC86pHr5yvjYlSnp0z08QJETcv7ezILRV97KKR7KmVN_wmsX6X8_ozRWiKKITYakeXisNG_ipQTFOE259tIM2odxjg11Up5JBacs9XB5vhQF5nYOTnqax3eP56MRnsU-GJsY-qx6t1PlbLq6a13AnYZajPEP9Y-fYPBmOIKtgIzT-xWNT6Xc/s960/ForkRetro02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8VxWO4o0fC86pHr5yvjYlSnp0z08QJETcv7ezILRV97KKR7KmVN_wmsX6X8_ozRWiKKITYakeXisNG_ipQTFOE259tIM2odxjg11Up5JBacs9XB5vhQF5nYOTnqax3eP56MRnsU-GJsY-qx6t1PlbLq6a13AnYZajPEP9Y-fYPBmOIKtgIzT-xWNT6Xc/s600/ForkRetro02.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Git clone the stable-retro forked source code repository and setup the following Git username and user email
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git config --global --get user.name&lt;br /&gt;
&amp;nbsp;git config --global --get user.email&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git config --global user.name &quot;SteveProXNA&quot;&lt;br /&gt;
&amp;nbsp;git config --global user.email &quot;steven_boland@hotmail.com&quot;&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Next, configure the stable-retro upstream destination code repository in order to complete any Pull Request:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git remote -v&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git remote add upstream git@github.com:Farama-Foundation/stable-retro.git&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;origin&lt;br /&gt;
&amp;nbsp;origin&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git@github.com:SteveProXNA/stable-retro.git (fetch)&lt;br /&gt;
&amp;nbsp;git@github.com:SteveProXNA/stable-retro.git (push)&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;upstream&lt;br /&gt;
&amp;nbsp;upstream&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git@github.com:Farama-Foundation/stable-retro.git (fetch)&lt;br /&gt;
&amp;nbsp;git@github.com:Farama-Foundation/stable-retro.git (push)&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;	
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlUSVFCkjK3s1xovOLU6rutW2a0boHTsdMk7-6Sr2sy6FWDzlPSQawUlPBjBOaTshnDP2OvN-WF65pfgelU1rnEmd6JVJvNow4t-pmMns_n4ScPGujT2Y3UrxTK8Nu6bXs66IgGim5y5iAbuBBLaJ9-Ni3nCf8lmUtwB5z4tZgBHYPN1oDAXEmhCe33Dc/s1168/ForkRetro05.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlUSVFCkjK3s1xovOLU6rutW2a0boHTsdMk7-6Sr2sy6FWDzlPSQawUlPBjBOaTshnDP2OvN-WF65pfgelU1rnEmd6JVJvNow4t-pmMns_n4ScPGujT2Y3UrxTK8Nu6bXs66IgGim5y5iAbuBBLaJ9-Ni3nCf8lmUtwB5z4tZgBHYPN1oDAXEmhCe33Dc/s600/ForkRetro05.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;
Launch PyCharm | Open Stable-Retro | Create virtual environment | Pip install all dependencies as required:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&amp;nbsp;pip install -e .&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;pip install --upgrade pip&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!-- --&gt;
&lt;br /&gt;
IMPORTANT&lt;br /&gt;
If Python Interpreter not set and/or Virtual Environment not available then choose File | Settings... | Project: Python Interpreter | Add Interpreter | Add Local Interpreter.  Launch terminal: &lt;b&gt;source .venv/bin/activate&lt;/b&gt;.  
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhklqJyB2zdNqzpUNuZK0_1w23t5vpIa1g76MxeuAxkYLKz7aQ8N8G-ZImdd6XbLIJJSjojfapdacR2fxVDDvRB4IyiJhY6w0QNGoTGRRFC-aZjignRYfc62jWk7qzo2ODxeDdrS_rZEMtnSPHEaTySdDjJy5-q8XgWxXW3Oedh-o0jGLioy4hZq9A8wDg/s1028/StableRetroVenv.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhklqJyB2zdNqzpUNuZK0_1w23t5vpIa1g76MxeuAxkYLKz7aQ8N8G-ZImdd6XbLIJJSjojfapdacR2fxVDDvRB4IyiJhY6w0QNGoTGRRFC-aZjignRYfc62jWk7qzo2ODxeDdrS_rZEMtnSPHEaTySdDjJy5-q8XgWxXW3Oedh-o0jGLioy4hZq9A8wDg/s600/StableRetroVenv.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;b&gt;Examples&lt;/b&gt;&lt;br /&gt;
Navigate to the &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/retro/examples&quot;&gt;examples&lt;/a&gt; sub-directory.  Checkout &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/blob/master/retro/examples/trivial_random_agent.py&quot;&gt;trivial_random_agent.py&lt;/a&gt; which should resemble the Hello Stable-Retro program above.  Airstriker-Genesis ROM is included by default.  Copy your Sega games into the corresponding &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/retro/data&quot;&gt;data&lt;/a&gt; directory stable | game directory.  Update name to the game ROM name.  Execute script! 
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKtFPBHqFB5caLiqALuZIUjz_YizrDwV4HV0aUwx8XtPvB6jFuFWgdC9_gNrHkHBAbu7HMlYfnitnC2ARa2YeUGAhmulYIIsoGdNZOJlVUjIzJPMsfw-PLMlWCWqMKO25rKtdR5tP6RpWpim4xXKbTEvrqKdF70Zo0wy_TbIjdYdjeEkPbrGYK84NjrJc/s1009/PyCharmDebugGames.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKtFPBHqFB5caLiqALuZIUjz_YizrDwV4HV0aUwx8XtPvB6jFuFWgdC9_gNrHkHBAbu7HMlYfnitnC2ARa2YeUGAhmulYIIsoGdNZOJlVUjIzJPMsfw-PLMlWCWqMKO25rKtdR5tP6RpWpim4xXKbTEvrqKdF70Zo0wy_TbIjdYdjeEkPbrGYK84NjrJc/s600/PyCharmDebugGames.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;b&gt;Tests&lt;/b&gt;&lt;br /&gt;
Navigate to the &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/test_python&quot;&gt;test_python&lt;/a&gt; sub-diretory.  Open any test file | right click | Run test or Debug test to step thru source code.  Important: you may need to install the pytest package if you get usual ModuleNotFound error:
&lt;!--&lt;br /&gt;--&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&amp;nbsp;pip install pytest&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;pip install --upgrade pip&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;!--&lt;br /&gt;--&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4mrkMSb0-L771AIHOQQYGEo_xMOEVk3dY1jeIpTvV4q6su0H1HqqwdAO3dtgqsBHRLM6qsEw0Np4tsY7W4uuz2RfBCFKV8a2_qoGVg2-sFamRP1GqMK4Sib6A02PadukuhRoHSx72O4ZC5blILsPRBKyvA7e3drbQE45VPROT65w2fmSV8-mxXMstGoQ/s1009/PyCharmDebugTests.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4mrkMSb0-L771AIHOQQYGEo_xMOEVk3dY1jeIpTvV4q6su0H1HqqwdAO3dtgqsBHRLM6qsEw0Np4tsY7W4uuz2RfBCFKV8a2_qoGVg2-sFamRP1GqMK4Sib6A02PadukuhRoHSx72O4ZC5blILsPRBKyvA7e3drbQE45VPROT65w2fmSV8-mxXMstGoQ/s600/PyCharmDebugTests.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Game Integration&lt;/u&gt;&lt;br /&gt;
As per the official Gym Retro &lt;a href=&quot;https://retro.readthedocs.io/en/latest/integration.html&quot;&gt;docs&lt;/a&gt; Integrating a game means taking a video game ROM file and setting it up as a reinforcement learning environment by defining 3 things: #1 A starting state, #2 A reward function, #3 A done condition.  However, in order to integrate a new game we must have the Game Integration tool &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/blob/master/docs/developing.md#linux&quot;&gt;setup&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Integration UI&lt;/b&gt;&lt;br /&gt;
Follow instructions as per &lt;a href=&quot;https://www.youtube.com/watch?v=lPYWaUAq_dY&quot;&gt;video&lt;/a&gt; to install all dependencies then build Game Integration UI tool and launch: 
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&amp;nbsp;sudo apt-get update&lt;br /&gt;
&amp;nbsp;sudo apt-get install capnproto&lt;br /&gt;
&amp;nbsp;sudo apt-get install libcapnp-dev&lt;br /&gt;
&amp;nbsp;sudo apt-get install libqt5opengl5-dev&lt;br /&gt;
&amp;nbsp;sudo apt-get install qtbase5-dev&lt;br /&gt;
&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;
&amp;nbsp;sudo apt-get install zlib1g-dev&lt;br /&gt;
&amp;nbsp;sudo apt autoremove&lt;br /&gt;
&amp;nbsp;cmake . -DBUILD_UI=ON -UPYLIB_DIRECTORY&lt;br /&gt;
&amp;nbsp;make -j$(grep -c ^processor /proc/cpuinfo)&lt;br /&gt;
&amp;nbsp;./gym-retro-integration&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitrgpRmJc8qiIt-b8S6W2NgllKTfrzpp1Jrk0v_aOwfcP4_nf9MlkqfMdO16OaWIV4UE4OkafeVYtWH5uowMi4dtm8kG1JnmLa-xcRfYbXpsAUVOW29fpFA1G1PaScUTZ6J5WeOKVHoPJeqxWAg4vtjvmXnUQuH0aHbV-wTzyUXZ6hoJcjgGTeFxjprxs/s1055/gym-retro-integration.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitrgpRmJc8qiIt-b8S6W2NgllKTfrzpp1Jrk0v_aOwfcP4_nf9MlkqfMdO16OaWIV4UE4OkafeVYtWH5uowMi4dtm8kG1JnmLa-xcRfYbXpsAUVOW29fpFA1G1PaScUTZ6J5WeOKVHoPJeqxWAg4vtjvmXnUQuH0aHbV-wTzyUXZ6hoJcjgGTeFxjprxs/s600/gym-retro-integration.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;i&gt;Supported ROMs&lt;/i&gt;&lt;br /&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/ROM_image&quot;&gt;ROM&lt;/a&gt; files contain the game itself.  Each system has a unique file extension to denote the compatible system:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;EXTN&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;SYSTEM&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;EXAMPLE&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;a26&lt;/td&gt;&lt;td&gt;&amp;nbsp;Atari 2600&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/automaton.a26&quot;&gt;automaton.a26&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;gb&lt;/td&gt;&lt;td&gt;&amp;nbsp;Nintendo Game Boy&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/dox-fire.gb&quot;&gt;dox-fire.gb&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;gba&lt;/td&gt;&lt;td&gt;&amp;nbsp;Nintendo Game Boy Advance&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/Vantage-LostMarbles.gba&quot;&gt;Vantage-LostMarbles.gba&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;gg&lt;/td&gt;&lt;td&gt;&amp;nbsp;Sega Game Gear&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/benryves-SegaTween.gg&quot;&gt;benryves-SegaTween.gg&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;md&lt;/td&gt;&lt;td&gt;&amp;nbsp;Sega Genesis [Mega Drive]&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/Dekadence-Dekadrive.md&quot;&gt;Dekadence-Dekadrive.md&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;nes&lt;/td&gt;&lt;td&gt;&amp;nbsp;Nintendo Entertainment System [Famicom]&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/Dr88-FamiconIntro.nes&quot;&gt;Dr88-FamiconIntro.nes&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;pce&lt;/td&gt;&lt;td&gt;&amp;nbsp;NEC TurboGrafx-16 [PC Engine]&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/chrisc-512_Colours.pce&quot;&gt;chrisc-512_Colours.pce&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;sfc&lt;/td&gt;&lt;td&gt;&amp;nbsp;Super Nintendo Entertainment System [Super Famicom]&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/Anthrox-SineDotDemo.sfc&quot;&gt;Anthrox-SineDotDemo.sfc&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;sms&lt;/td&gt;&lt;td&gt;&amp;nbsp;Sega Master System&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/tree/master/tests/roms/blind-happy10.sms&quot;&gt;blind-happy10.sms&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!--&lt;br /&gt;--&gt;
Launch CLion | Open Stable-Retro.  Navigate to &lt;b&gt;src/ui&lt;/b&gt; folder.  Open &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/blob/master/src/ui/main.cpp&quot;&gt;main.cpp&lt;/a&gt;.  Click &quot;Select CMakeLists.txt&quot;:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Vrfi-B9Y0-tnvxH9lcEjhQzq4DL-zHMune-S3HPZapo1tQhB8sPUKUlR7c_HKsPmjNoVQ1ry0OkP0CEPijk3PKZSfCmy20CSoAygSmpNbIJ5fqkIsUfCepGkONz2Sv2kmE6267rFFw_IqRHzrkVDDonH_qvbNNxKv7VuNEvGrJVPyo4mXAUSsuKAKqY/s979/SelectCMakeLists01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Vrfi-B9Y0-tnvxH9lcEjhQzq4DL-zHMune-S3HPZapo1tQhB8sPUKUlR7c_HKsPmjNoVQ1ry0OkP0CEPijk3PKZSfCmy20CSoAygSmpNbIJ5fqkIsUfCepGkONz2Sv2kmE6267rFFw_IqRHzrkVDDonH_qvbNNxKv7VuNEvGrJVPyo4mXAUSsuKAKqY/s600/SelectCMakeLists01.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;&lt;br /&gt;
Navigate to &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/blob/master/CMakeLists.txt&quot;&gt;CMakeLists.txt&lt;/a&gt; file | OK | Trust Project.  Afterwards CLion will index the project and update all symbols.  Click Edit configurations drop down list.  Choose gym-retro-integration | Debug.  Click Debug icon:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmrdKo5Zl7dboWF6fRSOHMobQr7uTDIdvTDtCPMeHxgCnNrLe__guVJL7NVQngEUP0ZJHO55xnDm40NIXqOLQ8xlGJ-rBipq-zDnVcDpaTfRYI4UMm-wfld-dNC2tMwnCNQWpLFGLaJGxs9BaL8XlASahiddeeSEa7OKium2H9uxRxaMtJsRWtMdAWt7Q/s1040/gym-retro-integration-debug.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmrdKo5Zl7dboWF6fRSOHMobQr7uTDIdvTDtCPMeHxgCnNrLe__guVJL7NVQngEUP0ZJHO55xnDm40NIXqOLQ8xlGJ-rBipq-zDnVcDpaTfRYI4UMm-wfld-dNC2tMwnCNQWpLFGLaJGxs9BaL8XlASahiddeeSEa7OKium2H9uxRxaMtJsRWtMdAWt7Q/s600/gym-retro-integration-debug.png&quot;/&gt;&lt;/a&gt;
&lt;!-- --&gt;
&lt;br /&gt;&lt;br /&gt;
Finally, debug tests.  Navigate to &lt;b&gt;tests&lt;/b&gt; folder.  Open &lt;a href=&quot;https://github.com/SteveProXNA/stable-retro/blob/master/tests/data.cpp&quot;&gt;data.cpp&lt;/a&gt;.  Choose tests-data | Debug.  Click Debug icon:  
&lt;br /&gt;
&lt;!-- --&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8H2yhl_zDDGIHNHNfxyyvozvjT95YOsgMpVxiJcKty49mGju62FhyphenhyphenjYc_net2zugwYAR5i4bS7Z2Bx_Xef0z7sI3hdiWSt_bcXJApIRu8oR5RVMVUUFawh0IbTIAMX88o89KY8iisNtUg6xe4Hzg5nSB4pahq660TTS-QyEn8Nv8uq8t3pTM37INgDUc/s1040/gym-retro-integration-tests.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8H2yhl_zDDGIHNHNfxyyvozvjT95YOsgMpVxiJcKty49mGju62FhyphenhyphenjYc_net2zugwYAR5i4bS7Z2Bx_Xef0z7sI3hdiWSt_bcXJApIRu8oR5RVMVUUFawh0IbTIAMX88o89KY8iisNtUg6xe4Hzg5nSB4pahq660TTS-QyEn8Nv8uq8t3pTM37INgDUc/s600/gym-retro-integration-tests.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;Process&lt;/u&gt;&lt;br /&gt;
Now that we have built the Game Integration tool setup either directly from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Command-line_interface&quot;&gt;CLI&lt;/a&gt; and/or built from source it is now possible to &lt;a href=&quot;https://medium.com/aureliantactics/integrating-new-games-into-retro-gym-12b237d3ed75&quot;&gt;integrate&lt;/a&gt; new games into Gym-Retro.  This process involves: #1 Creating states for Gym Retro environment to load, #2 Inspect ROM memory for points of interest, #3 Find those address and types.
&lt;br /&gt;&lt;br /&gt;
The following videos on OpenAI Game Integration tool &lt;a href=&quot;https://www.youtube.com/watch?v=lPYWaUAq_dY&quot;&gt;Part 1&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/watch?v=RZhf_ovCNWk&quot;&gt;Part 2&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/watch?v=kZAxM7QIq6k&quot;&gt;Part 3&lt;/a&gt; give some excellent examples on how to implement this process + create the following necessary files in order to Integrate brand new games:
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Files&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;State file&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Savestate from game beginning.  Restart the environment puts agent at this point in the game&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;data.json
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Defines the list of game-related variables that Python sees based on game memory addresses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;scenario
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;JSON file defines the reward function and done condition using variables defined at data.json
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;metadata
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;JSON file defines starting state if no state specified by user and miscellaneous debugging info
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have now setup Stable Retro environments for classic 8-bit video game systems like the Sega Master System and 16-bit video game systems like the Sega Genesis [MD] the next step would be to use reinforcement learning to train a bot to play classic emulated video games using this Gym Retro &lt;a href=&quot;https://github.com/andruschak/openai-gym-retro&quot;&gt;setup&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Consequently, Python &lt;a href=&quot;https://neat-python.readthedocs.io/en/latest&quot;&gt;NEAT&lt;/a&gt; is a popular library for training neural networks using genetic algorithms.  There is an excellent Open AI and NEAT &lt;a href=&quot;https://www.youtube.com/playlist?list=PLTWFMbPFsvz3CeozHfeuJIXWAJMkPtAdS&quot;&gt;Tutorial&lt;/a&gt; series that integrates Sonic the Hedgehog as a testbed for applied reinforcement learning to provide a rich, rewarding, and visually complex environment that is well-suited for evolving neural networks.  Ultimate goal: would be to use this as inspiration to integrate more Indie games!
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2024/11/openai-retro-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPg5lDn5BIDcj0-l8C-P-tTwHoFTFbPHaOFt0LcF-7Oc7-5teLiMO0y9Od48m4ZJRZ5IXWBQczz1YQ-V4DhZ-I3Xg6kkxdhj6qv52OWb1IALk1TXgRYu24MELKHgpGyj_b4NVMJ9nd-bLnHD2U8NwvhyphenhyphenUrB7K3OKx6kFoSXBNTSQk-H3KSjfllSXJmGVE/s72-c/Strider-Genesis.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-5099277125358675741</guid><pubDate>Sun, 15 Sep 2024 09:00:00 +0000</pubDate><atom:updated>2025-11-19T10:11:49.919-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">OpenAI</category><title>OpenAI Farma Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;  
&lt;a href=&quot;https://en.wikipedia.org/wiki/OpenAI&quot;&gt;OpenAI&lt;/a&gt; is an American Artificial Intelligence [&lt;a href=&quot;https://en.wikipedia.org/wiki/Artificial_intelligence&quot;&gt;AI&lt;/a&gt;] research organization founded Dec-2015 head-quartered in San Francisco.  In April 2016, OpenAI released a public beta of &quot;&lt;a href=&quot;https://wandb.ai/mukilan/intro_to_gym/reports/A-Gentle-Introduction-to-OpenAI-Gym--VmlldzozMjg5MTA3&quot;&gt;OpenAI Gym&lt;/a&gt;&quot;: its platform for reinforcement learning research.  Reinforcement Learning [&lt;a href=&quot;https://en.wikipedia.org/wiki/Reinforcement_learning&quot;&gt;RL&lt;/a&gt;] is an interdisciplinary area of machine learning and optimal control concerned with how an agent takes action in environment in order to maximize cumulative rewards.
&lt;br /&gt;&lt;br /&gt;
In 2021, the non-profit organization Farama Foundation took over &lt;a href=&quot;https://github.com/openai/gym&quot;&gt;Gym&lt;/a&gt;.  They &lt;a href=&quot;https://farama.org/Announcing-The-Farama-Foundation&quot;&gt;introduced&lt;/a&gt; new features into Gym and renamed the library to &lt;a href=&quot;https://github.com/Farama-Foundation/Gymnasium&quot;&gt;Gymnasium&lt;/a&gt; where the future maintenance of OpenAI Gym will take place.  
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJhCe_LjUoggkw1yWQy5g_ExXAmT4IuCvAsa1en_FFKzxvclCmh8JG3SXJza1WES-LTd3NxizAJPykC1zP-4HlmNNaf2gFNUFlHWGjEeeXGsPNDHos-YdPMnZy-8PlsurebkkPGUVfJYa908O7Si10Nn_3YQlMMCz_3OB2Kyf5pBvZ2CuhgE2hZUW_R2o/s856/Pacman-v5.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJhCe_LjUoggkw1yWQy5g_ExXAmT4IuCvAsa1en_FFKzxvclCmh8JG3SXJza1WES-LTd3NxizAJPykC1zP-4HlmNNaf2gFNUFlHWGjEeeXGsPNDHos-YdPMnZy-8PlsurebkkPGUVfJYa908O7Si10Nn_3YQlMMCz_3OB2Kyf5pBvZ2CuhgE2hZUW_R2o/s600/Pacman-v5.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out!  
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Gym&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/openai/gym&quot;&gt;OpenAI Gym&lt;/a&gt; is an open source Python library for developing reinforcement learning algorithms by providing standard API to communicate between algorithms and environments.  Gym soon became widely &lt;a href=&quot;https://wandb.ai/mukilan/intro_to_gym/reports/A-Gentle-Introduction-to-OpenAI-Gym--VmlldzozMjg5MTA3&quot;&gt;adopted&lt;/a&gt; by the community for creating and training algorithms in various environments for AI Reinforcement Learning.   
&lt;br /&gt;&lt;br /&gt;
Gym provides a wide range of &lt;a href=&quot;https://www.linkedin.com/pulse/exploring-differences-gym-gymnasium-environments-learning-sabir-ali&quot;&gt;environments&lt;/a&gt;, including classic control problems, Atari games, and robotics.  Gym also includes set of tools for monitoring and evaluating performance of reinforcement learning agents.
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Hello Gym&lt;/b&gt;&lt;br /&gt;
Creating a &lt;a href=&quot;https://github.com/openai/gym&quot;&gt;Gym&lt;/a&gt; environment e.g. Cart Pole.  Launch PyCharm | New Project | Name: HelloCartPoleGym [~/]
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFYBv5FzQAKxm7-2AcSy2myXRROMlD3sS9syfRm-nBC5oi9YFiBJIJF-IAKWzMkvHsq9eERXeJR-wlMUsmFnx5HuyrD7RUW0RXdTICn4AZ6m1mGIumLOUMDTVMy_sxSpjByL4a2NKLd7JpG-pzDGra7igd8rTyGU5RoPryGvhGW2TORfha1V9NGhDuDrE/s800/PyCharmGym.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFYBv5FzQAKxm7-2AcSy2myXRROMlD3sS9syfRm-nBC5oi9YFiBJIJF-IAKWzMkvHsq9eERXeJR-wlMUsmFnx5HuyrD7RUW0RXdTICn4AZ6m1mGIumLOUMDTVMy_sxSpjByL4a2NKLd7JpG-pzDGra7igd8rTyGU5RoPryGvhGW2TORfha1V9NGhDuDrE/s600/PyCharmGym.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;source .venv/bin/activate&lt;br /&gt;
&amp;nbsp;pip install --upgrade pip&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;pip install gym&lt;br /&gt;
&amp;nbsp;pip install gym[classic_control]&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
CODE
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;import gym&lt;br /&gt;
&amp;nbsp;env = gym.make(&quot;CartPole-v1&quot;, render_mode=&quot;human&quot;)&lt;br /&gt;
&amp;nbsp;observation, info = env.reset(seed=42)&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;for _ in range(1000):&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action = env.action_space.sample()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation, reward, terminated, truncated, info = env.step(action)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if terminated or truncated:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation, info = env.reset()&lt;br /&gt;
&amp;nbsp;env.close()&lt;br /&gt;
&lt;/tr&gt;&lt;/td&gt;
&lt;/table&gt;
YouTube videos online also introduce OpenAI Gym but include &lt;a href=&quot;https://www.youtube.com/watch?v=Vrro7W7iW2w&quot;&gt;Frozen Lake&lt;/a&gt; environment and &lt;a href=&quot;https://www.youtube.com/watch?v=tkDIb8yl69g&quot;&gt;Atari Breakout&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Gymnasium&lt;/u&gt;&lt;br /&gt;
The main problem with Gym was the lack of &lt;a href=&quot;https://wandb.ai/mukilan/intro_to_gym/reports/A-Gentle-Introduction-to-OpenAI-Gym--VmlldzozMjg5MTA3&quot;&gt;maintenance&lt;/a&gt;: OpenAI did not allocate substantial resources for the development of Gym since its inception seven years earlier and, by 2020, it simply was not maintained.
&lt;br /&gt;&lt;br /&gt;
&lt;a href=&quot;https://gymnasium.farama.org&quot;&gt;Gymnasium&lt;/a&gt; is a maintained fork of the OpenAI Gym library. The Gymnasium interface is simple, pythonic, and capable of representing general RL problems with a compatibility wrapper for old Gym environments:
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Hello Gymnasium&lt;/b&gt;&lt;br /&gt;
Creating &lt;a href=&quot;https://github.com/Farama-Foundation/Gymnasium&quot;&gt;/Gymnasium&lt;/a&gt; environment e.g. Cart Pole.  Launch PyCharm | New Project | HelloCartPoleGymnasium
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgQM_RjJcX6kI8nzyt0TADpI_ea4k92LBYGRLaIboIuvk_iB9fqhXDOpfpwztJecdRkApQvmzeSI7fRJgw7D_pLHIqgJisIrwcLgn_ZkZix2ILTVIwoKnQ-FnSF4zwDA3z35EmFr3APtTK2JaSw6yiFkRjF71zwwQvjd_6Pm7Bg1cPeTPJ9sfBVrh0Udc/s800/PyCharmGymnasium.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgQM_RjJcX6kI8nzyt0TADpI_ea4k92LBYGRLaIboIuvk_iB9fqhXDOpfpwztJecdRkApQvmzeSI7fRJgw7D_pLHIqgJisIrwcLgn_ZkZix2ILTVIwoKnQ-FnSF4zwDA3z35EmFr3APtTK2JaSw6yiFkRjF71zwwQvjd_6Pm7Bg1cPeTPJ9sfBVrh0Udc/s600/PyCharmGymnasium.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;source .venv/bin/activate&lt;br /&gt;
&amp;nbsp;pip install --upgrade pip&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;pip install gymnasium&lt;/br&gt;
&amp;nbsp;pip install gymnasium[classic-control]&lt;/br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
CODE  
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;import gymnasium as gym&lt;br /&gt;
&amp;nbsp;env = gym.make(&quot;CartPole-v1&quot;, render_mode=&quot;human&quot;)&lt;br /&gt;
&amp;nbsp;observation, info = env.reset(seed=42)&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;for _ in range(1000):&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;action = env.action_space.sample()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation, reward, terminated, truncated, info = env.step(action)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if terminated or truncated:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;observation, info = env.reset()&lt;br /&gt;
&amp;nbsp;env.close()&lt;br /&gt;
&lt;/tr&gt;&lt;/td&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;i&gt;Differences&lt;/i&gt;&lt;br /&gt;
While both Gym and Gymnasium are powerful tools for creating &lt;a href=&quot;https://www.linkedin.com/pulse/exploring-differences-gym-gymnasium-environments-learning-sabir-ali&quot;&gt;environments&lt;/a&gt; for reinforcement learning, it makes more &lt;a href=&quot;https://ai.stackexchange.com/questions/41763/should-i-make-my-environment-with-gym-or-gymnasium&quot;&gt;sense&lt;/a&gt; to prefer Gymnasium going forward as technically future support for Gym there is none.  Note: old &lt;i&gt;import gym&lt;/i&gt; &lt;a href=&quot;https://www.gymlibrary.dev&quot;&gt;documentation&lt;/a&gt; is replaced with &lt;i&gt;import gymnasium as gym&lt;/i&gt; convention going forward.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Farama Examples&lt;/u&gt;&lt;br /&gt;
Complete all Farama examples!  Create &lt;a href=&quot;https://github.com/SteveProXNA/OpenAItesting&quot;&gt;OpenAI Test&lt;/a&gt; repo.  Launch PyCharm | New Project | FarmaCheatSheet
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkW0x-SxwUG_DvRu9NWsEog5UKHsMPbL8W-OgnfyyBYvp7fbw2LytBfX-ghNYeuMx9muoO8bBRUsXw8gzBWQ6C-ml9OS-6bzkdQ34MbeczaIXE7WJHPmUUUy5k3C34g_M453KngGU2_V6Ey4CMSrulrNQ58hMbmN2i1p-fvDsA5hcYWlMrWjEIRRWD6Ag/s800/FarmaCheatSheetProject.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkW0x-SxwUG_DvRu9NWsEog5UKHsMPbL8W-OgnfyyBYvp7fbw2LytBfX-ghNYeuMx9muoO8bBRUsXw8gzBWQ6C-ml9OS-6bzkdQ34MbeczaIXE7WJHPmUUUy5k3C34g_M453KngGU2_V6Ey4CMSrulrNQ58hMbmN2i1p-fvDsA5hcYWlMrWjEIRRWD6Ag/s600/FarmaCheatSheetProject.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
IMPORTANT&lt;br /&gt;
If Python Interpreter not set and/or Virtual Environment not available then choose File | Settings... | Project: Python Interpreter | Add Interpreter | Add Local Interpreter.  Launch terminal: &lt;b&gt;source .venv/bin/activate&lt;/b&gt;.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKADNoMvONzUGdEvZZxPYmaQO5cwJ06Pp0Oyy04JyPjJ3tkZZ2wSva1l6pZBOQpAvqLJY0FIt1dSTtmdOVw4UuI-PsaDX-ylyGDxgLWOfKaW6e38xhKWj7GpGSR4pVMwEKXgzQAzrjC_MaqCrHAIgWzs1PS8iSnH7F-BP-kxH_0qeEYjC8WpQ7ea67Mzs/s1028/FarmaCheatSheetVenv.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKADNoMvONzUGdEvZZxPYmaQO5cwJ06Pp0Oyy04JyPjJ3tkZZ2wSva1l6pZBOQpAvqLJY0FIt1dSTtmdOVw4UuI-PsaDX-ylyGDxgLWOfKaW6e38xhKWj7GpGSR4pVMwEKXgzQAzrjC_MaqCrHAIgWzs1PS8iSnH7F-BP-kxH_0qeEYjC8WpQ7ea67Mzs/s600/FarmaCheatSheetVenv.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Copy the official Gymnasium &lt;i&gt;&lt;a href=&quot;https://github.com/Farama-Foundation/Gymnasium/blob/main/docs/requirements.txt&quot;&gt;requirements.txt&lt;/a&gt;&lt;/i&gt; from the Farama Foundation GitHub repository docs directory:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;pip install -r requirements.txt&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;pip install --upgrade pip&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Classic Control&lt;/b&gt;&lt;br /&gt;
There are five &lt;a href=&quot;https://gymnasium.farama.org/environments/classic_control&quot;&gt;Classic Control&lt;/a&gt; environments which are stochastic in terms of initial state within given range.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td colspan=&quot;4&quot;&gt;&amp;nbsp;pip install gymnasium&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ClassicControl/Acrobot-v1.py&#39;&gt;Acrobot-v1&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ClassicControl/CartPole-v1.py&#39;&gt;CartPole-v1&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ClassicControl/MountainCar-v0.py&#39;&gt;MountainCar-v0&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ClassicControl/Pendulum-v1.py&#39;&gt;Pendulum-v1&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Toy Text&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://gymnasium.farama.org/environments/toy_text&quot;&gt;Toy Text&lt;/a&gt; environments are designed to be extremely simple, with small discrete state and action spaces, and hence easy to learn. They are suitable for debugging implementations of reinforcement learning algorithms.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td colspan=&quot;4&quot;&gt;&amp;nbsp;pip install gymnasium&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ToyText/Blackjack-v1.py&#39;&gt;Blackjack-v1&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ToyText/CliffWalking-v0.py&#39;&gt;CliffWalking-v0&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ToyText/FrozenLake-v1.py&#39;&gt;FrozenLake-v1&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/ToyText/Taxi-v3.py&#39;&gt;Taxi-v3&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Box2D&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://gymnasium.farama.org/environments/box2d&quot;&gt;Box2D&lt;/a&gt; environments involve toy games based around box2d physics control and PyGame-based rendering.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;pip install gymnasium&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;pip install Box2D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Box2D/BipedalWalker-v3.py&#39;&gt;BipedalWalker-v3&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Box2D/CarRacing-v2.py&#39;&gt;CarRacing-v2&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Box2D/LunarLander-v2.py&#39;&gt;LunarLander-v2&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;MuJoCo&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://gymnasium.farama.org/environments/mujoco&quot;&gt;MuJoCo&lt;/a&gt; [Multi-Joint dynamics with Contact] is physics engine for facilitating research and development in robotics, biomechanics, graphics and animation, also areas where fast and accurate simulation is needed.  
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;pip install gymnasium&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;pip install mujoco==2.3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/Ant-v4.py&#39;&gt;Ant-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/Humanoid-v4.py&#39;&gt;Humanoid-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/InvertedPendulum-v4.py&#39;&gt;InvertedPendulum-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/Swimmer-v4.py&#39;&gt;Swimmer-v4&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/HalfCheetah-v4.py&#39;&gt;HalfCheetah-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/HumanoidStandup-v4.py&#39;&gt;HumanoidStandup-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/Pusher-v4.py&#39;&gt;Pusher-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/Walker2d-v4.py&#39;&gt;Walker2d-v4&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/Hopper-v4.py&#39;&gt;Hopper-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/InvertedDoublePendulum-v4.py&#39;&gt;InvertedDoublePendulum-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/MuJoCo/Reacher-v4.py&#39;&gt;Reacher-v4&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Atari&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://gymnasium.farama.org/environments/atari&quot;&gt;Atari&lt;/a&gt; environments are simulated via the Arcade Learning Environment (ALE) through the Stella emulator.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;pip install gymnasium[atari]==0.29.1&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;pip install gymnasium[accept-rom-license]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Adventure-v5.py&#39;&gt;Adventure-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Defender-v5.py&#39;&gt;Defender-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/KeystoneKapers-v5.py&#39;&gt;KeystoneKapers-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Seaquest-v5.py&#39;&gt;Seaquest-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/AirRaid-v5.py&#39;&gt;AirRaid-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/DemonAttack-v5.py&#39;&gt;DemonAttack-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/KingKong-v5.py&#39;&gt;KingKong-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/SirLancelot-v5.py&#39;&gt;SirLancelot-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Alien-v5.py&#39;&gt;Alien-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/DonkeyKong-v5.py&#39;&gt;DonkeyKong-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Klax-v5.py&#39;&gt;Klax-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Skiing-v5.py&#39;&gt;Skiing-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Amidar-v5.py&#39;&gt;Amidar-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/DoubleDunk-v5.py&#39;&gt;DoubleDunk-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Koolaid-v5.py&#39;&gt;Koolaid-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Solaris-v5.py&#39;&gt;Solaris-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Assault-v5.py&#39;&gt;Assault-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Earthworld-v5.py&#39;&gt;Earthworld-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Krull-v5.py&#39;&gt;Krull-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/SpaceInvaders-v5.py&#39;&gt;SpaceInvaders-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Asterix-v5.py&#39;&gt;Asterix-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/ElevatorAction-v5.py&#39;&gt;ElevatorAction-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/KungFuMaster-v5.py&#39;&gt;KungFuMaster-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/SpaceWar-v5.py&#39;&gt;SpaceWar-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Asteroids-v5.py&#39;&gt;Asteroids-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Enduro-v5.py&#39;&gt;Enduro-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/LaserGates-v5.py&#39;&gt;LaserGates-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/StarGunner-v5.py&#39;&gt;StarGunner-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Atlantis-v5.py&#39;&gt;Atlantis-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Entombed-v5.py&#39;&gt;Entombed-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/LostLuggage-v5.py&#39;&gt;LostLuggage-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Superman-v5.py&#39;&gt;Superman-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Atlantis2-v5.py&#39;&gt;Atlantis2-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Et-v5.py&#39;&gt;Et-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/MarioBros-v5.py&#39;&gt;MarioBros-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Surround-v5.py&#39;&gt;Surround-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Backgammon-v5.py&#39;&gt;Backgammon-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/FishingDerby-v5.py&#39;&gt;FishingDerby-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/MiniatureGolf-v5.py&#39;&gt;MiniatureGolf-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Tennis-v5.py&#39;&gt;Tennis-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/BankHeist-v5.py&#39;&gt;BankHeist-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/FlagCapture-v5.py&#39;&gt;FlagCapture-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/MontezumaRevenge-v5.py&#39;&gt;MontezumaRevenge-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Tetris-v5.py&#39;&gt;Tetris-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/BasicMath-v5.py&#39;&gt;BasicMath-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Freeway-v5.py&#39;&gt;Freeway-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/MrDo-v5.py&#39;&gt;MrDo-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/TicTacToe3D-v5.py&#39;&gt;TicTacToe3D-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/BattleZone-v5.py&#39;&gt;BattleZone-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Frogger-v5.py&#39;&gt;Frogger-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/MsPacman-v5.py&#39;&gt;MsPacman-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/TimePilot-v5.py&#39;&gt;TimePilot-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/BeamRider-v5.py&#39;&gt;BeamRider-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Frostbite-v5.py&#39;&gt;Frostbite-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/NameThisGame-v5.py&#39;&gt;NameThisGame-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Trondead-v5.py&#39;&gt;Trondead-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Berzerk-v5.py&#39;&gt;Berzerk-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Galaxian-v5.py&#39;&gt;Galaxian-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Othello-v5.py&#39;&gt;Othello-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Turmoil-v5.py&#39;&gt;Turmoil-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Blackjack-v5.py&#39;&gt;Blackjack-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Gopher-v5.py&#39;&gt;Gopher-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Pacman-v5.py&#39;&gt;Pacman-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Tutankham-v5.py&#39;&gt;Tutankham-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Bowling-v5.py&#39;&gt;Bowling-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Gravitar-v5.py&#39;&gt;Gravitar-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Phoenix-v5.py&#39;&gt;Phoenix-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/UpNDown-v5.py&#39;&gt;UpNDown-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Boxing-v5.py&#39;&gt;Boxing-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Hangman-v5.py&#39;&gt;Hangman-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Pitfall-v5.py&#39;&gt;Pitfall-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Venture-v5.py&#39;&gt;Venture-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Breakout-v5.py&#39;&gt;Breakout-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/HauntedHouse-v5.py&#39;&gt;HauntedHouse-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Pitfall2-v5.py&#39;&gt;Pitfall2-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/VideoCheckers-v5.py&#39;&gt;VideoCheckers-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Carnival-v5.py&#39;&gt;Carnival-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Hero-v5.py&#39;&gt;Hero-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Pong-v5.py&#39;&gt;Pong-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/VideoChess-v5.py&#39;&gt;VideoChess-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Casino-v5.py&#39;&gt;Casino-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/HumanCannonball-v5.py&#39;&gt;HumanCannonball-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Pooyan-v5.py&#39;&gt;Pooyan-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/VideoCube-v5.py&#39;&gt;VideoCube-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Centipede-v5.py&#39;&gt;Centipede-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/IceHockey-v5.py&#39;&gt;IceHockey-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/PrivateEye-v5.py&#39;&gt;PrivateEye-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/VideoPinball-v5.py&#39;&gt;VideoPinball-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/ChopperCommand-v5.py&#39;&gt;ChopperCommand-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Jamesbond-v5.py&#39;&gt;Jamesbond-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Qbert-v5.py&#39;&gt;Qbert-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/WizardOfWor-v5.py&#39;&gt;WizardOfWor-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/CrazyClimber-v5.py&#39;&gt;CrazyClimber-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/JourneyEscape-v5.py&#39;&gt;JourneyEscape-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Riverraid-v5.py&#39;&gt;Riverraid-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/WordZapper-v5.py&#39;&gt;WordZapper-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Crossbow-v5.py&#39;&gt;Crossbow-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Kaboom-v5.py&#39;&gt;Kaboom-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/RoadRunner-v5.py&#39;&gt;RoadRunner-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/YarsRevenge-v5.py&#39;&gt;YarsRevenge-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Darkchambers-v5.py&#39;&gt;Darkchambers-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Kangaroo-v5.py&#39;&gt;Kangaroo-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Robotank-v5.py&#39;&gt;Robotank-v5&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;a href=&#39;https://github.com/SteveProXNA/OpenAItesting/blob/main/FarmaCheatSheet/Atari/Zaxxon-v5.py&#39;&gt;Zaxxon-v5&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
IMPORTANT: when you &lt;b&gt;pip install gymnasium[atari]&lt;/b&gt; without specifying tag 0.29.1 then you may receive &lt;i&gt;gymnasium.error.NamespaceNotFound: Namespace ALE not found. Have you installed the proper package for ALE?&lt;/i&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Pull Request&lt;/u&gt;&lt;br /&gt;
Finally, submit Pull Request: upload Farma examples.  Navigate to source &lt;a href=&quot;https://github.com/Farama-Foundation/Gymnasium&quot;&gt;Gymnasium&lt;/a&gt; repo | Create new fork
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDPVyRMHD_wiO-tPjVJKEGYaCJEtGg8sL-jnpIMQiTcMIscRR7lzYEtIrCAYAuJV-suM0QkEdXHf3n17DIRhsRJY2MoUjJuol1ulIcCf9OT6G9oZsXN3vpEJ4TthB2srOqpNDo11urmuCv_CDNpOQFaCOcK63f4BB_tfVlSOaMCnn21zRarRPWZhpYifE/s1089/ForkFarma02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDPVyRMHD_wiO-tPjVJKEGYaCJEtGg8sL-jnpIMQiTcMIscRR7lzYEtIrCAYAuJV-suM0QkEdXHf3n17DIRhsRJY2MoUjJuol1ulIcCf9OT6G9oZsXN3vpEJ4TthB2srOqpNDo11urmuCv_CDNpOQFaCOcK63f4BB_tfVlSOaMCnn21zRarRPWZhpYifE/s600/ForkFarma02.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Git clone the forked Gymnasium source code repository and setup the following Git username and useremail
&lt;br /&gt;  
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git config --global --get user.name&lt;br /&gt;
&amp;nbsp;git config --global --get user.email&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git config --global user.name &quot;SteveProXNA&quot;&lt;br /&gt;
&amp;nbsp;git config --global user.email &quot;steven_boland@hotmail.com&quot;&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Next, configure the Gymnasium upstream destination code repository in order to complete the &lt;a href=&quot;https://github.com/Farama-Foundation/Gymnasium/pull/1150&quot;&gt;Pull Request&lt;/a&gt;:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git remote -v&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git remote add upstream git@github.com:Farama-Foundation/Gymnasium.git&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;origin&lt;br /&gt;
&amp;nbsp;origin&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git@github.com:SteveProXNA/Gymnasium.git (fetch)&lt;br /&gt;
&amp;nbsp;git@github.com:SteveProXNA/Gymnasium.git (push)&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;upstream&lt;br /&gt;
&amp;nbsp;upstream&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;git@github.com:Farama-Foundation/Gymnasium.git (fetch)&lt;br /&gt;
&amp;nbsp;git@github.com:Farama-Foundation/Gymnasium.git (push)&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;	
&lt;/table&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx1TQkM5TRqPULqISAS61VP9mK-AiGG3lQOnTeryxvsosRnAfPki6xhL72ZItfvKmptCR9x8EgAVCSJ0acKuePU-an9VNe0hm5fk3W514mk9_OMKIX1rTkjkq2HjwuJ1PqHKNLYIrpcBd-SeoeW7pZSGTigGGWONIFvfw55YdkPzjsjzD_rJ-6g4wQpoA/s1114/ForkFarma05.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjx1TQkM5TRqPULqISAS61VP9mK-AiGG3lQOnTeryxvsosRnAfPki6xhL72ZItfvKmptCR9x8EgAVCSJ0acKuePU-an9VNe0hm5fk3W514mk9_OMKIX1rTkjkq2HjwuJ1PqHKNLYIrpcBd-SeoeW7pZSGTigGGWONIFvfw55YdkPzjsjzD_rJ-6g4wQpoA/s600/ForkFarma05.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
Launch PyCharm | Open Gymnasium | Create virtual environment | Install requirements	as pre-requisites:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;
&amp;nbsp;pip install -r docs/requirements.txt&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;pip install --upgrade pip&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Uncomment game from &lt;a href=&quot;https://github.com/SteveProXNA/Gymnasium/tree/GymnasiumGameExamples/examples/ClassicControl&quot;&gt;ClassicControl&lt;/a&gt; sub-directory files.txt or &lt;a href=&quot;https://github.com/SteveProXNA/Gymnasium/tree/GymnasiumGameExamples/examples/ToyText&quot;&gt;ToyText&lt;/a&gt; files.txt.  Open main.py.  Run script:  
&lt;br /&gt;
&lt;table width=&quot;99%&quot;&gt;  
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuodvasDS5xqKgUgNDB-tgtZ0s2nQHWgqh4youZJJwNdinw5BUnh7m9l2yuCseUZQocRjKJTRJ2iyklFBmEgK8bsJPG_TU352X6nydrNvXvlYymaHt5O5K33nujl5tGuFLKwJIE0tTQjpFfDyvMSL5BlNHegD0xbJP_KiQIcpFPSz2OAkt_4VofyPaAo0/s602/CartPole-v1.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuodvasDS5xqKgUgNDB-tgtZ0s2nQHWgqh4youZJJwNdinw5BUnh7m9l2yuCseUZQocRjKJTRJ2iyklFBmEgK8bsJPG_TU352X6nydrNvXvlYymaHt5O5K33nujl5tGuFLKwJIE0tTQjpFfDyvMSL5BlNHegD0xbJP_KiQIcpFPSz2OAkt_4VofyPaAo0/s600/CartPole-v1.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMrfoPxOvmF1gcw5FbMv9V28olf6HespNcpCB1QXmgY3MZ7a7ZVqo7nQ3b150nLJOHO-1AQ11oA3gScyKlrC7AoHjDyBAaadQVKIpBrDRPDCQUsa6_6KiF1aP630e2HdoVuMrct9tRLtWRYMoqw6J9BDsJdxR3KLlhZswFAnqXGntoKLvh-owEVvZOlkQ/s602/FrozenLake-v1.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMrfoPxOvmF1gcw5FbMv9V28olf6HespNcpCB1QXmgY3MZ7a7ZVqo7nQ3b150nLJOHO-1AQ11oA3gScyKlrC7AoHjDyBAaadQVKIpBrDRPDCQUsa6_6KiF1aP630e2HdoVuMrct9tRLtWRYMoqw6J9BDsJdxR3KLlhZswFAnqXGntoKLvh-owEVvZOlkQ/s600/FrozenLake-v1.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Install Box2D and MuJoCo dependencies.  Uncomment game from &lt;a href=&quot;https://github.com/SteveProXNA/Gymnasium/tree/GymnasiumGameExamples/examples/Box2D&quot;&gt;Box2D&lt;/a&gt; files.txt or &lt;a href=&quot;https://github.com/SteveProXNA/Gymnasium/tree/GymnasiumGameExamples/examples/MuJoCo&quot;&gt;MuJoCo&lt;/a&gt;.  Run main.py:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;b&gt;Box2D&lt;/b&gt;&lt;br /&gt;&amp;nbsp;pip install Box2D&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;&lt;b&gt;MuJoCo&lt;/b&gt;&lt;br /&gt;&amp;nbsp;pip install mujoco==2.3.0&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot;&gt;  
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgylj3jUcvVtNCwEg8dLYmQrCRXebm8eNTRagPJpk6eG6-tKBnY2ZdR0reGMy4i3HggLjyfmhATMG8KZZappGuxVyltWj7sx9jUVGvIH3YXS5ipa2FTVfJX1XqKKVO60rR60xWJ5k8tI6OpTy5i88Fx1gz4lcFN43MgDeX3rP17s6xUDnF287Xw20R-e-8/s602/LunarLander-v2.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgylj3jUcvVtNCwEg8dLYmQrCRXebm8eNTRagPJpk6eG6-tKBnY2ZdR0reGMy4i3HggLjyfmhATMG8KZZappGuxVyltWj7sx9jUVGvIH3YXS5ipa2FTVfJX1XqKKVO60rR60xWJ5k8tI6OpTy5i88Fx1gz4lcFN43MgDeX3rP17s6xUDnF287Xw20R-e-8/s600/LunarLander-v2.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZdt33_ZhMZdlE0xWNb944OiiKhMTyuHnCrIe33XtFlx_nmlqdjhMtPNDcoBW-WHBo0XChJ0v3aJR-Aq5T3o1P70P4D5JqZgCX4SLm9LaJpeSRlRmIe0eA9aGM15w_0DeizbXQ5owDTySlUowmLO3SX1pLDZAmdyWGnNceoSzX2Ta7YfterEyQAhBkdXQ/s602/Ant-v4.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZdt33_ZhMZdlE0xWNb944OiiKhMTyuHnCrIe33XtFlx_nmlqdjhMtPNDcoBW-WHBo0XChJ0v3aJR-Aq5T3o1P70P4D5JqZgCX4SLm9LaJpeSRlRmIe0eA9aGM15w_0DeizbXQ5owDTySlUowmLO3SX1pLDZAmdyWGnNceoSzX2Ta7YfterEyQAhBkdXQ/s600/Ant-v4.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Finally, in order to integrate &lt;a href=&quot;https://github.com/SteveProXNA/Gymnasium/tree/GymnasiumGameExamples/examples/Atari&quot;&gt;Atari&lt;/a&gt; game examples I found this only worked cut from &lt;b&gt;tag v0.29.1&lt;/b&gt; [&lt;a href=&quot;https://github.com/Farama-Foundation/Gymnasium/commit/81b87efb9f011e975f3b646bab6b7871c522e15e&quot;&gt;81b87ef&lt;/a&gt;]:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;git fetch --tags --prune --prune-tags&lt;br /&gt;&amp;nbsp;git fetch --all&lt;br /&gt;&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;git tag | grep v0.29.1&lt;br /&gt;&amp;nbsp;git checkout tags/v0.29.1&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;table&gt;
&lt;br /&gt;
It seems after tag v0.29.1 any Atari game may throw the following: &lt;i&gt;gymnasium.error.NamespaceNotFound: Namespace ALE not found. Have you installed the proper package for ALE?&lt;/i&gt;.  Resume Atari tag v0.29.1 setup:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install gymnasium[atari]&lt;/td&gt;
&lt;td width=&quot;50%&quot;&gt;&amp;nbsp;pip install gymnasium[accept-rom-license]&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJqR9yBBF4dGCoY6dNX45Ono8BSMqdomUCobeFzcozXDf3e1qtRy0yIxxzhF2tt5U86rfhuCaE23t3mYZgLirGiBCk1roS3wHIwSCyCOyJhX4I2_boz0u2RF46PNGN1Rk8S4nhiCQfQwphBKHaOK06GJAjgQYCFn4GaUnoT3_8y1Lker5fjGPI_yWJebg/s858/Breakout-Atari.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJqR9yBBF4dGCoY6dNX45Ono8BSMqdomUCobeFzcozXDf3e1qtRy0yIxxzhF2tt5U86rfhuCaE23t3mYZgLirGiBCk1roS3wHIwSCyCOyJhX4I2_boz0u2RF46PNGN1Rk8S4nhiCQfQwphBKHaOK06GJAjgQYCFn4GaUnoT3_8y1Lker5fjGPI_yWJebg/s600/Breakout-Atari.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Retrospectives&lt;/u&gt;&lt;br /&gt;
In Jan-2020 &lt;a href=&quot;https://steveproxna.blogspot.com/2020/01/retrospective-xi.html&quot;&gt;Retrospective XI&lt;/a&gt;, we learned about an interesting development connecting Artificial Intelligence and retro video games leveraging Reinforcement Learning.  In Jan-2021 &lt;a href=&quot;https://steveproxna.blogspot.com/2021/01/retrospective-xii.html&quot;&gt;Retrospective XII&lt;/a&gt;, we then discussed video games as an interesting field of &lt;a href=&quot;https://www.youtube.com/watch?v=vufTSJbzKGU&quot;&gt;study&lt;/a&gt; and retro game development of Pacman and Doom clones as an excellent avenue to pursue with regards to future applications in software with Artificial Intelligence and RL.
&lt;br /&gt;&lt;br /&gt;
Consequently, in the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2024/08/doom-code-walkthru.html&quot;&gt;post&lt;/a&gt;, we disovered how to debug step thru cloned versions of Doom to better understand the original source code: an important pre-requisite to extend knowledge for further research in reinforcement learning, in particular.  For example, &lt;a href=&quot;https://vizdoom.cs.put.edu.pl&quot;&gt;ViZDoom&lt;/a&gt; allows developing AI bots that play Doom using visual data.  In 2022, &lt;a href=&quot;https://github.com/Farama-Foundation/ViZDoom?tab=readme-ov-file&quot;&gt;ViZDoom&lt;/a&gt; joined Farama Foundation featuring new &lt;a href=&quot;https://gymnasium.farama.org&quot;&gt;Gymnasium&lt;/a&gt; environment wrappers.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, we have now setup Gymnasium environments for Classic Control, Toy Text, Box 2D, MuJo Co and Atari.  NB: all Atari &lt;a href=&quot;https://github.com/Farama-Foundation/Arcade-Learning-Environment&quot;&gt;environments&lt;/a&gt; leverage the Atari Arcade Learning Environment [ALE] emulator Stella.
&lt;br /&gt;&lt;br /&gt;
In fact, reverting back to OpenAI which hosts the &lt;a href=&quot;https://github.com/openai/retro&quot;&gt;Retro&lt;/a&gt; Git source code repository, also including Emulated Systems like Atari.  However, Retro also includes many other Emulated Systems we have developed for in the past including &lt;a href=&quot;https://steveproxna.blogspot.com/2023/11/gbdk-programming-sample.html&quot;&gt;Nintendo&lt;/a&gt; GameBoy / GameBoy Color, Sega &lt;a href=&quot;https://steveproxna.blogspot.com/2020/11/sgdk-programming-sample.html&quot;&gt;MegaDrive&lt;/a&gt; and or course the Sega &lt;a href=&quot;https://steveproxna.blogspot.com/2022/07/devkitsms-programming-sample-v.html&quot;&gt;Master System&lt;/a&gt;!  This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2024/11/openai-retro-cheat-sheet.html&quot;&gt;post&lt;/a&gt;.
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2024/09/openai-farma-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJhCe_LjUoggkw1yWQy5g_ExXAmT4IuCvAsa1en_FFKzxvclCmh8JG3SXJza1WES-LTd3NxizAJPykC1zP-4HlmNNaf2gFNUFlHWGjEeeXGsPNDHos-YdPMnZy-8PlsurebkkPGUVfJYa908O7Si10Nn_3YQlMMCz_3OB2Kyf5pBvZ2CuhgE2hZUW_R2o/s72-c/Pacman-v5.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-2937468039815560963</guid><pubDate>Sat, 31 Aug 2024 10:30:00 +0000</pubDate><atom:updated>2024-08-31T03:30:47.692-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">DOOM</category><title>Doom Code WalkThru</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Doom_(1993_video_game)&quot;&gt;Doom&lt;/a&gt; is a First-Person Shooter developed and published by &lt;a href=&quot;https://en.wikipedia.org/wiki/Id_Software&quot;&gt;id Software&lt;/a&gt; in December 1993.  Doom is the first franchise installment and one of the most widely &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_Doom_ports&quot;&gt;ported&lt;/a&gt; video games since the &lt;a href=&quot;https://github.com/id-Software/DOOM&quot;&gt;code&lt;/a&gt; was released Dec-1997.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjg9C-hiIFh3hE02zIcEQ7qCZsmXYiHf_wrOmJ6GnTDaAvstDlx2jBtc2OMvOGt7fWYbGSJF5SZG-tTi8Y7Nfl4ddxPmRsWVaQ4HaVY-WAhyphenhyphen6_0eQj5kBEGAWBMYJ-NvWg5JEnKaCK5jz_QNDUHD5ruY_9jSnu_fjtG02pRdSgIHhRZyIqKeofhP08ahw/s640/Doom1.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjg9C-hiIFh3hE02zIcEQ7qCZsmXYiHf_wrOmJ6GnTDaAvstDlx2jBtc2OMvOGt7fWYbGSJF5SZG-tTi8Y7Nfl4ddxPmRsWVaQ4HaVY-WAhyphenhyphen6_0eQj5kBEGAWBMYJ-NvWg5JEnKaCK5jz_QNDUHD5ruY_9jSnu_fjtG02pRdSgIHhRZyIqKeofhP08ahw/s600/Doom1.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Ports&lt;/u&gt;&lt;br /&gt;
In order to better understand the Doom source &lt;a href=&quot;https://github.com/id-Software/DOOM&quot;&gt;code&lt;/a&gt; we would like to debug step thru both the Doom port &lt;a href=&quot;https://wiki.archlinux.org/title/PrBoom&quot;&gt;PrBoom&lt;/a&gt; on Linux and the Doom port &lt;a href=&quot;https://github.com/bradharding/doomretro/wiki&quot;&gt;DoomRetro&lt;/a&gt; on Windows written in &lt;a href=&quot;https://en.wikipedia.org/wiki/C_(programming_language)&quot;&gt;C&lt;/a&gt; using modern-day software tools:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Linux&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://sourceforge.net/projects/prboom-plus/files/prboom-plus/2.5.1.3&quot;&gt;PrBoom&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Cross-platform version of Doom ported to Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Windows&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/bradharding/doomretro&quot;&gt;DoomRetro&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Classic refined Doom source port for Windows PC&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;WAD Files&lt;/u&gt;&lt;/br /&gt;
&lt;a href=&quot;https://doomwiki.org/wiki/WAD&quot;&gt;WAD&lt;/a&gt; is the acronym for &quot;Where&#39;s All the Data?&quot; which is the file format used by Doom and all Doom engine-based games for storing data.  A WAD file consists of a header, a directory and the data &lt;a href=&quot;https://doomwiki.org/wiki/Lump&quot;&gt;lumps&lt;/a&gt; that make up the resources stored within the file.  A WAD file can be one of two types: an Internal WAD or a Patch WAD:
&lt;br /&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://doomwiki.org/wiki/IWAD&quot;&gt;IWAD&lt;/a&gt;&lt;/b&gt;&amp;nbsp;&lt;/td&gt;	
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Internal WAD&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Core WAD file loaded by engine that provides all data required to run game&lt;/td&gt;	
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://doomwiki.org/wiki/PWAD&quot;&gt;PWAD&lt;/a&gt;&lt;/b&gt;&amp;nbsp;&lt;/td&gt;	
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Patch WAD&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Optional file that replaces IWAD data and provides additional data to engine&lt;/td&gt;	
&lt;/tr&gt;
&lt;/table&gt;
According to &lt;a href=&quot;https://doomwiki.org/wiki/Entryway&quot;&gt;doomwiki&lt;/a&gt; there is List of &lt;a href=&quot;https://doomwiki.org/wiki/List_of_notable_WADs&quot;&gt;notable&lt;/a&gt; WADs available to download beginning with &lt;a href=&quot;https://doomwiki.org/wiki/DOOM1.WAD&quot;&gt;Doom1.wad&lt;/a&gt; etc.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Doom Bible&lt;/u&gt;&lt;/br /&gt;
The &lt;a href=&quot;https://doomwiki.org/wiki/Doom_Bible&quot;&gt;Doom Bible&lt;/a&gt; is the original design document which includes the specifications for the WAD file format structure that initiated an incredible &lt;a href=&quot;https://en.wikipedia.org/wiki/Doom_modding&quot;&gt;modding&lt;/a&gt; scene in which fans created their own WAD files containing new levels commonplace for first-person shooter games!  Now let&#39;s debug step thru Doom &lt;a href=&quot;https://en.wikipedia.org/wiki/C_(programming_language)&quot;&gt;C&lt;/a&gt; source code.
&lt;br /&gt;&lt;br /&gt;  
&lt;u&gt;PrBoom&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://wiki.archlinux.org/title/PrBoom&quot;&gt;PrBoom&lt;/a&gt; is a cross-platform version of the classic 3D first-person shooter Doom from id Software.  PrBoom has since been ported to Linux and many other platforms.  PrBoom requires the original &lt;a href=&quot;https://zdoom.org/wiki/IWAD&quot;&gt;IWAD&lt;/a&gt; data files.
&lt;br /&gt;&lt;br /&gt;
Follow this &lt;a href=&quot;https://www.youtube.com/watch?v=Cd8T5-j1QwQ&quot;&gt;YouTube&lt;/a&gt; video to setup PrBoom in VS Code and build and debug step through the source code!  Launch Terminal.  Install the following Linux packages as PrBoom pre-requisites, if not currently installed:
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;sudo apt-get install libghc-opengl-dev&lt;br /&gt;
&amp;nbsp;sudo apt-get install libghc-sdl-dev&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Download prboom-plus-2.5.1.3 from &lt;b&gt;&lt;a href=&quot;https://sourceforge.net/projects/prboom-plus/files/prboom-plus/2.5.1.3&quot;&gt;sourceforge.net&lt;/a&gt;&lt;/b&gt;.  That is the link that seemed to work OK for me.  Launch Terminal.  Execute following commands to extract source code, configure, build and run PrBoom:
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;tar -xvf prboom-plus-2.5.1.3.tar.gz&lt;br /&gt;
&amp;nbsp;cd ~/prboom-plus&lt;br /&gt;
&amp;nbsp;chmod +x configure&lt;br /&gt;
&amp;nbsp;./configure&lt;br /&gt;
&amp;nbsp;make&lt;br /&gt;
&amp;nbsp;chmod +x src/prboom-plus&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
If you get the following &lt;i&gt;configure: error: *** You must have the SDL libraries installed before you can compile prboom
 *** See http://prboom.sourceforge.net/linux.html&lt;/i&gt; then install the following packages:
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;sudo apt-get install libsdl1.2-dev&lt;br /&gt;
&amp;nbsp;sudo apt-get install libsdl-mixer1.2-dev&lt;br /&gt;
&amp;nbsp;sudo apt-get install libsdl-net1.2-dev&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Copy all files from the DoomCodeWalkThru &lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/tree/main/Files&quot;&gt;Files&lt;/a&gt; directory to the local hidden directory &lt;b&gt;~/.prboom-plus&lt;/b&gt;
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;cp ~/GitHub/SteveProXNA/Doom/Files/* ~/.prboom-plus&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;br /&gt;
Launch VS Code.  Create &lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Linux/prboom-plus/build.sh&quot;&gt;build&lt;/a&gt; shell script, hidden &lt;b&gt;.vscode&lt;/b&gt; directory with &lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Linux/prboom-plus/.vscode/tasks.json&quot;&gt;tasks.json&lt;/a&gt; and &lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Linux/prboom-plus/.vscode/launch.json&quot;&gt;launch.json&lt;/a&gt; files
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Linux/prboom-plus/.vscode/tasks.json&quot;&gt;tasks.json&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Linux/prboom-plus/.vscode/launch.json&quot;&gt;launch.json&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;  
&lt;td valign=&quot;top&quot;&gt;
&lt;pre code=&quot;C#&quot;&gt;
&amp;nbsp;{
&amp;nbsp;    &quot;version&quot;: &quot;2.0.0&quot;,
&amp;nbsp;    &quot;label&quot;: &quot;build&quot;,
&amp;nbsp;    &quot;type&quot;: &quot;shell&quot;,
&amp;nbsp;    &quot;linux&quot;: {
&amp;nbsp;        &quot;command&quot;: &quot;./build.sh&quot;
&amp;nbsp;    },
&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre code=&quot;C#&quot;&gt;
&amp;nbsp;{
&amp;nbsp;  &quot;version&quot;: &quot;0.2.0&quot;,
&amp;nbsp;  &quot;configurations&quot;: [
&amp;nbsp;    {
&amp;nbsp;      &quot;name&quot;: &quot;(gdb) Launch&quot;,
&amp;nbsp;      &quot;type&quot;: &quot;cppdbg&quot;,
&amp;nbsp;      &quot;request&quot;: &quot;launch&quot;,
&amp;nbsp;      &quot;program&quot;: &quot;${workspaceFolder}/src/prboom-plus&quot;,
&amp;nbsp;      &quot;args&quot;: [
&amp;nbsp;        &quot;-iwad&quot;,
&amp;nbsp;        &quot;Doom1.wad&quot;
&amp;nbsp;      ],
&amp;nbsp;      &quot;stopAtEntry&quot;: false,
&amp;nbsp;      &quot;cwd&quot;: &quot;${workspaceFolder}&quot;,
&amp;nbsp;      &quot;externalConsole&quot;: false,
&amp;nbsp;      &quot;MIMode&quot;: &quot;gdb&quot;,
&amp;nbsp;    }
&amp;nbsp;  ]
&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Open &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Linux/prboom-plus/src/SDL/i_main.c&quot;&gt;i_main.c&lt;/a&gt;&lt;/b&gt;.  Set breakpoints.  Press Ctrl+Shift+B to build and F5 to debug step through source code!
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0EEnizqqW4uPCmvBTdqO3rPwp-FEpuxGsLJ-gLDkjK9wPhVQLPZ3Gr5RNd9blH4LPjCisW3szVJhHghWYMk4jc0vxPrvrqy_83I1TdeYD4GYrz6oJSNv5hpqkm-jVGAgRtTAUwW41RqwpONQcUy1cYG-cH5Y3gCso4G8-3hcHqdItYaOc0Er64EpftVY/s1125/VScodeDebug.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0EEnizqqW4uPCmvBTdqO3rPwp-FEpuxGsLJ-gLDkjK9wPhVQLPZ3Gr5RNd9blH4LPjCisW3szVJhHghWYMk4jc0vxPrvrqy_83I1TdeYD4GYrz6oJSNv5hpqkm-jVGAgRtTAUwW41RqwpONQcUy1cYG-cH5Y3gCso4G8-3hcHqdItYaOc0Er64EpftVY/s600/VScodeDebug.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
IMPORTANT - the first character of IWAD file &lt;b&gt;must&lt;/b&gt; be &lt;b&gt;I&lt;/b&gt; not &lt;b&gt;P&lt;/b&gt; otherwise may get an &quot;IWAD not found&quot; &lt;a href=&quot;https://www.doomworld.com/forum/topic/52918-prboom-cannot-find-my-iwad&quot;&gt;error&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
CRITICAL - specify the arguments &lt;b&gt;-iwad&lt;/b&gt; and WAD file e.g. &lt;b&gt;Doom1.wad&lt;/b&gt; otherwise you will encounter error:
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;  
&lt;pre code=&quot;C#&quot;&gt;
&amp;nbsp;M_LoadDefaults: Load system defaults.
&amp;nbsp; default file: ~/.prboom-plus/prboom-plus.cfg
&amp;nbsp;  found ~/.prboom-plus/prboom-plus.wad
&amp;nbsp;
&amp;nbsp;prboom-plus v2.5.1.3 (http://prboom-plus.sourceforge.net/)
&amp;nbsp;I_SetAffinityMask: manual affinity mask is 1
&amp;nbsp;IdentifyVersion: IWAD not found
&lt;/pre&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Keys&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUdyuUtxpsHR4bPUugD7lGbFfgdhJZ26HoC5lu7BCjVn6wAoBiwApOrbbXE3h1fmCtKJ2u6bBZC00WZd5TL7GeIwZB_CV8oIwOp7WVk10bwPVyoWj9u9QKQuHscueBk6IavgBrR3mS8-QuFCwpfGZxIvmr_3RXeocxysLr7sCUy0041v3pyylaec8KHZQ/s1024/PrBoomKeys.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUdyuUtxpsHR4bPUugD7lGbFfgdhJZ26HoC5lu7BCjVn6wAoBiwApOrbbXE3h1fmCtKJ2u6bBZC00WZd5TL7GeIwZB_CV8oIwOp7WVk10bwPVyoWj9u9QKQuHscueBk6IavgBrR3mS8-QuFCwpfGZxIvmr_3RXeocxysLr7sCUy0041v3pyylaec8KHZQ/s600/PrBoomKeys.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F1&lt;/td&gt;&lt;td&gt;&amp;nbsp;Help&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F2&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F3&lt;/td&gt;&lt;td&gt;&amp;nbsp;Load game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F4&lt;/td&gt;&lt;td&gt;&amp;nbsp;Sound volume&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F5&lt;/td&gt;&lt;td&gt;&amp;nbsp;Change HUD&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F6&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F7&lt;/td&gt;&lt;td&gt;&amp;nbsp;End game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F8&lt;/td&gt;&lt;td&gt;&amp;nbsp;Message toggle&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F9&lt;/td&gt;&lt;td&gt;&amp;nbsp;Quick load&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F10&lt;/td&gt;&lt;td&gt;&amp;nbsp;Quit application&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Escape&lt;/td&gt;&lt;td&gt;&amp;nbsp;Menu back&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Enter&lt;/td&gt;&lt;td&gt;&amp;nbsp;Menu forward&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Home&lt;/td&gt;&lt;td&gt;&amp;nbsp;Restart game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Tab&lt;/td&gt;&lt;td&gt;&amp;nbsp;Map&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;0-9&lt;/td&gt;&lt;td&gt;&amp;nbsp;Change weapons&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Left arrow&lt;/td&gt;&lt;td&gt;&amp;nbsp;Rotate left&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Right arrow&lt;/td&gt;&lt;td&gt;&amp;nbsp;Rotate right&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Up arrow&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move forward&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Down arrow&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move back&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Ctrl&lt;/td&gt;&lt;td&gt;&amp;nbsp;Shoot&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Space&lt;/td&gt;&lt;td&gt;&amp;nbsp;Open door&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Strafe left&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Strafe right&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;/&lt;/td&gt;&lt;td&gt;&amp;nbsp;Rotate 180&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
Note: &lt;b&gt;F11&lt;/b&gt; does Gamma correction.  Also, re-copy &lt;b&gt;Prboom-plus.cfg&lt;/b&gt; and &lt;b&gt;Prboom-plus.wad&lt;/b&gt; to reset HUD.
&lt;br /&gt;&lt;br /&gt;
The YouTube video shows some examples how to hack the &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Linux/prboom-plus/src/d_englsh.h&quot;&gt;d_englsh.h&lt;/a&gt;&lt;/b&gt; to make custom text and sounds!
&lt;br /&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoo8JXJLTlQY-zqIEWZWkrQ7zqdpfcW0cT1eNniUpkeSz9W3iSkoLSP6ZryNrmuNg6Gv-ML9y8IN7Egg9QOh6bhfnqvCPQGGvvBZRk674Ff-gJY45vu_OX3u00ZCnVArNmVkv5q3_UaxRZ3mLnZph_CLpk7HtnZYoGTC8pTWgA36XmwbA4HZQUp1Sl3zc/s640/Doom1.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoo8JXJLTlQY-zqIEWZWkrQ7zqdpfcW0cT1eNniUpkeSz9W3iSkoLSP6ZryNrmuNg6Gv-ML9y8IN7Egg9QOh6bhfnqvCPQGGvvBZRk674Ff-gJY45vu_OX3u00ZCnVArNmVkv5q3_UaxRZ3mLnZph_CLpk7HtnZYoGTC8pTWgA36XmwbA4HZQUp1Sl3zc/s600/Doom1.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb4aMy6FygHRo6S0uHgYPnJ7boCwWHM0ltd1wKV4UUssPObfnsxsiKKh1OvmUleMFDsSOL8jEob-rgItWvLDo0QeKL3aZg3Jp45eMalaJ-eIwttlAJzbb9MzxEG2l3vQ_MeF2lbq-IJ730D3JTGjuOXtYq5CdNI4c_igaCqp8Lc2tJV6imb0iA8OzcAEk/s640/Doom2.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb4aMy6FygHRo6S0uHgYPnJ7boCwWHM0ltd1wKV4UUssPObfnsxsiKKh1OvmUleMFDsSOL8jEob-rgItWvLDo0QeKL3aZg3Jp45eMalaJ-eIwttlAJzbb9MzxEG2l3vQ_MeF2lbq-IJ730D3JTGjuOXtYq5CdNI4c_igaCqp8Lc2tJV6imb0iA8OzcAEk/s600/Doom2.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-Dd7WuiscVA52WZyOoMurFMkvib3BmR73RjMgGeBcZn-7wrGfjJZUx471ykD2tnZv7fgMgskA9jj_VGIruxXE4HiotULRnTnXhpRRhg6urVtyHIcn24DeiDFPGDlUQiUjW9utzmkO2lOUVzyssyefxD2bWt0SfWMWeUemHVmn1XXJ5vSvovTs1UsXjBI/s640/Plutonia.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-Dd7WuiscVA52WZyOoMurFMkvib3BmR73RjMgGeBcZn-7wrGfjJZUx471ykD2tnZv7fgMgskA9jj_VGIruxXE4HiotULRnTnXhpRRhg6urVtyHIcn24DeiDFPGDlUQiUjW9utzmkO2lOUVzyssyefxD2bWt0SfWMWeUemHVmn1XXJ5vSvovTs1UsXjBI/s600/Plutonia.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYNHIJ3DVsX7VnZbu0nhAmNEc384bLifin2SV0Ih1g3RafeOIrABYaMckZ1DYXCTbjKpk4MKh48aFUtzi53zTGoN8InM1-vJ2Qv-qpxyfcFg2pukc-rQgka_J2CRWdhShCSsaG4gNBXEqoYE5UpMOb4_m-MD6LLZlUfzqgFyfr-dlN6hML3fKy2_ziXtg/s640/Tnt.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYNHIJ3DVsX7VnZbu0nhAmNEc384bLifin2SV0Ih1g3RafeOIrABYaMckZ1DYXCTbjKpk4MKh48aFUtzi53zTGoN8InM1-vJ2Qv-qpxyfcFg2pukc-rQgka_J2CRWdhShCSsaG4gNBXEqoYE5UpMOb4_m-MD6LLZlUfzqgFyfr-dlN6hML3fKy2_ziXtg/s600/Tnt.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;DoomRetro&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/bradharding/doomretro/wiki&quot;&gt;Doom Retro&lt;/a&gt; is the classic, refined Doom source port for Windows PC.  Written in &lt;a href=&quot;https://en.wikipedia.org/wiki/C_(programming_language)&quot;&gt;C&lt;/a&gt;, Doom Retro source code is maintained in &lt;a href=&quot;https://github.com/bradharding/doomretro&quot;&gt;doomretro&lt;/a&gt; Git repository and regularly compiled for both 32 and 64-bit using Visual Studio.
&lt;br /&gt;&lt;br /&gt;
Launch Visual Studio 2022.  Open &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Windows/doomretro/msvc/doomretro.sln&quot;&gt;doomretro.sln&lt;/a&gt;&lt;/b&gt;.  Choose Debug | 32-bit.  Right click Solution and Rebuild.  Ensure the Platform Toolset is Visual Studio 2022 (v143) in the project Properties | Configuration Properties.
&lt;br /&gt;&lt;br /&gt;
Open &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/blob/main/Windows/doomretro/src/doomretro.c&quot;&gt;doomretro.c&lt;/a&gt;&lt;/b&gt;. Set breakpoints. Press Ctrl+Shift+B to build and F5 to debug step through source code!  The function &lt;i&gt;D_OpenWADLauncher()&lt;/i&gt; will &lt;a href=&quot;https://github.com/bradharding/doomretro/wiki/STARTING-A-GAME#USING-THE-WAD-LAUNCHER&quot;&gt;prompt&lt;/a&gt; WAD file selection.  Choose a WAD file from &lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/tree/main/Files&quot;&gt;Files&lt;/a&gt; directory.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2rLZbAKVwQR6wp_LcBP_T0iXJRQQr92bg4i18Pl3rXAJJ-pH2c9qBrf1zpDM9Vi_BQf3bI7tzFDmpz8E7v5VAUl0nyJHADwPuontblMMEOdPOWEtD0kRazI5RL1aigIr0kUuqyNezc-_kTERtwLtqkETX3RbRD6HyuSSo4OZ7C4zIk9FdzdIbmh6HKXw/s1081/VS2022Debug.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2rLZbAKVwQR6wp_LcBP_T0iXJRQQr92bg4i18Pl3rXAJJ-pH2c9qBrf1zpDM9Vi_BQf3bI7tzFDmpz8E7v5VAUl0nyJHADwPuontblMMEOdPOWEtD0kRazI5RL1aigIr0kUuqyNezc-_kTERtwLtqkETX3RbRD6HyuSSo4OZ7C4zIk9FdzdIbmh6HKXw/s600/VS2022Debug.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Keys&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrgmVIMSNAdv_dnfz9ldmHbLqasAYPIDvce_7uu5Oynd4icZNMtBcB-ia88xzGPzFwpf9VR_5a3mkUPc9nkeRRMwAQbVfaqYSo3ru_rEISVJwpqi2xp0Zubc7L50PfXyuLnxZPc32A3mijFaR73FHwEJy_M-c13clOFtqH5IGvLDMWfXPeeqvGLqKGpSc/s635/DoomRetroKeys.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrgmVIMSNAdv_dnfz9ldmHbLqasAYPIDvce_7uu5Oynd4icZNMtBcB-ia88xzGPzFwpf9VR_5a3mkUPc9nkeRRMwAQbVfaqYSo3ru_rEISVJwpqi2xp0Zubc7L50PfXyuLnxZPc32A3mijFaR73FHwEJy_M-c13clOFtqH5IGvLDMWfXPeeqvGLqKGpSc/s600/DoomRetroKeys.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F1&lt;/td&gt;&lt;td&gt;&amp;nbsp;Help&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F2&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F3&lt;/td&gt;&lt;td&gt;&amp;nbsp;Load game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F4&lt;/td&gt;&lt;td&gt;&amp;nbsp;Sound volume&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F5&lt;/td&gt;&lt;td&gt;&amp;nbsp;Graphics toggle&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F6&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F7&lt;/td&gt;&lt;td&gt;&amp;nbsp;End game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F8&lt;/td&gt;&lt;td&gt;&amp;nbsp;Message toggle&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F9&lt;/td&gt;&lt;td&gt;&amp;nbsp;Quick load&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;F10&lt;/td&gt;&lt;td&gt;&amp;nbsp;Quit application&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Escape&lt;/td&gt;&lt;td&gt;&amp;nbsp;Menu back&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Enter&lt;/td&gt;&lt;td&gt;&amp;nbsp;Menu forward&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Tab&lt;/td&gt;&lt;td&gt;&amp;nbsp;Map&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;0-9&lt;/td&gt;&lt;td&gt;&amp;nbsp;Change weapons&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Left arrow&lt;/td&gt;&lt;td&gt;&amp;nbsp;Rotate left&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Right arrow&lt;/td&gt;&lt;td&gt;&amp;nbsp;Rotate right&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Up arrow [W]&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move forward&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Down arrow [S]&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move back&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Ctrl&lt;/td&gt;&lt;td&gt;&amp;nbsp;Shoot&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Space&lt;/td&gt;&lt;td&gt;&amp;nbsp;Open door&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;A or &lt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Strafe left&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;D or &gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;Strafe right&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Caps Lock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Always run toggle&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;Back Tick&lt;/td&gt;&lt;td&gt;&amp;nbsp;Console commands&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
&lt;b&gt;Commands&lt;/b&gt;&lt;br /&gt;
Press the back tick [&lt;b&gt;`&lt;/b&gt;] key prompts the &lt;a href=&quot;https://github.com/bradharding/doomretro/wiki/Console-Commands&quot;&gt;Console Commands&lt;/a&gt; dialog box.  Here are some useful commands:
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;clear&lt;/td&gt;&lt;td&gt;&amp;nbsp;Clears console&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cmdlist&lt;/td&gt;&lt;td&gt;&amp;nbsp;Lists all commands&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;god&lt;/td&gt;&lt;td&gt;&amp;nbsp;Toggle &lt;b&gt;God&lt;/b&gt; mode&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;health 100&lt;/td&gt;&lt;td&gt;&amp;nbsp;Set health = 100%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;playerstats&lt;/td&gt;&lt;td&gt;&amp;nbsp;Shows player stats&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;quit&lt;/td&gt;&lt;td&gt;&amp;nbsp;Quit application&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;maplist&lt;/td&gt;&lt;td&gt;&amp;nbsp;List all maps to play&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;map E1M7&lt;/td&gt;&lt;td&gt;&amp;nbsp;Warp to map &lt;b&gt;E1M7&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;playerstats&lt;/td&gt;&lt;td&gt;&amp;nbsp;Shows player stats&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;restartmap&lt;/td&gt;&lt;td&gt;&amp;nbsp;Restart current map&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;newgame&lt;/td&gt;&lt;td&gt;&amp;nbsp;Start new game&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;endgame&lt;/td&gt;&lt;td&gt;&amp;nbsp;End the game&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjg9C-hiIFh3hE02zIcEQ7qCZsmXYiHf_wrOmJ6GnTDaAvstDlx2jBtc2OMvOGt7fWYbGSJF5SZG-tTi8Y7Nfl4ddxPmRsWVaQ4HaVY-WAhyphenhyphen6_0eQj5kBEGAWBMYJ-NvWg5JEnKaCK5jz_QNDUHD5ruY_9jSnu_fjtG02pRdSgIHhRZyIqKeofhP08ahw/s640/Doom1.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot;  src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjg9C-hiIFh3hE02zIcEQ7qCZsmXYiHf_wrOmJ6GnTDaAvstDlx2jBtc2OMvOGt7fWYbGSJF5SZG-tTi8Y7Nfl4ddxPmRsWVaQ4HaVY-WAhyphenhyphen6_0eQj5kBEGAWBMYJ-NvWg5JEnKaCK5jz_QNDUHD5ruY_9jSnu_fjtG02pRdSgIHhRZyIqKeofhP08ahw/s600/Doom1.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSvThhH5tP01WobsbMM6tJLKYajC9SFujW_ezqMQxJiiEmbLigDcrOz9Nb_niVUGRKA_NEQfFD_poLRCNxvMsTViqfKvV43gMXj4r2kLYOPmjcNUu6OuMyVpigd_F62t0L6ag2dNN_S46eZIN_C9OMca0qo80Fnm_7UNymi5SkwFGTQKlQUYcUiq0eKF8/s638/Doom2.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSvThhH5tP01WobsbMM6tJLKYajC9SFujW_ezqMQxJiiEmbLigDcrOz9Nb_niVUGRKA_NEQfFD_poLRCNxvMsTViqfKvV43gMXj4r2kLYOPmjcNUu6OuMyVpigd_F62t0L6ag2dNN_S46eZIN_C9OMca0qo80Fnm_7UNymi5SkwFGTQKlQUYcUiq0eKF8/s600/Doom2.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoOO1jnEnbYRa0f_HouGfEOsWV1C959tQIJPYuVk_tpNPQl7Solo2e829NFZDGSBZZ01uTWodzaWmv-AdBUfXkMdV31lbyk8nD7nrnQmH0QKn3mtCKXhaGBMQ4VdQk78yyAktk5GIqto6yXaa2TemK4X1r97fN2w9yKVaavNUxPtPnNiY2PjGi_wzduPc/s640/Plutonia.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoOO1jnEnbYRa0f_HouGfEOsWV1C959tQIJPYuVk_tpNPQl7Solo2e829NFZDGSBZZ01uTWodzaWmv-AdBUfXkMdV31lbyk8nD7nrnQmH0QKn3mtCKXhaGBMQ4VdQk78yyAktk5GIqto6yXaa2TemK4X1r97fN2w9yKVaavNUxPtPnNiY2PjGi_wzduPc/s600/Plutonia.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAAnNsSgPcgiL43QjiYj7huJ-IRlouSWfBBkgfUMG3XrlZ98YCfmPx-wTS3lJj7rqvTXAdV8ps55TrqBZ2yLxPDwbedfv_lp1M2jx26NZesVZGD3EHexUOwFtJKNPJbcAzb1iwrdChm35QfXlsLWf_axvGyjiodjRW9T9iGXc1oi9TFh0VgJTRFjQzZHg/s640/Tnt.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAAnNsSgPcgiL43QjiYj7huJ-IRlouSWfBBkgfUMG3XrlZ98YCfmPx-wTS3lJj7rqvTXAdV8ps55TrqBZ2yLxPDwbedfv_lp1M2jx26NZesVZGD3EHexUOwFtJKNPJbcAzb1iwrdChm35QfXlsLWf_axvGyjiodjRW9T9iGXc1oi9TFh0VgJTRFjQzZHg/s600/Tnt.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Documentation&lt;/u&gt;&lt;/br /&gt;
The &lt;a href=&quot;https://fabiensanglard.net/gebbdoom&quot;&gt;Game Engine Black Book&lt;/a&gt;: DOOM book is excellent reference material which goes into great depth about the development process of Doom in 1993.  &lt;a href=&quot;https://en.wikipedia.org/wiki/Masters_of_Doom&quot;&gt;Masters of Doom&lt;/a&gt; documents the history of id Software and goes into great depth about development of many id Software franchises leading up-and-including Doom success.
&lt;br /&gt;&lt;br /&gt; 
&lt;u&gt;Summary&lt;/u&gt;&lt;/br /&gt;
To summarize, we have now setup Doom ports on both &lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/tree/main/Linux&quot;&gt;Linux&lt;/a&gt; and &lt;a href=&quot;https://github.com/SteveProXNA/DoomCodeWalkThru/tree/main/Windows&quot;&gt;Windows&lt;/a&gt; computers to debug step through and better understand the source code.  While this has been a fun and nostalgic exercise, many believe that this is crucial that Software Developers should &lt;a href=&quot;https://embeddedartistry.com/blog/2019/05/06/programmers-lets-study-source-code-classics&quot;&gt;review&lt;/a&gt; influential source code: rather than repeat the same past mistakes, we should study great works that preceded us and learn from and build upon their lessons.
&lt;br /&gt;&lt;br /&gt;
Another motivation to study classic video game source code is their relevance to modern day AI topics such as Reinforcement Learning.  For example: &lt;a href=&quot;https://github.com/Farama-Foundation/ViZDoom&quot;&gt;VizDoom&lt;/a&gt; allows developing AI bots to play Doom using only visual information.  Hosted by The &lt;a href=&quot;https://farama.org/Announcing-The-Farama-Foundation&quot;&gt;Farama&lt;/a&gt;-Foundation &lt;a href=&quot;https://vizdoom.farama.org/index.html&quot;&gt;VizDoom&lt;/a&gt; allows creating environments based on the Doom engine.  The library provides Python API wrappers for the &lt;a href=&quot;https://en.wikipedia.org/wiki/OpenAI&quot;&gt;OpenAI&lt;/a&gt; Gym / &lt;a href=&quot;https://gymnasium.farama.org/index.html&quot;&gt;Gymnasium&lt;/a&gt; interface and provides an excellent opportunity to research machine visual learning and deep reinforcement learning in the future!
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2024/08/doom-code-walkthru.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjg9C-hiIFh3hE02zIcEQ7qCZsmXYiHf_wrOmJ6GnTDaAvstDlx2jBtc2OMvOGt7fWYbGSJF5SZG-tTi8Y7Nfl4ddxPmRsWVaQ4HaVY-WAhyphenhyphen6_0eQj5kBEGAWBMYJ-NvWg5JEnKaCK5jz_QNDUHD5ruY_9jSnu_fjtG02pRdSgIHhRZyIqKeofhP08ahw/s72-c/Doom1.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-4635172250409518412</guid><pubDate>Thu, 04 Jul 2024 10:00:00 +0000</pubDate><atom:updated>2025-04-27T05:13:56.097-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Source Control</category><title>GitLab Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In 2016, we checked out &lt;a href=&quot;http://steveproxna.blogspot.com/2016/08/github-cheat-sheet.html&quot;&gt;GitHub Cheat Sheet&lt;/a&gt;: a distributed version control system for Open Source projects.  Now we will explore differences in GitLab to streamline collaborative workflow and leverage &lt;a href=&quot;https://www.bomberbot.com/devops/automate-your-software-development-lifecycle-with-gitlab-ci-cd&quot;&gt;CI/CD pipelines&lt;/a&gt;.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfdryn90ILEQjxlge0UqwMW56nzSHXLsRAkYD0iz3Kr0e3PbwLmRbdkn_FUgSn_pX43Y0SViVk1BDpb_bN9TYxrbtWENbO_A4uAHJLAqwrQ4z6hohhScg4NRV_ZCWZZBMS1AkFFY0Qlv7E9L7uQJr_9dFml5CaoXCwENAeF7My9r9k0mn7jW9Qc4l9Ovg/s713/GitLab.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfdryn90ILEQjxlge0UqwMW56nzSHXLsRAkYD0iz3Kr0e3PbwLmRbdkn_FUgSn_pX43Y0SViVk1BDpb_bN9TYxrbtWENbO_A4uAHJLAqwrQ4z6hohhScg4NRV_ZCWZZBMS1AkFFY0Qlv7E9L7uQJr_9dFml5CaoXCwENAeF7My9r9k0mn7jW9Qc4l9Ovg/s600/GitLab.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt; 
&lt;u&gt;GitLab&lt;/u&gt;&lt;br /&gt;
As per previous post assumes an account setup on &lt;a href=&quot;https://github.com/SteveProXNA&quot;&gt;github.com&lt;/a&gt;.  Create an account on &lt;a href=&quot;https://gitlab.com/SteveProXNA&quot;&gt;gitlab.com&lt;/a&gt; if you have not already done so.  As GitLab also uses underlying git we setup the following on localhost for development:
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;SSH Keys&lt;/b&gt;&lt;br /&gt;
An SSH key is an access credential for the SSH network protocol.  Git supports both RSA and ED25519 keys.  Launch Terminal.  Issue the following commands to &lt;a href=&quot;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent&quot;&gt;generate&lt;/a&gt; new SSH key and &lt;a href=&quot;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#adding-your-ssh-key-to-the-ssh-agent&quot;&gt;adding&lt;/a&gt; SSH key to ssh-agent:
&lt;br /&gt;
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;RSA&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;ED25519&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;cd ~/.ssh&lt;/td&gt;
&lt;td&gt;&amp;nbsp;cd ~/.ssh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;ssh-keygen -t rsa -b 4096 -C &quot;steven_boland@hotmail.com&quot;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;ssh-keygen -t ed25519 -C &amp;lt;email&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;Passphrase &amp;lt;redacted&amp;gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Passphrase &amp;lt;redacted&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;eval &quot;$(ssh-agent -s)&quot;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;eval &quot;$(ssh-agent -s)&quot;&lt;/td&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;ssh-add ~/.ssh/id_rsa&lt;/td&gt;
&lt;td&gt;&amp;nbsp;ssh-add ~/.ssh/id_ed25519&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;xclip -selection clipboard &lt; ~/.ssh/id_rsa.pub&lt;/td&gt;
&lt;td&gt;&amp;nbsp;xclip -selection clipboard &lt; &amp;lt;key&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
IMPORTANT:&lt;br /&gt;
If &lt;b&gt;xclip&lt;/b&gt; is not installed then issue 2x commands: &lt;i&gt;sudo apt-get update&lt;/i&gt; and &lt;i&gt;sudo apt-get install xclip&lt;/i&gt;.  Finally, navigate to github.com Settings | &lt;a href=&quot;https://github.com/settings/keys&quot;&gt;SSH and GPG&lt;/a&gt; keys | New SSH key | Paste contents from id_rsa.pub here.
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Personal Access Token&lt;/b&gt;&lt;br /&gt;
If you favor HTTPS then Personal Access Tokens offer security benefits over password-based &lt;a href=&quot;https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations&quot;&gt;authentication&lt;/a&gt;.  Launch &lt;a href=&quot;https://gitlab.com/SteveProXNA&quot;&gt;gitlab.com&lt;/a&gt;.  Navigate to Edit Profile | Access Tokens | Add new token.  &lt;a href=&quot;https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token&quot;&gt;Create&lt;/a&gt; personal access token.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1wDKBpfmtIOFqgzXHsQvpzgwfg2xeZeES03OwSDC5IbM9Xl9IXSHD2TgaAciFgM4-1LUHfIVBtyg9N1YWtCH6VE9j6DOh9ih1U2QD34xiDnz4aQrOsYIBUIWEZh2CYafvGcMQWdYBit42VQlt6TJ-YiuM7q31-yX45cvAhtmWEfaeIkdvJ13bemSxgzQ/s1209/PersonalAccessToken.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1wDKBpfmtIOFqgzXHsQvpzgwfg2xeZeES03OwSDC5IbM9Xl9IXSHD2TgaAciFgM4-1LUHfIVBtyg9N1YWtCH6VE9j6DOh9ih1U2QD34xiDnz4aQrOsYIBUIWEZh2CYafvGcMQWdYBit42VQlt6TJ-YiuM7q31-yX45cvAhtmWEfaeIkdvJ13bemSxgzQ/s600/PersonalAccessToken.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
After new Personal Access Token is created upload into source control software for example Source Tree on Windows and Mac OS/X and JetBrains products on Linux that integrate Git like PyCharm for Python etc etc.
&lt;br /&gt;&lt;br /&gt;
&lt;i&gt;Source Tree&lt;/i&gt;&lt;br /&gt;
Launch Source Tree | Settings | Accounts Add... | Enter the following details | Paste personal access token:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoe_STkSKCChQRNh1KuIAge9dKx-bfQwgfkfjHIL5PaNb8l808ZXcgnAXuc-aXAuHpvc6EHuXl0c9lAXZNo35ItpFq212AjWZy6VHmZF-gMbN7srBtvQlT1Q0fjw4LTvzg1XlymKxmj1CU6t6hqg8YreD5rj2R1UHOYRPEneO19XZO-oS1vzvWuoYaEEE/s476/PrivateToken.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoe_STkSKCChQRNh1KuIAge9dKx-bfQwgfkfjHIL5PaNb8l808ZXcgnAXuc-aXAuHpvc6EHuXl0c9lAXZNo35ItpFq212AjWZy6VHmZF-gMbN7srBtvQlT1Q0fjw4LTvzg1XlymKxmj1CU6t6hqg8YreD5rj2R1UHOYRPEneO19XZO-oS1vzvWuoYaEEE/s600/PrivateToken.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;  
&lt;i&gt;JetBrains IDE&lt;/i&gt;&lt;br /&gt;
Launch PyCharm | File | Settings... | Version Control | GitLab.  Click &quot;+&quot; button | Enter GitLab token | Log In:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoLlhDerqsiX9yoLP66MwbrbaejlN-ySRugsaaq7iI_qphyZtk5QRdbfFSmjf5X2VdSfTtBNshBro-2bnECxgnxw6QKhS_H2dREDshBhlyLMtyT6gTP92WXsWJMObXvFEd5DlWXEc_awf2CzQSU520-nPlj_SRwuS3W1Iau_Dx4ACN0Lph8Xl0Ozz6dYg/s1022/JetBrainsLogin.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoLlhDerqsiX9yoLP66MwbrbaejlN-ySRugsaaq7iI_qphyZtk5QRdbfFSmjf5X2VdSfTtBNshBro-2bnECxgnxw6QKhS_H2dREDshBhlyLMtyT6gTP92WXsWJMObXvFEd5DlWXEc_awf2CzQSU520-nPlj_SRwuS3W1Iau_Dx4ACN0Lph8Xl0Ozz6dYg/s600/JetBrainsLogin.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Example&lt;/u&gt;&lt;br /&gt;
In 2021, we coded an &lt;a href=&quot;http://steveproxna.blogspot.com/2021/09/kubernetes-cheat-sheet.html&quot;&gt;example&lt;/a&gt; from scratch as full end-to-end Web API demo on local host, in Docker and Kubernetes.  Let&#39;s replicate with &lt;a href=&quot;https://blog.devops.dev/ci-cd-using-gitlab-and-docker-python-app-example-3f19ef26c2e8&quot;&gt;Python Flask API&lt;/a&gt; but this time include Gitlab CI/CD deployment pipelines.
&lt;br /&gt;&lt;br /&gt;
Navigate to &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet&quot;&gt;gitlab.com&lt;/a&gt;.  Create blank project.  Launch PyCharm.  Create the new project &lt;b&gt;gitlabcheatsheet&lt;/b&gt;.
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdqqC9Y8zFXYnH6fLnE-19x2NGdufNlAk-nntpH5zPwPlwNndYqJTD4qdIdbbyvxRlA4ZgBM1eZPb9lm1KBGK2uEZMx0mWjp-dS3WKKn2MZprE8NZ4gSsV3nFPuprhcLKi4WeXEADweRIJEPqGYPvAb52ySN6YHUApCDexLsM8BGZc8TxTVTwINjLRMk0/s925/BlankProject.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdqqC9Y8zFXYnH6fLnE-19x2NGdufNlAk-nntpH5zPwPlwNndYqJTD4qdIdbbyvxRlA4ZgBM1eZPb9lm1KBGK2uEZMx0mWjp-dS3WKKn2MZprE8NZ4gSsV3nFPuprhcLKi4WeXEADweRIJEPqGYPvAb52ySN6YHUApCDexLsM8BGZc8TxTVTwINjLRMk0/s600/BlankProject.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT5O32B_bQ_V4w6igR5jnHlotjLGjl_CEkwFYMQxQLP5m6bSNFwmBcjZXvr1szF236wl5eTdnG5DOKqD-QCof3PK1u5ta_J0eKDKC3SBSaOulD9MRu0-yEjwbuunmmfMhgOdMw1Q6XHN4C0EOc3L36x39slpEvqlDts_qL-P1K3E3r4ORxdKeMRZu_YNA/s800/NewProject.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjT5O32B_bQ_V4w6igR5jnHlotjLGjl_CEkwFYMQxQLP5m6bSNFwmBcjZXvr1szF236wl5eTdnG5DOKqD-QCof3PK1u5ta_J0eKDKC3SBSaOulD9MRu0-yEjwbuunmmfMhgOdMw1Q6XHN4C0EOc3L36x39slpEvqlDts_qL-P1K3E3r4ORxdKeMRZu_YNA/s600/NewProject.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Enter &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/main.py&quot;&gt;main.py&lt;/a&gt; code.  Install &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/requirements.txt&quot;&gt;packages&lt;/a&gt;.  Press F5 to debug.  Launch Terminal | curl &lt;b&gt;http://localhost:8080&lt;/b&gt;
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/main.py&quot;&gt;main.py&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/Dockerfile&quot;&gt;Dockerfile&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;from flask import Flask
&amp;nbsp;app = Flask(__name__)
&amp;nbsp;@app.route(&#39;/&#39;)
&amp;nbsp;def root():
&amp;nbsp;    return &quot;Hello World (Python)!\n&quot;
&amp;nbsp;if __name__ == &quot;__main__&quot;:
&amp;nbsp;    app.run(host=&quot;0.0.0.0&quot;, port=8080)
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;FROM python:3-alpine
&amp;nbsp;WORKDIR /service
&amp;nbsp;COPY requirements.txt .
&amp;nbsp;RUN pip install -r requirements.txt
&amp;nbsp;COPY . ./
&amp;nbsp;EXPOSE 8080
&amp;nbsp;ENTRYPOINT [&quot;python3&quot;, &quot;main.py&quot;]
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Code &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/Dockerfile&quot;&gt;Dockefile&lt;/a&gt;.  Launch Terminal | Enter the following Docker commands | curl &lt;b&gt;http://localhost:8080&lt;/b&gt;  
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;docker build --pull --rm -f &quot;Dockerfile&quot; -t flask-api:latest &quot;.&quot;&lt;br /&gt;
&amp;nbsp;docker run --rm -d -p 8080:8080/tcp flask-api:latest --name &quot;flask-api&quot;&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Create local &lt;a href=&quot;https://kind.sigs.k8s.io&quot;&gt;KinD&lt;/a&gt; cluster.  Enter all the following &lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/Kubernetes.yaml&quot;&gt;Kubernetes&lt;/a&gt; Deployment and Service YAML configuration:
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot;&gt;&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/Kubernetes.yaml&quot;&gt;Kubernetes.yaml&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;--- Deployment
&amp;nbsp;apiVersion: apps/v1
&amp;nbsp;kind: Deployment
&amp;nbsp;metadata:
&amp;nbsp;  name: flask-api-deployment
&amp;nbsp;  namespace: test-ns
&amp;nbsp;spec:
&amp;nbsp;  replicas: 1
&amp;nbsp;  selector:
&amp;nbsp;    matchLabels:
&amp;nbsp;      app: flask-api
&amp;nbsp;  template:
&amp;nbsp;    metadata:
&amp;nbsp;      labels:
&amp;nbsp;        app: flask-api
&amp;nbsp;    spec:
&amp;nbsp;      containers:
&amp;nbsp;        - name: flask-api
&amp;nbsp;          image: flask-api:latest
&amp;nbsp;          imagePullPolicy: Never
&amp;nbsp;          ports:
&amp;nbsp;            - containerPort: 8080
&lt;/pre&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;--- Service
&amp;nbsp;apiVersion: v1
&amp;nbsp;kind: Service
&amp;nbsp;metadata:
&amp;nbsp;  name: flask-api-service
&amp;nbsp;  namespace: test-ns
&amp;nbsp;spec:
&amp;nbsp;  selector:
&amp;nbsp;    app: flask-api
&amp;nbsp;  type: NodePort
&amp;nbsp;  ports:
&amp;nbsp;    - protocol: TCP
&amp;nbsp;      port: 80
&amp;nbsp;      targetPort: 8080
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&amp;nbsp;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Finally test: Launch Terminal | Enter the following Kubernetes commands | curl &lt;b&gt;http://localhost:8080&lt;/b&gt;
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;kubectl config set-context --current --namespace=test-ns&lt;br /&gt;
&amp;nbsp;kind load docker-image flask-api:latest --name flask-cluster&lt;br /&gt;
&amp;nbsp;kubectl apply -f Kubernetes.yaml&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;kubectl port-forward service/flask-api-service 8080:80&lt;br /&gt;
&amp;nbsp;curl http://localhost:8080&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt; 
&lt;u&gt;Cluster&lt;/u&gt;&lt;br /&gt;
Extend example but this time include Gitlab CI/CD deployment pipelines.  Ensure you have all Pre-Requisites:
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;Python 3.8&lt;br /&gt;
&amp;nbsp;&lt;a href=&quot;https://gitlab.com/SteveProXNA&quot;&gt;GitLab&lt;/a&gt; account [CI/CD]&lt;br /&gt;
&amp;nbsp;Microsoft &lt;a href=&quot;https://portal.azure.com&quot;&gt;Azure&lt;/a&gt; subscription [AZ CLI]&lt;br /&gt;
&amp;nbsp;VS Code Docker + Kubernetes &lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;&lt;a href=&quot;https://hub.docker.com/u/steveproxna&quot;&gt;Docker&lt;/a&gt; Hub account&lt;br /&gt;
&amp;nbsp;Kubernetes in Docker [KinD]&lt;br /&gt;
&amp;nbsp;docker [CLI]&lt;br /&gt;
&amp;nbsp;kubectl [CLI]&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Azure AKS&lt;/b&gt;&lt;br /&gt;
Launch Terminal | Login to Azure portal.  Enter commands to extract Service Principal and generate SSH key:
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;az login&lt;br /&gt;
&amp;nbsp;az ad sp create-for-rbac --name ${USER}-sp&lt;br /&gt;
&amp;nbsp;cd ~/.ssh&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;ssh-keygen -t rsa -b 4096 -N &#39;&#39; -f master_ssh_key&lt;br /&gt;
&amp;nbsp;eval $(ssh-agent -s)&lt;br /&gt;
&amp;nbsp;ssh-add master_ssh_key&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Export the following environment variables.  Note: use the Service Principal information for first 3x ENV VARs
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;export AZ_SP_ID=&amp;lt;value_from_appId&amp;gt;&lt;br /&gt;
&amp;nbsp;export AZ_SP_PASSWORD=&amp;lt;value_from_password&amp;gt;&lt;br /&gt;
&amp;nbsp;export AZ_TENANT_ID=&amp;lt;value_from_tenant&amp;gt;&lt;br /&gt;
&amp;nbsp;export CLUSTER_NAME=stevepro-dev-cluster&lt;br /&gt;
&amp;nbsp;export CLUSTER_NODES=3&lt;br /&gt;
&amp;nbsp;export MASTER_SSH_KEY=~/.ssh/master_ssh_key.pub&lt;br /&gt;
&lt;/td&gt;
&lt;td&gt;
&amp;nbsp;export AZ_NETWORK_MODE=transparent&lt;br /&gt;
&amp;nbsp;export AZ_CREATE_MODE=AKS&lt;br /&gt;
&amp;nbsp;export AZ_LB_SKU=standard&lt;br /&gt;
&amp;nbsp;export AZ_VM_SIZE=Standard_D2s_v3&lt;br /&gt;
&amp;nbsp;export AZ_LOCATION=northeurope&lt;br /&gt;
&amp;nbsp;export KUBERNETES_VERSION=1.28&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Create the Azure resource group then finally create the AKS cluster.  Note: this process can take few minutes
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;az group create --name ${CLUSTER_NAME} --location ${AZ_LOCATION} --debug
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;az aks create --name ${CLUSTER_NAME} --resource-group ${CLUSTER_NAME} \&lt;br /&gt;
&amp;nbsp; --dns-name-prefix ${CLUSTER_NAME} --node-count ${CLUSTER_NODES} \&lt;br /&gt;
&amp;nbsp; --node-vm-size ${AZ_VM_SIZE} --kubernetes-version ${KUBERNETES_VERSION} \&lt;br /&gt;
&amp;nbsp; --ssh-key-value ${MASTER_SSH_KEY} --service-principal ${AZ_SP_ID} \&lt;br /&gt;
&amp;nbsp; --client-secret ${AZ_SP_PASSWORD} --load-balancer-sku ${AZ_LB_SKU} \&lt;br /&gt;
&amp;nbsp; --network-plugin azure --debug&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Finally, execute following commands to download + export &lt;b&gt;KUBECONFIG&lt;/b&gt; file on localhost and setup context
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;export KUBECONFIG=~/.kube/config&lt;br /&gt;
&amp;nbsp;az aks get-credentials --name ${CLUSTER_NAME} \&lt;br /&gt;
&amp;nbsp; --resource-group ${CLUSTER_NAME} --file ${KUBECONFIG}&lt;br /&gt;
&amp;nbsp;kubectl create ns test-ns&lt;br /&gt;
&amp;nbsp;kubectl config set-context --current --namespace=test-ns&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Pipeline&lt;/b&gt;&lt;br /&gt;
Follow this &lt;a href=&quot;https://docs.gitlab.com/ee/ci/quick_start&quot;&gt;tutorial&lt;/a&gt; to create and run your first GitLab CI/CD pipeline.  Create &lt;b&gt;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/blob/main/.gitlab-ci.yml&quot;&gt;.gitlab-ci.yml&lt;/a&gt;&lt;/b&gt; file at root the of the project directory.  Refactor all YAML configuration in files beneath the &lt;b&gt;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/tree/main/cicd&quot;&gt;cicd&lt;/a&gt;&lt;/b&gt; directory.  &lt;a href=&quot;https://robinjanke1.medium.com/automating-helm-chart-builds-and-deployment-with-gitlab-ci-cd-2dbfad30a86c&quot;&gt;Automate&lt;/a&gt; CI/CD to the Kubernetes cluster using &lt;b&gt;&lt;a href=&quot;https://gitlab.com/SteveProXNA/gitlabcheatsheet/-/tree/main/helm&quot;&gt;helm&lt;/a&gt;&lt;/b&gt; charts.  This way, multiple environments can be targeted and customized.
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Variables&lt;/b&gt;&lt;br /&gt;
Navigate to gitlab.com | Settings | CI/CD | Variables.  Enter all GitLab &lt;a href=&quot;https://docs.gitlab.com/ee/ci/variables/predefined_variables.html &quot;&gt;Variables&lt;/a&gt; here e.g. Docker registry host and username.  &lt;a href=&quot;https://cloudifydevops.com/secured-gitlab-pipeline-with-base64&quot;&gt;Secure&lt;/a&gt; sensitive information like Docker password using Base64.  Add &lt;b&gt;KUBECONFIG&lt;/b&gt;:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTGUUUNMTyMV4kq_Y2SJizIsd4oE-xkATtYVeR1h16opxVtVz-CJ_rLS0mj8LNe9TX1Zqd8myjR4jUUx5Hl3KHWWig2-ZZVdqiGu7JQ5sZ8ANp8nk7z17VcVTzLAGpPNvICDI8gf2nWsj7Xs45v-uA3beTPlmhyphenhyphenf7EsOpEybKGswa358EKVViAR57vR60/s883/CICDvariables.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTGUUUNMTyMV4kq_Y2SJizIsd4oE-xkATtYVeR1h16opxVtVz-CJ_rLS0mj8LNe9TX1Zqd8myjR4jUUx5Hl3KHWWig2-ZZVdqiGu7JQ5sZ8ANp8nk7z17VcVTzLAGpPNvICDI8gf2nWsj7Xs45v-uA3beTPlmhyphenhyphenf7EsOpEybKGswa358EKVViAR57vR60/s600/CICDvariables.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;b&gt;Deployment&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://cto.ai/blog/using-gitlab-ci-cd-with-a-kubernetes-cluster&quot;&gt;Trigger&lt;/a&gt; CI/CD pipeline.  Launch Terminal | Repeat &lt;i&gt;kubectl port-forward&lt;/i&gt;.  Test: curl &lt;b&gt;http://localhost:8080&lt;/b&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCMB-DtZzsybnDWbna8rv5wVUDH8hyphenhyphenzJkQy2GpQBT1c8pNwDOBrLwc-fF4jJsYdlT1-NdMRboAEKPhsTwOw5p7SnCT35Nzxbq3bjuNUlbYdzd_PeCS9VFTJLPKzsAVXPCM_GPK7UaCBSAY9CftH7W95-viOtbcczXsE70UwDlxK51tBqvWQ2Fc7g_VWXU/s770/BuildPipelines.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCMB-DtZzsybnDWbna8rv5wVUDH8hyphenhyphenzJkQy2GpQBT1c8pNwDOBrLwc-fF4jJsYdlT1-NdMRboAEKPhsTwOw5p7SnCT35Nzxbq3bjuNUlbYdzd_PeCS9VFTJLPKzsAVXPCM_GPK7UaCBSAY9CftH7W95-viOtbcczXsE70UwDlxK51tBqvWQ2Fc7g_VWXU/s600/BuildPipelines.png&quot;/&gt;&lt;/a&gt;  
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;kubectl port-forward service/flask-api-service 8080:80&lt;br /&gt;
&amp;nbsp;curl http://localhost:8080&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;GitFlow&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow&quot;&gt;Gitflow&lt;/a&gt; is an alternative Git branching model that involves the use of feature branches and multiple primary branches.  Here is practical &lt;a href=&quot;https://hackernoon.com/from-git-flow-to-cicd-a-practical-guide-to-implement-git-workflow&quot;&gt;guide&lt;/a&gt; to implement GitFlow using GitLab with the corresponding git commands.
&lt;br /&gt;&lt;br /&gt;
Launch &lt;a href=&quot;https://gitlab.com&quot;&gt;gitlab.com&lt;/a&gt;.  Create new project.  Default branch will be main.  Git clone repository to localhost.  For completeness cut initial Tag 0.1.  In SourceTree setup GitFlow: Repository | Git-flow | Initialize Repository:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvGW7oKKtSjFsTDDBWddpfXELIMOcA0KHDwkzj2oWSZkBuVppHEr7Rxg_tUR55avW0pOw0o-e9yWdfbboCm6RMazX77GbKBIRofpVl1UYdQ4cz5xs6PSLckEGqbiGjSWstXElPHRF-8v5qHGAC0oH1xOLd2si-_zZCkj6dBmydnftN8fVrwUdqT_LqNcw/s413/sourcetree.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvGW7oKKtSjFsTDDBWddpfXELIMOcA0KHDwkzj2oWSZkBuVppHEr7Rxg_tUR55avW0pOw0o-e9yWdfbboCm6RMazX77GbKBIRofpVl1UYdQ4cz5xs6PSLckEGqbiGjSWstXElPHRF-8v5qHGAC0oH1xOLd2si-_zZCkj6dBmydnftN8fVrwUdqT_LqNcw/s600/sourcetree.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
In gitlab.com set develop as default branch: GitLab | Setttings | Repository | Branch defaults | &lt;b&gt;develop&lt;/b&gt;.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table width=&quot;99%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;FEATURE&lt;/b&gt; [start]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout -b feature/my-feature develop&lt;/td&gt;&lt;td&gt;&amp;nbsp;# cut feature branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push --set-upstream origin feature/my-feature&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push feature to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout develop&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git merge --no-ff feature/my-feature&lt;/td&gt;&lt;td&gt;&amp;nbsp;# merge feature to develop&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push develop to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;FEATURE&lt;/b&gt; [end]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git branch -d feature/my-feature&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete local branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push origin -d feature/my-feature&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete remote branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;RELEASE&lt;/b&gt; [start]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout -b release/1.0 develop&lt;/td&gt;&lt;td&gt;&amp;nbsp;# cut release branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push --set-upstream origin release/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push release to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;BUGFIX&lt;/b&gt; [start]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout -b bugfix/1.0 release/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# cut bugfix branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push --set-upstream origin bugfix/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push bugfix to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout release/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git merge --no-ff bugfix/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# merge bugfix to release&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push release to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;BUGFIX&lt;/b&gt; [end]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git branch -d bugfix/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete local branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push origin -d bugfix/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete remote branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;RELEASE&lt;/b&gt; [end]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout main&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git merge --no-ff release/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# merge release to main&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push&lt;/td&gt;&lt;td&gt;&amp;nbsp;# sync release with main&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git tag -a 1.0 -m &quot;Tag 1.0&quot;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# cut tag 1.0 off main&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push origin tag 1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push tag 1.0 to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout develop&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git merge --no-ff release/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# merge release to develop&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push&lt;/td&gt;&lt;td&gt;&amp;nbsp;# sync release with develop&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git branch -d release/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete local branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push origin -d release/1.0&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete remote branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;HOTFIX&lt;/b&gt; [start]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout main&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout -b hotfix/1.1 main&lt;/td&gt;&lt;td&gt;&amp;nbsp;# cut hotfix branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push --set-upstream origin hotfix/1.1&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push hotfix to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;HOTFIX&lt;/b&gt; [end]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout main&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git merge --no-ff hotfix/1.1&lt;/td&gt;&lt;td&gt;&amp;nbsp;# merge hotfix to main&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push&lt;/td&gt;&lt;td&gt;&amp;nbsp;# sync hotfix with main&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git tag -a 1.1 -m &quot;Tag 1.1&quot;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# cut Tag 1.1 off main&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push origin tag 1.1&lt;/td&gt;&lt;td&gt;&amp;nbsp;# push Tag 1.1 to remote&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout develop&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git merge --no-ff hotfix/1.1&lt;/td&gt;&lt;td&gt;&amp;nbsp;# merge hotfix to develop&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push&lt;/td&gt;&lt;td&gt;&amp;nbsp;# sync hotfix with develop&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git branch -d hotfix/1.1&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete local branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git push origin -d hotfix/1.1&lt;/td&gt;&lt;td&gt;&amp;nbsp;# delete remote branch&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
IMPORTANT - you can compare two branches [source vs. target] anytime issuing the following commands:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table width=&quot;99%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git checkout develop&lt;/td&gt;&lt;td&gt;&amp;nbsp;# source branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git diff --name-only main&lt;/td&gt;&lt;td&gt;&amp;nbsp;# target branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;&amp;nbsp;&lt;b&gt;OR&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# target branch&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;git diff-tree --no-commit-id --name-only -r main..develop&lt;/td&gt;&lt;td&gt;&amp;nbsp;# source vs. target branch&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, now that we have discussed the &lt;a href=&quot;https://www.geeksforgeeks.org/difference-between-gitlab-and-github&quot;&gt;differences&lt;/a&gt; between GitHub and GitLab, we have extended our previous end-to-end Web API demo on local host, in Docker and Kubernetes but now leveraged GitLab CI/CD pipelines to automate deployments to the cloud.  Our next steps would be more GitFlow integration: Replicate deployments across multiple environments and complete the full Software Development LifeCyle!
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2024/07/gitlab-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfdryn90ILEQjxlge0UqwMW56nzSHXLsRAkYD0iz3Kr0e3PbwLmRbdkn_FUgSn_pX43Y0SViVk1BDpb_bN9TYxrbtWENbO_A4uAHJLAqwrQ4z6hohhScg4NRV_ZCWZZBMS1AkFFY0Qlv7E9L7uQJr_9dFml5CaoXCwENAeF7My9r9k0mn7jW9Qc4l9Ovg/s72-c/GitLab.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-6961902998500543606</guid><pubDate>Sat, 01 Jun 2024 10:00:00 +0000</pubDate><atom:updated>2025-09-27T08:34:15.137-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">MacOS</category><title>MacOS Setup Cheat Sheet II</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2024/05/macos-setup-cheat-sheet.html&quot;&gt;post&lt;/a&gt; we checked out MacOS Setup Cheat Sheet to seamlessly transfer all keyboard shortcuts from Windows to Mac.  Now we would like to transfer all Application navigation as &lt;a href=&quot;https://en.wikipedia.org/wiki/Apple_M1&quot;&gt;M1&lt;/a&gt; powered MacBooks are more appealing for &lt;a href=&quot;https://medium.com/@abhishek.quicktech/why-companies-run-better-on-a-mac-than-on-windows-61272da87980&quot;&gt;companies&lt;/a&gt; than ever.  Especially with the rise of &lt;a href=&quot;https://www.linkedin.com/pulse/apple-m1-m2-chips-what-good-deep-learning-denovo-team-fydrf&quot;&gt;A.I.&lt;/a&gt; requirements for faster data access.  
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq1YSFVTPkHH46ynNtUAc_Ab4T0F-zolbEIqa7qmPcjHnQ0jo0f2YUfOv-m63uFKNo8myj1HxgYrzBtgeQgy4Wn-kvdEmNotzwNqJkVzhNIStf0Lvf1-8KcRn2-MpXQeLNFU67rUCX6mcXFcYy0Ad3k6p2MAtn8z07MGP45tme7HX16ZiC8zjMc3SLd4Q/s1280/MacOSX.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; height=&quot;275px&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq1YSFVTPkHH46ynNtUAc_Ab4T0F-zolbEIqa7qmPcjHnQ0jo0f2YUfOv-m63uFKNo8myj1HxgYrzBtgeQgy4Wn-kvdEmNotzwNqJkVzhNIStf0Lvf1-8KcRn2-MpXQeLNFU67rUCX6mcXFcYy0Ad3k6p2MAtn8z07MGP45tme7HX16ZiC8zjMc3SLd4Q/s600/MacOSX.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Navigation&lt;/u&gt;&lt;br /&gt;
In the previous post, we began looking at using keyboard &lt;a href=&quot;https://support.apple.com/en-us/HT201236&quot;&gt;shortcuts&lt;/a&gt; on Mac.  Now we would like to compare document shortcuts that we are used to for navigation on Windows however now using Ctrl instead of Cmd:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Home&lt;/td&gt;	
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Move to beg of line&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Home&lt;/td&gt;	
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Move to beg of file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt; 
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;End&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Move to end of line&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + End&lt;/td&gt;	
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Move to end of file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Left&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Move to prev word&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Shift + Left&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Select the prev word&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;  
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Right&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Move to next word&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Shift + Right&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Select the next word&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt; 
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Shift + Home&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Select to beg of line&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Shift + Home&lt;/td&gt;	
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Select to beg of file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Shift + End&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Select to end of line&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Shift + End&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Select to end of file&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
The main issue is there doesn&#39;t seem to be generic shortcut mapping; navigation seems application specific!
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;TextEdit&lt;/u&gt;&lt;br /&gt;
The Mac text system uses generalized key &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/TextDefaultsBindings/TextDefaultsBindings.html&quot;&gt;bindings&lt;/a&gt; mechanism that is completely re-mappable by all users.  The standard bindings include all system defaults but you can override bindings in your own custom dict file:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;SYSTEM&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;/System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;CUSTOM&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;~/Library/KeyBindings/DefaultKeyBinding.dict&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Here is &lt;a href=&quot;https://ss64.com/mac/syntax-keybindings.html&quot;&gt;how to&lt;/a&gt; override MacOS key bindings:  Launch Terminal and create new a &lt;i&gt;DefaultKeyBinding.dict&lt;/i&gt; file:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;sudo bash&lt;br /&gt;
&amp;nbsp;mkdir -p ~/Library/KeyBindings&lt;br /&gt;
&amp;nbsp;touch ~/Library/KeyBindings/DefaultKeyBinding.dict&lt;br /&gt;
&amp;nbsp;open -e ~/Library/KeyBindings/DefaultKeyBinding.dict&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Typically, the default key bindings for the Home and End &lt;a href=&quot;https://www.evansweb.info/2005/03/24/mac-os-x-and-home-end-keys&quot;&gt;keys&lt;/a&gt; in MacOS are different to any other operating system.  Thus you may like to &lt;a href=&quot;https://medium.com/@elhayefrat/how-to-fix-the-home-and-end-buttons-for-an-external-keyboard-in-mac-4da773a0d3a2&quot;&gt;fix&lt;/a&gt; the Home and End buttons first and in combination with Shift and Ctrl keys.
&lt;br /&gt;&lt;br /&gt;
Next key bindings that may not be working is to move &lt;a href=&quot;https://apple.stackexchange.com/questions/428543/defaultkeybinding-dict-method-not-working-to-move-cursor-from-word-to-wordwhich&quot;&gt;cursor&lt;/a&gt; from word to word.  Integrate &lt;a href=&quot;https://forum.keyboardmaestro.com/t/os-x-text-system-keybindings/4929/1&quot;&gt;Keycode&lt;/a&gt; Modifier learnt from the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2024/05/macos-setup-cheat-sheet.html&quot;&gt;post&lt;/a&gt; to complete custom dict file to change all MasOS key &lt;a href=&quot;https://blog.victormendonca.com/2020/04/27/how-to-change-macos-key-bindings&quot;&gt;bindings&lt;/a&gt;.  Here is my file: 
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfLine:&quot;;&lt;/td&gt;&lt;td&gt;/* Home Button*/&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfLine:&quot;;&lt;/td&gt;&lt;td&gt;/* End  Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;$\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfLineAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Shift+ Home Button */ &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;$\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfLineAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Shift+ End  Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfDocument:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + Home Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfDocument:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + Home Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfDocument:&quot;;&lt;/td&gt;&lt;td&gt;/* Win + Home Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfDocument:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + End  Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfDocument:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + End  Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfDocument:&quot;;&lt;/td&gt;&lt;td&gt;/* Win + End  Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@$\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfDocumentAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + Shift + Home Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^$\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfDocumentAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + Shift + Home Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~$\UF729&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToBeginningOfDocumentAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Win  + Shift + Home Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@$\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfDocumentAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + Shift + End Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^$\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfDocumentAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + Shift + End Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~$\UF72B&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveToEndOfDocumentAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Win + Shift + End Button */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@\UF702&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordLeft:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + Left */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^\UF702&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordLeft:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + Left */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~\UF702&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordLeft:&quot;;&lt;/td&gt;&lt;td&gt;/* Win + Left */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@\UF703&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordRight:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + Right */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^\UF703&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordRight:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + Right */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~\UF703&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordRight:&quot;;&lt;/td&gt;&lt;td&gt;/* Win + Right */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@$\UF702&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordLeftAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + Shift + Left */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^$\UF702&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordLeftAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + Shift + Left */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~$\UF702&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordLeftAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Win + Shift + Left */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;@$\UF703&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordRightAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Ctrl + Shift + Right */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;^$\UF703&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordRightAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Alt + Shift + Right */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&quot;~$\UF703&quot; = &lt;/td&gt;&lt;td&gt;&quot;moveWordRightAndModifySelection:&quot;;&lt;/td&gt;&lt;td&gt;/* Win + Shift + Right */&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;}&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
For completeness, here is a thorough KeyBindings &lt;a href=&quot;http://xahlee.info/kbd/osx_keybinding.html&quot;&gt;tutorial&lt;/a&gt; explaining MacOS Keybinding &lt;a href=&quot;http://xahlee.info/kbd/osx_keybinding_key_syntax.html&quot;&gt;Key Syntax&lt;/a&gt; and the &lt;a href=&quot;http://xahlee.info/kbd/osx_keybinding_action_code.html&quot;&gt;Action Code&lt;/a&gt;.  Detailed &lt;a href=&quot;https://web.archive.org/web/20160314030051/http://osxnotes.net/keybindings.html&quot;&gt;DefaultKeyBinding&lt;/a&gt;.dict examples shared online by users &lt;a href=&quot;https://gist.github.com/Belphemur/5a45ce6826c609a65421cc10a1e607c1&quot;&gt;Belphemu&lt;/a&gt;, &lt;a href=&quot;https://gist.github.com/trusktr/1e5e516df4e8032cbc3d&quot;&gt;trusktr&lt;/a&gt; and &lt;a href=&quot;https://gist.github.com/zsimic/1367779&quot;&gt;zsimic&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Finally, in researching Default Key Bindings many posts promote &lt;a href=&quot;https://karabiner-elements.pqrs.org&quot;&gt;Karabiner-Elements&lt;/a&gt; as a powerful keyboard customizer for macOS.  However, it has been &lt;a href=&quot;https://www.reddit.com/r/MacOS/comments/mxq20w/option_leftright_arrows_remapped_to&quot;&gt;recommended&lt;/a&gt; &lt;b&gt;not&lt;/b&gt; to use on M1 hardware due to kernel panics.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Terminal&lt;/u&gt;&lt;br /&gt;
Ideally we would like to update navigation on Terminal due to frequent use: Terminal | Settings... | Profiles.  Keyboard tab customize Key and Action settings.  Check &lt;i&gt;Use Option as Meta Key&lt;/i&gt; to &quot;&lt;a href=&quot;https://stackoverflow.com/questions/327664/mac-os-x-terminal-map-optiondelete-to-backward-delete-word&quot;&gt;backward delete word&lt;/a&gt;&quot;.  Unfortunately, Terminal navigation not aligned therefore will prefer IDEs like VS Code or PyCharm terminals.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;VS Code&lt;/u&gt;&lt;br /&gt;
Visual Studio Code is a cross-platform code &lt;a href=&quot;https://code.visualstudio.com/docs/editor/whyvscode&quot;&gt;editor&lt;/a&gt; available on Windows, Linux and Mac.  However, unlike the TextEdit, VS Code does not &lt;a href=&quot;https://github.com/microsoft/vscode/issues/111950&quot;&gt;respect&lt;/a&gt; DefaultKeyBinding.dict on MacOS.  Therefore, &lt;a href=&quot;https://stackoverflow.com/questions/33791097/how-can-i-change-keyboard-shortcut-bindings-in-visual-studio-code&quot;&gt;change&lt;/a&gt; keyboard shorcuts!
&lt;br /&gt;&lt;br /&gt;
Customize VS Code keybindings to align navigation: Launch VS Code | Settings | Keyboard Shortcuts | Add:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Command&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Keybinding&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
  
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorTop&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Home&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to beg of file&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorTopSelect&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Home&lt;/td&gt;&lt;td&gt;&amp;nbsp;Select to beg of file&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorBottom&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + End&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to end of file&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorBottomSelect&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + End&lt;/td&gt;&lt;td&gt;&amp;nbsp;Select to end of file&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorWordLeft&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Left&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to prev word&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorWordLeftSelect&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Left&lt;/td&gt;&lt;td&gt;&amp;nbsp;Select the prev word&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorWordRight&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Right&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to next word&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;cursorWordRightSelect&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Right&lt;/td&gt;&lt;td&gt;&amp;nbsp;Select the next word&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;deleteWordLeft&lt;/td&gt;&lt;td&gt;&amp;nbsp;Alt + Backspace&lt;/td&gt;&lt;td&gt;&amp;nbsp;Delete the prev word&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Continue to customize Menu keyboard shortcuts that one is accustomed to aligning VS Code navigation e.g.:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Command&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Keybinding&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;File: Open Folder...&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + K Ctrl + O&lt;/td&gt;&lt;td&gt;&amp;nbsp;workbench.action.files.openFolderViaWorkspace&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Terminal: Clear&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + L&lt;/td&gt;&lt;td&gt;&amp;nbsp;workbench.action.terminal.clear&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Terminal: Create New Terminal&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + T&lt;/td&gt;&lt;td&gt;&amp;nbsp;workbench.action.terminal.new&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;renameFile&lt;/td&gt;&lt;td&gt;&amp;nbsp;F2&lt;/td&gt;&lt;td&gt;&amp;nbsp;renameFile&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
The &lt;a href=&quot;https://code.visualstudio.com/docs/getstarted/keybindings&quot;&gt;keybindings&lt;/a&gt; for VS Code are updated in &lt;i&gt;~/Library/Application\ Support/Code/User/keybindings.json&lt;/i&gt; file.  Update keybindings.json directly for Terminal keyboard shortcuts like &lt;a href=&quot;https://stackoverflow.com/questions/57824640/how-to-delete-the-prior-word-with-vs-code-terminal&quot;&gt;delete&lt;/a&gt; word prior + cursor &lt;a href=&quot;https://apple.stackexchange.com/questions/336382/how-can-i-make-ctrlright-left-arrow-jump-words-in-visual-studio-code&quot;&gt;movement&lt;/a&gt;:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;key&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;alt+backspace&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;command&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;workbench.action.terminal.sendSequence&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;args&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;{ &quot;text&quot;: &quot;\u001b\u007f&quot; },&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;when&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;terminalFocus&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;},&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;key&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;cmd+backspace&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;command&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;workbench.action.terminal.sendSequence&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;args&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;{ &quot;text&quot;: &quot;\u001b\u007f&quot; },&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;when&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;terminalFocus&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;},&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;key&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;cmd+left&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;command&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;workbench.action.terminal.sendSequence&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;args&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;{ &quot;text&quot;: &quot;\u001bb&quot; },&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;when&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;terminalFocus&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;},&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;key&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;cmd+right&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;command&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;workbench.action.terminal.sendSequence&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;args&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;{ &quot;text&quot;: &quot;\u001bf&quot; },&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;when&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;terminalFocus&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;},&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;key&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;cmd+z&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;command&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;workbench.action.terminal.sendSequence&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;args&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;{ &quot;text&quot;: &quot;\u0003&quot; },&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;when&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;terminalFocus&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;},&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;key&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;cmd+f5&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;command&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;workbench.action.debug.start&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;},&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;{&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;key&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;f5&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;command&quot;:&lt;/td&gt;&lt;td&gt;&amp;nbsp;&quot;workbench.action.debug.continue&quot;,&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;}&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
&lt;u&gt;PyCharm Community&lt;/u&gt;&lt;br /&gt;
Align PyCharm Keymap to VS Code Keymap for consistent keyboard shortcuts and developer IDE experience.  In the &quot;Welcome to PyCharm&quot; popup choose Plugins | VSCode Keymap | Install. Navigate back to Customize.  Under Keymap change default value VSCode (macOS). Now &lt;b&gt;most&lt;/b&gt; VS Code shortcuts will work like Windows.
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIPiZRtbCmjc4VVuvn-yVVkrFPlLAIGwpDRNFsfc6r-sRV6qmh3PcXZuc7tByM1v1QEdAyKcr95Yl7pTp3-BCsr7Nk0Rnt-RemYDzxFxDb3KXFTyK84Ub3Q4lsqc3hJYLgYihulZchKCeuV5WfPVqttdwP72gfGGZpP7-xGaub-lzRNN3XW2CWqytBXGM/s980/VSCodekeymap01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIPiZRtbCmjc4VVuvn-yVVkrFPlLAIGwpDRNFsfc6r-sRV6qmh3PcXZuc7tByM1v1QEdAyKcr95Yl7pTp3-BCsr7Nk0Rnt-RemYDzxFxDb3KXFTyK84Ub3Q4lsqc3hJYLgYihulZchKCeuV5WfPVqttdwP72gfGGZpP7-xGaub-lzRNN3XW2CWqytBXGM/s600/VSCodekeymap01.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit4hn7b3yCPKaPab8yR_EWt0Ex-qfirlAUx-tOxlA0ZJmz-2YdSIJnzNCVwTilyv5zr3r0yjGUJ2nzT2AvbsPrItNn2JCChsf_0pPXH46Zvz5sJ1GblCxF0edJt4Pez7-pAIejlU77v5Isb-eUzUbepPx6ZWiHHvYmIDN6TERUA0Zx11KBsebYakm1Eyw/s981/VSCodekeymap02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit4hn7b3yCPKaPab8yR_EWt0Ex-qfirlAUx-tOxlA0ZJmz-2YdSIJnzNCVwTilyv5zr3r0yjGUJ2nzT2AvbsPrItNn2JCChsf_0pPXH46Zvz5sJ1GblCxF0edJt4Pez7-pAIejlU77v5Isb-eUzUbepPx6ZWiHHvYmIDN6TERUA0Zx11KBsebYakm1Eyw/s600/VSCodekeymap02.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
However, in order to better align full navigation, update the following from PyCharm | Settings... | Keymap:
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Text Start&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Home&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Text Start with Selection&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Home&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Text End&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + End&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Text End with Selection&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + End&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Previous Word&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Left&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Previous Word with Selection&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Left&lt;/td&gt;&lt;/tr&gt;  
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Next Word&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Right&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Caret to Next Word with Selection&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Right&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Up and Scroll with Selection&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Up&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move Down and Scroll with Selection&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Shift + Down&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Editor Actions&lt;/td&gt;&lt;td&gt;&amp;nbsp;Delete to Word Start&lt;/td&gt;&lt;td&gt;&amp;nbsp;Alt + Backspace&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Main Menu&lt;/td&gt;&lt;td&gt;&amp;nbsp;Navigate Back&lt;/td&gt;&lt;td&gt;&amp;nbsp;Alt + Up&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Main Menu&lt;/td&gt;&lt;td&gt;&amp;nbsp;Navigate Forward&lt;/td&gt;&lt;td&gt;&amp;nbsp;Alt + Down&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Main Menu&lt;/td&gt;&lt;td&gt;&amp;nbsp;Navigate | Go to Line: Column&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + G&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Main Menu&lt;/td&gt;&lt;td&gt;&amp;nbsp;Run | Run/Debug | Run&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + F5&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Plugins&lt;/td&gt;&lt;td&gt;&amp;nbsp;Terminal | Clear Terminal&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + L&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
IMPORTANT: typically use Alt + Left to Navigate Back but this is now doubled to Move Word left as priority!
&lt;br /&gt;&lt;br /&gt;
NOTE&lt;br /&gt;
If Ctrl + Shift + O launches Symbols then remove duplicate: Choose Settings | Keymap | filter as &quot;symbol&quot;. Double click Navigate | Go to Symbol | Edit | Remove Ctrl+Shift+O | Apply | OK. Repeat this as necessary.
&lt;br /&gt;&lt;br /&gt; 
&lt;u&gt;Excel&lt;/u&gt;&lt;br /&gt;
Keyboard &lt;a href=&quot;https://support.microsoft.com/en-us/office/keyboard-shortcuts-in-excel-1798d9d5-842a-42b8-9c99-9b7213f0040f#PickTab=Windows&quot;&gt;shortcuts&lt;/a&gt; in Excel like Ctrl+Home and Ctrl+End won&#39;t work so prefer to use arrow keys to navigate
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;	
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Left&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to first cell of selected row&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Right&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to last cell of selected row&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Up&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to first cell of selected column&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Down&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move to last cell of selected column&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;PostgreSQL&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.postgresql.org&quot;&gt;PostgreSQL&lt;/a&gt; is preferred by companies because it offers data types not found in MySQL.  Plus MySQL can be used for web-based/online or mapping functions, whereas PostgreSQL is &lt;a href=&quot;https://kruschecompany.com/postgresql-vs-mysql&quot;&gt;recommended&lt;/a&gt; for large analytical processes.
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Postgres&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.youtube.com/watch?v=wTqosS71Dc4&quot;&gt;Setup&lt;/a&gt; a local PostgreSQL database server on &lt;a href=&quot;https://www.prisma.io/dataguide/postgresql/setting-up-a-local-postgresql-database#setting-up-postgresql-on-macos&quot;&gt;Mac&lt;/a&gt; OS/X.  &lt;a href=&quot;https://postgresapp.com/downloads.html&quot;&gt;Download&lt;/a&gt; Postgres.app &lt;a href=&quot;https://github.com/PostgresApp/PostgresApp/releases/download/v2.7.2/Postgres-2.7.2-16.dmg&quot;&gt;PostgreSQL 16&lt;/a&gt; (Universal).
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;pgAdmin&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.pgadmin.org/download/pgadmin-4-macos&quot;&gt;Download&lt;/a&gt; and install local &lt;a href=&quot;https://www.pgadmin.org&quot;&gt;pgAdmin&lt;/a&gt; database client on &lt;a href=&quot;https://www.postgresql.org/ftp/pgadmin/pgadmin4/v8.6/macos&quot;&gt;Mac&lt;/a&gt; OS/X to administer and PostgreSQL &lt;a href=&quot;https://ftp.postgresql.org/pub/pgadmin/pgadmin4/v8.6/macos/pgadmin4-8.6-arm64.dmg&quot;&gt;instances&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;PyCharm Professional&lt;/u&gt;&lt;br /&gt;
After installing Postgres server one can use pgAdmin client for data access.  However, it seems challenging to customize navigation here.  An excellent alternative is Database Tools + SQL &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/postgresql.html&quot;&gt;plugin&lt;/a&gt; available from PyCharm.
&lt;br /&gt;&lt;br /&gt;  
This plugin is available only in PyCharm Professional but may prove to be a valuable investment longterm &lt;span style=&#39;font-family:Wingdings&#39;&gt;J&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;PyCharm Community&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;PyCharm Professional&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkaIYm2wy4jbMF-RGqe-7lailnzgSLwlpcVct76K9Lk9f8LhDj7NvlZ_9Dl-sQrQaKExNPeiBvITMc2GL852sKr6I9HypIBEKhna8vQfG2Z5UbIHMtDyFOdNI9DtG3tj8bkPvGjV7zXdGULSmVCqSjMaYgDdejgVoCkF88Qo2rDkvowOYnjZNmkzkcGTc/s730/00-DatabaesToolsCE.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkaIYm2wy4jbMF-RGqe-7lailnzgSLwlpcVct76K9Lk9f8LhDj7NvlZ_9Dl-sQrQaKExNPeiBvITMc2GL852sKr6I9HypIBEKhna8vQfG2Z5UbIHMtDyFOdNI9DtG3tj8bkPvGjV7zXdGULSmVCqSjMaYgDdejgVoCkF88Qo2rDkvowOYnjZNmkzkcGTc/s600/00-DatabaesToolsCE.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgilr4GMj_WPyKvePmd5U4WR7BNjn0wQ1xDKTajthEgEv7eCzp9aKdLMyUd27_wB-Wgu2L4BcsOngLV6EzfLiDUkXiAZFVDFXdnYEoeXB53XuUkNt5pPDN135DqMhxRUKlv6lBLkZcsbE4TSOHXvmZr2IEAat7_FxBN8l14a9f0JNgJKKvVKPr6tsiJjdM/s725/01-DatabaseToolsProf.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgilr4GMj_WPyKvePmd5U4WR7BNjn0wQ1xDKTajthEgEv7eCzp9aKdLMyUd27_wB-Wgu2L4BcsOngLV6EzfLiDUkXiAZFVDFXdnYEoeXB53XuUkNt5pPDN135DqMhxRUKlv6lBLkZcsbE4TSOHXvmZr2IEAat7_FxBN8l14a9f0JNgJKKvVKPr6tsiJjdM/s600/01-DatabaseToolsProf.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;a href=&quot;https://www.jetbrains.com/pycharm/download/download-thanks.html?platform=macM1&quot;&gt;Download&lt;/a&gt; and install PyCharm Professional for &lt;a href=&quot;https://www.jetbrains.com/pycharm/download/?section=mac&quot;&gt;macOS&lt;/a&gt;.  Launch PyCharm Professional.  Import Settings from PyCharm Community Edition.  Thus you should have all navigation aligned!  Note the Database Tools + SQL plugin will be enabled by default.  Interesting plugins PostgreSQL Debugger and SQL Optimizer + Indexing.
&lt;br /&gt;&lt;br /&gt;
Connect to database: View menu | Database | Click &quot;+&quot; | Data Source | PostgreSQL.  Enter credentials | OK.
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiznRAKflWQHhAcaEjCmcjlWXXzs6LEqMnZ2UBHkwehdEgP83AtOBOdltQgJt1Tc8IdeRO2OgbV6_IQimXKt-Jxsj6WNEvLqlIAIxNzXHyfITGedzgJ5F4BxUPGriUb9mu9lpkIxpMPYyqtrvIGnumptbj7ktNo3QUra3dhh7LewiUmP8zyZwfmV2azbgM/s563/02-DataSource.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiznRAKflWQHhAcaEjCmcjlWXXzs6LEqMnZ2UBHkwehdEgP83AtOBOdltQgJt1Tc8IdeRO2OgbV6_IQimXKt-Jxsj6WNEvLqlIAIxNzXHyfITGedzgJ5F4BxUPGriUb9mu9lpkIxpMPYyqtrvIGnumptbj7ktNo3QUra3dhh7LewiUmP8zyZwfmV2azbgM/s600/02-DataSource.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje65CiY8KDxIMk9DxH42Bppg7fcIB9iQmi-kl1yyBIoKPbVYGvU4fGReMujlAlSK6Tn3RUwTsxT8B-80U7IJx_ikuc1kPjvCEBjmBOlJGwqK0pmK1DTGW7lRW3I1KO1Nsj9h0Pc6kBi96X1RYt-QhE7yXD53IRMKQKfl6felKnK3j13O8ViK4SL1b2paw/s551/03-DatabaseConnection.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje65CiY8KDxIMk9DxH42Bppg7fcIB9iQmi-kl1yyBIoKPbVYGvU4fGReMujlAlSK6Tn3RUwTsxT8B-80U7IJx_ikuc1kPjvCEBjmBOlJGwqK0pmK1DTGW7lRW3I1KO1Nsj9h0Pc6kBi96X1RYt-QhE7yXD53IRMKQKfl6felKnK3j13O8ViK4SL1b2paw/s600/03-DatabaseConnection.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Checkout the PyCharm &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/run-a-query.html&quot;&gt;documentation&lt;/a&gt; to Run queries.  Align F5 to Execute queries similar to SQL Server Mgt Studio: Settings | Keymap | Database | Console Toolbar | Execute.  Right click | Add keyboard shortcut | F5.
&lt;br /&gt;&lt;br /&gt;
Checkout the PyCharm &lt;a href=&quot;https://www.jetbrains.com/help/pycharm/code-style-sql-case.html&quot;&gt;documentation&lt;/a&gt; to update Word Case as per SQL convention: Settings | Editor | Code Style | SQL | PostgreSQL.  Inherit general SQL style	DISABLE | Word Case | Keywords To upper.  Also update Code Completion as Ctrl + Space: Settings | Keymap | Main Menu | Code | Code Completion | Ctrl + Space.
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgidazDfD8fbnvwFRL_-ZsLrbmzFoeKYZJGeutzzJM7StXIk9RA3r9Fp7yDmpJFeGp-_WGGFYgFd_Ngm5hs-ihlLNJMDKbq86H0gJH1daq9EQEL_TTwP08PwcoYFbYkzY1fKGZcw7hY8s5KBuPbXroJbJbMLa7XPfHmSggzSVVblAuSg5raQO3xNBCkV7A/s673/04-DatabaseCodeStyle.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgidazDfD8fbnvwFRL_-ZsLrbmzFoeKYZJGeutzzJM7StXIk9RA3r9Fp7yDmpJFeGp-_WGGFYgFd_Ngm5hs-ihlLNJMDKbq86H0gJH1daq9EQEL_TTwP08PwcoYFbYkzY1fKGZcw7hY8s5KBuPbXroJbJbMLa7XPfHmSggzSVVblAuSg5raQO3xNBCkV7A/s600/04-DatabaseCodeStyle.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQG8vMhAHzMxB1KsziTkdjysWQ-D8ponte1j4n3d7pF7_KcEEi0nLYHmthwaqUIPSRdrFxato_M2SqHzZ85Tc2WbjxFvCbbVlqLWqm1V4teotuSLuNT3i2UB0PSjNiLsWOqgrNGHVnVUYPCsu9qCykSzxF5k4oYZDC7mB14nH2LkjNd1CLGjRSYGVN1DU/s652/05-CodeCompletion.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQG8vMhAHzMxB1KsziTkdjysWQ-D8ponte1j4n3d7pF7_KcEEi0nLYHmthwaqUIPSRdrFxato_M2SqHzZ85Tc2WbjxFvCbbVlqLWqm1V4teotuSLuNT3i2UB0PSjNiLsWOqgrNGHVnVUYPCsu9qCykSzxF5k4oYZDC7mB14nH2LkjNd1CLGjRSYGVN1DU/s600/05-CodeCompletion.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Finally in Settings | Editor | General | Code Completion enable the following options: Automatically insert single suggestions, Sort suggestions alphabetically, Show suggestions as you type, Match case: First letter.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, armed with this knowledge we have setup the MacOS to better align keyboard shortcuts and application navigation techniques accumulated from years of Windows development experience.  From here, we are in now an excellent position to leverage the M1 chip for faster data access as per A.I. requirements!  

&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2024/06/macos-setup-cheat-sheet-ii.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq1YSFVTPkHH46ynNtUAc_Ab4T0F-zolbEIqa7qmPcjHnQ0jo0f2YUfOv-m63uFKNo8myj1HxgYrzBtgeQgy4Wn-kvdEmNotzwNqJkVzhNIStf0Lvf1-8KcRn2-MpXQeLNFU67rUCX6mcXFcYy0Ad3k6p2MAtn8z07MGP45tme7HX16ZiC8zjMc3SLd4Q/s72-c/MacOSX.png" height="72" width="72"/><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-5084882879253110322</guid><pubDate>Wed, 01 May 2024 08:00:00 +0000</pubDate><atom:updated>2025-08-23T08:44:17.587-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">MacOS</category><title>MacOS Setup Cheat Sheet</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In late 2020, Apple &lt;a href=&quot;https://www.apple.com/ie/newsroom/2020/11/apple-unleashes-m1&quot;&gt;unleashed&lt;/a&gt; its industry-leading performant &lt;a href=&quot;https://en.wikipedia.org/wiki/Apple_M1&quot;&gt;M1&lt;/a&gt; chip designed specifically for the Mac.  As a result, M1 powered MacBooks have provened to be much faster than Windows thus making Apple computers more appealing for &lt;a href=&quot;https://medium.com/@abhishek.quicktech/why-companies-run-better-on-a-mac-than-on-windows-61272da87980&quot;&gt;companies&lt;/a&gt; than ever.  Especially with the rise of &lt;a href=&quot;https://www.linkedin.com/pulse/apple-m1-m2-chips-what-good-deep-learning-denovo-team-fydrf&quot;&gt;A.I.&lt;/a&gt; requirements for faster data access.
&lt;br /&gt;&lt;br /&gt;
The issue now for Windows users is to seamlessly transfer all keyboard shortcuts + muscle memory to Mac!
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq1YSFVTPkHH46ynNtUAc_Ab4T0F-zolbEIqa7qmPcjHnQ0jo0f2YUfOv-m63uFKNo8myj1HxgYrzBtgeQgy4Wn-kvdEmNotzwNqJkVzhNIStf0Lvf1-8KcRn2-MpXQeLNFU67rUCX6mcXFcYy0Ad3k6p2MAtn8z07MGP45tme7HX16ZiC8zjMc3SLd4Q/s1280/MacOSX.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; height=&quot;275px&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq1YSFVTPkHH46ynNtUAc_Ab4T0F-zolbEIqa7qmPcjHnQ0jo0f2YUfOv-m63uFKNo8myj1HxgYrzBtgeQgy4Wn-kvdEmNotzwNqJkVzhNIStf0Lvf1-8KcRn2-MpXQeLNFU67rUCX6mcXFcYy0Ad3k6p2MAtn8z07MGP45tme7HX16ZiC8zjMc3SLd4Q/s600/MacOSX.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Documentation&lt;/u&gt;&lt;br /&gt;
If you are new to the Mac then the first thing to do is acquaint yourself with keyboard &lt;a href=&quot;https://support.apple.com/en-us/HT201236&quot;&gt;shortcuts&lt;/a&gt; as outlined in various online documentation pages and especially with what are those &lt;a href=&quot;https://support.apple.com/en-ie/guide/mac-help/cpmh0011/mac&quot;&gt;symbols&lt;/a&gt; shown in menus on Mac:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyFKJhv9toFzp8i4Wo2GxzISm6o2V3p-45W9Dk8LC2eJUclr8XHJ0UFKASXPS56myKUij0CseT28Xq7fRQJMOkddRu_Y8pUNHVGsplBZTV31hsw1-R3kKhurMuyb65vlU1KkkS_zXADYv2X4Dgtk3qQ0kHTyLTeU14frCvMdQaBiVvtNM3TY9aoQYAqnk/s818/MacKeyboardShortcuts.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyFKJhv9toFzp8i4Wo2GxzISm6o2V3p-45W9Dk8LC2eJUclr8XHJ0UFKASXPS56myKUij0CseT28Xq7fRQJMOkddRu_Y8pUNHVGsplBZTV31hsw1-R3kKhurMuyb65vlU1KkkS_zXADYv2X4Dgtk3qQ0kHTyLTeU14frCvMdQaBiVvtNM3TY9aoQYAqnk/s600/MacKeyboardShortcuts.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Keyboards&lt;/u&gt;&lt;br /&gt;
The major &lt;a href=&quot;https://helpdeskgeek.com/help-desk/mac-vs-windows-keyboard-whats-different&quot;&gt;differences&lt;/a&gt; between Windows and Mac keyboards are the special keys found on either side of the spacebar known as modifier keys and are typically used for System &lt;a href=&quot;https://forum.keyboardmaestro.com/t/os-x-text-system-keybindings/4929/1&quot;&gt;Keybindings&lt;/a&gt;. Here is quick comparison:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Location&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Windows&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Mac OS&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Keycode Modifier&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;b&gt;Menu Symbol&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Left&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl&lt;/td&gt;&lt;td&gt;&amp;nbsp;@&lt;/td&gt;&lt;td&gt;&amp;nbsp;⌃&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Middle&lt;/td&gt;&lt;td&gt;&amp;nbsp;WinKey&lt;/td&gt;&lt;td&gt;&amp;nbsp;Option&lt;/td&gt;&lt;td&gt;&amp;nbsp;~&lt;/td&gt;&lt;td&gt;&amp;nbsp;⌥&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Right&lt;/td&gt;&lt;td&gt;&amp;nbsp;Alt&lt;/td&gt;&lt;td&gt;&amp;nbsp;Command&lt;/td&gt;&lt;td&gt;&amp;nbsp;^&lt;/td&gt;&lt;td&gt;&amp;nbsp;⌘&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Left&lt;/td&gt;&lt;td&gt;&amp;nbsp;Shift&lt;/td&gt;&lt;td&gt;&amp;nbsp;Shift&lt;/td&gt;&lt;td&gt;&amp;nbsp;$&lt;/td&gt;&lt;td&gt;&amp;nbsp;⇧&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Out-of-the-box, there are some common keyboard shortcuts shared across Windows and Mac, for example:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Alt + Tab&lt;/td&gt;&lt;td&gt;&amp;nbsp;Toggle between all open applications&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Tab&lt;/td&gt;&lt;td&gt;&amp;nbsp;Toggle between all open tabs within an application&lt;/td&gt;&lt;/tr&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
However, for all common Ctrl + type Windows keyboard shortcuts the Mac prefers to use the &lt;a href=&quot;https://www.macinstruct.com/tutorials/how-to-switch-the-control-and-command-keys/#google_vignette&quot;&gt;Command&lt;/a&gt; key:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + A&lt;/td&gt;&lt;td&gt;&amp;nbsp;Select all&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Q&lt;/td&gt;&lt;td&gt;&amp;nbsp;Quit application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + C&lt;/td&gt;&lt;td&gt;&amp;nbsp;Copy item&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + S&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save item&lt;/td&gt;
&lt;/tr&gt;  
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + F&lt;/td&gt;&lt;td&gt;&amp;nbsp;Find item&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + V&lt;/td&gt;&lt;td&gt;&amp;nbsp;Paste item&lt;/td&gt;
&lt;/tr&gt; 
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + N&lt;/td&gt;&lt;td&gt;&amp;nbsp;New item&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + W&lt;/td&gt;&lt;td&gt;&amp;nbsp;Close window&lt;/td&gt;
&lt;/tr&gt; 
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + O&lt;/td&gt;&lt;td&gt;&amp;nbsp;Open item&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + X&lt;/td&gt;&lt;td&gt;&amp;nbsp;Cut item&lt;/td&gt;
&lt;/tr&gt; 
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + P&lt;/td&gt;&lt;td&gt;&amp;nbsp;Print item&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Z&lt;/td&gt;&lt;td&gt;&amp;nbsp;Undo action&lt;/td&gt;
&lt;/tr&gt; 
&lt;/table&gt;
&lt;br /&gt;
Therefore, &lt;a href=&quot;https://www.theverge.com/23591533/mac-remap-keyboard-how-to&quot;&gt;remap&lt;/a&gt; the &lt;a href=&quot;https://www.lifewire.com/what-are-windows-keyboard-equivalents-to-mac-2260203&quot;&gt;modifier&lt;/a&gt; keys in System Settings | Keyboard | Keyboard Shortcuts... | Modifier Keys:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhQrJR2XcUmAZX4sfieOIHGU4Q-iDDb275sM0EkUONFoHRAOcpGrzTUUTZk3QB0LZI4jx5rKvWOZXK_Ccjq2NJxrxqYEjD4bsQD_6LDaoqq45cj1VWkkYK4zTaNbgZZPOUkAryFWR4Nr728m3Q6FLddXWlp8cZWMrGa3j6jDADR5V9Lh7I033efISVdmg/s417/00-ModifierKeys.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; height=&quot;100%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhQrJR2XcUmAZX4sfieOIHGU4Q-iDDb275sM0EkUONFoHRAOcpGrzTUUTZk3QB0LZI4jx5rKvWOZXK_Ccjq2NJxrxqYEjD4bsQD_6LDaoqq45cj1VWkkYK4zTaNbgZZPOUkAryFWR4Nr728m3Q6FLddXWlp8cZWMrGa3j6jDADR5V9Lh7I033efISVdmg/s600/00-ModifierKeys.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
IMPORTANT: in order to retain Alt + Tab functionality we have now had to re-map Option to Command also!  There is an &lt;a href=&quot;https://alt-tab-macos.netlify.app&quot;&gt;AltTab&lt;/a&gt; utility but companies may disallow the installation of third party software, unfortunately.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;System Settings&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://support.apple.com/en-ie/guide/mac-help/mh15217/mac&quot;&gt;Customize&lt;/a&gt; your Mac with System Settings.  Launch System Settings from Dock and make following changes:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;General&lt;/td&gt;&lt;td&gt;&amp;nbsp;Language &amp; Region&lt;/td&gt;&lt;td&gt;&amp;nbsp;Region = New Zealand&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Accessibility&lt;/td&gt;&lt;td&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Full Keyboard Access&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Accessibility&lt;/td&gt;&lt;td&gt;&amp;nbsp;Pointer Control | Trackpad Options&lt;/td&gt;&lt;td&gt;&amp;nbsp;Use trackpad for scrolling = DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Appearance&lt;/td&gt;&lt;td&gt;&amp;nbsp;Show scroll bars&lt;/td&gt;&lt;td&gt;&amp;nbsp;Automatically based on mouse or trackpad&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Desktop &amp; Dock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Dock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Size = Small&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Desktop &amp; Dock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Dock &lt;/td&gt;&lt;td&gt;&amp;nbsp;Position on screen = Left&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Desktop &amp; Dock&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Desktop &amp; Stage Manager&lt;/td&gt;&lt;td&gt;&amp;nbsp;Click wallpaper to reveal desktop =&lt;br /&gt;&amp;nbsp;Only in Stage Manager&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Desktop &amp; Dock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Group windows by application&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Desktop &amp; Dock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Displays have separate Spaces&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Displays&lt;/td&gt;&lt;td&gt;&amp;nbsp;Dual Monitors&lt;/td&gt;&lt;td&gt;&amp;nbsp;1920 x 1080 (Default)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Users &amp; Groups&lt;/td&gt;&lt;td&gt;&amp;nbsp;Administrator&lt;/td&gt;&lt;td&gt;&amp;nbsp;Update login photo&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Key repeat rate&lt;/td&gt;&lt;td&gt;&amp;nbsp;Fast&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Delay until repeat&lt;/td&gt;&lt;td&gt;&amp;nbsp;Short&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Turn keyboard backlight off after inactivity&lt;/td&gt;&lt;td&gt;&amp;nbsp;Never&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Press fn key to&lt;/td&gt;&lt;td&gt;&amp;nbsp;Do Nothing&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Keyboard navigation&lt;/td&gt;&lt;td&gt;&amp;nbsp;Enabled&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Trackpad&lt;/td&gt;&lt;td&gt;&amp;nbsp;Scroll &amp; Zoom&lt;/td&gt;&lt;td&gt;&amp;nbsp;Natural scrolling = DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Here is some more information explaining the rationale behind some of these System Settings options set:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;ol&gt;
&lt;li&gt;Use trackpad for scrolling enables scroll bars visible unconditionally + not autohide&lt;/li&gt;
&lt;li&gt;Displays have separate Spaces on dual monitors &lt;a href=&quot;https://www.duetdisplay.com/help-center/when-i-fullscreen-an-app-on-my-mac-the-other-screens-go-black#:~:text=This%20behavior%20is%20caused%20by,an%20app%20is%20full%20screened.&quot;&gt;prevents&lt;/a&gt; other screen to go black&lt;/li&gt;
&lt;li&gt;Displays | Dual Monitors | Ensure resolution is the same default for both monitors&lt;/li&gt;
&lt;li&gt;Keyboard | Key repeat rate | Fast ensures that holding key down &lt;a href=&quot;https://www.howtogeek.com/267463/how-to-enable-key-repeating-in-macos&quot;&gt;prevents&lt;/a&gt; accents&lt;/li&gt;
&lt;li&gt;Trackpad | Natural scrolling Disabled ensures vertical scrolling naturally downward&lt;/li&gt;
&lt;/ol&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Keyboard Shortcuts&lt;/b&gt;&lt;br /&gt;
Customize your general Mac keyboard shortcuts.  Launch System Settings | Keyboard | Keyboard Shortcuts:
&lt;br /&gt;
&lt;table width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVh9xAV-zdBlad9ou5ExKnPO6DzQE6kNJYbXqHX9InjjeA0uAUMJFHc9oz83KDD7skqHtO0jyTTIx3HvkjOecAPbeyMJHnE4g78uXPTjsk_O9L6mCH9Nvp-RYrBdxLr8YFuMG77rKv0YooSub1wNO8eic7J-lPKkt9wjAeSFbL03sgzznRcbUr_zrzOl4/s611/01-LaunchpadDock.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVh9xAV-zdBlad9ou5ExKnPO6DzQE6kNJYbXqHX9InjjeA0uAUMJFHc9oz83KDD7skqHtO0jyTTIx3HvkjOecAPbeyMJHnE4g78uXPTjsk_O9L6mCH9Nvp-RYrBdxLr8YFuMG77rKv0YooSub1wNO8eic7J-lPKkt9wjAeSFbL03sgzznRcbUr_zrzOl4/s600/01-LaunchpadDock.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE0OR7mmGHc5NhUOfl9mHrr43_GhUh1GUOhOlvOvXcuR7lZp7-lHHGcHRT0fnIW-Ygctt1igK3vMd_RkW-JrFCZizJbr6Ni8brKHAobPwBtz-ylwyQeZAnZo-0azIst0QKggWQerxyOLv3MxFcLNMFlQiuNdQTzvVfAmeC5qsCVy95sNixMpNth2-wMtc/s617/05-Screenshots.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE0OR7mmGHc5NhUOfl9mHrr43_GhUh1GUOhOlvOvXcuR7lZp7-lHHGcHRT0fnIW-Ygctt1igK3vMd_RkW-JrFCZizJbr6Ni8brKHAobPwBtz-ylwyQeZAnZo-0azIst0QKggWQerxyOLv3MxFcLNMFlQiuNdQTzvVfAmeC5qsCVy95sNixMpNth2-wMtc/s600/05-Screenshots.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bjkTzgULpmW3ORFPRxQmr3GFddc1pbe0VqRMZVIZL-53ReISbTiJ0_-kktQmj9KY3RJv_Qkz5DDd4MwiFAQWS70TOWZ9nH5xWul44CQo1JGuc4s9mUgiQ4DBoJT1Wb8hyEVc721TQlbOcChMBLAWT0ftvRtewWN2ai8XXz6WoOda_HCvKMKFnGMDMZk/s618/02-MissionControl.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bjkTzgULpmW3ORFPRxQmr3GFddc1pbe0VqRMZVIZL-53ReISbTiJ0_-kktQmj9KY3RJv_Qkz5DDd4MwiFAQWS70TOWZ9nH5xWul44CQo1JGuc4s9mUgiQ4DBoJT1Wb8hyEVc721TQlbOcChMBLAWT0ftvRtewWN2ai8XXz6WoOda_HCvKMKFnGMDMZk/s600/02-MissionControl.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwWCeDwqGKhA7h1fTvHTkBt3Or0nE9yhbkLS4wIFyjPXIDa7PHvLL67HBdbNfgx5m70mh3vQqXoyvwztSJF8kROcfj592oQN1F5dix-LIMi01fbsMrsBKpj0EqKrobh4iCJ7KS2wLEvOWSVtBRriAIVgV1FBXVR-vceXoN7UxPvhOOxD_jSRuxQ8XGyc4/s611/06-Spotlight.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwWCeDwqGKhA7h1fTvHTkBt3Or0nE9yhbkLS4wIFyjPXIDa7PHvLL67HBdbNfgx5m70mh3vQqXoyvwztSJF8kROcfj592oQN1F5dix-LIMi01fbsMrsBKpj0EqKrobh4iCJ7KS2wLEvOWSVtBRriAIVgV1FBXVR-vceXoN7UxPvhOOxD_jSRuxQ8XGyc4/s600/06-Spotlight.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh7kYXnJJzbCBhTHP1i_RnqXcQskeBeI_FhiLuOq4R0waWz9w2d74KeyE2oYg-1mLQgOJme0DowiJi8bxTFw2DdyfsCayjvWbD1ULrKcOfauL4Vhyphenhyphen4VyGC40p9-DQJ6AdFdMOafyqm5CSsHVNXsibi9Og5rrZHdlZfibpgqR-toW8OEY9XRb-R0NsMW04/s617/03-Keyboard.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh7kYXnJJzbCBhTHP1i_RnqXcQskeBeI_FhiLuOq4R0waWz9w2d74KeyE2oYg-1mLQgOJme0DowiJi8bxTFw2DdyfsCayjvWbD1ULrKcOfauL4Vhyphenhyphen4VyGC40p9-DQJ6AdFdMOafyqm5CSsHVNXsibi9Og5rrZHdlZfibpgqR-toW8OEY9XRb-R0NsMW04/s600/03-Keyboard.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitc-bftuIer31PibX3xzlQXa66i4DBcn5w9clODrnds346jh2IYBjpiVaPKjUtldQs5Hrbr-8L9sbpV415oegdlIPk1Hgj7aznfEIqMr0fXVFexW_0CPtsmld-N-M2-72hYKQ6H2Jh9I8dbtwEqUpRKPjCHi6zlj6pG1IZl0pkdVog0Dp03egpikuhI4w/s614/07-Accessibility.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitc-bftuIer31PibX3xzlQXa66i4DBcn5w9clODrnds346jh2IYBjpiVaPKjUtldQs5Hrbr-8L9sbpV415oegdlIPk1Hgj7aznfEIqMr0fXVFexW_0CPtsmld-N-M2-72hYKQ6H2Jh9I8dbtwEqUpRKPjCHi6zlj6pG1IZl0pkdVog0Dp03egpikuhI4w/s600/07-Accessibility.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAHzyqbRSmXG4PtXbyoJBROiSdz7um6SpUVgFBY6r3ef5g4k3I4PAwtvieeMc0wYKhggk5N7B4ed6Hrsfw_VFPjw-ZBDXuMuvGUGtXIgzsT6xL8wGqRT_a7bNTL00lAkl2lSBOPzlVrHISNPPi7LbBAMJVeFELqErOlniin80RjBiDRuWaajV01bUZXf8/s617/04-InputSources.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAHzyqbRSmXG4PtXbyoJBROiSdz7um6SpUVgFBY6r3ef5g4k3I4PAwtvieeMc0wYKhggk5N7B4ed6Hrsfw_VFPjw-ZBDXuMuvGUGtXIgzsT6xL8wGqRT_a7bNTL00lAkl2lSBOPzlVrHISNPPi7LbBAMJVeFELqErOlniin80RjBiDRuWaajV01bUZXf8/s600/04-InputSources.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWtU8b5Amtpm5b5LGgsYanB4w73bX9cvpcAlNiasHpZoxBsRRp4vbV5F7h2qCz93GliNP1Z5KVSTNTBH9F84pCP8b345vcc_9yQgo7iwn6HeomDOB4rtYXUR0D878DxOA6I5p5iZw_lJBrOrA-IvAXPhqL5sRnqoGt5SBUU2jaWNKtVp0BybynaUmrO3M/s617/08-AppShortcuts.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWtU8b5Amtpm5b5LGgsYanB4w73bX9cvpcAlNiasHpZoxBsRRp4vbV5F7h2qCz93GliNP1Z5KVSTNTBH9F84pCP8b345vcc_9yQgo7iwn6HeomDOB4rtYXUR0D878DxOA6I5p5iZw_lJBrOrA-IvAXPhqL5sRnqoGt5SBUU2jaWNKtVp0BybynaUmrO3M/s600/08-AppShortcuts.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Here is my quick summary of Keyboard Shortcuts setup that will be compatible with Application navigation:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Launchpad &amp; Dock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Turn Dock hiding on/off&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Launchpad &amp; Dock&lt;/td&gt;&lt;td&gt;&amp;nbsp;Show Lauchpad&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Mission Control&lt;/td&gt;&lt;td&gt;&amp;nbsp;Show Desktop [F11]&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Mission Control&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move left a space [Cmd + left]&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Mission Control&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move right a space [Cmd + right]&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move focus to the window toolbar [Cmd + F5]&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Keyboard&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move focust to next window [Ctrl + `]&lt;/td&gt;&lt;td&gt;&amp;nbsp;ENABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Input Sources&lt;/td&gt;&lt;td&gt;&amp;nbsp;Select previous input source [Cmd + Space]&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Screenshots&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save picture of screen as a file [Ctrl + 3]&lt;/td&gt;&lt;td&gt;&amp;nbsp;ENABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Screenshots&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save picture of selected area as a file [Ctrl + Shift + 4]&lt;/td&gt;&lt;td&gt;&amp;nbsp;ENABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Spotlight&lt;/td&gt;&lt;td&gt;&amp;nbsp;Show Spotlight search [Ctrl + Space]&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Accessibility&lt;/td&gt;&lt;td&gt;&amp;nbsp;Turn VoiceOver on or off [Ctrl + F5]&lt;/td&gt;&lt;td&gt;&amp;nbsp;DISABLED&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;App Shortcuts&lt;/td&gt;&lt;td&gt;&amp;nbsp;All Applications | Rename&lt;/td&gt;&lt;td&gt;&amp;nbsp;F2&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Here is more information explaining the rationale behind some of these Keyboard Shortcuts... options set:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;ol&gt;
&lt;li&gt;Disable F11 &lt;a href=&quot;https://allaboutmynonexistedworld.wordpress.com/2021/11/15/mac-stop-f11-from-showing-desktop&quot;&gt;prevents&lt;/a&gt; the Desktop from always showing&lt;/li&gt;
&lt;li&gt;Disable Cmd + left prevents move former word collision&lt;/li&gt;
&lt;li&gt;Disable Cmd + right prevents move next word collision&lt;/li&gt;
&lt;li&gt;Disable Cmd + F5 key prevents IDE debugging collision&lt;/li&gt;
&lt;li&gt;Disable Cmd + Space prevents IDE intellisense collision&lt;/li&gt;
&lt;li&gt;Disable Ctrl + Space prevents IDE intellisense collision&lt;/li&gt;
&lt;li&gt;Disable Ctrl + F5 key prevents Voice Over alternating&lt;/li&gt;
&lt;/ol&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Finder&lt;/u&gt;&lt;br /&gt;
The &lt;a href=&quot;https://en.wikipedia.org/wiki/Finder_(software)&quot;&gt;Finder&lt;/a&gt; is the home base for your Mac: you use the Finder to &lt;a href=&quot;https://support.apple.com/en-ie/guide/mac-help/mchlp2605/mac&quot;&gt;organize&lt;/a&gt; your folders and files on the Mac.  Launch Finder | Settings... Leave all options in Finder Settings but check all checkboxes on Advanced tab:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI7spX3PP8v88Y5lOhqI1w-RnghP-DQX2VMqw36nwKtxo512LWtQBjA9bKsQVFEmFNfQ9JFqH3yfJWXhWP0fqPYuioRWSCUS5tG3eOUakl_Sjm1f4rFftBC2aBJQKt7P1pvBOWL08uvPB224WOmRLAgkVkE4CF1X-3FEyGh-UVH0oe250KcvkhiWL75CU/s369/00.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%%&quot; height=&quot;300px&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI7spX3PP8v88Y5lOhqI1w-RnghP-DQX2VMqw36nwKtxo512LWtQBjA9bKsQVFEmFNfQ9JFqH3yfJWXhWP0fqPYuioRWSCUS5tG3eOUakl_Sjm1f4rFftBC2aBJQKt7P1pvBOWL08uvPB224WOmRLAgkVkE4CF1X-3FEyGh-UVH0oe250KcvkhiWL75CU/s600/00.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
In View menu check &quot;as Columns&quot; + &quot;Sort By Name&quot;.  Show all relevant Sidebar, Toolbar, Status options etc:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;35%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfxwFjXPmdyvkfvvzhCbNxPdbixAggOMRnXQHOLeNyzRMJV0C7MB5EAlcciItgDsj8tWqA0cB3mucn44prAZDDbRRdZyu4Cr4Q7WgvzdYwUOqRCbzvnYJNZ2MYLONRWz6MsBbEOghKpnPhXQVEaLVHs5tzQjFSW_EiFlvoHFrNs13Ab4f_chdRMviclew/s461/01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfxwFjXPmdyvkfvvzhCbNxPdbixAggOMRnXQHOLeNyzRMJV0C7MB5EAlcciItgDsj8tWqA0cB3mucn44prAZDDbRRdZyu4Cr4Q7WgvzdYwUOqRCbzvnYJNZ2MYLONRWz6MsBbEOghKpnPhXQVEaLVHs5tzQjFSW_EiFlvoHFrNs13Ab4f_chdRMviclew/s600/01.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;table width=&quot;99%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;View menu | Select the following:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;Check &quot;as Columns&quot;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Sort By | Name&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Show Sidebar&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Show Preview&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Show Toolbar&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Hide All Tabs&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Hide Tab Bar&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Show Path Bar&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Show Status Bar&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Hide View Options&lt;/li&gt;
&lt;li&gt;&amp;nbsp;Hide Preview Options&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Here are some Windows keyboard shortcut equivalents.  &lt;b&gt;*&lt;/b&gt;Customization via App Shortcuts as shown below:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + N&lt;/td&gt;&lt;td&gt;&amp;nbsp;New Finder Window&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Shift + N&lt;/td&gt;&lt;td&gt;&amp;nbsp;New Folder&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + O&lt;/td&gt;&lt;td&gt;&amp;nbsp;Open File&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Ctrl + Shift + G&lt;/td&gt;&lt;td&gt;&amp;nbsp;Go to Folder...&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;F2&lt;b&gt;*&lt;/b&gt; | Enter&lt;/td&gt;&lt;td&gt;&amp;nbsp;Rename File / Folder&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Alt + Backspace&lt;/td&gt;&lt;td&gt;&amp;nbsp;Delete File / Folder&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Shortcuts: Right click folder | Show in Enclosing folder.  Right click folder the Status Bar | Copy &lt;folder&gt; as Pathname.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td  valign=&quot;top&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJH5Y1bGlW2Fu_vnbNq4VdrWNh_snbIb5noeUYzUBAoJU1icROIbaNj83wfz-p7mQV37iKAL8qcVynBmMwPwE8hNzl8AbZ1sVxk24fAT0O4Do3u4GuILRb63kVRGnpKPVpAOmmhhvyL2XEi_78WhoNBOicDSWKBYsQQDijivqX5REGBc2ZA9Twr0PY_VY/s351/10.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJH5Y1bGlW2Fu_vnbNq4VdrWNh_snbIb5noeUYzUBAoJU1icROIbaNj83wfz-p7mQV37iKAL8qcVynBmMwPwE8hNzl8AbZ1sVxk24fAT0O4Do3u4GuILRb63kVRGnpKPVpAOmmhhvyL2XEi_78WhoNBOicDSWKBYsQQDijivqX5REGBc2ZA9Twr0PY_VY/s600/10.png&quot;/&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td  valign=&quot;top&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDz_ZgeeHYmBbGxpMCo2apcp-YXbiTG7HuLOc5S4tgWTcmmc4u0YsmDGN6PgggS6xj1L-mADDSsCIVTHXgKkexvt5pKJPE6y3owKNoL3qi3mUQ5F8qYoMNp96hdPBgEp9G7OqGNazY-bDGwQOkqRmhRaV9BaWzOcP2xsGcv9s1EEer1TG0KiJarYBwGSM/s478/20.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDz_ZgeeHYmBbGxpMCo2apcp-YXbiTG7HuLOc5S4tgWTcmmc4u0YsmDGN6PgggS6xj1L-mADDSsCIVTHXgKkexvt5pKJPE6y3owKNoL3qi3mUQ5F8qYoMNp96hdPBgEp9G7OqGNazY-bDGwQOkqRmhRaV9BaWzOcP2xsGcv9s1EEer1TG0KiJarYBwGSM/s600/20.png&quot;/&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Finally, here are two handy aliases to hide and show private files and folders on Mac via &lt;b&gt;~/.bash_profile&lt;/b&gt;:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;alias showFiles=&#39;defaults write com.apple.finder AppleShowAllFiles YES; killall Finder &amp;nbsp;&amp;nbsp;/System/Library/CoreServices/Finder.app&#39;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;alias hideFiles=&#39;defaults write com.apple.finder AppleShowAllFiles NO; killall Finder &amp;nbsp;&amp;nbsp;/System/Library/CoreServices/Finder.app&#39;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/tr&gt;
&lt;/td&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Python&lt;/u&gt;&lt;br /&gt;
As per this &lt;a href=&quot;https://steveproxna.blogspot.com/2020/07/python-setup-cheat-sheet.html&quot;&gt;post&lt;/a&gt;, Python is installed on most Mac OS/X systems by default.  Also, one can install Python when you &lt;a href=&quot;https://www.freecodecamp.org/news/install-xcode-command-line-tools&quot;&gt;install&lt;/a&gt; Xcode Command Line Tools.  Another option is update &lt;a href=&quot;https://www.python.org/downloads/macos&quot;&gt;Python&lt;/a&gt; from the official website e.g. &lt;a href=&quot;https://www.python.org/ftp/python/3.12.3/python-3.12.3-macos11.pkg&quot;&gt;v3.12&lt;/a&gt;.  IMPORTANT: when coding in Python activate the created virtual environment: &lt;b&gt;&lt;i&gt;source .venv/bin/activate&lt;/i&gt;&lt;/b&gt;.
&lt;br /&gt;&lt;br /&gt;
As per this &lt;a href=&quot;https://steveproxna.blogspot.com/2020/08/python-setup-cheat-sheet-ii.html&quot;&gt;post&lt;/a&gt;, we installed open source Python distribution &lt;a href=&quot;https://en.wikipedia.org/wiki/Anaconda_(Python_distribution)&quot;&gt;Anaconda&lt;/a&gt; used for data science.  However, on the Mac after launch Terminal and enter &lt;b&gt;jupyter notebook&lt;/b&gt; you may encounter the following couple errors:
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Error #1&lt;/b&gt;: &lt;i&gt;Jupyter Notebook 500 : Internal Server Error&lt;/i&gt; - follow instructions &lt;a href=&quot;https://stackoverflow.com/questions/36851746/jupyter-notebook-500-internal-server-error&quot;&gt;here&lt;/a&gt; to resolve the issue:
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;pip install --upgrade jupyterhub&lt;br /&gt;
&amp;nbsp;pip install --upgrade --user nbconvert&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Error #2&lt;/b&gt;: &lt;i&gt;ModuleNotFoundError: No module named &#39;jupyter_server.contents&#39;&lt;/i&gt; - follow instructions &lt;a href=&quot;https://stackoverflow.com/questions/77549493/modulenotfounderror-no-module-named-jupyter-server-contents&quot;&gt;here&lt;/a&gt;:
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;pip uninstall traitlets&lt;br /&gt;
&amp;nbsp;pip install traitlets==5.9.0&lt;br /&gt;
&amp;nbsp;jupyter notebook&lt;br /&gt;
&amp;nbsp;http://localhost:8889/notebooks&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;u&gt;Terminal&lt;/u&gt;&lt;br /&gt;
The Mac terminal may be &lt;b&gt;zsh&lt;/b&gt; by default.  However, change your &lt;a href=&quot;https://support.apple.com/en-us/102360&quot;&gt;default&lt;/a&gt; shell via Settings... | General | Shell open with: Command path &lt;i&gt;/bin/bash&lt;/i&gt; or enter &lt;b&gt;chsh -s /bin/bash&lt;/b&gt;.  Confirm BASH is now in Terminal title!
&lt;br /&gt;&lt;br /&gt;
IMPORTANT: remove silence deprecation warning | Enter the following into Terminal for &lt;b&gt;~/.bash_profile&lt;/b&gt;:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;echo &quot;export BASH_SILENCE_DEPRECATION_WARNING=1&quot; &gt;&gt; ~/.bash_profile&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Customize the Mac terminal to always &lt;a href=&quot;https://superuser.com/questions/239994/how-to-have-full-directory-path-always-shown-in-mac-terminal-like-linux-termina&quot;&gt;show&lt;/a&gt; full directory path as the cursor similar to the Linux terminal:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;echo &quot;export PS1=&#39;\u@\h:\w$ &#39;&quot; &gt;&gt; ~/.bash_profile&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
Finally, keyboard shortcuts like Ctrl + C or Ctrl + Z may &lt;a href=&quot;https://superuser.com/questions/394100/ctrl-c-and-ctrl-z-not-working-in-terminal&quot;&gt;not work&lt;/a&gt; to break on Mac thus prefer &lt;b&gt;Ctrl + &quot;.&quot;&lt;/b&gt;.
&lt;br /&gt;
&lt;br /&gt;

&lt;b&gt;Homebrew&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://brew.sh&quot;&gt;Homebrew&lt;/a&gt; is a package manager for macOS which lets you install free and open-source software using your terminal.  Launch terminal and issue the following commands to install Homebrew and update bash_profile:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&amp;nbsp;/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
&lt;br /&gt;
&amp;nbsp;echo &#39;eval &quot;$(/opt/homebrew/bin/brew shellenv)&quot;&#39; &gt;&gt; ~/.bash_profile
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Install free and open-source software for Cloud Computing for example: &lt;a href=&quot;https://formulae.brew.sh/formula/minikube&quot;&gt;minikube&lt;/a&gt;, &lt;a href=&quot;https://formulae.brew.sh/formula/kind&quot;&gt;KinD&lt;/a&gt;, &lt;a href=&quot;https://helm.sh/docs/intro/install&quot;&gt;Helm&lt;/a&gt;, &lt;a href=&quot;https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli&quot;&gt;Terraform&lt;/a&gt;:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;minikube&lt;/td&gt;&lt;td&gt;&amp;nbsp;brew install minikube&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;KinD&lt;/td&gt;&lt;td&gt;&amp;nbsp;brew install kind&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Helm&lt;/td&gt;&lt;td&gt;&amp;nbsp;brew install helm&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Terraform&lt;/td&gt;&lt;td&gt;&amp;nbsp;brew tap hashicorp/tap | brew install hashicorp/tap/terraform&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;

&lt;b&gt;Cloud CLIs&lt;/b&gt;&lt;br /&gt;
Download and install Command Line Interfaces for all managed cloud providers e.g.: AWS, Azure, Google:
&lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&quot;&gt;Install&lt;/a&gt; the latest version of the &lt;b&gt;AWS&lt;/b&gt; CLI.  Download the &lt;a href=&quot;https://awscli.amazonaws.com/AWSCLIV2.pkg&quot;&gt;macOS pkg&lt;/a&gt; file.  Confirm installation &lt;i&gt;aws version&lt;/i&gt;.
&lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-macos&quot;&gt;Install&lt;/a&gt; &lt;b&gt;Azure&lt;/b&gt; CLI on macOS using brew &lt;i&gt;brew update &amp;&amp; brew install azure-cli&lt;/i&gt;.  Confirm install &lt;i&gt;az version&lt;/i&gt;.
&lt;a href=&quot;https://cloud.google.com/sdk/docs/install-sdk#mac&quot;&gt;Install&lt;/a&gt; the &lt;b&gt;Google&lt;/b&gt; Cloud CLI.  Download the Apple M1 &lt;a href=&quot;https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-473.0.0-darwin-arm.tar.gz&quot;&gt;package&lt;/a&gt;.  Extract and execute &lt;i&gt;install.sh&lt;/i&gt; | &lt;i&gt;gcloud init&lt;/i&gt;.
&lt;br /&gt;&lt;br /&gt;

&lt;b&gt;Kubernetes&lt;/b&gt;&lt;br /&gt;
As per this &lt;a href=&quot;https://steveproxna.blogspot.com/2021/09/kubernetes-cheat-sheet.html&quot;&gt;post&lt;/a&gt;, install Kubernetes with Docker Desktop on Mac OS/X.  Next, install and setup &lt;a href=&quot;https://kubernetes.io/docs/tasks/tools/install-kubectl-macos&quot;&gt;kubectl&lt;/a&gt; on the Mac OS/X.  However, the default kubectl autocomplete setup quick &lt;a href=&quot;https://kubernetes.io/docs/reference/kubectl/quick-reference&quot;&gt;reference&lt;/a&gt; may produce the following error
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;i&gt;bash: completion: function `__start_kubectl` not found&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;br /&gt;
If you experience this error then &lt;a href=&quot;https://stackoverflow.com/questions/45240862/why-doesnt-kubectl-bash-completion-work-on-macos-os-x&quot;&gt;here&lt;/a&gt; is an alternative approach: first &lt;b&gt;brew install bash bash-completion&lt;/b&gt;  Set Terminal to use bash: Settings... | General | Shell open with: Command path &lt;i&gt;/opt/homebrew/bin/bash&lt;/i&gt;
&lt;br /&gt;&lt;br /&gt;
Finally, update &lt;b&gt;~/.bash_profile&lt;/b&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&lt;table width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td&gt;
&amp;nbsp;alias k=&quot;kubectl&quot;&lt;br /&gt;
&amp;nbsp;complete -F __start_kubectl k&lt;br /&gt;
&amp;nbsp;source /opt/homebrew/etc/profile.d/bash_completion.sh&lt;br /&gt;
&amp;nbsp;source &lt;(kubectl completion bash)&lt;br /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;BASH Profile&lt;/u&gt;&lt;br /&gt;
Dump out the contents of the &lt;b&gt;~/.bash_profile&lt;/b&gt; file and verify all the following aliases and commands exist:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;99%&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;export BASH_SILENCE_DEPRECATION_WARNING=1&lt;/td&gt;&lt;td&gt;&amp;nbsp;# https://support.apple.com/en-us/102360&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;export PS1=&#39;\u@\h:\w$ &#39;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# Show always fullpath on terminal&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;eval &quot;$(/opt/homebrew/bin/brew shellenv)&quot;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# brew&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;alias d=&#39;docker&#39;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# Docker&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;alias k=&#39;kubectl&#39;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# Kubernetes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;complete -F __start_kubectl k&lt;/td&gt;&lt;td&gt;&amp;nbsp;# Kubernetes autocomplete&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;source /opt/homebrew/etc/profile.d/bash_completion.sh&lt;/td&gt;&lt;td&gt;&amp;nbsp;# Kubernetes autocomplete&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;source &lt;(kubectl completion bash)&lt;/td&gt;&lt;td&gt;&amp;nbsp;# Kubernetes autocomplete&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;alias sba=&#39;source .venv/bin/activate&#39;&lt;/td&gt;&lt;td&gt;&amp;nbsp;# Python virtual environment&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot; colspan=&quot;2&quot;&gt;&amp;nbsp;alias showFiles=&#39;defaults write com.apple.finder AppleShowAllFiles YES; killall Finder &amp;nbsp;&amp;nbsp;/System/Library/CoreServices/Finder.app&#39;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot; colspan=&quot;2&quot;&gt;&amp;nbsp;alias hideFiles=&#39;defaults write com.apple.finder AppleShowAllFiles NO; killall Finder &amp;nbsp;&amp;nbsp;/System/Library/CoreServices/Finder.app&#39;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/tr&gt;
&lt;/td&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
To summarize, by remapping the modifier keys in System Settings has helped tremendously, however this method does not provide a complete one-to-one mapping for all keyboard shortcuts from Windows to Mac. 
&lt;br /&gt;&lt;br /&gt;
Another option is investigate global &lt;a href=&quot;https://apple.stackexchange.com/questions/124896/how-is-it-possible-to-have-global-hotkeys-in-osx&quot;&gt;hotkeys&lt;/a&gt; in App Shortcuts for All Applications and specific Applications.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFLH0llOsEbaEquzvLDWDZXsAMhlvlz1-ZOHrZXhNkbJFRVrSD9zL-FIjhFaZLI_cUiZ_CHEnCOk0X-KVIBW6CVF04Ibs9xlZ3MHOas3EfoNZKQKsIFIFoWDGin5-MifEZWJoTxqE7oN0RmkSfVqw67KDIEpdjz_NUWjy02wqkaNfsKtUSO7Qxg5JLezI/s659/AllApps.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFLH0llOsEbaEquzvLDWDZXsAMhlvlz1-ZOHrZXhNkbJFRVrSD9zL-FIjhFaZLI_cUiZ_CHEnCOk0X-KVIBW6CVF04Ibs9xlZ3MHOas3EfoNZKQKsIFIFoWDGin5-MifEZWJoTxqE7oN0RmkSfVqw67KDIEpdjz_NUWjy02wqkaNfsKtUSO7Qxg5JLezI/s600/AllApps.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
However, this could be extremely time-consuming and unsuccessful thus will keep the setup as is for now.  Therefore, he is short list of mismatched keyboard shortcuts going forward and new key combos to learn:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;General&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + H&lt;/td&gt;&lt;td&gt;&amp;nbsp;Hide current window of this front app&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;General&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + M&lt;/td&gt;&lt;td&gt;&amp;nbsp;Minimize all open windows to the Dock&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;General&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + 1&lt;/td&gt;&lt;td&gt;&amp;nbsp;Restoring &lt;a href=&quot;https://discussions.apple.com/thread/6305641&quot;&gt;minimized&lt;/a&gt; window from Dock&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;General&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + `&lt;/td&gt;&lt;td&gt;&amp;nbsp;Move &lt;a href=&quot;https://apple.stackexchange.com/questions/193937/shortcut-for-toggling-between-different-windows-of-same-app&quot;&gt;focus&lt;/a&gt; to next window of same app&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;General&lt;/td&gt;&lt;td&gt;&amp;nbsp;Win + Tab&lt;/td&gt;&lt;td&gt;&amp;nbsp;Use instead of default Ctrl + Tab option&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Applications&lt;/td&gt;&lt;td&gt;&amp;nbsp;Ctrl + Enter&lt;/td&gt;&lt;td&gt;&amp;nbsp;Save current open document then exit&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
After aligning keyboard shortcuts from Windows to Mac the next step is to transfer Application navigation!  This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2024/06/macos-setup-cheat-sheet-ii.html&quot;&gt;post&lt;/a&gt;.
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2024/05/macos-setup-cheat-sheet.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq1YSFVTPkHH46ynNtUAc_Ab4T0F-zolbEIqa7qmPcjHnQ0jo0f2YUfOv-m63uFKNo8myj1HxgYrzBtgeQgy4Wn-kvdEmNotzwNqJkVzhNIStf0Lvf1-8KcRn2-MpXQeLNFU67rUCX6mcXFcYy0Ad3k6p2MAtn8z07MGP45tme7HX16ZiC8zjMc3SLd4Q/s72-c/MacOSX.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-2822416861303194853</guid><pubDate>Mon, 01 Jan 2024 09:00:00 +0000</pubDate><atom:updated>2024-01-01T01:00:08.477-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Retrospective</category><title>Retrospective XV</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt; 
Last year, I conducted a simple retrospective for 2022. Therefore, here is a retrospective for 2023.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;2023 Achievements&lt;/u&gt;&lt;br /&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
Complete fifteen year &lt;a href=&quot;https://steveproxna.blogspot.com&quot;&gt;blog&lt;/a&gt; on agile software application to game development and beyond
&lt;/li&gt;
&lt;li&gt;
Enter &lt;a href=&quot;https://www.smspower.org/Homebrew/LilEvelKnievel-SMS&quot;&gt;Lil Evel Knievel&lt;/a&gt; in SMS Power! 2023 competition as side scrolling Wonderboy tribute
&lt;/li&gt;
&lt;li&gt;
Port Sega Master System games to Sega MegaDrive then &lt;a href=&quot;https://steveproxna.blogspot.com/2023/06/sega-console-game-port.html&quot;&gt;document&lt;/a&gt; development process
&lt;/li&gt;
&lt;li&gt;
Apply Sega Master System development techniques to eBPF &lt;a href=&quot;https://steveproxna.blogspot.com/2023/07/ebpf-programming-setup.html&quot;&gt;setup&lt;/a&gt; using C code examples
&lt;/li&gt;
&lt;li&gt;
Resurrect test driven development and mock integration into Linux / C environment &lt;a href=&quot;https://steveproxna.blogspot.com/2023/08/ebpf-programming-sample.html&quot;&gt;setup&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
Transition 8-bit Sega Master System development &lt;a href=&quot;https://steveproxna.blogspot.com/2023/09/gbdk-programming-setup.html&quot;&gt;setup&lt;/a&gt; to the Nintendo Game Boy+Color
&lt;/li&gt;
&lt;li&gt;
Prepare Python environs for &lt;a href=&quot;https://github.com/openai/retro&quot;&gt;OpenAI retro&lt;/a&gt; video game Reinforcement Learning integration
&lt;/li&gt;
&lt;li&gt;
Experiment with &lt;a href=&quot;https://serenade.ai&quot;&gt;SerenadeAI&lt;/a&gt; and prototype &lt;a href=&quot;https://platform.openai.com/docs/api-reference&quot;&gt;ChatGPT APIs&lt;/a&gt; across multiple language range
&lt;/li&gt;
&lt;/ul&gt;
&lt;br&gt;
Note: leveraging Sega Master System development setup for Nintendo Game Boy is an achievement!
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;2024 Objectives&lt;/u&gt;&lt;br /&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
Resume Microservices application development and deploy across Distributed Systems at scale
&lt;/li&gt;
&lt;li&gt;
Apply &lt;a href=&quot;https://medium.com/@bijit211987/the-future-trends-of-infrastructure-as-code-iac-f16abc4c5bfc&quot;&gt;Infrastructure&lt;/a&gt; as Code and adopt DevOps best practices as software grows in complexity
&lt;/li&gt;
&lt;li&gt;
Extend Software Engineering experience across Design + &lt;a href=&quot;https://www.freecodecamp.org/news/an-introduction-to-software-architecture-patterns&quot;&gt;Architectural&lt;/a&gt; responsibilities in Cloud
&lt;/li&gt;
&lt;li&gt;
Integrate Artificial Intelligence to Software projects: Machine, Deep or Reinforcement Learning
&lt;/li&gt;
&lt;/ul&gt;
&lt;/table&gt;
&lt;br /&gt; 
&lt;u&gt;Architecture&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.xcubelabs.com/blog/software-architecture-understanding-styles-and-patterns-for-effective-system-design&quot;&gt;Software architecture&lt;/a&gt; plays crucial role in designing + developing effective software systems. Understanding various architectural styles + patterns available, you can make informed decisions in architectural endeavors to create scalable, maintainable, and reliable software solutions.  Architectural styles are high-level strategies that provide an abstract framework for a family of systems e.g. Layered, Event-Driven, and &lt;a href=&quot;https://www.xcubelabs.com/blog/microservices-architecture-implementing-communication-patterns-and-protocols&quot;&gt;Microservices&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Architect Types&lt;/u&gt;&lt;br /&gt;
Software architects, solution architects and enterprise architects all &lt;a href=&quot;https://www.linkedin.com/pulse/career-technology-software-architect-solution-enterprise-hasan&quot;&gt;play a part&lt;/a&gt; in designing, developing and implementing solutions that meet the needs of the business but differ with technical, company and IT focus:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot; offset=&quot;2&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Software&lt;br /&gt;&amp;nbsp;Architect&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;A professional who designs and oversees the development of each software system.&lt;br /&gt;&amp;nbsp;Ensures that the system meets the needs of the business and is technically feasible.
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Solution&lt;br /&gt;&amp;nbsp;Architect&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;A professional who designs and implements solutions that meet needs of the business.&lt;br /&gt;&amp;nbsp;They have a deep understanding of both the business and the technology landscapes.
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Enterprise&lt;br /&gt;&amp;nbsp;Architect&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;A professional who designs and oversees the overall IT architecture of an organization.&lt;br /&gt;&amp;nbsp;Ensures architecture aligned with business strategy and supports goals and objectives.
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;Cloud Variants&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.indeed.com/career-advice/finding-a-job/cloud-engineer-vs-cloud-architect&quot;&gt;Cloud computing&lt;/a&gt; is becoming common for accessing data and using appliations in web-based environments.  Growing demand for technology solutions in this area request need for cloud architects and cloud engineers:
&lt;br /&gt;
&lt;!-- --&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot; offset=&quot;2&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Cloud&lt;br /&gt;&amp;nbsp;Architect&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;A professional who deploys cloud-based applications according to business specifications.&lt;br /&gt;&amp;nbsp;Architects focus work on the frameworks and infrastructure of cloud-based applications.
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Cloud&lt;br /&gt;&amp;nbsp;Engineer&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;A professional who designs, creates and develops cloud-based systems and solutions.&lt;br /&gt;&amp;nbsp;Involved in building and testing technical requirements within all these cloud systems.
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!-- --&gt;
&lt;br /&gt;
&lt;u&gt;Microservices&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.xcubelabs.com/blog/the-future-of-microservices-architecture-and-emerging-trends&quot;&gt;Microservices&lt;/a&gt; have become a game-changer in the quickly changing technological landscape where flexibility, speed and scalability are crucial.  Microservices architecture provides a more agile and effective substitute to conventional monolithic techniques and has seen rapidly increasing industry adoption in recent years.
&lt;br /&gt;&lt;br /&gt;
Microservices align seamlessly with DevOps principles, fostering development and operations collaboration for continuous delivery and automation.  Microservices architecture also aligns with containerization and orchestration tools like Kubernetes, simplifying the deployment and management of services at scale.
&lt;br /&gt;&lt;br /&gt;
Industry predictions in Microservices expect growth to $1.7b by 2028 as 82% of organizations plan to adopt microservices in the next 3yrs.  Microservices are well-suited to leverage emerging technologies such as IoT, edge computing, and blockchain and A.I. has potential to disrupt and innovate in the &lt;a href=&quot;https://www.linkedin.com/pulse/what-advantages-using-ai-microservices-hatem-gad&quot;&gt;microservices&lt;/a&gt; space.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Future&lt;/u&gt;&lt;br /&gt;
The &lt;a href=&quot;https://cloudmize.medium.com/top-tech-careers-for-2024-02054f0ddcc9&quot;&gt;Top Tech Skills for 2024&lt;/a&gt; corroborates this as specialization in the cloud computing market is predicted to grow at an annual rate of 18% plus Artificial Intelligence and Machine Learning continue to drive innovations across all industries including using AI in Microservices; AI is becoming an essential part of the microservices ecosystem, enabling businesses to build and maintain large, complex applications more efficiently.  It will be interesting to see new innovative ways in which AI may integrate across the Software Engineering spectrum!
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2024/01/retrospective-xv.html</link><author>noreply@blogger.com (SteveProXNA)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-3413691940252215836</guid><pubDate>Wed, 15 Nov 2023 08:00:00 +0000</pubDate><atom:updated>2024-09-15T02:59:18.923-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">GBDK</category><title>GBDK Programming Sample</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2023/09/gbdk-programming-setup.html&quot;&gt;post&lt;/a&gt;, we checked out GBDK Programming Setup. The &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020&quot;&gt;GBDK&lt;/a&gt; is a cross-platform development kit for sm83, z80 and 6502 based gaming consoles including the Nintendo &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_Boy&quot;&gt;Game Boy&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_Boy_Color&quot;&gt;Game Boy Color&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Using the GBDK, it is now possible to write game code using the &lt;a href=&quot;http://en.wikipedia.org/wiki/C_(programming_language)&quot;&gt;C language&lt;/a&gt; rather than pure &lt;a href=&quot;http://en.wikipedia.org/wiki/Zilog_Z80#Z80_assembly_language&quot;&gt;Z80 assembly&lt;/a&gt;. Therefore, we would like to extend this knowledge and checkout some code samples and homebrew games.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiqTU3PsECzHr-OQ2EBPrAmrEro1GJ9swSzBkHYIItXJhDi0uz0BvlLtySuELKqmAGOrkk-4plXheukVQDMVuPySqa8t2SK7Ng66uSa0iFlpZd1hn9xZED7z78TJktHmSzM4SjJAC6jMQt-ZBQxHMcd9Sgb9Z0-HOSbHrn_E4S4fY-42ramaMtegEuXDk/s486/PacmanGameboy.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiqTU3PsECzHr-OQ2EBPrAmrEro1GJ9swSzBkHYIItXJhDi0uz0BvlLtySuELKqmAGOrkk-4plXheukVQDMVuPySqa8t2SK7Ng66uSa0iFlpZd1hn9xZED7z78TJktHmSzM4SjJAC6jMQt-ZBQxHMcd9Sgb9Z0-HOSbHrn_E4S4fY-42ramaMtegEuXDk/s600/PacmanGameboy.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out! 
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Software&lt;/u&gt;&lt;br /&gt;
Follow all instructions from the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2023/09/gbdk-programming-setup.html&quot;&gt;post&lt;/a&gt;: this documents how to setup all the pre-requisite software.
&lt;br /&gt;
Note: ensure you have downloaded and installed the GBDK devkit and Small Device C Compiler [&lt;a href=&quot;https://sourceforge.net/p/sdcc/wiki/Home&quot;&gt;SDCC&lt;/a&gt;].
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Examples&lt;/u&gt;&lt;br /&gt;
As per the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2023/09/gbdk-programming-setup.html&quot;&gt;post&lt;/a&gt;, after the GBDK has been downloaded, installed and setup, we should now checkout C:\gbdk\&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples&quot;&gt;examples&lt;/a&gt;\gb to learn more about APIs available in the devkit.  Replicate prior Hello World &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/01-HelloWorld&quot;&gt;example&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Launch Visual Studio 2015. File | New | Project... | Visual C++ | Win32 | Win32 Project
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEDNgJToC2epoIaoL0SkKwslIPTpKO3swjZDsbJuTz0gmEBCzBsx32-pRxLF7VNdsgdRkgzZcF6dK1rZaR1mdgquOtn_Eyzc2AgKUxwOyaY7yWc9IS_TPMjugnRWzjd2VG8cT9wfYQdc-uutYqzWvx9V46Ldr3VkpgzdAskBl5XEmMPHsozMVVBvIED3g/s941/VisualStudio01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEDNgJToC2epoIaoL0SkKwslIPTpKO3swjZDsbJuTz0gmEBCzBsx32-pRxLF7VNdsgdRkgzZcF6dK1rZaR1mdgquOtn_Eyzc2AgKUxwOyaY7yWc9IS_TPMjugnRWzjd2VG8cT9wfYQdc-uutYqzWvx9V46Ldr3VkpgzdAskBl5XEmMPHsozMVVBvIED3g/s600/VisualStudio01.png&quot;/&gt;&lt;/a&gt;
&lt;table width=&quot;82%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Name:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Game&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C:\apa_image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Create directory for solution&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;UNCHECKED&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Copy over all original folders and files from the corresponding &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/apa_image&quot;&gt;example&lt;/a&gt;.  Copy from prior Hello World example the hidden &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/apa_image/.vscode&quot;&gt;.vscode&lt;/a&gt;&lt;/b&gt; folder and files.  Copy also &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/02-examples/apa_image/build.bat&quot;&gt;build.bat&lt;/a&gt; and align with source &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/02-examples/apa_image/compile.bat&quot;&gt;compile.bat&lt;/a&gt; file.  Add relevant files to Visual Studio 2015.  Press Ctrl+1 to build, link and run code similar to the prior Hello World example!
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj8QzU60QxF5G7K4D7Cxd_GHjD-sw5RqOIAOgo_wxT19oyluxeDGB5G2FW7JxpB2xrpLVClu0tfwKaCPYoC1UAFwN63ym24FfeYLZpH4sSLeqAhZt6nlIhJXkcpF1yKGc3ljz26WocbJ9-2rRwD8YIrl8NQuMrr4gkXu2Q6eDCSlDEJXwBdPyMKyqNjz4/s1085/VisualStudio01b.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj8QzU60QxF5G7K4D7Cxd_GHjD-sw5RqOIAOgo_wxT19oyluxeDGB5G2FW7JxpB2xrpLVClu0tfwKaCPYoC1UAFwN63ym24FfeYLZpH4sSLeqAhZt6nlIhJXkcpF1yKGc3ljz26WocbJ9-2rRwD8YIrl8NQuMrr4gkXu2Q6eDCSlDEJXwBdPyMKyqNjz4/s600/VisualStudio01b.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Launch Visual Studio Code.  Open example &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/apa_image&quot;&gt;folder&lt;/a&gt;.  Set breakpoint in &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/02-examples/apa_image/src/main.c&quot;&gt;main.c&lt;/a&gt;.  Press F5 to debug step thru code
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWeHDD_HW7bG4nFR0jfPLyw7vZHRZwCuTQ_WfGkpO26RJYB4mdgpDYgFWjLLASz0DuOIFE5KkI63ezf71bKiCw5EW0_4qhk_Pv5pT1e81h7xh81pGeWri1TF4GfeLUs0d4O2MJa3VpZReo4iq_2UNO1vR02SnewIVeUPXV5rbcfjYbM8LI7vRvpPu_ROI/s1083/VisualStudioCode01c.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWeHDD_HW7bG4nFR0jfPLyw7vZHRZwCuTQ_WfGkpO26RJYB4mdgpDYgFWjLLASz0DuOIFE5KkI63ezf71bKiCw5EW0_4qhk_Pv5pT1e81h7xh81pGeWri1TF4GfeLUs0d4O2MJa3VpZReo4iq_2UNO1vR02SnewIVeUPXV5rbcfjYbM8LI7vRvpPu_ROI/s600/VisualStudioCode01c.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
Here is the complete list:
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/apa_image&quot;&gt;apa_image&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/apa_image&quot;&gt;apa_image&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/banks&quot;&gt;banks&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/banks&quot;&gt;banks&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/bcd&quot;&gt;bcd&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/bcd&quot;&gt;bcd&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/colorbar&quot;&gt;colorbar&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/colorbar&quot;&gt;colorbar&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/comm&quot;&gt;comm&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/comm&quot;&gt;comm&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/crash&quot;&gt;crash&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/crash&quot;&gt;crash&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/dscan&quot;&gt;dscan&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/dscan&quot;&gt;dscan&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/filltest&quot;&gt;filltest&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/filltest&quot;&gt;filltest&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/galaxy&quot;&gt;galaxy&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/galaxy&quot;&gt;galaxy&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/gb-dtmf&quot;&gt;gb-dtmf&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/gb-dtmf&quot;&gt;gb-dtmf&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/gbdecompress&quot;&gt;gbcompress&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/gbdecompress&quot;&gt;gbcompress&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/incbin&quot;&gt;incbin&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/incbin&quot;&gt;incbin&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/irq&quot;&gt;irq&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/irq&quot;&gt;irq&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/isr_vector&quot;&gt;isr_vector&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/isr_vector&quot;&gt;isr_vector&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/large_map&quot;&gt;large_map&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/large_map&quot;&gt;large_map&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/lcd_isr_wobble&quot;&gt;lcd_isr_wob&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/lcd_isr_wobble&quot;&gt;lcd_isr_wob&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/linkerfile&quot;&gt;linkerfile&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/linkerfile&quot;&gt;linkerfile&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/metasprites&quot;&gt;metasprites&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/metasprites&quot;&gt;metasprites&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/paint&quot;&gt;paint&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/paint&quot;&gt;paint&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/ram_function&quot;&gt;ram_function&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/ram_function&quot;&gt;ram_function&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/rand&quot;&gt;rand&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/rand&quot;&gt;rand&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/rpn&quot;&gt;rpn&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/rpn&quot;&gt;rpn&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/scroller&quot;&gt;scroller&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/scroller&quot;&gt;scroller&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/sgb_border&quot;&gt;sgb_border&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/sgb_border&quot;&gt;sgb_border&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/sgb_multiplayer&quot;&gt;sgb_multiplay&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/sgb_multiplayer&quot;&gt;sgb_multiplay&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/sgb_pong&quot;&gt;sgb_pong&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/sgb_pong&quot;&gt;sgb_pong&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/sgb_sfx&quot;&gt;sgb_sfx&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/sgb_sfx&quot;&gt;sgb_sfx&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/simple_physics&quot;&gt;simple_physics&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/simple_physics&quot;&gt;simple_physics&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/sound&quot;&gt;sound&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/sound&quot;&gt;sound&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/template_minimal&quot;&gt;temp_minimal&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/template_minimal&quot;&gt;temp_minimal&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/template_subfolders&quot;&gt;temp_subfolder&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/template_subfolders&quot;&gt;temp_subfolder&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples/wav_sample&quot;&gt;wav_sample&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/master/gbdk-lib/examples/gb/wav_sample&quot;&gt;wav_sample&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Samples&lt;/u&gt;&lt;br /&gt;
Gaming Monsters YouTube &lt;a href=&quot;https://www.youtube.com/playlist?list=PLeEj4c2zF7PaFv5MPYhNAkBGrkx4iPGJo&quot;&gt;channel&lt;/a&gt; has many &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode&quot;&gt;samples&lt;/a&gt; to teach how to develop your own GameBoy games:
&lt;br /&gt;&lt;br /&gt;
Launch Visual Studio 2015. File | New | Project... | Visual C++ | Win32 | Win32 Project
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy6vO2pV9H4Q8dtNR9xNVPYk29R0DXtt9h2g2tqPgrWq_fjXXmssclmo2vxmcR9fFCKAWqdV-0tTQ10E91tls1g8NcbevDog_6ozcV3JgNFHGn-yxJq7z0AoJdAc1pwyJyoQej0vshm-yXivLIuw43Moic34wONo-jlBt2iScTabzqS-wRfpsn3cjw0vE/s941/VisualStudio02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy6vO2pV9H4Q8dtNR9xNVPYk29R0DXtt9h2g2tqPgrWq_fjXXmssclmo2vxmcR9fFCKAWqdV-0tTQ10E91tls1g8NcbevDog_6ozcV3JgNFHGn-yxJq7z0AoJdAc1pwyJyoQej0vshm-yXivLIuw43Moic34wONo-jlBt2iScTabzqS-wRfpsn3cjw0vE/s600/VisualStudio02.png&quot;/&gt;&lt;/a&gt;
&lt;table width=&quot;82%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Name:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Game&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C:\SimpleSprites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Create directory for solution&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;UNCHECKED&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Copy over all original folders and files from the corresponding &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/02_simplesprites&quot;&gt;example&lt;/a&gt;.  Copy from prior Hello World example the hidden &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/02_simplesprites/.vscode&quot;&gt;.vscode&lt;/a&gt;&lt;/b&gt; folder and files.  Copy also &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Sample/01-gingemonster/02_simplesprites/build.bat&quot;&gt;build.bat&lt;/a&gt; and align with source&#39;s &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/blob/master/02_simplesprites/make.bat&quot;&gt;make.bat&lt;/a&gt; file.  Add relevant files to Visual Studio 2015.  Press Ctrl+1 to build, link and run code similar to the prior Hello World example!
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDIOH2Q21j5KaGH4tNOJLwP1Nj0HWG-L0VtFOaafuk9f5q-kDDnBGSS3aA8wQNX_XTyIXRiD5SInCABcVwgqxgfK1ljYjjClpQ5LmBnFYa0tcQGmO_-Piwjq6whecx0SUvlxeKqjMrnLfqgl39WuFuPH6kU80V1gK-YUhEbRJL13UPY-DtnIsaOoybJjE/s1085/VisualStudio02b.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDIOH2Q21j5KaGH4tNOJLwP1Nj0HWG-L0VtFOaafuk9f5q-kDDnBGSS3aA8wQNX_XTyIXRiD5SInCABcVwgqxgfK1ljYjjClpQ5LmBnFYa0tcQGmO_-Piwjq6whecx0SUvlxeKqjMrnLfqgl39WuFuPH6kU80V1gK-YUhEbRJL13UPY-DtnIsaOoybJjE/s600/VisualStudio02b.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Launch Visual Studio Code.  Open example &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Sample/01-gingemonster/02_simplesprites&quot;&gt;folder&lt;/a&gt;.  Set breakpoint in &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Sample/01-gingemonster/02_simplesprites/main.c&quot;&gt;main.c&lt;/a&gt;.  Press F5 to debug step thru code
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1PuBtPSXYAdHjFSsLe-pqaSYxhJSLpQ_8rAAeZNhv9pHNy3zKJjgmksY6gRiibBZHQh0hipjWs0Y4vWCTMYNWjOT8Uw7lNHrjlFL5PkDP9PyRhmLmI23aWpGKFeHtLVhfPuGZns4P4m5i1A0ihAGP6kq7yp1uQIYbUyOvTzPKsXiOioeNUKO1guSj7PY/s1083/VisualStudioCode02c.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1PuBtPSXYAdHjFSsLe-pqaSYxhJSLpQ_8rAAeZNhv9pHNy3zKJjgmksY6gRiibBZHQh0hipjWs0Y4vWCTMYNWjOT8Uw7lNHrjlFL5PkDP9PyRhmLmI23aWpGKFeHtLVhfPuGZns4P4m5i1A0ihAGP6kq7yp1uQIYbUyOvTzPKsXiOioeNUKO1guSj7PY/s600/VisualStudioCode02c.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
Here is the complete list:
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/01_helloworld&quot;&gt;helloworld&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/01_helloworld&quot;&gt;helloworld&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/02_simplesprites&quot;&gt;simplesprites&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/02_simplesprites&quot;&gt;simplesprites&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/03_movesprites&quot;&gt;movesprites&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/03_movesprites&quot;&gt;movesprites&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/04_background&quot;&gt;background&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/04_background&quot;&gt;background&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/05_window&quot;&gt;window&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/05_window&quot;&gt;window&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/06_sound&quot;&gt;sound&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/06_sound&quot;&gt;sound&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/07_noise&quot;&gt;noise&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/07_noise&quot;&gt;noise&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/08_simplejumping&quot;&gt;simplejumping&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/08_simplejumping&quot;&gt;simplejumping&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/09_metasprites&quot;&gt;metasprites&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/09_metasprites&quot;&gt;metasprites&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/10_sprite_collision&quot;&gt;spritecollision&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/10_sprite_collision&quot;&gt;spritecollision&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/11_background_collision&quot;&gt;bkgdcollision&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/11_background_collision&quot;&gt;bkgdcollision&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/12_splashscreens&quot;&gt;splashscreens&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/12_splashscreens&quot;&gt;splashscreens&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/13_fade_effects&quot;&gt;fadeeffects&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/13_fade_effects&quot;&gt;fadeeffects&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/14_keyboard&quot;&gt;keyboard&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/14_keyboard&quot;&gt;keyboard&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/15_save_name&quot;&gt;savename&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/15_save_name&quot;&gt;savename&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/16_gameboy_color_sprites&quot;&gt;colorsprites&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/16_gameboy_colorsprites&quot;&gt;colorsprites&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/17_gameboy_color_backgrounds&quot;&gt;backgrounds&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/17_gameboy_color_backgrounds&quot;&gt;backgrounds&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/19_making_music&quot;&gt;makingmusic&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/19_making_music&quot;&gt;makingmusic&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/20_sprite_tricks&quot;&gt;spritetricks&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/20_sprite_tricks&quot;&gt;spritetricks&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/21_parallax_scrolling&quot;&gt;scrolling&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/21_parallax_scrolling&quot;&gt;scrolling&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/23_debugging&quot;&gt;debugging&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/23_debugging&quot;&gt;debugging&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/01-gingemonster/XX_platformer&quot;&gt;platformer&lt;/a&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/gingemonster/GamingMonstersGameBoySampleCode/tree/master/XX_platformer&quot;&gt;platformer&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Homebrew&lt;/u&gt;&lt;br /&gt;
Larold&#39;s Jubilant &lt;a href=&quot;https://laroldsjubilantjunkyard.com&quot;&gt;Junkyard&lt;/a&gt; is a website/blog/shop which focuses on creating digital products including game development projects and &lt;a href=&quot;https://laroldsjubilantjunkyard.com/tutorials&quot;&gt;tutorials&lt;/a&gt;.  The Nintendo GameBoy development tutorial series is very educational.
&lt;br /&gt;&lt;br /&gt;
Follow Larold&#39;s Jubilant Junkyard YouTube video &lt;a href=&quot;https://www.youtube.com/@laroldsjubilantjunkyard/videos&quot;&gt;channel&lt;/a&gt; for additional GBDK 2020 information and content:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SCREEN resolution&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;20 x 18 tiles&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;160 x 144 pixels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;BACKGROUND&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;32 x 32 tiles&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;256 x 256 pixels&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Compiler flags&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;-Wm-yc&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;GameBoy Color compatible&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;NB: lowercase &lt;b&gt;c&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;-Wm-yC&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;GameBoy Color only&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;NB: uppercase &lt;b&gt;C&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;-Wm-ys&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Super GameBoy compatible&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;GameBoy Color Tile Attributes&lt;/b&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 7&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;priority flag&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;0: tiles below sprites, 1: tiles above sprites&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 6&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;vertical flip&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;0: tiles normal, 1: flipped vertically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 5&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;horizontal flip&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;0: tiles normal, 1: flipped horizontally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 4&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;not used&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 3&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;character bank specification&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;0: tiles at bank0, 1: tiles at bank1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 2&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;see bit 0&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 1&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;see bit 0&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Bit 0&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;bits 0-2&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;indicate tile color palette assignment&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Launch Visual Studio 2015. File | New | Project... | Visual C++ | Win32 | Win32 Project
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1suPMHQ6wB1e1NSx61Q-LpYtAYl0OPZQ-7sYFBCqkWFBCY34Alw73a12YRmikmIg1SbR14iRhwqhMHvYQjeQ9SnTVO69kw1Y1D76OGz6sa9ozIBdx5GssdKShOdjcjybgeRqxIIvIDWhWJfnhPQ6l41WFQqw1kB3DNzF6g3WG0fxSMDq55mCOITx-GuA/s941/VisualStudio03.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1suPMHQ6wB1e1NSx61Q-LpYtAYl0OPZQ-7sYFBCqkWFBCY34Alw73a12YRmikmIg1SbR14iRhwqhMHvYQjeQ9SnTVO69kw1Y1D76OGz6sa9ozIBdx5GssdKShOdjcjybgeRqxIIvIDWhWJfnhPQ6l41WFQqw1kB3DNzF6g3WG0fxSMDq55mCOITx-GuA/s600/VisualStudio03.png&quot;/&gt;&lt;/a&gt;
&lt;table width=&quot;82%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Name:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Game&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C:\AlleywayGameboy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Create directory for solution&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;UNCHECKED&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Copy over all original folders and files from the corresponding &lt;a href=&quot;https://github.com/LaroldsJubilantJunkyard/alleyway-gameboy&quot;&gt;example&lt;/a&gt;.  Copy from prior Hello World example the hidden &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/02-LaroldsJubilantJunkyard/alleyway-gameboy/.vscode&quot;&gt;.vscode&lt;/a&gt;&lt;/b&gt; folder and files.  Copy also &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Sample/02-LaroldsJubilantJunkyard/alleyway-gameboy/build.bat&quot;&gt;build.bat&lt;/a&gt; and align with source&#39;s &lt;a href=&quot;https://github.com/LaroldsJubilantJunkyard/alleyway-gameboy/blob/master/make.bat&quot;&gt;make.bat&lt;/a&gt; file.  Add relevant files to Visual Studio 2015.  Press Ctrl+1 to build, link and run code similar to the prior Hello World example!
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI3zJhCTIt-djxyBjtoPc9WfnbxItWYMPhADQxg08ywWW8Zinwg_3-JkKC9xRP1efkhKO2bFRMfd71trXAjo3l7_kCNe4cdGgZjyovfa8xYBbiLNHX6587dHxtSxR2LAoW2NjEwBkEmZHZh_RQWPMD8EVuMZNUmfcNZV7SeOoU8eoennshhYnq78yo0DQ/s1085/VisualStudio03b.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI3zJhCTIt-djxyBjtoPc9WfnbxItWYMPhADQxg08ywWW8Zinwg_3-JkKC9xRP1efkhKO2bFRMfd71trXAjo3l7_kCNe4cdGgZjyovfa8xYBbiLNHX6587dHxtSxR2LAoW2NjEwBkEmZHZh_RQWPMD8EVuMZNUmfcNZV7SeOoU8eoennshhYnq78yo0DQ/s600/VisualStudio03b.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
NOTE: ensure that the GBDK header files are included for Intellisense:  Right click project | Properties |
&lt;br /&gt;
Configuration Properties | C/C++ | General | Additional Include Directories | &lt;b&gt;%GBDK_WIN%/include; $(SolutionDir)/headers/gen; $(SolutionDir)/headers/main; %(AdditionalIncludeDirectories)&lt;/b&gt;.
&lt;br /&gt;&lt;br /&gt;
Here is the complete list:
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/02-LaroldsJubilantJunkyard/alleyway-gameboy&quot;&gt;alleyway&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/LaroldsJubilantJunkyard/alleyway-gameboy&quot;&gt;alleyway&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/02-LaroldsJubilantJunkyard/flappy-bird-gameboy&quot;&gt;flappy-bird&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/LaroldsJubilantJunkyard/flappy-bird-gameboy&quot;&gt;flappy-bird&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/02-LaroldsJubilantJunkyard/pacman-gameboy&quot;&gt;pacman&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/LaroldsJubilantJunkyard/pacman-gameboy&quot;&gt;pacman&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Sample/02-LaroldsJubilantJunkyard/space-invaders-gameboy&quot;&gt;space-invaders&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/LaroldsJubilantJunkyard/space-invaders&quot;&gt;space-invaders&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC1uTz8yEFUeC_1Kam3Ke4_5IzpeXb2TCYXAK8pqaWB10oG-GyRal0EpBWY7xX2LqU07SiplaXB26GGBh4yCMtQovu1BTjFwjJkBzAj3WSuPY1RW2QDZNe0DF7Dr8RB39_E7i8AQf4yAjqB418Ji8wN4vpdX6sQaY-gdk4QjsUxV1tzp9_CmDcqxfDCc4/s243/BreakoutGameboy.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC1uTz8yEFUeC_1Kam3Ke4_5IzpeXb2TCYXAK8pqaWB10oG-GyRal0EpBWY7xX2LqU07SiplaXB26GGBh4yCMtQovu1BTjFwjJkBzAj3WSuPY1RW2QDZNe0DF7Dr8RB39_E7i8AQf4yAjqB418Ji8wN4vpdX6sQaY-gdk4QjsUxV1tzp9_CmDcqxfDCc4/s600/BreakoutGameboy.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9tG0p32-Ondv1BHRVDA7GCdxusLz8bI4AsPc4Ys7c75uEAervp18uipZ09gH0P-qgkflWeMIKmK6yojjrxeV422aidpFjXooOEol4eO8VjE-Fx7kesNKZ8Qclsa-YRY0EoofKFgUlpIAJRQiJU_VGOOAJKx74T-yClCc3UcBs_Aye_TSlpPQs6688LuA/s243/PacmanGameboy.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9tG0p32-Ondv1BHRVDA7GCdxusLz8bI4AsPc4Ys7c75uEAervp18uipZ09gH0P-qgkflWeMIKmK6yojjrxeV422aidpFjXooOEol4eO8VjE-Fx7kesNKZ8Qclsa-YRY0EoofKFgUlpIAJRQiJU_VGOOAJKx74T-yClCc3UcBs_Aye_TSlpPQs6688LuA/s600/PacmanGameboy.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEyg-zo3rK1cM99rO_UPsSSNg7E5aUmhbZHuWkMsaWmGLydNtVJJFoZyqdRaySns6it_1B6ERVhCI8_QF6FyaTcIFUYbClYVV8IfPFy1nPz7lsMM0UmEqDQguNVWw6R9-sgV_69uUYg7JS8W9hxq6gPBMcEi_JoYIujKMnIxlNnC1padWV7Hpq9rxH6D0/s243/FlappybirdGameboy.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEyg-zo3rK1cM99rO_UPsSSNg7E5aUmhbZHuWkMsaWmGLydNtVJJFoZyqdRaySns6it_1B6ERVhCI8_QF6FyaTcIFUYbClYVV8IfPFy1nPz7lsMM0UmEqDQguNVWw6R9-sgV_69uUYg7JS8W9hxq6gPBMcEi_JoYIujKMnIxlNnC1padWV7Hpq9rxH6D0/s600/FlappybirdGameboy.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;50%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3-vK3VZq8xjTFk9P3sGZu9SltnkLaNxH-OBlzM0DMUf1V3v-0zKhKNXfBbmFDkVLpnvHVPflPwYbjm0kg8yH7d5sq3V77iDrv9X8zt-iAJgstvDtip-ZcCLzEL6oT7GhbMWRyMEqUnsvcgTr6EBt9uPm1Fjk5y7AbIe9nOQgx0PgdXEOdgGJC2FgaPU/s243/SpaceInvadersGameboy.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3-vK3VZq8xjTFk9P3sGZu9SltnkLaNxH-OBlzM0DMUf1V3v-0zKhKNXfBbmFDkVLpnvHVPflPwYbjm0kg8yH7d5sq3V77iDrv9X8zt-iAJgstvDtip-ZcCLzEL6oT7GhbMWRyMEqUnsvcgTr6EBt9uPm1Fjk5y7AbIe9nOQgx0PgdXEOdgGJC2FgaPU/s600/SpaceInvadersGameboy.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
Armed with all this knowledge, we are now in an excellent position to build complete video games for the Nintendo &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_Boy&quot;&gt;Game Boy&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_Boy_Color&quot;&gt;Game Boy Color&lt;/a&gt;.  In the interim, we see the GameBoy &lt;a href=&quot;https://itch.io/jam/gbcompo23&quot;&gt;Competition&lt;/a&gt; 2023 is &lt;a href=&quot;https://www.youtube.com/watch?v=tezGoSgHZZQ&quot;&gt;here&lt;/a&gt;!
&lt;br /&gt;&lt;br /&gt;
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2023/11/gbdk-programming-sample.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiqTU3PsECzHr-OQ2EBPrAmrEro1GJ9swSzBkHYIItXJhDi0uz0BvlLtySuELKqmAGOrkk-4plXheukVQDMVuPySqa8t2SK7Ng66uSa0iFlpZd1hn9xZED7z78TJktHmSzM4SjJAC6jMQt-ZBQxHMcd9Sgb9Z0-HOSbHrn_E4S4fY-42ramaMtegEuXDk/s72-c/PacmanGameboy.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-8077886453028678261</guid><pubDate>Fri, 15 Sep 2023 09:00:00 +0000</pubDate><atom:updated>2023-11-15T00:01:29.391-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">GBDK</category><title>GBDK Programming Setup</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In 2017, we checked out &lt;a href=&quot;http://steveproxna.blogspot.com/2017/09/devkitsms-programming-setup.html&quot;&gt;devkitSMS Programming Setup&lt;/a&gt; to build 8-bit video games for Sega Master System.  Here we installed all the tools required including a powerful emulator: &lt;b&gt;&lt;a href=&quot;https://emulicious.net&quot;&gt;Emulicious&lt;/a&gt;&lt;/b&gt; to test the video games.  
&lt;br /&gt;&lt;br /&gt;
&lt;a href=&quot;http://emulicious.net/downloads&quot;&gt;Emulicious&lt;/a&gt; is a free multi-system emulator popular for Sega Master System and Sega Game Gear games but can also play Nintendo &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_Boy&quot;&gt;Game Boy&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Game_Boy_Color&quot;&gt;Game Boy Color&lt;/a&gt; games.  Therefore, let&#39;s leverage Sega Master System development setup to build and test games for Nintendo Game Boy and Game Boy Color using the &lt;b&gt;&lt;a href=&quot;https://gbdev.gg8.se/wiki/articles/GBDK&quot;&gt;GBDK&lt;/a&gt;&lt;/b&gt;.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw8AaSIiC8FF2stZ-XBEimFdnjtSLeGNLUbqY0JchKTa95VHVd8upE_UgExkFDUQS3a535SCAaBXAl81_ytRZaDuMr3P4NFGMRgmGAnYfgY_5C2Ll9lxEQAW1nhiWtDHZGvURSzUBCTk8AYTz4y-moFpo2VXf0oeZFn3EohvmxFs5gB52ddAAFrThHCgo/s757/GitHubTitle.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw8AaSIiC8FF2stZ-XBEimFdnjtSLeGNLUbqY0JchKTa95VHVd8upE_UgExkFDUQS3a535SCAaBXAl81_ytRZaDuMr3P4NFGMRgmGAnYfgY_5C2Ll9lxEQAW1nhiWtDHZGvURSzUBCTk8AYTz4y-moFpo2VXf0oeZFn3EohvmxFs5gB52ddAAFrThHCgo/s600/GitHubTitle.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out! 
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;GDDK&lt;/u&gt;&lt;br /&gt;
The &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020&quot;&gt;GBDK&lt;/a&gt; is a cross-platform development kit for sm83, z80 and 6502 based gaming consoles including the Nintendo Game Boy and Game Boy Color.  It includes libraries, toolchain utilities and &lt;a href=&quot;https://sourceforge.net/p/sdcc/wiki/Home&quot;&gt;SDCC&lt;/a&gt; C compiler suite.
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Software&lt;/u&gt;&lt;br /&gt;
Follow all instructions from the previous &lt;a href=&quot;http://steveproxna.blogspot.com/2017/09/devkitsms-programming-setup.html&quot;&gt;post&lt;/a&gt;: this documents how to setup the pre-requisite software.
&lt;br /&gt;
&lt;br /&gt;
Here is a summary of all required software to be installed:
&lt;table width=&quot;90%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Name&lt;/b&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Version&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C IDE Editor&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://my.visualstudio.com/Downloads?q=visual%20studio%202015&amp;wt.mc_id=o~msft~vscom~older-downloads&quot;&gt;Visual Studio 2015&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C IDE Editor&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://code.visualstudio.com/docs/?dv=win&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Cross compiler&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://sourceforge.net/projects/sdcc/files/sdcc-win64/4.1.0/sdcc-4.1.0-x64-setup.exe/download&quot;&gt;Small Device C Compiler&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Name&lt;/b&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Version&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Make files&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;http://cygwin.com/install.html&quot;&gt;Cygwin&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Emulators&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;http://emulicious.net/downloads&quot;&gt;Emulicious&lt;/a&gt;, &lt;a href=&quot;https://bgb.bircd.org/#downloads&quot;&gt;BGB&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Debugger&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=emulicious.emulicious-debugger&quot;&gt;Emulicious Debugger&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
Note: this &lt;a href=&quot;http://steveproxna.blogspot.com/2022/06/devkitsms-programming-setup-ii.html&quot;&gt;post&lt;/a&gt; documents how to download and install SDCC v4.1.0 on both Windows and Linux.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;GBDK&lt;/b&gt;&lt;br /&gt;
Navigate to the &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020&quot;&gt;gbdk-2020&lt;/a&gt; repository on github: gbdk-2020 has full instructions &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/tree/develop/docs&quot;&gt;here&lt;/a&gt;.  Download the latest &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/releases&quot;&gt;release&lt;/a&gt; from gbdk-2020 archive e.g. &lt;a href=&quot;https://github.com/gbdk-2020/gbdk-2020/releases/download/4.1.1/gbdk-win64.zip&quot;&gt;gbdk-4.1.1&lt;/a&gt; or git clone latest source code. Extract code into C:\gbdk.
&lt;br /&gt;&lt;br /&gt;
Setup the following environment variable for GBDK_WIN as it can be useful throughout GBDK development.  Add the following one environment variable: System | Advanced system settings | Environment Variables:
&lt;br /&gt;
&lt;table width=&quot;98%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Variable&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Value&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;GBDK_WIN&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C:\gbdk&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Windows path format&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Example&lt;/u&gt;&lt;br /&gt;
As an example, let&#39;s write a simple program that prints Hello World to the screen using the GameBoy DevKit.  Create new directory: C:\HelloWorld.  Create new file &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/main.c&quot;&gt;main.c&lt;/a&gt;.  Copy in the following code to print Hello World. 
&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/main.c&quot;&gt;main.c&lt;/a&gt;
&lt;br /&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
#include &amp;lt;gb/gb.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

void main()
{
	printf( &quot;HELLO WORLD&quot; );
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;u&gt;Build&lt;/u&gt;&lt;br /&gt;
Manually compile and link the Hello World program.  Launch command prompt: Start | Run | cmd.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghwDn1hOAOfe6YVaBXl1zg0py2ibhc42kE8VVTf2dsZHx8o2OjOOXCdKvfP1S4T9eKT5EmLraKDi2OlLl-jk4Kit8h9KGDOrssnR_X1KO0TXa9EaTcbcz1q7fw36naxKZi9CVYi9K8ylSPmdl6ZveleDmKJQzAac5MOY3l-2VIGhTshGsKtagvV-53Vsk/s635/HelloWorld.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghwDn1hOAOfe6YVaBXl1zg0py2ibhc42kE8VVTf2dsZHx8o2OjOOXCdKvfP1S4T9eKT5EmLraKDi2OlLl-jk4Kit8h9KGDOrssnR_X1KO0TXa9EaTcbcz1q7fw36naxKZi9CVYi9K8ylSPmdl6ZveleDmKJQzAac5MOY3l-2VIGhTshGsKtagvV-53Vsk/s600/HelloWorld.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
Change directory cd C:\HelloWorld.  Next, execute the following 2x commands (in bold):
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;ACTION&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;COMMAND&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;OUTPUT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Compile&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;%GBDK_WIN%/bin/lcc -Wa-l -Wl-m -Wl-j -c -o main.o main.c&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;main.o&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Link&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;%GBDK_WIN%/bin/lcc -Wa-l -Wl-m -Wl-j -o output.gb main.o&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;output.gb&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Finally, type &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/output.gb&quot;&gt;output.gb&lt;/a&gt;&lt;/b&gt;.  The Hello World program should launch in the Emulicious emulator.
&lt;br /&gt;
Congratulations! You have just written your first test program using the GameBoy DevKit.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcOTutAeAgKj5i7YMWOEveThWpQKxD2wJEY6ya0VB3lSx8U4cGkqv53yCtS7254JZt9Eq2E5Bfuv3um7xPPVfPSIzmh3LagM0O4Phwiht1oBWFlyF7O4zDUdqKqMf5F2c3Z2mDu4mpfhFzT9fxg65ZyNQiWoQjK5uqY5b21sZM3Hm1rIqGXnjd8EJwGUU/s486/HWoutput.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcOTutAeAgKj5i7YMWOEveThWpQKxD2wJEY6ya0VB3lSx8U4cGkqv53yCtS7254JZt9Eq2E5Bfuv3um7xPPVfPSIzmh3LagM0O4Phwiht1oBWFlyF7O4zDUdqKqMf5F2c3Z2mDu4mpfhFzT9fxg65ZyNQiWoQjK5uqY5b21sZM3Hm1rIqGXnjd8EJwGUU/s600/HWoutput.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
IMPORTANT&lt;br /&gt;
If game does not initially render correct then select Options menu | System | Game Boy or Game Boy Color.
&lt;br /&gt;
&lt;br /&gt;  
&lt;u&gt;Automate&lt;/u&gt;&lt;br /&gt;
Let&#39;s automate the build process: create C:\HelloWorld\&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/build.bat&quot;&gt;build.bat&lt;/a&gt; script file that contains the commands:
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
@echo off
%GBDK_WIN%/bin/lcc -Wa-l -Wl-m -Wl-j -c -o main.o main.c
%GBDK_WIN%/bin/lcc -Wa-l -Wl-m -Wl-j -o output.gb main.o
output.gb
&lt;/pre&gt;
&lt;br /&gt;
&lt;u&gt;Visual Studio 2015&lt;/u&gt;&lt;br /&gt;
Similar to Sega Master System development using devkitSMS, setup Visual Studio 2015 as per instructions &lt;a href=&quot;https://steveproxna.blogspot.com/2019/04/devkitsms-programming-sample-iii.html&quot;&gt;here&lt;/a&gt;.  Also, follow instructions &lt;a href=&quot;https://steveproxna.blogspot.com/2017/09/devkitsms-programming-setup.html&quot;&gt;here&lt;/a&gt; to connect Ctrl+1 hot key to automatically compile, link and run code.
&lt;br /&gt;&lt;br /&gt;
Launch Visual Studio 2015.  File | New | Project... | Visual C++ | Win32 | Win32 Project
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitx2fmYxSpHafglnXX56lf_dI3PMftHvhog9OeNBnc_Y_O-lf_Jh2LS2ua75ycMhaFusuT9DVmDOH8t6jF_p4q6iq3nPx0sgT74hWj-MxgIUphzz_6ZQvLNYA4Bj1a3_rhE6S2r_nODSJWKdI9Wy1CC5VGF-i9uHEHqFL3WGBKnFtTj9jNpriYDxI0jiI/s941/VisualStudio01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitx2fmYxSpHafglnXX56lf_dI3PMftHvhog9OeNBnc_Y_O-lf_Jh2LS2ua75ycMhaFusuT9DVmDOH8t6jF_p4q6iq3nPx0sgT74hWj-MxgIUphzz_6ZQvLNYA4Bj1a3_rhE6S2r_nODSJWKdI9Wy1CC5VGF-i9uHEHqFL3WGBKnFtTj9jNpriYDxI0jiI/s600/VisualStudio01.png&quot;/&gt;&lt;/a&gt;
&lt;table width=&quot;82%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Name:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;HelloWorld&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C:\&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Create directory for solution&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;UNCHECKED&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGSPHyB2uv6YP0XVK8S29AZb6dE3nsI9kxe1vB4wecW-Y79q_GCmYbP1bPQhwJLQNqL9lO3FBGI_ZnjXdFgp3NYnf6Apc6SSJl0oZjZCFHaOj2EXSnXnu5Sl9B4SIqv0aBxuF0FxpoSUkfohC6VELHF3l-D3FRGaUSp_IEWZo3kwBbvdI58vQdztsMQ2w/s667/VisualStudio02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGSPHyB2uv6YP0XVK8S29AZb6dE3nsI9kxe1vB4wecW-Y79q_GCmYbP1bPQhwJLQNqL9lO3FBGI_ZnjXdFgp3NYnf6Apc6SSJl0oZjZCFHaOj2EXSnXnu5Sl9B4SIqv0aBxuF0FxpoSUkfohC6VELHF3l-D3FRGaUSp_IEWZo3kwBbvdI58vQdztsMQ2w/s600/VisualStudio02.png&quot;/&gt;&lt;/a&gt;
&lt;table width=&quot;82%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Application type:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Console application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Additional options:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Empty project CHECKED&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
Navigate to C:\HelloWorld.  Add existing: &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/main.c&quot;&gt;main.c&lt;/a&gt; and &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/build.bat&quot;&gt;build.bat&lt;/a&gt;  at the same folder level as HelloWorld.sln.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvTaTyDCM34aiJZzv7HqP-vUofC0nbMmdSu8qcI-VkMjhlEjEJLsymRyG2gKdaU-ZHssFH8a7BdVlYXUFoYpXO6HJF24TtSpV8VIkZJ-0M7sdZ68lPMHtGfE2mIan6srNnWcPYACWAopnYanYPY4uvPrhBtIBKq4flQivzuwsM_4OmGzpJDhKIFe99v0U/s940/VisualStudio03.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvTaTyDCM34aiJZzv7HqP-vUofC0nbMmdSu8qcI-VkMjhlEjEJLsymRyG2gKdaU-ZHssFH8a7BdVlYXUFoYpXO6HJF24TtSpV8VIkZJ-0M7sdZ68lPMHtGfE2mIan6srNnWcPYACWAopnYanYPY4uvPrhBtIBKq4flQivzuwsM_4OmGzpJDhKIFe99v0U/s600/VisualStudio03.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
Finally, ensure that the GBDK header files are included for Intellisense:  Right click project | Properties |
&lt;br /&gt;
Configuration Properties | C/C++ | General | Additional Include Directories | &lt;b&gt;%GBDK_WIN%/include&lt;/b&gt;.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQbJ533uNiYy5enB3q2mUaBATsZMHgA8Dfv5h2sFaLNl9iOn0IdfoVl3yQWFTXLAT9g-a6apG39yoIuPToDYiCaF1q7DTkokZpfqZmZFlWQy6QGpLXC-qOKfk5Gp0AQeExa6QFgxOGwBTwEXIlUq0VAid6iaEaJH_zzH17swMIOrcR6qlMUkfPnQTSz5w/s838/VisualStudio04.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQbJ533uNiYy5enB3q2mUaBATsZMHgA8Dfv5h2sFaLNl9iOn0IdfoVl3yQWFTXLAT9g-a6apG39yoIuPToDYiCaF1q7DTkokZpfqZmZFlWQy6QGpLXC-qOKfk5Gp0AQeExa6QFgxOGwBTwEXIlUq0VAid6iaEaJH_zzH17swMIOrcR6qlMUkfPnQTSz5w/s600/VisualStudio04.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Press Ctrl+1 to build, link and run!
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;  
&lt;u&gt;Visual Studio Code&lt;/u&gt;&lt;br /&gt;
Similar to Sega Master System development using devkitSMS, setup Visual Studio Code as per instructions &lt;a href=&quot;https://steveproxna.blogspot.com/2022/06/devkitsms-programming-setup-ii.html&quot;&gt;here&lt;/a&gt;.  Add hidden &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/01-HelloWorld/01_helloworld/.vscode&quot;&gt;.vscode&lt;/a&gt;&lt;/b&gt; folder + include &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/.vscode/tasks.json&quot;&gt;tasks.json&lt;/a&gt; and &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/.vscode/launch.json&quot;&gt;launch.json&lt;/a&gt; files beneath to build + debug code.
&lt;br /&gt;&lt;br /&gt;
Launch Visual Studio Code.  Open folder C:\HelloWorld.  Add the &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/01-HelloWorld/01_helloworld/.vscode&quot;&gt;.vscode&lt;/a&gt;&lt;/b&gt; folder the following files beneath:
&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/.vscode/c_cpp_properties.json&quot;&gt;c_cpp_properties.json&lt;/a&gt;
&lt;br /&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
{
  &quot;configurations&quot;: [
    {
      &quot;name&quot;: &quot;stevepro&quot;,
      &quot;intelliSenseMode&quot;: &quot;clang-x64&quot;,
      &quot;includePath&quot;: [
        &quot;${env:GBDK_WIN}/include&quot;
      ],
      &quot;cStandard&quot;: &quot;c11&quot;,
      &quot;cppStandard&quot;: &quot;c++17&quot;,
      &quot;browse&quot;: {
        &quot;path&quot;: [
          &quot;${workspaceFolder}&quot;
        ],
        &quot;limitSymbolsToIncludedHeaders&quot;: true,
        &quot;databaseFilename&quot;: &quot;&quot;
      }
    }
  ],
  &quot;version&quot;: 4
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/.vscode/tasks.json&quot;&gt;tasks.json&lt;/a&gt;
&lt;br /&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
{
    &quot;version&quot;: &quot;2.0.0&quot;,
    &quot;label&quot;: &quot;build&quot;,
    &quot;type&quot;: &quot;shell&quot;,
    &quot;windows&quot;: {
        &quot;command&quot;: &quot;./build.bat&quot;
      },
    &quot;presentation&quot;: {&quot;echo&quot;: true, &quot;reveal&quot;: &quot;always&quot;, &quot;focus&quot;: false, &quot;panel&quot;: &quot;shared&quot;, &quot;showReuseMessage&quot;: false, &quot;clear&quot;: true},
    &quot;group&quot;: {&quot;kind&quot;: &quot;build&quot;, &quot;isDefault&quot;: true},
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/.vscode/launch.json&quot;&gt;launch.json&lt;/a&gt;
&lt;br /&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
{
    &quot;version&quot;: &quot;0.2.0&quot;,
    &quot;configurations&quot;: [
        {
            &quot;type&quot;: &quot;emulicious-debugger&quot;,
            &quot;request&quot;: &quot;launch&quot;,
            &quot;name&quot;: &quot;Launch in Emulicious&quot;,
            &quot;program&quot;: &quot;${workspaceFolder}/output.gb&quot;,
            &quot;port&quot;: 58870,
            &quot;stopOnEntry&quot;: false,
        }
    ]
}
&lt;/pre&gt;
&lt;br /&gt;
Open &lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/blob/main/Setup/01-HelloWorld/01_helloworld/main.c&quot;&gt;main.c&lt;/a&gt;.  Set breakpoint.  Press Ctrl + Shift + B to build source code.  Press F5 to debug step thru code:  
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuY0S6dZH3dnauVn6eu4Wy_VXrd4qDXhexk71NOnKQmRiJqyLIzHd0BGmNrPesTYiysWMVwoAUruM0r5G-GJDcEBLV7MPPe0SECW4uD4YNAkXh-NbRt0dpRhD_TZcsLUlCd5cMMmmCy7R8CPKiUGKMTU0wPyEoqIziszaSdkvToRPvSTZaOK1kJPmwqYI/s1019/VScodeDebug.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuY0S6dZH3dnauVn6eu4Wy_VXrd4qDXhexk71NOnKQmRiJqyLIzHd0BGmNrPesTYiysWMVwoAUruM0r5G-GJDcEBLV7MPPe0SECW4uD4YNAkXh-NbRt0dpRhD_TZcsLUlCd5cMMmmCy7R8CPKiUGKMTU0wPyEoqIziszaSdkvToRPvSTZaOK1kJPmwqYI/s600/VScodeDebug.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
In Emulicious, choose Tools menu | Debugger to be able to fully debug step thru the Z80 assembly code:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizwLk_2g4vCxWtdQSG7dgzu5pYN-BNKNncHzCL_XVRum23lxVeY3yKJ8_RsN2EY2rdAZncdGQvPoJ5fPuzAewtkguANjdzdE8HpXgYgkBVKMQNXI9a9Gfzp_p_ty9au81mL0jo2z01N9emRt8AuHeg9iyYj4pf0uk9brslQcKapgkMsf-HPBmmqBeeEC8/s1920/VScodeDebugASM.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizwLk_2g4vCxWtdQSG7dgzu5pYN-BNKNncHzCL_XVRum23lxVeY3yKJ8_RsN2EY2rdAZncdGQvPoJ5fPuzAewtkguANjdzdE8HpXgYgkBVKMQNXI9a9Gfzp_p_ty9au81mL0jo2z01N9emRt8AuHeg9iyYj4pf0uk9brslQcKapgkMsf-HPBmmqBeeEC8/s600/VScodeDebugASM.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;  
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
Now the GBDK has been downloaded, installed and setup, we should checkout C:\gbdk\&lt;a href=&quot;https://github.com/SteveProXNA/GBDKcode/tree/main/Setup/02-examples&quot;&gt;examples&lt;/a&gt;\gb to learn more about the APIs available in the devkit + checkout some code samples and complete homebrew games.  This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2023/11/gbdk-programming-sample.html&quot;&gt;post&lt;/a&gt;.
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2023/09/gbdk-programming-setup.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw8AaSIiC8FF2stZ-XBEimFdnjtSLeGNLUbqY0JchKTa95VHVd8upE_UgExkFDUQS3a535SCAaBXAl81_ytRZaDuMr3P4NFGMRgmGAnYfgY_5C2Ll9lxEQAW1nhiWtDHZGvURSzUBCTk8AYTz4y-moFpo2VXf0oeZFn3EohvmxFs5gB52ddAAFrThHCgo/s72-c/GitHubTitle.png" height="72" width="72"/><thr:total>2</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-511336063019560626</guid><pubDate>Thu, 31 Aug 2023 08:00:00 +0000</pubDate><atom:updated>2023-08-31T10:16:28.480-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">eBPF</category><title>eBPF Programming Sample</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In the previous &lt;a href=&quot;http://steveproxna.blogspot.com/2023/07/ebpf-programming-setup.html&quot;&gt;post&lt;/a&gt;, we checked out &lt;a href=&quot;https://en.wikipedia.org/wiki/EBPF&quot;&gt;eBPF&lt;/a&gt; Programming Setup. Extended Berkeley Packet Filter [eBPF] is technology that runs sandboxed programs in privileged context like the OS kernel to safely and efficiently extend the capabilities of the kernel at runtime without requiring changes to the kernel source code.  One issue is there are currently limited methods to &lt;a href=&quot;https://www.youtube.com/watch?v=R8-GbeaIOwc&quot;&gt;debug&lt;/a&gt; BPF programs thus we&#39;d like to explore test options.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglM6Dz0JhtGBagI4XR-6pkK1OnpsQQKcemem2ArVYzyS3jI3LPC772Rk6mh00XUanwrZhbE7f1oe6krSRXGPJhoybEUFDt2_64jnx-oEJm_4d0vQMY8AZzElYQTIJm5tEez4qQGeRkYz3a1e0D29_cWlDMjF_L2xdrr9bATfv4aKQUeU6m5AmFUTsv9oI/s850/EBPF_logo.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglM6Dz0JhtGBagI4XR-6pkK1OnpsQQKcemem2ArVYzyS3jI3LPC772Rk6mh00XUanwrZhbE7f1oe6krSRXGPJhoybEUFDt2_64jnx-oEJm_4d0vQMY8AZzElYQTIJm5tEez4qQGeRkYz3a1e0D29_cWlDMjF_L2xdrr9bATfv4aKQUeU6m5AmFUTsv9oI/s600/EBPF_logo.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out! 
&lt;br /&gt;&lt;br /&gt;  
&lt;u&gt;Software&lt;/u&gt;&lt;br /&gt;
Follow all instructions from the previous &lt;a href=&quot;http://steveproxna.blogspot.com/2019/10/linux-setup-cheat-sheet-ii.html&quot;&gt;post&lt;/a&gt; to install &lt;b&gt;CLion&lt;/b&gt; and &lt;b&gt;VS Code&lt;/b&gt; on Ubuntu Linux.  Also install the following components for low level C code unit testing, mocking and integration: &lt;b&gt;&lt;a href=&quot;http://www.throwtheswitch.org/unity&quot;&gt;Unity&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a href=&quot;http://www.throwtheswitch.org/cmock&quot;&gt;CMock&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a href=&quot;http://www.throwtheswitch.org/ceedling&quot;&gt;Ceedling&lt;/a&gt;&lt;/b&gt;.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/ThrowTheSwitch/Unity&quot;&gt;Unity&lt;/a&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Unit testing framework built for C projects with a focus on working with embedded toolchains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/ThrowTheSwitch/CMock&quot;&gt;CMock&lt;/a&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Mock and stub generator and runtime for unit testing C designed to work smoothly with Unity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/ThrowTheSwitch/Ceedling&quot;&gt;Ceedling&lt;/a&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;Build system for C projects using Ruby Rake [make] build system to integrate Unity + CMock&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;  
&lt;u&gt;Pre-requisites&lt;/u&gt;&lt;br /&gt;
As above, Ceedling requires Ruby installed otherwise &lt;i&gt;sudo: gem: command not found&lt;/i&gt; errors may be thrown.  Also, CMock requires Ruby bundle be installed otherwise &lt;i&gt;Command &#39;bundle&#39; not found&lt;/i&gt; errors may be thrown.
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;sudo apt install ruby&lt;/td&gt;
&lt;td&gt;&amp;nbsp;sudo apt install ruby-bundler&lt;/td&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;b&gt;Unity&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.throwtheswitch.org/unity&quot;&gt;Unity&lt;/a&gt; is a unit testing framework built for C, with a focus on working with embedded toolchains, which we would like to try and &lt;a href=&quot;https://github.com/ThrowTheSwitch/Unity&quot;&gt;leverage&lt;/a&gt; for BPF development.  Follow instructions &lt;a href=&quot;https://github.com/ThrowTheSwitch/Unity/issues/302&quot;&gt;here&lt;/a&gt; to install and configure Unity.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git clone git@github.com:ThrowTheSwitch/Unity.git&lt;br /&gt;
&amp;nbsp;cd Unity&lt;br /&gt;
&amp;nbsp;cmake .&lt;br /&gt;
&amp;nbsp;make&lt;br /&gt;
&amp;nbsp;sudo make install&lt;br /&gt;
&amp;nbsp;sudo cp libunity.a /usr/local/lib&lt;br /&gt;
&amp;nbsp;sudo cp src/unity*.h /usr/local/include/unity&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigHo7-E8E8BwXpbneb-Lah2iL3sjeI321CwDcSkpLD-BQPbRCkGNsthVhCfNvzs7Tf7MbuWU7877vljTTQV2r7kV-Pt38ED3r36akYdsk7gNU1bneNaKL5KIT6Im2ff2DPWW5aPN9G2Teom7eNVA_AsjAEcN_7TjYMkAe5lCtWHpw-JPc4oHNapx_lTMA/s934/01-unity.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigHo7-E8E8BwXpbneb-Lah2iL3sjeI321CwDcSkpLD-BQPbRCkGNsthVhCfNvzs7Tf7MbuWU7877vljTTQV2r7kV-Pt38ED3r36akYdsk7gNU1bneNaKL5KIT6Im2ff2DPWW5aPN9G2Teom7eNVA_AsjAEcN_7TjYMkAe5lCtWHpw-JPc4oHNapx_lTMA/s600/01-unity.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikUUb5t6yMGwhFoyk9cvn0sA1q1vPjLm8uR3Nz6CGlStSpzn2bEB0ZBa5zZv1t5TgXubnqobyumb8uzahy6NsoWEabAXtGbVU2P0qoTcvtx7wgFb2DlIblY-6r-lHhnLgoD7UdYZ39_3BxNZIwed7MBJ-p8O3EjpZNmCCaLu2yf68iWWuIpr6-HQAaTQY/s889/02-unity.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikUUb5t6yMGwhFoyk9cvn0sA1q1vPjLm8uR3Nz6CGlStSpzn2bEB0ZBa5zZv1t5TgXubnqobyumb8uzahy6NsoWEabAXtGbVU2P0qoTcvtx7wgFb2DlIblY-6r-lHhnLgoD7UdYZ39_3BxNZIwed7MBJ-p8O3EjpZNmCCaLu2yf68iWWuIpr6-HQAaTQY/s600/02-unity.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;CMock&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.throwtheswitch.org/cmock&quot;&gt;CMock&lt;/a&gt; is a mock and stub generator designed to work smoothly with Unity. CMock automagically parses the C headers and creates useful mock interfaces used for unit testing.  Follow instructions &lt;a href=&quot;https://github.com/ThrowTheSwitch/CMock&quot;&gt;here&lt;/a&gt; to install CMock.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git clone --recursive https://github.com/throwtheswitch/cmock.git&lt;br /&gt;
&amp;nbsp;cd cmock&lt;br /&gt;
&amp;nbsp;bundle install&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ceedling&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.throwtheswitch.org/ceedling&quot;&gt;Ceedling&lt;/a&gt; is a build system for C projects using Ruby Rake [make] build system.  Ceedling also makes TDD Test Driven Development simple by integrating CMock + Unity.  Follow instructions &lt;a href=&quot;https://spin.atomicobject.com/2019/02/07/cmock-get-started&quot;&gt;here&lt;/a&gt; to install Ceedling.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;ruby -v&lt;br /&gt;
&amp;nbsp;sudo gem install ceedling&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHH0bdvUt3Jtd8xHarpED4IWNzNOc9VfzjNgPFLEbSaUYshe5-vJINvAT0JElTNuKw4IZBfdOgCSp0f3fZr_a1WAK28YaaCmXX3izV7W9n6c1W-BwKivf6nr0oi5sKtbdw-4D0AzrxzOubTa8pHRwBh-8mwiup0LMOeHFJXMVaJ6CFIzQPDE_JfeJNxIE/s736/01-ceedling.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHH0bdvUt3Jtd8xHarpED4IWNzNOc9VfzjNgPFLEbSaUYshe5-vJINvAT0JElTNuKw4IZBfdOgCSp0f3fZr_a1WAK28YaaCmXX3izV7W9n6c1W-BwKivf6nr0oi5sKtbdw-4D0AzrxzOubTa8pHRwBh-8mwiup0LMOeHFJXMVaJ6CFIzQPDE_JfeJNxIE/s600/01-ceedling.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit2Ae-5krstLh2Y6aOkGS1-BSLKOW1D0i5Y7QQaHhWclqQz7BTmWQQEAXtraGbOtPl5nu1_fkyQGNW1ynCOKEXNMPvG6r7K1mu8MmexeKcEHbGS5Rm3m6tCOdfD4s91VpiG8zebcawpW34VHuDcDGBFFmhd9BVYEyTy6p3K3l1jMNbNkbxD0CYfkOJAGU/s826/02-ceedling.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit2Ae-5krstLh2Y6aOkGS1-BSLKOW1D0i5Y7QQaHhWclqQz7BTmWQQEAXtraGbOtPl5nu1_fkyQGNW1ynCOKEXNMPvG6r7K1mu8MmexeKcEHbGS5Rm3m6tCOdfD4s91VpiG8zebcawpW34VHuDcDGBFFmhd9BVYEyTy6p3K3l1jMNbNkbxD0CYfkOJAGU/s600/02-ceedling.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Hello Unity&lt;/u&gt;&lt;br /&gt;
In the previous &lt;a href=&quot;http://steveproxna.blogspot.com/2023/07/ebpf-programming-setup.html&quot;&gt;post&lt;/a&gt;, examples installed the &lt;a href=&quot;https://docs.kernel.org/bpf/libbpf/libbpf_overview.html&quot;&gt;libbpf&lt;/a&gt; C-based library.  Therefore, extend an example and write tests that invoke simple libbpf APIs, for example, &lt;i&gt;&lt;a href=&quot;https://github.com/libbpf/libbpf/blob/master/src/libbpf.c#L12828&quot;&gt;libbpf_num_possible_cpus&lt;/a&gt;&lt;/i&gt; directly using Unity framework.
&lt;br /&gt;&lt;br /&gt;
Launch CLion | New Project | C Executable | Location: &lt;b&gt;/home/stevepro/HelloUnity&lt;/b&gt; | Language std: C11
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKvgpLLXwwCZ8K5WXInspuYVs5SzmyYpshIWTroDvZyZrAXZf1DuHlnW35UKZLIfEFvUnaYc0LlheLMwog3A_ASjbcAJolneLRnQqI5fjrHRzzA3hqBYKHxeOU_j6pH5MZ_XkmHXqg7-bI-obfWoySGnqIjM5OlUXjVl17124JGE60ak6rUFZtktqtWLk/s704/HelloUnity.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKvgpLLXwwCZ8K5WXInspuYVs5SzmyYpshIWTroDvZyZrAXZf1DuHlnW35UKZLIfEFvUnaYc0LlheLMwog3A_ASjbcAJolneLRnQqI5fjrHRzzA3hqBYKHxeOU_j6pH5MZ_XkmHXqg7-bI-obfWoySGnqIjM5OlUXjVl17124JGE60ak6rUFZtktqtWLk/s600/HelloUnity.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Create
&lt;br /&gt;&lt;br /&gt;
Organize &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/tree/main/Sample/01-HelloUnity/src&quot;&gt;src&lt;/a&gt;&lt;/b&gt; and &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/tree/main/Sample/01-HelloUnity/test&quot;&gt;test&lt;/a&gt;&lt;/b&gt; directory structure.  Install &lt;a href=&quot;https://github.com/libbpf/libbpf&quot;&gt;libbpf&lt;/a&gt; beneath &lt;b&gt;src&lt;/b&gt; folder.  Rename main.c to &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Sample/01-HelloUnity/test/all_tests.c&quot;&gt;all_tests.c&lt;/a&gt; and move beneath test folder.  Update all prod and unit test code.  Complete &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Sample/01-HelloUnity/CMakeLists.txt&quot;&gt;CMakeLists.txt&lt;/a&gt; to include library files:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;cmake_minimum_required(VERSION 3.19)&lt;br /&gt;
&amp;nbsp;project(HelloUnity C)&lt;br /&gt;
&amp;nbsp;set(CMAKE_C_STANDARD 11)&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;include_directories(src/ /usr/local/include/unity/ src/include/libbpf/src)&lt;br /&gt;
&amp;nbsp;link_directories(/usr/local/lib/ src/include/libbpf/src/amd64)&lt;br /&gt;
&amp;nbsp;&lt;br /&gt;
&amp;nbsp;file(GLOB CODE_FILES src/*.c)&lt;br /&gt;
&amp;nbsp;file(GLOB TEST_FILES test/*.c)&lt;br /&gt;
&amp;nbsp;add_executable(HelloUnity ${CODE_FILES} ${TEST_FILES} )&lt;br /&gt;
&amp;nbsp;target_link_libraries(HelloUnity unity bpf elf z)&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Edit configurations | Run with root privileges | Set breakpoints | Press F5 to debug step thru source code.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMaNSjbjTkXJ3Ay0ZKh97qhd_04e82sGhBPvBYlsQkbnCpO9oJsaLrLiosCESn_oIOlu-f6VPu9N2ZPH6iiQuAkGCBCQXC_U8oJpVa8WOHP5T9h-U2YhJ0_1Mdhio88GWptXn03jZYnwFsTDAWnYalp44UoZeHksn_lTuL5NR4VpVrlZP0sROnSLZg3Fc/s993/10-HelloUnity.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMaNSjbjTkXJ3Ay0ZKh97qhd_04e82sGhBPvBYlsQkbnCpO9oJsaLrLiosCESn_oIOlu-f6VPu9N2ZPH6iiQuAkGCBCQXC_U8oJpVa8WOHP5T9h-U2YhJ0_1Mdhio88GWptXn03jZYnwFsTDAWnYalp44UoZeHksn_lTuL5NR4VpVrlZP0sROnSLZg3Fc/s600/10-HelloUnity.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Hello CMock&lt;/u&gt;&lt;br /&gt;
At the time of writing, there is currently no way to &lt;a href=&quot;https://www.youtube.com/watch?v=R8-GbeaIOwc&amp;t=1100s&quot;&gt;debug&lt;/a&gt; BPF programs&#39; source code interactively.  Therefore, we would like to attempt to &lt;a href=&quot;https://www.youtube.com/watch?v=vkYKXlTQ6cg&quot;&gt;mock&lt;/a&gt; BPF programs or at least underlying C sourc code somehow using CMock.
&lt;br /&gt;&lt;br /&gt;
Follow the example &lt;a href=&quot;https://spin.atomicobject.com/2019/02/07/cmock-get-started&quot;&gt;Spin up CMock&lt;/a&gt;.  This article uses Ceedling to automate project setup and generate mocks but we will complete the following manually first to better understand the process.  Original code found &lt;a href=&quot;https://github.com/joaniedavis/cmock_example&quot;&gt;here&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Open folder &lt;b&gt;/home/stevepro/&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/tree/main/Sample/02-HelloCMock&quot;&gt;HelloCMock&lt;/a&gt;&lt;/b&gt;.  Copy inc/&lt;a href=&quot;https://github.com/joaniedavis/cmock_example/blob/master/inc/rectangle.h&quot;&gt;rectangle.h&lt;/a&gt; + &lt;a href=&quot;https://github.com/joaniedavis/cmock_example/blob/master/project.yml&quot;&gt;project.yml&lt;/a&gt;.  Execute mock command:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;ruby ~/GitHub/ThrowTheSwitch/cmock/lib/cmock.rb -oproject.yml inc/rectangle.h&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
This creates &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/tree/main/Sample/02-HelloCMock/mocks&quot;&gt;mocks&lt;/a&gt; folder two corresponding files: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Sample/02-HelloCMock/mocks/mock_rectangle.h&quot;&gt;mock_rectangle.h&lt;/a&gt; and &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Sample/02-HelloCMock/mocks/mock_rectangle.c&quot;&gt;mock_rectangle.c&lt;/a&gt;.  Notice we did not attempt to use CLion as is not currently &lt;a href=&quot;https://groups.google.com/g/throwtheswitch/c/dbPNtBZ_84M/m/0_qZaa4KAgAJ?pli=1&quot;&gt;integrated&lt;/a&gt;; any attempt may produce Multiple Definition &lt;a href=&quot;https://github.com/ThrowTheSwitch/CMock/issues/97&quot;&gt;issue&lt;/a&gt;!
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Hello Ceedling&lt;/u&gt;&lt;br /&gt;
Complete previous &lt;a href=&quot;https://github.com/joaniedavis/cmock_example&quot;&gt;example&lt;/a&gt; but this time try Ceedling using the &lt;a href=&quot;https://spin.atomicobject.com/2019/02/07/cmock-get-started&quot;&gt;article&lt;/a&gt; as a guideline:  Launch the Terminal:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;cd $HOME&lt;br /&gt;
&amp;nbsp;ceedling new HelloCeedling&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Copy all project files into &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/tree/main/Sample/03-HelloCeedling/src&quot;&gt;src&lt;/a&gt;&lt;/b&gt; and &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/tree/main/Sample/03-HelloCeedling/test&quot;&gt;test&lt;/a&gt;&lt;/b&gt; directories.  Include &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/tree/main/Sample/03-HelloCeedling/inc&quot;&gt;inc&lt;/a&gt;&lt;/b&gt; and update &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Sample/03-HelloCeedling/project.yml&quot;&gt;project.yml&lt;/a&gt; with the inc directory:
&lt;br /&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
  :paths:
  :test:
    - +:test/**
    - -:test/support
  :source:
    - src/**
  :include:
    - inc/**
  :support:
    - test/support
  :libraries: []
&lt;/pre&gt;
&lt;br /&gt;
Run tests manually simply by typing &lt;b&gt;ceedling&lt;/b&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_iEa91TFucjzWcbM9xPGQ9_TykLVhnHPhqjQ71tgOtcDkMNzeBgr0xUXPOk9-UwomMEaIowbWKkzbjM7VRP_5Ra9HRbzJhmz0gi-HhDCr052e2pmpyJDjsTLEGld1YIMk-RhJn4IX3pWxPUHlS9ALyjIsX_LVPU2XjE_tQzr-fUF2Tz_9SHGZTZ1J4rw/s468/ceedling_run.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_iEa91TFucjzWcbM9xPGQ9_TykLVhnHPhqjQ71tgOtcDkMNzeBgr0xUXPOk9-UwomMEaIowbWKkzbjM7VRP_5Ra9HRbzJhmz0gi-HhDCr052e2pmpyJDjsTLEGld1YIMk-RhJn4IX3pWxPUHlS9ALyjIsX_LVPU2XjE_tQzr-fUF2Tz_9SHGZTZ1J4rw/s600/ceedling_run.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Debug tests &lt;a href=&quot;https://stackoverflow.com/questions/41488664/how-to-use-gdb-with-ceedling&quot;&gt;interactively&lt;/a&gt; with GDB as follows: Launch VS Code.  Press F5 to add &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Sample/03-HelloCeedling/.vscode/launch.json&quot;&gt;launch.json&lt;/a&gt; file to complete:
&lt;br /&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
{
    &quot;version&quot;: &quot;0.2.0&quot;,
    &quot;configurations&quot;: [
        {
            &quot;name&quot;: &quot;ceedling_gdb&quot;,
            &quot;type&quot;: &quot;cppdbg&quot;,
            &quot;request&quot;: &quot;launch&quot;,
            &quot;program&quot;: &quot;${workspaceFolder}/build/test/out/test_shape_container.out&quot;,
            &quot;args&quot;: [],
            &quot;stopAtEntry&quot;: false,
            &quot;cwd&quot;: &quot;${workspaceFolder}&quot;,
            &quot;environment&quot;: [],
            &quot;externalConsole&quot;: true,
            &quot;MIMode&quot;: &quot;gdb&quot;,
            &quot;miDebuggerPath&quot;: &quot;/usr/bin/gdb&quot;,
            &quot;setupCommands&quot;: [
                {
                    &quot;description&quot;: &quot;Enable pretty-printing for gdb&quot;,
                    &quot;text&quot;: &quot;-enable-pretty-printing&quot;,
                    &quot;ignoreFailures&quot;: true
                }
            ]
        }
    ]
}
&lt;/pre&gt;
Set breakpoint in &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Sample/03-HelloCeedling/test/test_shape_container.c&quot;&gt;test_shape_container.c&lt;/a&gt; | Press F5 to debug step thru source code:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgepgDmDhtm0w9zbAv9okSiXRIEM-mwTSv3h1sl_mYW-yYMmrqomBXFp7AHeuskwzzG0JDq2pDTJO40-M-O8BU-CfOxf0DRpNGoTfHOncWjQdst_JnFhp_oPPjXsr0VfnBPHaU2GZIYNE-JsvS18NFEJPZ3J1PShAFGQgcEQ_X0ZF7pZUu-OMSCkK1x0cg/s1391/10-ceedling.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgepgDmDhtm0w9zbAv9okSiXRIEM-mwTSv3h1sl_mYW-yYMmrqomBXFp7AHeuskwzzG0JDq2pDTJO40-M-O8BU-CfOxf0DRpNGoTfHOncWjQdst_JnFhp_oPPjXsr0VfnBPHaU2GZIYNE-JsvS18NFEJPZ3J1PShAFGQgcEQ_X0ZF7pZUu-OMSCkK1x0cg/s600/10-ceedling.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
According to &lt;a href=&quot;https://chat.openai.com&quot;&gt;ChatGPT&lt;/a&gt;, eBPF is versatile technology that allows safe and efficient code execution within the Linux kernel without requiring modification of kernel code.  This feature makes it attractive for applications including network packet filtering, security, logging + tracing, monitoring, and performance optimization.
&lt;br /&gt;&lt;br /&gt;
In summary, while eBPF is a valuable addition to the Linux ecosystem, it is not expected to replace kernel development.  Instead, eBPF complements this by currently providing a flexible and efficient way to extend specific kernel features.  Therefore, it will be interesting to see if this technology is dominant in the &lt;a href=&quot;https://www.youtube.com/watch?v=hCixFexl9YU&quot;&gt;future&lt;/a&gt;.
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2023/08/ebpf-programming-sample.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglM6Dz0JhtGBagI4XR-6pkK1OnpsQQKcemem2ArVYzyS3jI3LPC772Rk6mh00XUanwrZhbE7f1oe6krSRXGPJhoybEUFDt2_64jnx-oEJm_4d0vQMY8AZzElYQTIJm5tEez4qQGeRkYz3a1e0D29_cWlDMjF_L2xdrr9bATfv4aKQUeU6m5AmFUTsv9oI/s72-c/EBPF_logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-7423285052868666419</guid><pubDate>Tue, 04 Jul 2023 09:00:00 +0000</pubDate><atom:updated>2023-08-31T02:26:24.918-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">eBPF</category><title>eBPF Programming Setup</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
Extended Berkeley Packet Filter [&lt;b&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/EBPF&quot;&gt;eBPF&lt;/a&gt;&lt;/b&gt;] is a technology that runs sandboxed programs in privileged context like the OS kernel to safely and efficiently extend the capabilities of the kernel at runtime without requiring changes to the kernel source code.  &lt;a href=&quot;https://docs.kernel.org/bpf/libbpf/libbpf_overview.html&quot;&gt;libbpf&lt;/a&gt; is a C-based library that takes compiled BPF object files and loads and verifies them into the kernel attachiing BPF programs to various kernel hooks and execute custom code.
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglM6Dz0JhtGBagI4XR-6pkK1OnpsQQKcemem2ArVYzyS3jI3LPC772Rk6mh00XUanwrZhbE7f1oe6krSRXGPJhoybEUFDt2_64jnx-oEJm_4d0vQMY8AZzElYQTIJm5tEez4qQGeRkYz3a1e0D29_cWlDMjF_L2xdrr9bATfv4aKQUeU6m5AmFUTsv9oI/s850/EBPF_logo.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglM6Dz0JhtGBagI4XR-6pkK1OnpsQQKcemem2ArVYzyS3jI3LPC772Rk6mh00XUanwrZhbE7f1oe6krSRXGPJhoybEUFDt2_64jnx-oEJm_4d0vQMY8AZzElYQTIJm5tEez4qQGeRkYz3a1e0D29_cWlDMjF_L2xdrr9bATfv4aKQUeU6m5AmFUTsv9oI/s600/EBPF_logo.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Let&#39;s check it out! 
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Software&lt;/u&gt;&lt;br /&gt;
Follow all instructions from the previous &lt;a href=&quot;http://steveproxna.blogspot.com/2019/10/linux-setup-cheat-sheet-ii.html&quot;&gt;post&lt;/a&gt; to install &lt;b&gt;CLion&lt;/b&gt; and &lt;b&gt;VS Code&lt;/b&gt; on Ubuntu Linux.  Also install the &lt;b&gt;&lt;a href=&quot;https://man.archlinux.org/man/bpftool.8.en&quot;&gt;bpftool&lt;/a&gt;&lt;/b&gt; which was added to the 2017 Linux kernel as a user space utility to introspect the eBPF subsystem.
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git&lt;br /&gt;
&amp;nbsp;cd linux&lt;br /&gt;
&amp;nbsp;cd tools/bpf/bpftool&lt;br /&gt;
&amp;nbsp;make&lt;br /&gt;
&amp;nbsp;sudo make install&lt;br /&gt;
&amp;nbsp;bpftool version
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyg5CqVJShDhLkZWgf2zJNr3HNQjgCWTCGHvgNbQwsLVvxovYtPeZcMAvsoiq-RnRu7k9eouptdbJNPtRF1-j3O8-b2_cRgqiNDyLBUvezizXNGzoKVnwqCHLLnUL8XbNWr7wXjoyMru2Ut67e9FoxgWq5zUuV_MQb68pVItRUN26Izni0SL85nP7ypx0/s1078/01-bpftool.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyg5CqVJShDhLkZWgf2zJNr3HNQjgCWTCGHvgNbQwsLVvxovYtPeZcMAvsoiq-RnRu7k9eouptdbJNPtRF1-j3O8-b2_cRgqiNDyLBUvezizXNGzoKVnwqCHLLnUL8XbNWr7wXjoyMru2Ut67e9FoxgWq5zUuV_MQb68pVItRUN26Izni0SL85nP7ypx0/s600/01-bpftool.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzmYlxCUky6tGUQNQ-u8iOFKcNhDT1Pv93XvdJplY6ygE4rCD5SfWg3mMIJaOeIBNBEjeycUc4yoAvsC4xGMecJ_eFLRaQg6huDwyfaqXw6w37qfWzIGCR5C0QAqLqcsvmqTFpf0qOXyx5SiSQY5DQyHAJHhLcoYt9POs3yeJudjCfZ9hniMwvaJe4BnQ/s817/02-bpftool.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzmYlxCUky6tGUQNQ-u8iOFKcNhDT1Pv93XvdJplY6ygE4rCD5SfWg3mMIJaOeIBNBEjeycUc4yoAvsC4xGMecJ_eFLRaQg6huDwyfaqXw6w37qfWzIGCR5C0QAqLqcsvmqTFpf0qOXyx5SiSQY5DQyHAJHhLcoYt9POs3yeJudjCfZ9hniMwvaJe4BnQ/s600/02-bpftool.png&quot;/&gt;&lt;/a&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJfo8_H0gZmK3uAYKymCOA2WJwSnIE3UFlO127Kj70oyUNXXcvIGDieRmo6P2w9KWSmm4kIADIWCPs4i0kSENosda6p97HGVkJnkKWToPaNe1H-KHSA0c5CW-PgB_fm0dlXVvWq9FsQwUGd5uha1dBsWFsvLtwlNdOjowpc1wHzM9GnuE1iyEXQm9Kh3Y/s817/03-bpftool.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJfo8_H0gZmK3uAYKymCOA2WJwSnIE3UFlO127Kj70oyUNXXcvIGDieRmo6P2w9KWSmm4kIADIWCPs4i0kSENosda6p97HGVkJnkKWToPaNe1H-KHSA0c5CW-PgB_fm0dlXVvWq9FsQwUGd5uha1dBsWFsvLtwlNdOjowpc1wHzM9GnuE1iyEXQm9Kh3Y/s600/03-bpftool.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Alternatively, download &lt;b&gt;&lt;a href=&quot;https://man.archlinux.org/man/bpftool.8.en&quot;&gt;bpftool&lt;/a&gt;&lt;/b&gt; binary from the Github &lt;a href=&quot;https://github.com/libbpf/bpftool/releases&quot;&gt;releases&lt;/a&gt; and extract into &lt;b&gt;/usr/local/bin&lt;/b&gt; directory.
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Hello World&lt;/u&gt;&lt;br /&gt;
Create your first BPF &lt;a href=&quot;https://github.com/sartura/ebpf-hello-world&quot;&gt;program&lt;/a&gt; using this simple eBPF &lt;a href=&quot;https://nakryiko.com/posts/bpf-core-reference-guide&quot;&gt;CO-RE&lt;/a&gt; &lt;a href=&quot;https://www.sartura.hr/blog/simple-ebpf-core-application&quot;&gt;application&lt;/a&gt; as a reference however using CLion.  Launch CLion | New Project | C Executable | Location: &lt;b&gt;/home/stevepro/HelloWorld&lt;/b&gt; | Language std: &lt;b&gt;C11&lt;/b&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx1jnPxY9wKeLiBxiWSdHs7nGqOys4cryU1sEMkwvjEYP9vDeN83YAOEV3oE5igHbamVKTFF-iyUSPBijQ_cN8T1LUEZod4BwnpFMt6IzASsQFDhJEiYjFWHnYDmnT7woVQ8BBrNVrxsuXR8Ybf7Voi1wjNY7jUatuu092Qb2iybxjHat2tNg4GH0E/s800/HelloWorld01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx1jnPxY9wKeLiBxiWSdHs7nGqOys4cryU1sEMkwvjEYP9vDeN83YAOEV3oE5igHbamVKTFF-iyUSPBijQ_cN8T1LUEZod4BwnpFMt6IzASsQFDhJEiYjFWHnYDmnT7woVQ8BBrNVrxsuXR8Ybf7Voi1wjNY7jUatuu092Qb2iybxjHat2tNg4GH0E/s600/HelloWorld01.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Create
&lt;br /&gt;&lt;br /&gt;
A new C project will be created which automatically adds the following two files: main.c and CMakeLists.txt
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;main.c
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;CMakeLists.txt
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;99%&quot;&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;#include &amp;lt;stdio.h&amp;gt;
&amp;nbsp;int main()
&amp;nbsp;{
&amp;nbsp;  printf( &quot;Hello, World!\n&quot; );
&amp;nbsp;  return 0;
&amp;nbsp;}
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;99%&quot;&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;cmake_minimum_required(VERSION 3.19)
&amp;nbsp;project(HelloWorld C)
&amp;nbsp;
&amp;nbsp;set(CMAKE_C_STANDARD 11)
&amp;nbsp;
&amp;nbsp;add_executable(HelloWorld main.c)
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
In the Terminal window within CLion IDE enter the following commands to install and buld the &lt;a href=&quot;https://github.com/libbpf/libbpf&quot;&gt;libbpf&lt;/a&gt; library:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;git clone https://github.com/libbpf/libbpf&lt;br /&gt;
&amp;nbsp;cd libbpf/src&lt;br /&gt;
&amp;nbsp;make&lt;br /&gt;
&amp;nbsp;sudo make install&lt;br /&gt;
&amp;nbsp;cd ../..&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Next, enter commands to create the &lt;a href=&quot;https://blog.aquasec.com/vmlinux.h-ebpf-programs&quot;&gt;vmlinux.h&lt;/a&gt; file.  Create and build the Hello BPF program + skeleton file:
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&amp;nbsp;bpftool btf dump file /sys/kernel/btf/vmlinux format c &gt; vmlinux.h&lt;br /&gt;
&amp;nbsp;touch hello.bpf.c&lt;br /&gt;
&amp;nbsp;clang -g -O2 -target bpf -D__TARGET_ARCH_x86_64 -I libbpf/src -c hello.bpf.c -o hello.bpf.o&lt;br /&gt;
&amp;nbsp;bpftool gen skeleton hello.bpf.o &gt; hello.skel.h&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/01-HelloWorld/hello.bpf.c&quot;&gt;hello.bpf.c&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/01-HelloWorld/CMakeLists.txt&quot;&gt;CMakeLists.txt&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;99%&quot;&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;#include &quot;vmlinux.h&quot;
&amp;nbsp;#include &quot;bpf_helpers.h&quot;
&amp;nbsp;
&amp;nbsp;SEC(&quot;tracepoint/syscalls/sys_enter_execve&quot;)
&amp;nbsp;int hello_bpf(struct trace_event_raw_sys_enter *ctx)
&amp;nbsp;{
&amp;nbsp;  bpf_printk(&quot;Hello world!\n&quot;);
&amp;nbsp;  return 0;
&amp;nbsp;}
&amp;nbsp;char LICENSE[] SEC(&quot;license&quot;) = &quot;GPL&quot;;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;99%&quot;&gt;
&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;
&amp;nbsp;cmake_minimum_required(VERSION 3.19)
&amp;nbsp;project(HelloWorld C)
&amp;nbsp;
&amp;nbsp;set(CMAKE_C_STANDARD 11)
&amp;nbsp;
&amp;nbsp;include_directories(.)
&amp;nbsp;link_directories(libbpf libbpf/src)
&amp;nbsp;
&amp;nbsp;add_executable(HelloWorld main.c)
&amp;nbsp;target_link_libraries(HelloWorld bpf elf z)
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
Rename main.c to &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/01-HelloWorld/hello.c&quot;&gt;hello.c&lt;/a&gt; and update the driver program code.  Edit configurations | Run with root privileges
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSzYLhQDy1CIQWyE_mU13bb_WEJjCLeGrwqN4blumS2PnyALwJHMoEY90Y9PeCLUp1zDTN7g_QwmbcUEuQWsEMVwhgvxHOdtn9JMLkRsxgVW9MFlVEXhS9dlHHTL9WsIE9vqT4xuOj_mPdnQn1aBjcJYke3cJcp4aq_FaU5tfWlM_14jG7P7dpHrnS/s844/HelloWorld03.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSzYLhQDy1CIQWyE_mU13bb_WEJjCLeGrwqN4blumS2PnyALwJHMoEY90Y9PeCLUp1zDTN7g_QwmbcUEuQWsEMVwhgvxHOdtn9JMLkRsxgVW9MFlVEXhS9dlHHTL9WsIE9vqT4xuOj_mPdnQn1aBjcJYke3cJcp4aq_FaU5tfWlM_14jG7P7dpHrnS/s600/HelloWorld03.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
Set break point in &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/01-HelloWorld/hello.c&quot;&gt;hello.c&lt;/a&gt; | HelloWorld | Debug or Press F5 to launch your first Hello World BPF program!
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikCEtyl0dPlR4FSyipBBhsFTk0ajre60fNXd5gCmLqhizoFEzk7vzepmd0hN26zIeHDIf8Fh8qxa45ibS5WGAZUZuvjPvbEol5ONna6RpSXUzHlDKGLA4SjApTY3MphH4TMa8bsSfATHb8Y5iri8EBo7MFzjRr8CgQh9t6bqWLhabjFJJMa9HQOaLx/s941/HelloWorld04.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikCEtyl0dPlR4FSyipBBhsFTk0ajre60fNXd5gCmLqhizoFEzk7vzepmd0hN26zIeHDIf8Fh8qxa45ibS5WGAZUZuvjPvbEol5ONna6RpSXUzHlDKGLA4SjApTY3MphH4TMa8bsSfATHb8Y5iri8EBo7MFzjRr8CgQh9t6bqWLhabjFJJMa9HQOaLx/s600/HelloWorld04.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
IMPORTANT you can tail BPF output in Terminal window: &lt;i&gt;sudo cat /sys/kernel/debug/tracing/trace_pipe&lt;/i&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Hello Maps&lt;/u&gt;&lt;br /&gt;
BPF &lt;a href=&quot;https://docs.kernel.org/bpf/maps.html&quot;&gt;maps&lt;/a&gt; are generic structures for storing different types of data accessible between kernel + user space.  Launch CLion | New Project | C Executable | Location: &lt;b&gt;/home/stevepro/HelloMaps&lt;/b&gt; | Language std: &lt;b&gt;C11&lt;/b&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkok-druaSYapIJC585J9LAnqubq-4yfXYO7k4MNYj_p1sTaP8fUW-MVZHsRtjbF85bw9gLZ9xaktcEG70vRbT6aBI0js1Tg4EZ5yrPT0Gzevqz165X9d_LvYsMFwFz8GmvH71sgX1bxcW8gdwZMt2BpePt03ADFDw4mjXr9KRyVbzwpz7zYGCKQCKZ9A/s800/HelloMaps01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkok-druaSYapIJC585J9LAnqubq-4yfXYO7k4MNYj_p1sTaP8fUW-MVZHsRtjbF85bw9gLZ9xaktcEG70vRbT6aBI0js1Tg4EZ5yrPT0Gzevqz165X9d_LvYsMFwFz8GmvH71sgX1bxcW8gdwZMt2BpePt03ADFDw4mjXr9KRyVbzwpz7zYGCKQCKZ9A/s600/HelloMaps01.png&quot;/&gt;&lt;/a&gt;
&lt;br/&gt;
Create
&lt;br /&gt;&lt;br /&gt;
Repeat the process similar to Hello World: Install the &lt;a href=&quot;https://github.com/libbpf/libbpf&quot;&gt;libbpf&lt;/a&gt; library.  Create the vmlinux &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/02-HelloMaps/vmlinux.h&quot;&gt;header&lt;/a&gt; file, the Maps BPF &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/02-HelloMaps/maps.bpf.c&quot;&gt;program&lt;/a&gt; and driver &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/02-HelloMaps/maps.c&quot;&gt;code&lt;/a&gt;.  Compile code.  Update the &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/01-HelloWorld/02-HelloMaps/CMakeLists.txt&quot;&gt;CMakeLists&lt;/a&gt; build script and Run with root privileges:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJFq4g30RU4htG_2w6Mu3hdqGVTNVsSrw8lbIGztwNdlKnJe52RpQrlYLd9EvHGCB4Yz_yz4ru4Dko2e4VNUmmX2Z_eBDNan6MMP26BP21ltHM2FtxiXT7YHHVxZI5wigBFqzsdMU8fi7Aa9o8FAHrWXGqRBZ2sF9dJ7Gg0rLjS4JMXzLL7MVQ35PQFGs/s941/HelloMaps02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJFq4g30RU4htG_2w6Mu3hdqGVTNVsSrw8lbIGztwNdlKnJe52RpQrlYLd9EvHGCB4Yz_yz4ru4Dko2e4VNUmmX2Z_eBDNan6MMP26BP21ltHM2FtxiXT7YHHVxZI5wigBFqzsdMU8fi7Aa9o8FAHrWXGqRBZ2sF9dJ7Gg0rLjS4JMXzLL7MVQ35PQFGs/s600/HelloMaps02.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;libbpf-bootstrap&lt;/u&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap&quot;&gt;libbpf-bootstrap&lt;/a&gt; provides a starting point for building your own BPF applications with things like BPF Compile Once-Run Everywhere [&lt;a href=&quot;https://nakryiko.com/posts/bpf-core-reference-guide&quot;&gt;CO-RE&lt;/a&gt;] and &lt;a href=&quot;https://blog.aquasec.com/vmlinux.h-ebpf-programs&quot;&gt;vmlinux.h&lt;/a&gt;.  Numerous more BPF &lt;a href=&quot;https://github.com/torvalds/linux/tree/master/samples/bpf&quot;&gt;samples&lt;/a&gt; can be found at the Linux repo. 
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/01-minimal/minimal.bpf.c&quot;&gt;minimal&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/minimal.bpf.c&quot;&gt;minimal&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/02-minimal_ns/minimal_ns.bpf.c&quot;&gt;minimal_ns&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/minimal_ns.bpf.c&quot;&gt;minimal_ns&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/03-minimal_legacy/minimal_legacy.bpf.c&quot;&gt;minimal_legacy&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/minimal_legacy.bpf.c&quot;&gt;minimal_legacy&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/04-bootstrap/bootstrap.bpf.c&quot;&gt;bootstrap&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/bootstrap.bpf.c&quot;&gt;bootstrap&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/05-uprobe/uprobe.bpf.c&quot;&gt;uprobe&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/uprobe.bpf.c&quot;&gt;uprobe&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/06-usdt/usdt.bpf.c&quot;&gt;usdt&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/usdt.bpf.c&quot;&gt;usdt&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/07-fentry/fentry.bpf.c&quot;&gt;fentry&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/fentry.bpf.c&quot;&gt;fentry&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/08-kprobe/kprobe.bpf.c&quot;&gt;kprobe&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/kprobe.bpf.c&quot;&gt;kprobe&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/09-ksyscall/ksyscall.bpf.c&quot;&gt;ksyscall&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/ksyscall.bpf.c&quot;&gt;ksyscall&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/10-tc/tc.bpf.c&quot;&gt;tc&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/tc.bpf.c&quot;&gt;tc&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/11-profile/profile.bpf.c&quot;&gt;profile&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/profile.bpf.c&quot;&gt;profile&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;CUSTOM: &lt;a href=&quot;https://github.com/SteveProXNA/eBPFcode/blob/main/Setup/02-libbpf-bootstrap/12-sockfilter/sockfilter.bpf.c&quot;&gt;sockfilter&lt;/a&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;SOURCE: &lt;a href=&quot;https://github.com/libbpf/libbpf-bootstrap/blob/master/examples/c/sockfilter.bpf.c&quot;&gt;sockfilter&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
Although &lt;a href=&quot;https://docs.kernel.org/bpf/libbpf/libbpf_overview.html&quot;&gt;libbpf&lt;/a&gt; allows BPF programs to be loaded, verified and attached to various kernel hooks and execute custom code there is currently no way to &lt;a href=&quot;https://www.youtube.com/watch?v=R8-GbeaIOwc&amp;t=1100s&quot;&gt;debug&lt;/a&gt; BPF programs&#39; source code interactively.  Therefore, this now presents alternatives to explore unit testing and &lt;a href=&quot;https://www.youtube.com/watch?v=vkYKXlTQ6cg&quot;&gt;mock&lt;/a&gt; BPF programs.  This will be the topic of the next &lt;a href=&quot;https://steveproxna.blogspot.com/2023/08/ebpf-programming-sample.html&quot;&gt;post&lt;/a&gt;.
&lt;/span&gt;</description><link>http://steveproxna.blogspot.com/2023/07/ebpf-programming-setup.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglM6Dz0JhtGBagI4XR-6pkK1OnpsQQKcemem2ArVYzyS3jI3LPC772Rk6mh00XUanwrZhbE7f1oe6krSRXGPJhoybEUFDt2_64jnx-oEJm_4d0vQMY8AZzElYQTIJm5tEez4qQGeRkYz3a1e0D29_cWlDMjF_L2xdrr9bATfv4aKQUeU6m5AmFUTsv9oI/s72-c/EBPF_logo.png" height="72" width="72"/><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8584570627780730363.post-3936774243674099145</guid><pubDate>Thu, 01 Jun 2023 07:07:00 +0000</pubDate><atom:updated>2024-11-18T12:08:49.520-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Master System</category><title>Sega Console Game Port</title><description>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;
In 2017, we checked out &lt;a href=&quot;http://steveproxna.blogspot.com/2017/09/devkitsms-programming-setup.html&quot;&gt;devkitSMS Programming Setup&lt;/a&gt; to build code in C for the 8-bit Sega Master System.  Then, in 2020, we checked out &lt;a href=&quot;http://steveproxna.blogspot.com/2020/09/sgdk-programming-setup.html&quot;&gt;SGDK Programming Setup&lt;/a&gt; to build code in C for the 16-bit Sega Mega Drive.
&lt;br /&gt;&lt;br /&gt;
Leveraging this knowledge, we would now like to &lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport&quot;&gt;port&lt;/a&gt; existing code built for the 8-bit Sega Master System, for example, &lt;a href=&quot;https://github.com/SteveProXNA/SimpsonsTriviaSMS&quot;&gt;Simpsons Trivia SMS&lt;/a&gt; to the 16-bit Mega Drive &lt;a href=&quot;https://github.com/SteveProXNA/SimpsonsTriviaMD&quot;&gt;Simpsons Trivia MD&lt;/a&gt; and document the process.
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;&amp;nbsp;&lt;b&gt;SEGA MASTER SYSTEM&lt;/b&gt;&amp;nbsp;[256 x 192]&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;&amp;nbsp;&lt;b&gt;SEGA MEGA DRIVE&lt;/b&gt;&amp;nbsp;[320 x 224]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOQAur4QBLkqjekg11RwWNsadVo5TVKOuk3NebMs-4FS-mUuPUZGW31IC8EpbQjs9yX0FGq3GVyz2kVCnRgAomWGE-65dAz6aMNxKmsO5Th7kkhHfrONqDvhllTzFKyoP6rrd-l_w2vbrDVRX8gcl2BlTFZSz4YE_1Lw9Y4Hufg5EcDW8mCtcFcgLJ/s642/SimpsonsSMS.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOQAur4QBLkqjekg11RwWNsadVo5TVKOuk3NebMs-4FS-mUuPUZGW31IC8EpbQjs9yX0FGq3GVyz2kVCnRgAomWGE-65dAz6aMNxKmsO5Th7kkhHfrONqDvhllTzFKyoP6rrd-l_w2vbrDVRX8gcl2BlTFZSz4YE_1Lw9Y4Hufg5EcDW8mCtcFcgLJ/s600/SimpsonsSMS.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjg5t66uT1DuU7FevlSXuMKYr1FZYdhGul7mzAMJHpG0rdmOH2-OnY7xH0CfwENj4zsV2qJTVVoEu3UyLpxDaeLStWWVm8yiQWLi1QUlvjNrDT3EJHe9o_OBwtejr8l6dK79G_dPubimf8dwuXBI9-B4ihSOWaBOltki1hkeQ54DWAJ9jDf0nrb-vbP/s642/SimpsonsMD.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjg5t66uT1DuU7FevlSXuMKYr1FZYdhGul7mzAMJHpG0rdmOH2-OnY7xH0CfwENj4zsV2qJTVVoEu3UyLpxDaeLStWWVm8yiQWLi1QUlvjNrDT3EJHe9o_OBwtejr8l6dK79G_dPubimf8dwuXBI9-B4ihSOWaBOltki1hkeQ54DWAJ9jDf0nrb-vbP/s600/SimpsonsMD.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;tr&gt;
&lt;/table&gt;
&lt;!--&lt;br /&gt;--&gt;
Let&#39;s check it out!
&lt;br /&gt;&lt;br /&gt;
&lt;u&gt;Software&lt;/u&gt;&lt;br /&gt;
Follow most instructions from the previous &lt;a href=&quot;https://steveproxna.blogspot.com/2020/09/sgdk-programming-setup.html&quot;&gt;post&lt;/a&gt;: this documents how to setup some pre-requisite software.
&lt;br /&gt;&lt;br /&gt;
Here is a summary of some of the software to be installed:
&lt;br /&gt;
&lt;table width=&quot;98%&quot; border=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Name&lt;/b&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Version&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C IDE Editor&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://my.visualstudio.com/Downloads?q=visual%20studio%202015&amp;wt.mc_id=o~msft~vscom~older-downloads&quot;&gt;Visual Studio 2015&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Emulators&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp&lt;a href=&quot;https://retrocdn.net/images/6/6c/Fusion364.7z&quot;&gt;Fusion&lt;/a&gt;, &lt;a href=&quot;https://retrocdn.net/images/4/43/Gens_KMod_v0.7.3.7z&quot;&gt;Gens KMod&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Name&lt;/b&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;b&gt;Version&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Cross compiler&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;https://gcc.gnu.org/&quot;&gt;GCC&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Make files&lt;/td&gt;&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;&lt;a href=&quot;http://cygwin.com/install.html&quot;&gt;Cygwin&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Setup Project&lt;/u&gt;&lt;br /&gt;
Create folder C:\&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/01-SetupProject&quot;&gt;SimpsonsTriviaMD&lt;/a&gt;.  Copy new SGDK custom library &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDK_Library/Library/lib&quot;&gt;lib&lt;/a&gt;&lt;/b&gt; folder  here. Create sub-folder: &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKdemos/01-HelloWorld/dev&quot;&gt;dev&lt;/a&gt;&lt;/b&gt;.  Change directory to dev folder and create the following sub-folders as indicated per &lt;a href=&quot;https://github.com/Stephane-D/SGDK/wiki/SGDK-Usage&quot;&gt;Usage&lt;/a&gt;: &lt;i&gt;inc&lt;/i&gt;, &lt;i&gt;out&lt;/i&gt;, &lt;i&gt;res&lt;/i&gt;, &lt;i&gt;src&lt;/i&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKLMvBD-jxIt4sZiO_5Ww38Rs374dYS4stLbED54ntmcLV3-1dSn3LvFs4ySYOxdDPDoOwXPtSmD0f7cEYahCaUB3euGbMAwaYKtJ0Lycx59b-Fc_y_mfL2upOzhwSkw4UTSWSJOOQrINMJWe2s-s9uE1BYbTAPZiHHTMRlGC7fFVwlLq3LrTEVbVG/s736/SetupProject01.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKLMvBD-jxIt4sZiO_5Ww38Rs374dYS4stLbED54ntmcLV3-1dSn3LvFs4ySYOxdDPDoOwXPtSmD0f7cEYahCaUB3euGbMAwaYKtJ0Lycx59b-Fc_y_mfL2upOzhwSkw4UTSWSJOOQrINMJWe2s-s9uE1BYbTAPZiHHTMRlGC7fFVwlLq3LrTEVbVG/s600/SetupProject01.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
Launch Visual Studio 2015.  File | New | Project... | Visual C++ | Win32 | Win32 Project
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ_ZdaaDQiW9Ikrf0FgoEP2k1IVJRyC9N8hsOcf2tBab-LVa66z3zKs9GXk2K6C1x9DvKMO7_6pRC9M0nU8_hyMzVS2XQEU0eR8ksWfCUH8DSQKRxb54QdJh5kpbQBGm7YUvoN7kuV0o6LjYgCcxxVGQDzkfvqE37lM1tVpoDXu5xnNy3PLsssOUYT/s829/SetupProject02.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ_ZdaaDQiW9Ikrf0FgoEP2k1IVJRyC9N8hsOcf2tBab-LVa66z3zKs9GXk2K6C1x9DvKMO7_6pRC9M0nU8_hyMzVS2XQEU0eR8ksWfCUH8DSQKRxb54QdJh5kpbQBGm7YUvoN7kuV0o6LjYgCcxxVGQDzkfvqE37lM1tVpoDXu5xnNy3PLsssOUYT/s600/SetupProject02.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;33%&quot;&gt;&amp;nbsp;Name:&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;66%&quot;&gt;&amp;nbsp;Game&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Location:&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;C:\SimpsonsTriviaMD\dev&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;33%&quot;&gt;&amp;nbsp;Create directory for solution&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;66%&quot;&gt;&amp;nbsp;UNCHECKED&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
OK
&lt;br /&gt;&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;33%&quot;&gt;&amp;nbsp;Application type:&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;66%&quot;&gt;&amp;nbsp;Console application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;33%&quot;&gt;&amp;nbsp;Additional options:&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;66%&quot;&gt;&amp;nbsp;Empty project CHECKED&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
Finish
&lt;br /&gt;
&lt;br /&gt;
First, remove x64 build configuration!  Right click Solution | Properties.  Click Configuration Manager button.  Click Active solution platform drop down | Edit.  Click x64 option | Remove.  Now will have only Win32 build.
&lt;br /&gt;
&lt;br /&gt;
Right click Project | Properties | Configuration Properties | General.  Set Output and Intermediate directories:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL-ifStLxp7baQOVK_R95f7K6cSqiUx_Tvl87bwo_RLR6DyovLYLfx9_WT3MOYMz4NJPb0Bdq_rMXNOxiIgDDBwzNqcAPB6xnZyvQH1xpV10EZNcXObtwhl3WrWxF-b771OfXPHFtWR0WtmQkV_f0y6JsUSUCX1SFi-C-ichxtBu_QhMW9HColkgrJ/s921/SetupProject03.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL-ifStLxp7baQOVK_R95f7K6cSqiUx_Tvl87bwo_RLR6DyovLYLfx9_WT3MOYMz4NJPb0Bdq_rMXNOxiIgDDBwzNqcAPB6xnZyvQH1xpV10EZNcXObtwhl3WrWxF-b771OfXPHFtWR0WtmQkV_f0y6JsUSUCX1SFi-C-ichxtBu_QhMW9HColkgrJ/s600/SetupProject03.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;33%&quot;&gt;&amp;nbsp;Output Directory:&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;66%&quot;&gt;&amp;nbsp;$(SolutionDir)..\bin\$(ConfigurationName)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;33%&quot;&gt;&amp;nbsp;Intermediate Directory:&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;66%&quot;&gt;&amp;nbsp;$(SolutionDir)..\obj\$(ConfigurationName)&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!--&lt;br /&gt;--&gt;  
Right click Project | Properties | Configuration Properties | C++ | General.  Set Additional Include Directories:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiByYSpe0QbYMs65LXGR_Cft3XnhwyCq2i3XvVUW3fYxC7YULzB1cBZnT3dJRTic-hZChIxZcZZbTPrOcdv7mUyLffXSDldCygAleJitxDrE5QFmIh2O7GUhvmkizhNYd2l6Gg_X2R3EZTCHNZOAyvsEHjy3CGS_saju1t4GqyxGByJ6UNfVF3or9gM/s920/SetupProject04.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiByYSpe0QbYMs65LXGR_Cft3XnhwyCq2i3XvVUW3fYxC7YULzB1cBZnT3dJRTic-hZChIxZcZZbTPrOcdv7mUyLffXSDldCygAleJitxDrE5QFmIh2O7GUhvmkizhNYd2l6Gg_X2R3EZTCHNZOAyvsEHjy3CGS_saju1t4GqyxGByJ6UNfVF3or9gM/s600/SetupProject04.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Value:&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;$(SolutionDir)..\lib;$(ProjectDir)inc;$(ProjectDir)res;$(GDK_WIN)\inc;$(IncludePath)&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!--&lt;br /&gt;--&gt;
Right click Project | Properties | Configuration Properties | Linker | General | Additional Library Directories:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_5oOJCNp2MzPikp7RVuAILVbv5uSeZdrIcXHfLtZ7wLfWymM8oRErjf0nbI2uYtndZEDQwfAT3NroN1Y7Mj4dtYwBVPHVbF9-CpDDJN8ikgLaoJ1SVEe2GV2EsTuaJcSj3ea2MCmSB8BIUh1VXC50KZyL1FNUkdTPJ5y8sGMd1FuskMCfVkgIwN6X/s920/SetupProject05.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_5oOJCNp2MzPikp7RVuAILVbv5uSeZdrIcXHfLtZ7wLfWymM8oRErjf0nbI2uYtndZEDQwfAT3NroN1Y7Mj4dtYwBVPHVbF9-CpDDJN8ikgLaoJ1SVEe2GV2EsTuaJcSj3ea2MCmSB8BIUh1VXC50KZyL1FNUkdTPJ5y8sGMd1FuskMCfVkgIwN6X/s600/SetupProject05.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;25%&quot;&gt;&amp;nbsp;Value:&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;75%&quot;&gt;&amp;nbsp;$(SolutionDir)..\lib&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!--&lt;br /&gt;--&gt;
Right click Project | Properties | Configuration Properties | Linker | Input.  Set the Additional Dependencies:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXnOw7trRd5tlro6lN9wp7PBSllZu_dqxeHzN0xK_wI2I8cxYwutIpgYVWVfOFn3SEwU8M9HbexVzUCgNMZ6F1jD9ZNraC0rJo06zCinBXmpKT6OM-e9XAqxeJ_8EZHJDJNwuspesc2_K8lKSC-mUOmB0_fuOJ-QsO7jaQAYBhFgP17xrNC7-nop0_/s922/SetupProject06.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXnOw7trRd5tlro6lN9wp7PBSllZu_dqxeHzN0xK_wI2I8cxYwutIpgYVWVfOFn3SEwU8M9HbexVzUCgNMZ6F1jD9ZNraC0rJo06zCinBXmpKT6OM-e9XAqxeJ_8EZHJDJNwuspesc2_K8lKSC-mUOmB0_fuOJ-QsO7jaQAYBhFgP17xrNC7-nop0_/s600/SetupProject06.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table width=&quot;99%&quot;border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;25%&quot;&gt;&amp;nbsp;Value:&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;75%&quot;&gt;&amp;nbsp;_genesis.lib;%(AdditionalDependencies)&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!--&lt;br /&gt;--&gt;
The final solution should look like this:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcI_-wveWFhdC8fAuFx273LZ0VwWRU9ie21lP5QpamAk4wLQzaUi0PLuxpUq_GxXhANtYSFtjq29psiT5ONWpRl5SY8_R6Kb9CztPxD8FkPIR5AFycCyZttoIMZp-qJUvCSrHE0Hb4T87LK2KwsTInTNxzyddynEb0XvG6AZ69wMaTGab7neXnFQa9/s736/SetupProject07.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcI_-wveWFhdC8fAuFx273LZ0VwWRU9ie21lP5QpamAk4wLQzaUi0PLuxpUq_GxXhANtYSFtjq29psiT5ONWpRl5SY8_R6Kb9CztPxD8FkPIR5AFycCyZttoIMZp-qJUvCSrHE0Hb4T87LK2KwsTInTNxzyddynEb0XvG6AZ69wMaTGab7neXnFQa9/s600/SetupProject07.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;  
&lt;u&gt;Setup Resources&lt;/u&gt;&lt;br /&gt;
Import all resources into your project as media files that your game will use such as images for background tiles + sprites, audio for music + sound effects etc.  &lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/01-SetupProject&quot;&gt;Clone&lt;/a&gt; the &quot;Setup Project&quot; folder and follow these steps:
&lt;br /&gt;
&lt;br /&gt;
Change directory to &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/02-SetupResources/dev/res&quot;&gt;res&lt;/a&gt;&lt;/b&gt; folder under &lt;i&gt;dev&lt;/i&gt; folder.  Copy all resources here.  Create corresponding &lt;b&gt;*.res&lt;/b&gt; files.  Next execute &lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/02-SetupResources/dev/build.bat&quot;&gt;build.bat&lt;/a&gt; to compile all resources then generate all corresponding &lt;b&gt;gfx&lt;/b&gt; and &lt;b&gt;sfx&lt;/b&gt; header files.
&lt;br /&gt;&lt;br /&gt;
Create folder &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/02-SetupResources/gfx&quot;&gt;gfx&lt;/a&gt;&lt;/b&gt; at same level as &lt;i&gt;dev&lt;/i&gt; folder.  Create sub folder &lt;i&gt;res&lt;/i&gt;.  Add dummy corresponding translation unit files under &lt;i&gt;res&lt;/i&gt; sub folder.  Repeat process with &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/02-SetupResources/sfx&quot;&gt;sfx&lt;/a&gt;&lt;/b&gt; folder.  Import all translation units into Visual Studio.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Setup Folders&lt;/u&gt;&lt;br /&gt;
Larger game projects will require nested folders in the &lt;b&gt;inc&lt;/b&gt; or &lt;b&gt;src&lt;/b&gt; directories to organize engine and screen code etc.  &lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/02-SetupResources&quot;&gt;Clone&lt;/a&gt; the &quot;Setup Resources&quot; folder and add all necessary subfolders + then update the makefile.
&lt;br /&gt;&lt;br /&gt;
Launch Visual Studio and include resource files as before.  Next, scale out engine and screen code but now organize into subfolders.  Create as New Filters under Visual Studio Header Files and Source Files solution:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMLYxMPqY_IP1xEa1GLpIfeASws3dmpHGfUgpuoq7q366iMWzdbMDP_g-JfH3ktKsJmj3CxfIMlacNFRhhGvz3rbBI32GyNL6Qgvppg348zRZqV_cwj-Wqf9lj4A1o96hnuCZQCedJgR71muVWvVT-ltQhZrOglwwBsutSN1bZETM40Ko5J7lcPfLT/s856/SolutionExplorer.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMLYxMPqY_IP1xEa1GLpIfeASws3dmpHGfUgpuoq7q366iMWzdbMDP_g-JfH3ktKsJmj3CxfIMlacNFRhhGvz3rbBI32GyNL6Qgvppg348zRZqV_cwj-Wqf9lj4A1o96hnuCZQCedJgR71muVWvVT-ltQhZrOglwwBsutSN1bZETM40Ko5J7lcPfLT/s600/SolutionExplorer.png&quot;/&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;!--&lt;br /&gt;--&gt;
Create corresponding engine and screen subfolders beneath &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/02-SetupFolders/dev/inc&quot;&gt;inc&lt;/a&gt;&lt;/b&gt; folder under &lt;i&gt;dev&lt;/i&gt;.  Add header files.  Create engine and screen subfolders beneath &lt;b&gt;&lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/tree/master/SGDKport/SimpsonsTriviaMD/02-SetupFolders/dev/src&quot;&gt;src&lt;/a&gt;&lt;/b&gt; folder under &lt;i&gt;dev&lt;/i&gt;.  Add all the corresponding translation unit code.
&lt;br /&gt;&lt;br /&gt; 
Right click Project | Properties | Configuration Properties | C++ | General.  Set Additional Include Directories:
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd6PPII5sPaJzhQMcA-UXAPipYbmMh9j0tFJO_1KBmLOv9_Qol8wniks_NFFF8SWe3zRaZaClo9LJz7M59MKg1HqYAqzS15y9zqQzW6oUOJoWhfABDQDdqd0TJ5vdRwIkI_o48PF5TO2I/s1600/HelloWorld02.png&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;385&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd6PPII5sPaJzhQMcA-UXAPipYbmMh9j0tFJO_1KBmLOv9_Qol8wniks_NFFF8SWe3zRaZaClo9LJz7M59MKg1HqYAqzS15y9zqQzW6oUOJoWhfABDQDdqd0TJ5vdRwIkI_o48PF5TO2I/s640/HelloWorld02.png&quot; width=&quot;98%&quot; /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;table border=&quot;1&quot; width=&quot;99%&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;Value:&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&amp;nbsp;$(SolutionDir)..\lib;$(ProjectDir)inc;$(ProjectDir)res;$(GDK_WIN)\inc;$(IncludePath);&lt;br /&gt;&amp;nbsp;$(ProjectDir)inc\engine;$(ProjectDir)inc\object;$(ProjectDir)inc\screen&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;!--&lt;br /&gt;--&gt;
Customize the makefile.gen file to include the new subfolders accordingly.  Copy &lt;i&gt;%GDK_WIN%\&lt;a href=&quot;https://github.com/Stephane-D/SGDK/blob/master/makefile.gen&quot;&gt;makefile.gen&lt;/a&gt;&lt;/i&gt; to local &lt;b&gt;dev&lt;/b&gt; folder.  Update makefile: Add new &lt;b&gt;$(wildcard $(SRC)/&lt;/b&gt; and &lt;b&gt;-I$(INCLUDE)&lt;/b&gt; entries per folder.
&lt;br /&gt;&lt;br /&gt;
Update &lt;b&gt;dev&lt;/b&gt; built.bat file to use new local custom &lt;a href=&quot;https://github.com/SteveProXNA/SGDKcode/blob/master/SGDKport/SimpsonsPort/03-SetupFolders/dev/makefile.gen&quot;&gt;makefile.gen&lt;/a&gt; instead of de-facto &lt;b&gt;%GDK_WIN% version&lt;/b&gt;.
&lt;br /&gt;
If you remove pre-build step to speed up makefile build then don&#39;t forget to create out subfolders manually.
&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Convert APIs&lt;/u&gt;&lt;br /&gt;
Finally, copy over all engine, object, screen etc. files from the Sega Master System code base into the Sega Mega Drive port.  Convert all &lt;a href=&quot;https://github.com/sverx/devkitSMS&quot;&gt;devkitSMS&lt;/a&gt; APIs to the &lt;a href=&quot;https://github.com/Stephane-D/SGDK&quot;&gt;SGDK&lt;/a&gt; equivalents.  Allow for different screen resolution!
&lt;br /&gt;&lt;br /&gt;
Here is quick cheat of &lt;a href=&quot;https://github.com/sverx/devkitSMS&quot;&gt;devkitSMS&lt;/a&gt; to &lt;a href=&quot;https://github.com/Stephane-D/SGDK&quot;&gt;SGDK&lt;/a&gt; API conversions; of course not all APIs are one-to-one mapping:  
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
 &lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;&amp;nbsp;&lt;b&gt;SEGA MASTER SYSTEM&lt;/b&gt;&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;&amp;nbsp;&lt;b&gt;SEGA MEGA DRIVE&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Audio&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;PSGPlay();&lt;br /&gt;
&amp;nbsp;PSGStop();&lt;br /&gt;
&amp;nbsp;PSGGetStatus();&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;XGM_startPlayPCM();&lt;br /&gt;
&amp;nbsp;XGM_stopPlayPCM();&lt;br /&gt;
&amp;nbsp;XGM_isPlayingPCM();&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Dimensions&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;256 x 192 [32x24]&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;320 x 224 [40x28]&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Font&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;SMS_setNextTileatXY();&lt;br /&gt;
&amp;nbsp;SMS_setTile();&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;VDP_setMapEx();&lt;br /&gt;
&amp;nbsp;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Graphics&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;SMS_loadPSGaidencompressedTiles();&lt;br /&gt;
&amp;nbsp;SMS_loadBGPalette();&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;VDP_drawImageEx();&lt;br /&gt;
&amp;nbsp;VDP_setPalette();&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Hack&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;Address : 0x0050&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;Address : 0x01E0&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Input&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;SMS_getKeysStatus();&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;JOY_readJoypad();&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Random&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;rand();&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;random();&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;20%&quot;&gt;&amp;nbsp;Sprites&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;SMS_addSprite();&lt;br /&gt;
&amp;nbsp;SMS_copySpritestoSAT();&lt;br /&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&amp;nbsp;SPR_addSprite();&lt;br /&gt;
&amp;nbsp;SPR_update();&lt;br /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;u&gt;Summary&lt;/u&gt;&lt;br /&gt;
Repeat process with &lt;a href=&quot;https://steveproxna.itch.io/skazka&quot;&gt;Skazka&lt;/a&gt;.  In summary, the &lt;a href=&quot;https://github.com/SteveProXNA/SkazkaSMS&quot;&gt;Master System&lt;/a&gt; to &lt;a href=&quot;https://github.com/SteveProXNA/SkazkaMD&quot;&gt;Mega Drive&lt;/a&gt; port should be fairly seemless &lt;span style=&#39;font-family:Wingdings&#39;&gt;J&lt;/span&gt;&lt;span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;table width=&quot;100%&quot; border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;&amp;nbsp;&lt;b&gt;SEGA MASTER SYSTEM&lt;/b&gt;&amp;nbsp;[256 x 192]&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;&amp;nbsp;&lt;b&gt;SEGA MEGA DRIVE&lt;/b&gt;&amp;nbsp;[320 x 224]&lt;/td&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDZE-YOUvI2zQzI6ME-Ssln9DkhVyO7Y_OZrAemELq9nF1HlhqU7n5wtCpWex2yiZ-N2nqoiZ2j519jN_1vOb2TP7BpUWHv31MoCuMWLHGGWun0tSudt2IAS8AzF864JWuinAZ2tntXoLR-5-oVS5InOX4r4lci7XxVCvOraIPjy2fsHDJW7adXBPq/s642/SkazkaSMS.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDZE-YOUvI2zQzI6ME-Ssln9DkhVyO7Y_OZrAemELq9nF1HlhqU7n5wtCpWex2yiZ-N2nqoiZ2j519jN_1vOb2TP7BpUWHv31MoCuMWLHGGWun0tSudt2IAS8AzF864JWuinAZ2tntXoLR-5-oVS5InOX4r4lci7XxVCvOraIPjy2fsHDJW7adXBPq/s600/SkazkaSMS.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;40%&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkb0s2xWNk_QjZiKPWeXX5KbIUqtoZrN0cjn16E7ABwLhFxeuoqnYJGlV2CBq3o1Xv1yXFqNzshFyQ8yYeHSLq_GneLYwn1QTOKktCiXsccOhGRYpKYbDUNOx2uhjyrt7Sbi3jDToT8sF0-tCP7kdWFC6Lkuowdl7y3d10sujobzXAe9X2p_5QYO4_/s642/SkazkaMD.png&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;98%&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkb0s2xWNk_QjZiKPWeXX5KbIUqtoZrN0cjn16E7ABwLhFxeuoqnYJGlV2CBq3o1Xv1yXFqNzshFyQ8yYeHSLq_GneLYwn1QTOKktCiXsccOhGRYpKYbDUNOx2uhjyrt7Sbi3jDToT8sF0-tCP7kdWFC6Lkuowdl7y3d10sujobzXAe9X2p_5QYO4_/s600/SkazkaMD.png&quot;/&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/span&gt;
</description><link>http://steveproxna.blogspot.com/2023/06/sega-console-game-port.html</link><author>noreply@blogger.com (SteveProXNA)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOQAur4QBLkqjekg11RwWNsadVo5TVKOuk3NebMs-4FS-mUuPUZGW31IC8EpbQjs9yX0FGq3GVyz2kVCnRgAomWGE-65dAz6aMNxKmsO5Th7kkhHfrONqDvhllTzFKyoP6rrd-l_w2vbrDVRX8gcl2BlTFZSz4YE_1Lw9Y4Hufg5EcDW8mCtcFcgLJ/s72-c/SimpsonsSMS.png" height="72" width="72"/><thr:total>0</thr:total></item></channel></rss>