<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	>

<channel>
	<title>Krystof.IO</title>
	<atom:link href="https://krystof.io/feed/" rel="self" type="application/rss+xml" />
	<link>https://krystof.io/</link>
	<description>Numerous hobbies, various ramblings.</description>
	<lastBuildDate>Mon, 29 May 2023 20:37:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.9</generator>

<image>
	<url>https://krystof.io/wp-content/uploads/2019/10/cropped-site-icon-low-32x32.jpg</url>
	<title>Krystof.IO</title>
	<link>https://krystof.io/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Octoprint with Multiple Printers on One Ubuntu Linux Mini-PC</title>
		<link>https://krystof.io/octoprint-with-multiple-printers-on-one-ubuntu-linux-mini-pc/</link>
					<comments>https://krystof.io/octoprint-with-multiple-printers-on-one-ubuntu-linux-mini-pc/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Thu, 18 May 2023 13:14:36 +0000</pubDate>
				<category><![CDATA[3D Printing]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[3d Printing]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=2289</guid>

					<description><![CDATA[<p>Using Docker to connect three instances of Octoprint to three 3D Printers, all on one Linux machine with webcams.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/octoprint-with-multiple-printers-on-one-ubuntu-linux-mini-pc/">Octoprint with Multiple Printers on One Ubuntu Linux Mini-PC</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on May 27, 2023.</p>
<p>I&#8217;m a big fan of Octoprint, and in the past I used it on a couple of Raspberry Pi computers, one instance per Pi.  Those things are harder to come by these days, so as I try to get my 3d printers up and running again after a long hiatus in storage, I wanted to try to take one cheap Windows Mini-PC and see if I could install Linux on it and utilize Docker to have multiple Octoprint instances, one for each printer, all running on one PC.  Each 3D Printer will also have a webcam attached.  I also wanted to use an external Wifi Adapter as the built in adapter on the Mini-PC didn&#8217;t have as much power.  So those are the goals: </p>



<ul>
<li>One PC to handle three printers
<ul>
<li>One Octoprint instance per Printer</li>



<li>USB Powered Hub to expand available ports</li>
</ul>
</li>



<li>Each printer has a webcam</li>



<li>External WiFi Adapter (better than the internal)</li>



<li>Docker containerization for ease of setup / config</li>
</ul>



<p>This article serves as the general build and install log of that setup.    It covers the basic install of Ubuntu, Docker, Octoprint, and some USB UDEV rules so we can make sure the printers and webcams always run under the expected device names.</p>



<h2 class="wp-block-heading" id="h-wiring-connections">Wiring Connections</h2>



<p>The Mini-PC I have has two USB 3.0 and two USB 2.0 ports.  I&#8217;ve got to hook up three webcams, three printers, and an external WiFi adapter, so that&#8217;s already 7.  So I had one six port powered USB 3.0 hub, which I wanted to attach the 3D Printer related stuff to, use the other USB 3.0 port for the WiFi adapter, and then have the other two ports open as needed.  That was the goal at least, it didn&#8217;t work out that way, but close.  I had to remove one camera from the hub and use one of the USB 2.0 ports for it (perhaps I was maxing out the hub with video?).  Nevertheless, that at least left one port open for something else someday. It&#8217;s going to be a headless system for the most part.</p>



<h2 class="wp-block-heading">Mini-PC Linux Software and Config</h2>



<p>This was fairly straightforward for the install side. <a href="https://ubuntu.com/download" target="_blank" rel="noreferrer noopener">Downloaded</a> the latest Ubuntu <strong>server </strong>image (could have done desktop, but it&#8217;s a headless system), used <a href="https://etcher.balena.io" target="_blank" rel="noreferrer noopener">Balena Etcher</a> to pop it on an SD Card, then shoved that card right into the Windows Mini PC and started the install (wiping out everything).  Once that was done, I installed <a href="https://www.cyberciti.biz/faq/how-to-install-ssh-on-ubuntu-linux-using-apt-get/" target="_blank" rel="noreferrer noopener" class="broken_link">open ssh</a> (if it wasn&#8217;t installed as part of the initial OS install) so I can just use Putty to connect via my main PC for ease of copy/paste. </p>



<h3 class="wp-block-heading">WiFi Adapter Compile and Install</h3>



<p>More optional than anything, since this is an adapter that doesn&#8217;t have direct Linux support at this time.  It&#8217;s better than the internal one my PC had though, so I&#8217;ll be using it.  It&#8217;s the <a href="https://www.amazon.com/gp/product/B01MZD7Z76/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&amp;psc=1" target="_blank" rel="noreferrer noopener nofollow">Alfa AC1900 WiFi Adapter</a> and it requires special but easy handling.</p>



<p>Copy of the documentation from their website: <a href="https://docs.alfa.com.tw/Support/Linux/RTL8814AU/" target="_blank" rel="noreferrer noopener nofollow">https://docs.alfa.com.tw/Support/Linux/RTL8814AU/</a></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt update
sudo apt install git build-essential
git clone https://github.com/aircrack-ng/rtl8812au.git
cd rtl8812au
make
sudo make install
</pre></div>


<p>After that I did a recycle, still wired in.  I had to update my netplan config to take the new settings for the new adapter.</p>



<p>My internal adapter on the PC (that sucks), was named <code>wlp2s0</code>.  But I need the name of the new adapter, so to get that&#8230;</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo lshw -C network
</pre></div>


<p>This gives me the output of network adapters, and I can see a new one beyond my default internal, which should be the adapter we just compiled drivers for:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
*-network DISABLED
       description: Wireless interface
       physical id: 8
       bus info: usb@1:3
       logical name: wlx00c0caaedc2d
       serial: .....
       capabilities: ethernet physical wireless
       configuration: broadcast=yes driver=rtl88XXau driverversion=5.15.0-72-generic multicast=yes wireless=unassociated

</pre></div>


<p>The logical name <code>wlx00c0caaedc2d</code> is what I&#8217;m interested in.  Now I&#8217;ll edit the netplan config to set both ethernet and wifi as optional interfaces and get the adapter ready to connect to my SSID.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo vi /etc/netplan/00-installer-config.yaml
</pre></div>


<p>That may bring up some default networking stuff.  I pretty much replace it with these contents:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
network:
  ethernets:
    enp1s0:
      dhcp4: true
      optional: true
  wifis:
    #    wlp2s0:
    #  optional: true
    #  access-points:
    #    &lt;SSID&gt;:
    #      password: &lt;PASSWORD&gt;
    #  dhcp4: true
    wlx00c0caaedc2d:
      optional: true
      access-points:
        &lt;SSID&gt;:
          password: &lt;PASSWORD&gt;
      dhcp4: true
  version: 2

</pre></div>


<p>After that we apply the settings with <code>sudo netplan apply</code> and we&#8217;re off.  I can see the adapter light blinking.  I reboot with the network cable disconnected to make sure I can still connect via WiFi.</p>



<h3 class="wp-block-heading">USB and UDEV rules</h3>



<p>I want to set some UDEV rules so that we know exactly the USB ports our devices are being plugged into (included devices attached to the powered hub I bought), so that I can create aliases accordingly (i.e. I want to use <code>/dev/ttyPrinter1</code> and <code>/dev/videoPrinter1</code> and so on instead of assuming <code>/dev/video0</code> is always the first camera.)</p>



<p>To do this, I open up an SSH session and type:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
udevadm monitor
</pre></div>


<p>This will now spit large walls of text every time I plug something in or take something out of USB ports.  I plugin the hub, and figure out which ports I&#8217;m going to use for which printer.  The goal here is to grab the right &#8216;port identifier&#8217; and use UDEV rules to map that consistently to the right device name.  <strong>I will always plug the printers/cameras into the same USB ports</strong>.  So I used a simple video camera and went from port to port, copying down the key line that shows which identifier the system uses for the specific port I just plugged into.  You&#8217;ll see a bunch of lines, but look for the one that defines a video device like /dev/video0 and then look to the left of that line.  You&#8217;ll see text like this, which I copied down into a notepad session:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
...
/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.1/1-4.1.2/1-4.1.2:1.0/  (printer-2)
...
/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.1/1-4.1.1/1-4.1.1:1.0/  (video-printer2)
...
/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.4/1-4.4:1.0/  (printer1)
...
/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.3/1-4.3:1.0/  (video-printer1)
</pre></div>


<p>As I move the camera from port to port I see which key identifiers change (see the 1-4.1.2:1.0 becomes 1-4.1.<strong>1</strong>:1.0, or 1-4.<strong>4</strong>:1.0 as I move down the line)</p>



<p>I use those identifiers to build the udev rules file.  I store mine in <code>/etc/udev/rules.d/01-krystof-usb.rules</code> so here are my contents (as root):</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
SUBSYSTEM==&quot;tty&quot;, KERNELS==&quot;1-4.4:1.0&quot;, SYMLINK+=&quot;ttyPrinter1&quot;
SUBSYSTEM==&quot;tty&quot;, KERNELS==&quot;1-4.4:1.0&quot;, RUN+=&quot;/var/lib/docker/composers/octoprint/restart-octoprint.sh octoprint1&quot;
SUBSYSTEM==&quot;tty&quot;, KERNELS==&quot;1-4.1.2:1.0&quot;, SYMLINK+=&quot;ttyPrinter2&quot;
SUBSYSTEM==&quot;tty&quot;, KERNELS==&quot;1-4.1.2:1.0&quot;, RUN+=&quot;/var/lib/docker/composers/octoprint/restart-octoprint.sh octoprint2&quot;
SUBSYSTEM==&quot;tty&quot;, KERNELS==&quot;1-4.1.4:1.0&quot;, SYMLINK+=&quot;ttyPrinter3&quot;
SUBSYSTEM==&quot;tty&quot;, KERNELS==&quot;1-4.1.4:1.0&quot;, RUN+=&quot;/var/lib/docker/composers/octoprint/restart-octoprint.sh octoprint3&quot;
SUBSYSTEM==&quot;video4linux&quot;, KERNELS==&quot;1-4.3:1.0&quot;, ATTR{index}==&quot;0&quot;, SYMLINK+=&quot;videoPrinter1&quot;
SUBSYSTEM==&quot;video4linux&quot;, KERNELS==&quot;1-4.1.1:1.0&quot;, ATTR{index}==&quot;0&quot;, SYMLINK+=&quot;videoPrinter2&quot;
SUBSYSTEM==&quot;video4linux&quot;, KERNELS==&quot;1-8:1.0&quot;, ATTR{index}==&quot;0&quot;, SYMLINK+=&quot;videoPrinter3&quot;
</pre></div>


<p>The printers use subsystem TTY, and the videos use subsystem video4Linux.  The &#8220;KERNELS&#8221; argument is where I put those uniquely changing identifiers from watching <code>udevadm monitor</code> running, and the actions afterwards are what we want to do with that device when it&#8217;s plugged in.  For my case, I want to create a symbolic link under /dev/ for the printer.  (I could have named them towards the printer model, but some of my models are the same so I just went with printer1, printer2, etc.  &#8211; You could easily put A B C, BobsPrinter, DavesPrinter (even if Dave&#8217;s not here), etc.</p>



<p>You&#8217;ll notice the lines are duplicated for the printers and then there&#8217;s a RUN option.  That executes a script for docker later when the printers are plugged in.  It attempts to restart the docker instances of OctoPrint when the printer is disconnected and reconnected (sometimes it OctoPrint in a container can&#8217;t detect that very well, so we basically perform a restart).  That script looks like this if you want to use it (if you don&#8217;t, remove those lines)  &#8211; Obviously those scripts don&#8217;t exist yet but will after I set up docker.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#!/bin/sh
sleep 10
docker stop $1
sleep 10
docker start $1
exit 0
</pre></div>


<p>To apply the UDEV rules, and make sure there aren&#8217;t any errors in the config:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo udevadm control --reload-rules &amp;&amp; sudo udevadm trigger
</pre></div>


<p>You can see if it works by connecting one printer or video camera to the hub you wrote down your identifiers for and put into the rules.  If you plug in the right device to the right port, you should get a <code>/dev/ttyPrinter1</code>, or <code>/dev/videoPrinter1</code> device available:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
#Plugged the printer into USB port designated for printer 1:
erkrystof@pc-octoprint:/etc/udev/rules.d$ ls /dev/tty*Pr*
/dev/ttyPrinter1
#Unplugged the printer from USB port that I designated for printer 1 and put it in printer 2:
erkrystof@pc-octoprint:/etc/udev/rules.d$ ls /dev/tty*Pr*
/dev/ttyPrinter2
</pre></div>


<h2 class="wp-block-heading">Docker and the OctoPrint Containers</h2>



<p>Followed the standard docker install for Ubuntu:</p>



<p><a href="https://docs.docker.com/engine/install/ubuntu/" target="_blank" rel="noreferrer noopener">https://docs.docker.com/engine/install/ubuntu/</a></p>



<p>I also like to use Portainer, but that&#8217;s entirely optional for you (it&#8217;s a web admin interface for Docker containers)</p>



<p><a href="https://www.portainer.io/install" target="_blank" rel="noreferrer noopener">https://www.portainer.io/install</a></p>



<p>Once docker is installed, we need to create the docker-compose.yml file.  I like to put mine under <code>/var/lib/docker/composers/octoprint</code>.  (I created the directory as root).  I use the &#8216;official&#8217; <a href="https://hub.docker.com/r/octoprint/octoprint" target="_blank" rel="noreferrer noopener">OctoPrint image</a>, which I&#8217;ve had no issues with thus far in its current state.  Read that page over to better understand what is happening below.</p>



<p><code>sudo vi /var/lib/docker/composers/octoprint/docker-compose.yml</code></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
version: &quot;2.4&quot;

services:
  octoprint1:
    container_name: octoprint1
    image: octoprint/octoprint
    restart: unless-stopped
    ports:
      - &quot;8001:80&quot;
    devices:
      - /dev/ttyPrinter1:/dev/ttyUSB0
      - /dev/videoPrinter1:/dev/video0
    volumes:
      - ./octoprint1:/octoprint
    environment:
      - ENABLE_MJPG_STREAMER=true
      - MJPG_STREAMER_INPUT=-n -r 1280x720
  octoprint2:
    container_name: octoprint2
    image: octoprint/octoprint
    restart: unless-stopped
    ports:
      - &quot;8002:80&quot;
    devices:
      - /dev/ttyPrinter2:/dev/ttyUSB0
      - /dev/videoPrinter2:/dev/video0
    volumes:
      - ./octoprint2:/octoprint
    environment:
      - ENABLE_MJPG_STREAMER=true
      - MJPG_STREAMER_INPUT=-n -r 1280x720
  octoprint3:
    container_name: octoprint3
    image: octoprint/octoprint
    restart: unless-stopped
    ports:
      - &quot;8003:80&quot;
    devices:
      - /dev/ttyPrinter3:/dev/ttyUSB0
      - /dev/videoPrinter3:/dev/video0
    volumes:
      - ./octoprint3:/octoprint
    environment:
      - ENABLE_MJPG_STREAMER=true
      - MJPG_STREAMER_INPUT=-n -r 1280x720
</pre></div>


<p>Since I&#8217;ve got three printers, and three webcams, I have three entries.  Easy enough.</p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>Configuring multiple OctoPrint instances?  You can just do one and then create a backup and restore to the others and change just the differences.  Saves time on initial installs and installing the same plugins 3X.</div></div>



<p>So then we <em>could</em> run the compose command from that directory (as root):</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker compose up -d
</pre></div>


<p>Now, if I do this without having the USB cameras and printers connected via USB, none of the instances will actually start.  Each OctoPrint instance expects a video camera and tty device now before it will start.  See how we map our well known aliases to /dev/ttyUSB0 and /dev/video0 for every single instance?  That allows us to create multiple OctoPrint installs, but utilize different USB devices.  The UDEV rules helped us map ports to well known aliases.</p>



<p>At this point, I hooked up the printers and video cameras to the Linux PC, recycled everything to make sure all was good there, <em>then I ran <code>docker compose up -d</code></em>.  After that, I was able to hit the web interface on each instance at http://pc-octoprint.lan:8001 through 8003.  (Your hostname may vary, that&#8217;s up to you).</p>



<p>Now underneath our composers directory we&#8217;ll have the three OctoPrint install directories designated under the volumes section.</p>



<p>Key notes on some settings in OctoPrint come from the <a href="https://hub.docker.com/r/octoprint/octoprint" target="_blank" rel="noreferrer noopener">OctoPrint Docker image</a> page:</p>



<h4 class="wp-block-heading">Webcam Setup in OctoPrint</h4>



<p>Use the following values in the webcam &amp; timelapse settings screen of the initial setup:</p>



<figure class="wp-block-table"><table><thead><tr><th>Setting</th><th>Value</th></tr></thead><tbody><tr><td>Stream URL</td><td><code>/webcam/?action=stream</code></td></tr><tr><td>Snapshot URL</td><td><code>http://localhost:8080/?action=snapshot</code></td></tr><tr><td>Path to FFMPEG</td><td><code>/usr/bin/ffmpeg</code></td></tr></tbody></table></figure>



<h4 class="wp-block-heading">Container Environment based configs</h4>



<p>There are configuration values that you pass using container&nbsp;<code>--environment</code>&nbsp;options. Listed below are the options and their defaults. These are implicit in example&nbsp;<a href="https://github.com/OctoPrint/octoprint-docker/tree/master/docker-compose.yml" target="_blank" rel="noreferrer noopener">docker-compose.yml</a>, and if you wish to change them, refer to the docker-compose docs on setting environment variables.</p>



<figure class="wp-block-table"><table><thead><tr><th>variable</th><th>default</th></tr></thead><tbody><tr><td><code>CAMERA_DEV</code></td><td><code>/dev/video0</code>&nbsp;(see&nbsp;<a href="https://hub.docker.com/r/octoprint/octoprint#devices_note" target="_blank" rel="noreferrer noopener">note</a>)</td></tr><tr><td><code>MJPG_STREAMER_INPUT</code></td><td><code>-y -n -r 640x480</code></td></tr><tr><td><code>ENABLE_MJPG_STREAMER</code></td><td><code>false</code></td></tr></tbody></table></figure>



<p>I tested the recycle script as well, so if I physically disconnect and reconnect, the docker instance tied to that port is recycled.</p>



<h2 class="wp-block-heading">References</h2>



<ul>
<li><a href="https://www.reddit.com/r/octoprint/comments/mouzdf/ive_been_testing_running_multiple_instances_of/" target="_blank" rel="noreferrer noopener" class="broken_link">https://www.reddit.com/r/octoprint/comments/mouzdf/ive_been_testing_running_multiple_instances_of/</a></li>



<li><a href="https://www.reddit.com/r/octoprint/comments/p3dk12/guidetutorial_multiinstance_octoprint_on_a/" target="_blank" rel="noreferrer noopener" class="broken_link">https://www.reddit.com/r/octoprint/comments/p3dk12/guidetutorial_multiinstance_octoprint_on_a/</a></li>



<li><a href="https://hub.docker.com/r/octoprint/octoprint" target="_blank" rel="noreferrer noopener">https://hub.docker.com/r/octoprint/octoprint</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://krystof.io/octoprint-with-multiple-printers-on-one-ubuntu-linux-mini-pc/">Octoprint with Multiple Printers on One Ubuntu Linux Mini-PC</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/octoprint-with-multiple-printers-on-one-ubuntu-linux-mini-pc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MiSTer FPGA Initial Setup and Network Mounting</title>
		<link>https://krystof.io/mister-fpga-initial-setup-and-network-mounting/</link>
					<comments>https://krystof.io/mister-fpga-initial-setup-and-network-mounting/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Sat, 08 Apr 2023 02:24:56 +0000</pubDate>
				<category><![CDATA[Retro Gaming]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Emulation]]></category>
		<category><![CDATA[Build Log]]></category>
		<category><![CDATA[fpga]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=2216</guid>

					<description><![CDATA[<p>Gathering a bunch of parts and building a MiSTer FPGA kit and case and performing some initial setup and network share mounting.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/mister-fpga-initial-setup-and-network-mounting/">MiSTer FPGA Initial Setup and Network Mounting</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on May 29, 2023.</p>
<h2 class="wp-block-heading" id="h-what-is-mister-fpga">What is MiSTer FPGA?</h2>



<p>I like to think of MiSTer FPGA as <em>hardware emulation</em> vs the <em>software emulation</em> I&#8217;m used to.  The MiSTer suite of cores and utilities are designed to be installed on the Terasic DE10-Nano FPGA board, and various add on boards to support more USB components or video/audio output.  MiSTer FPGA is a project that coordinates different &#8216;cores&#8217; (e.g. old computer systems or game consoles) and applies them to the FPGA board, effectively instructing the FPGA board to act as the chipsets of these old retro computer and console systems. </p>



<p><em>FPGA</em> itself stands for &#8216;Field Programmable Gate Array&#8217;.   It is a type of integrated circuit that can be programmed by the user to perform specific functions.  So think of it like a blank slate chip that you can program to act as another chip.  That&#8217;s how we do the hardware emulation.  Since this reprogramming of the chip can happen without having to manufacture a new chip, we can use the term &#8216;Field Programmable&#8217; &#8211; you can reprogram it <em>in the field</em>, outside of a chip manufacturing plant.</p>



<h2 class="wp-block-heading">Why MiSTer FPGA?</h2>



<p>I wanted to try MiSTer FPGA because I&#8217;ve never messed with <em>hardware</em> emulation.  It&#8217;s always been on the real deal or with software emulation (like DOSBOX or VICE).  My understanding is that lag is nearly non-existent when compared to emulators, and the &#8216;cores&#8217; (the systems we&#8217;re emulating) run more true to the original hardware than their software emulating counterparts.  Want to know some of the cores directly supported?  Check out the <a href="https://github.com/MiSTer-devel/Wiki_MiSTer/wiki/Cores" target="_blank" rel="noreferrer noopener">core list here</a>.</p>



<p>My motivation for doing this is because while I like to have genuine retro systems of the old systems I had as a child, I don&#8217;t care to try to own an Apple IIe, or an Atari ST.  I was a Commodore guy, so while I want to tinker with those systems, I definitely don&#8217;t want to hit up e-bay and start trying to build my own piece-by-piece setup for a system I never owned or had no vested interest in.  (See how I through that line in there?  I never owned a Commodore PET, but I wouldn&#8217;t turn a free one down)</p>



<p>The <a href="https://github.com/MiSTer-devel/Wiki_MiSTer/wiki" target="_blank" rel="noreferrer noopener">MiSTer Wiki</a> page has excellent information, tutorials, and references.</p>



<h2 class="wp-block-heading">The Parts List</h2>



<p>So from the hardware standpoint, we need at a minimum the Terasic DE10-Nano board.  This is the specific model of FPGA board that the open source MiSTer FPGA project software (Mr. Fusion) expects to be installed on, so it&#8217;s a must.  After that you have all sorts of add ons and adapters (adapters to even hook up old console specific adapters like light guns) to enhance your retro gaming experience.  I went with the following (links to where you could find them included &#8211; not necessarily the only place, but at least one place)</p>



<ul>
<li><a href="https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&amp;No=1046&amp;PartNo=8#order_list" target="_blank" rel="noreferrer noopener nofollow">Terasic DE10-Nano board</a> &#8211; The bare minimum as stated above.  I ordered mine from Terasic directly.</li>



<li><a href="https://misterfpga.co.uk/product/usb-hub-for-mister-fpga/" target="_blank" rel="noreferrer noopener nofollow">USB Hub V2.1 for MiSTer</a> &#8211; This gives us more USB ports to connect keyboards, mice, joysticks, etc. to the Terasic board.  It&#8217;s a powered HUB that is designed to mount underneath the Terasic.  It comes with a splitter power cable to split your power supply between the USB board and the Terasic <em>(but if you use the digital IO board you don&#8217;t use the splitter, see that part for more detail)</em></li>



<li><a href="https://misterfpga.co.uk/product/mister-sdram-128mb-module/" target="_blank" rel="noreferrer noopener nofollow">128MB SDRam Module</a> &#8211; Not required for all the cores, but it is required for enough of them that I wanted to mess with.  This slides into the top part of the Terasic board.  You can see the <a href="https://github.com/MiSTer-devel/Wiki_MiSTer/wiki/Cores-that-use-SDRAM" target="_blank" rel="noreferrer noopener">cores that require SDRam here</a>.</li>



<li><strong>I/O Boards:</strong> There are typically two I/O boards that people use for this.  I&#8217;m going to try both, but you only install one at a time.  Generally, for those that want to stream HDMI but play on a CRT, you&#8217;ll get the Analog board.  The Digital board offers some extra expansion capabilities, though.  Regardless of which one you get, <strong>this board sits on TOP of the Terasic, so when combined with the USB hub below, the Terasic is in the middle.</strong> Of note are the three switch buttons on top to easily access Reset, OSD (On screen display), and user defined functions.  Cases for these are also available, and assume you have the standard 3 board setup (USB board + Terasic board + IO Board)
<ul>
<li><a href="https://misterfpga.co.uk/product/mister-digital-io-board/?attribute_fan-type=Noctua+NF-A4x10" target="_blank" rel="noreferrer noopener nofollow">MiSTer Digital IO Board v1.2</a> &#8211; The MiSTer FPGA Digital IO Board v1.2 provides the following features: a dedicated power switch to turn the unit on and off with over-voltage protection, a 3.5mm audio jack for ADC In (Tape Input) a separate ADC-In addon board is not required, 3.5mm&nbsp;Mini-TOSLINK &amp; Digital TOSLINK Connectors, a secondary microSD card slot the functionality depends upon the core being used, a fan speed control jumper providing 3.3 volts or 5 volts, three status LEDs (red, yellow, green), three large push buttons providing system reset, on screen display menu and game reset, an expansion connector in the form of a USB 3.0 connector however this is not for standard USB devices. <strong>If you use this board, it comes with a cable so you power your entire setup through this board, power goes through the GPIO pins into the Terasic, and then you use the included barrel cable to go from the Terasic to the USB board.  So one power cable powers all three boards connected together.</strong>  <strong><a href="https://misterfpga.co.uk/product/mister-case-acrylic/?attribute_mister-case-colour=Neptune+Blue&amp;attribute_io-board-type=Digital+IO+v1.2" target="_blank" rel="noreferrer noopener">Acrylic Case Link</a></strong></li>



<li><a href="https://misterfpga.co.uk/product/mister-fpga-analog-io-board/?attribute_fan-type=Noctua+NF-A4x10" target="_blank" rel="noreferrer noopener nofollow">MiSTer Analog IO Board v6.1</a> &#8211; The MiSTer FPGA Analog IO board v6.1 includes the following useful features: a VGA (DB15) connector allowing for the output of a VGA/RGB/YPbPr signal depending on the cable being used, a 3.5mm audio jack with Mini-TOSLINK providing analog audio output and digital audio output, a secondary microSD card slot the functionality depends upon the core being used, a fan speed control providing a 3.3 volt / 5 volt selector jumper, a status LED control jumper allowing switching on or off the built in LEDs, a Sync-on-Green switch, three status LEDs (red, yellow, green), three large push buttons providing system reset, on screen display menu and game reset, an expansion connector in the form of a USB 3.0 connector however this is not for standard USB devices.  <strong><a href="https://misterfpga.co.uk/product/mister-case-acrylic/?attribute_mister-case-colour=Neptune+Blue&amp;attribute_io-board-type=Analog+IO+v5.5+%28Or+Newer%29" target="_blank" rel="noreferrer noopener">Acrylic Case Link</a></strong>
<ul>
<li>Configuration of the video output signal on the IO board is controlled via the MiSTer.ini file, more information on how to configure and download of the MiSTer.ini file see the <a href="https://github.com/MiSTer-devel/Wiki_MiSTer/wiki/Configuration-Files" target="_blank" rel="noreferrer noopener">https://github.com/MiSTer-devel/Wiki_MiSTer/wiki/Configuration-Files</a> configuration</li>
</ul>
</li>
</ul>
</li>



<li><strong>Wifi/Bluetooth USB Dongles</strong> &#8211; Generally, I think you can use whatever ones you may already have.  Terasic sells some from their site, I used some I already had.  They fit nicely into the USB board to give you connectivity as you desire.  Not every dongle dangles properly, so here are some recommended adapters for <a href="https://mister-devel.github.io/MkDocs_MiSTer/basics/wifi/" target="_blank" rel="noreferrer noopener nofollow">Wifi </a>and <a href="https://mister-devel.github.io/MkDocs_MiSTer/basics/bluetooth/" target="_blank" rel="noreferrer noopener nofollow">Bluetooth</a>.</li>
</ul>



<p>I also picked up some more &#8216;odd&#8217; add ons for this as well, more specific to my gaming taste:</p>



<ul>
<li><a href="https://ultimatemister.com/product/mister-snac-iec-c64/" target="_blank" rel="noreferrer noopener nofollow">MiSTer SNAC-IEC CBM 1541 Connector</a> &#8211; I believe with this I can hook up a real 1541 drive to the kit and use it with the C64 core. </li>



<li><a href="https://ultimatemister.com/product/ultimate-deamon-pro-dual-genesis/" target="_blank" rel="noreferrer noopener nofollow">Ultimate Dameon x2 Player MiSTer FPGA adapter</a> &#8211; The&nbsp;<strong>Ultimate Deamon PRO USB Dual Encoder</strong>&nbsp;for ATARI / SEGA MEGADRIVE / GENESIS.  This small form-factor USB adapter makes it possible to use SEGA MEGADRIVE / GENESIS controllers on your PC (Windows, Mac OS X, Linux), Raspberry Pi or MiSTer. The adapter has a&nbsp;<strong>native 1ms/1000Hz polling rate</strong>&nbsp;so input lag is minimal (the average is 0.75ms with a wired controller). Fully assembled in a Aluminium enclosure and includes&nbsp;<strong>USB-C cable</strong>&nbsp;to connect this adapter to your favorite&nbsp;setup.  (from <a href="https://ultimatemister.com/" target="_blank" rel="noreferrer noopener">ultimatemister.com</a>)</li>



<li><a href="https://misterfpga.co.uk/product/mister-real-time-clock-board-rtc/" target="_blank" rel="noreferrer noopener">MiSTer RTC Real Time Clock Board 1.4</a> &#8211; For cores that use a clock, mainly if your FPGA kit isn&#8217;t going to be internet connected for automatic time syncing, this one&#8217;s for you. I don&#8217;t believe you need this if you&#8217;ll have internet connectivity, though.</li>
</ul>



<h2 class="wp-block-heading" id="h-putting-the-parts-together">Putting the parts together</h2>



<p>While you don&#8217;t *need* a digital IO board or USB hub connected to your DE10-Nano, it sure makes things easier.  Our final configuration when this is setup will be the DE10-Nano sandwiched in between the USB hub board on the bottom, and the digital IO board on the top.  Wrap the acrylic case around it and we&#8217;re done.</p>



<h3 class="wp-block-heading">A note on orientation.</h3>



<p>When I say &#8216;top&#8217; or &#8216;right&#8217;, I&#8217;m orienting my Nano like the pictures on Terasic&#8217;s website.  The ethernet adapter is on the right side when the board is facing up:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" src="https://krystof.io/wp-content/uploads/2023/04/image-5-1024x779.png" alt="" class="wp-image-2231" width="512" height="390" srcset="https://krystof.io/wp-content/uploads/2023/04/image-5-1024x779.png 1024w, https://krystof.io/wp-content/uploads/2023/04/image-5-300x228.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-5-768x585.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-5-1170x891.png 1170w, https://krystof.io/wp-content/uploads/2023/04/image-5-585x445.png 585w, https://krystof.io/wp-content/uploads/2023/04/image-5-1320x1005.png 1320w, https://krystof.io/wp-content/uploads/2023/04/image-5.png 1390w" sizes="(max-width: 512px) 100vw, 512px" /></figure></div>


<h3 class="wp-block-heading">Heatsink</h3>



<p>Nothing wrong with that.  Picked mine up from <a href="https://misterfpga.co.uk/product/mister-fpga-ultimate-heatsink/" target="_blank" rel="noreferrer noopener nofollow">https://misterfpga.co.uk/product/mister-fpga-ultimate-heatsink/</a>, made to fit the Cyclone V SoC on the DE10-Nano board.</p>


<div class="wp-block-image">
<figure class="aligncenter size-medium"><img decoding="async" loading="lazy" width="300" height="208" src="https://krystof.io/wp-content/uploads/2023/04/image-300x208.png" alt="" class="wp-image-2224" srcset="https://krystof.io/wp-content/uploads/2023/04/image-300x208.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-768x533.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-585x406.png 585w, https://krystof.io/wp-content/uploads/2023/04/image.png 877w" sizes="(max-width: 300px) 100vw, 300px" /></figure></div>


<h3 class="wp-block-heading">USB HUB Board</h3>



<p>The USB Hub board sits below the DE10-Nano, and you&#8217;ll need to remove the standoffs from the Nano (I gently twisted with pliers, keep the screws for later but you&#8217;ll need to remove them) so that you can mount the USB board below it.  On the ethernet side of the Nano, on the very top right, there&#8217;s the USB-Micro style OTG (On The Go) port, which is how we connect the HUB to the Nano.  My board comes with a slick adapter that plugs into four pins of the USB board:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-3.png" alt="" class="wp-image-2229" width="323" height="297" srcset="https://krystof.io/wp-content/uploads/2023/04/image-3.png 646w, https://krystof.io/wp-content/uploads/2023/04/image-3-300x275.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-3-585x537.png 585w" sizes="(max-width: 323px) 100vw, 323px" /><figcaption class="wp-element-caption">The adapter that joins the USB board to the Nano. Top is for the Nano, bottom is for the USB board.</figcaption></figure></div>

<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-1.png" alt="" class="wp-image-2226" width="278" height="280" srcset="https://krystof.io/wp-content/uploads/2023/04/image-1.png 370w, https://krystof.io/wp-content/uploads/2023/04/image-1-298x300.png 298w, https://krystof.io/wp-content/uploads/2023/04/image-1-150x150.png 150w" sizes="(max-width: 278px) 100vw, 278px" /><figcaption class="wp-element-caption">USB Board, Top right side &#8211; four pins where the adapter plugs into.</figcaption></figure></div>


<p>and then zig zags up and out to the plug into the Nano&#8217;s OTG port:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-2.png" alt="" class="wp-image-2227" width="338" height="375" srcset="https://krystof.io/wp-content/uploads/2023/04/image-2.png 451w, https://krystof.io/wp-content/uploads/2023/04/image-2-271x300.png 271w" sizes="(max-width: 338px) 100vw, 338px" /></figure></div>


<p>So with the standoffs screwed into each other (leaving the top screws since we&#8217;ll be putting the digital board on top), we&#8217;re ready to continue.</p>



<h3 class="wp-block-heading">128MB SDRam Addon Board</h3>



<p>I next installed the ram board.  I could have done this prior to the USB board, but if nothing else I wanted to do it before a placed the I/O board on top of the Nano.  The two large SDRam chips face the inside of the nano for my version, and there&#8217;s a label on the opposite side that says &#8216;this side faces outwards&#8217;, so that helps orient you.  The SDRam goes into the pin header on the TOP of the Nano.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-4.png" alt="" class="wp-image-2230" width="375" height="266" srcset="https://krystof.io/wp-content/uploads/2023/04/image-4.png 750w, https://krystof.io/wp-content/uploads/2023/04/image-4-300x212.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-4-585x414.png 585w" sizes="(max-width: 375px) 100vw, 375px" /><figcaption class="wp-element-caption">This side faces inward, towards the center of your Nano.</figcaption></figure></div>


<h3 class="wp-block-heading">Digital IO Board (Or Analog if you have that)</h3>



<p>Next up is the IO Board, but before we install it, <strong>(for Digital IO Boards only),</strong> we need to flip a switch on the Nano.  Namely, SW3, and it&#8217;s right here (in our orientation, SW3 is on the left side of the bank, SW0 is on the right side)</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="616" height="330" src="https://krystof.io/wp-content/uploads/2023/04/image-6.png" alt="" class="wp-image-2232" srcset="https://krystof.io/wp-content/uploads/2023/04/image-6.png 616w, https://krystof.io/wp-content/uploads/2023/04/image-6-300x161.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-6-585x313.png 585w" sizes="(max-width: 616px) 100vw, 616px" /><figcaption class="wp-element-caption">Flip this baby UP.</figcaption></figure></div>


<p>After flipping it on (UP) (and ONLY for the digital IO board &#8211; for the analog IO board, all switches should be down/off), we&#8217;re ready to put the Digital board on top.  Our orientation has the &#8216;green&#8217; LED above the Red LED, this is how the IO board will look when putting it on top of the Nano if you&#8217;re using the orientation we are for our Nano (ethernet port on the right side).  We also put another set of standoffs on top of the Nano for this to rest on.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-143124.png" alt="" class="wp-image-2233" width="381" height="231" srcset="https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-143124.png 762w, https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-143124-300x182.png 300w, https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-143124-585x355.png 585w" sizes="(max-width: 381px) 100vw, 381px" /></figure></div>


<p>One troublesome thing I noticed was there are more headers (holes) on the Nano then there are pins on the IO board, so you&#8217;ll want to be careful.  With our orientation we&#8217;ve been using, the digital IO board <em>carefully</em> slides into the pins on the Nano. Gently make sure all of the pins line up. On the both top and bottom sides of the Nano, you&#8217;ll have more headers (holes) on the Nano then you actually will pins from the digital IO board.  Here are some shots from the <a href="https://misterfpga.co.uk" target="_blank" rel="noreferrer noopener nofollow">misterfpga.co.uk</a> site that show the differences of top and bottom headers/vs pins:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-7.png" alt="" class="wp-image-2234" width="582" height="370" srcset="https://krystof.io/wp-content/uploads/2023/04/image-7.png 582w, https://krystof.io/wp-content/uploads/2023/04/image-7-300x191.png 300w" sizes="(max-width: 582px) 100vw, 582px" /><figcaption class="wp-element-caption">View on the &#8216;BOTTOM&#8217; side of the nano/io board.  Red LED in front if you have the bottom facing you.</figcaption></figure></div>

<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="576" height="378" src="https://krystof.io/wp-content/uploads/2023/04/image-8.png" alt="" class="wp-image-2235" srcset="https://krystof.io/wp-content/uploads/2023/04/image-8.png 576w, https://krystof.io/wp-content/uploads/2023/04/image-8-300x197.png 300w" sizes="(max-width: 576px) 100vw, 576px" /><figcaption class="wp-element-caption">View on the &#8216;TOP&#8217; side of the nano/io board.  Green LED in front if you have the top facing you.</figcaption></figure></div>


<p>At pretty much anytime during this install, we could have turned the whole thing on and tried things out (hooking up a keyboard, HDMI, and power), but we&#8217;re going to cover that later.  For now, on to the Acrylic Case.  (If you&#8217;re not using a case, you can screw the IO board into the brass standoffs it should be touching &#8211; but if you ARE using a case, no screws yet)</p>



<h3 class="wp-block-heading">Acrylic Case</h3>



<p>More parts!  Don&#8217;t worry &#8211; it&#8217;s not uncommon that you will leave here with more brass standoffs than you started with, as individual parts often come with extras.  My case is designed for the digital IO board AND USB board in the mix.  There are other case variants that use the Analog IO board and USB board, naturally.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="631" src="https://krystof.io/wp-content/uploads/2023/04/image-9-1024x631.png" alt="" class="wp-image-2237" srcset="https://krystof.io/wp-content/uploads/2023/04/image-9-1024x631.png 1024w, https://krystof.io/wp-content/uploads/2023/04/image-9-300x185.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-9-768x474.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-9-1170x721.png 1170w, https://krystof.io/wp-content/uploads/2023/04/image-9-585x361.png 585w, https://krystof.io/wp-content/uploads/2023/04/image-9.png 1257w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>


<p>Put the top standoffs into your digital IO board now, before you start building your case walls.  (You can do it afterwards, it&#8217;s just annoying).  Rest the MiSTer on top of the bottom part of the case, and build your walls up by aligning holes to case sides.  The tabs on the case sides slid together easily enough for me.</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="851" height="419" src="https://krystof.io/wp-content/uploads/2023/04/image-10.png" alt="" class="wp-image-2239" srcset="https://krystof.io/wp-content/uploads/2023/04/image-10.png 851w, https://krystof.io/wp-content/uploads/2023/04/image-10-300x148.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-10-768x378.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-10-585x288.png 585w" sizes="(max-width: 851px) 100vw, 851px" /></figure>



<p>The part that was roughest for me was the three little separate plastic buttons that rest on top of the Digital IO board&#8217;s buttons.  I found it easiest to put the buttons in the top side of the case, turn the MiSTer upside down, and align the case top and buttons that way.</p>



<p>With the case top on, and making sure the buttons were in place, I put the four screws in to the top of the case, securing the boards and case all together.  We&#8217;re done assembling our FPGA sandwich!</p>



<h3 class="wp-block-heading">Power setup</h3>



<p>When using this style of kit, where we have the IO board on top of the Nano on top of the USB hub, we really only need to give power to one component, and then we daisy chain power down to the other two boards.  We power the Digital IO board directly, which then gives power to the Nano, then we use the included Male to Male barrel connector to go from Nano to USB board.  So my power side/HDMI side looks like this:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="689" src="https://krystof.io/wp-content/uploads/2023/04/image-11-1024x689.png" alt="" class="wp-image-2241" srcset="https://krystof.io/wp-content/uploads/2023/04/image-11-1024x689.png 1024w, https://krystof.io/wp-content/uploads/2023/04/image-11-300x202.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-11-768x517.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-11-1170x787.png 1170w, https://krystof.io/wp-content/uploads/2023/04/image-11-585x393.png 585w, https://krystof.io/wp-content/uploads/2023/04/image-11.png 1185w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>


<p>Don&#8217;t forget, the Digital IO board also comes with a power switch on the bottom left (a simple slider switch).  I&#8217;m also using an inline switch power adapter, just make sure you&#8217;re turning all the right parts on.  I just leave the digital board switch on and use the inline adapter switch, but you do you. 🙂  After this point, I hook up the HDMI, and USB keyboard/mouse and I&#8217;m ready to go&#8230; after we flash the SD card with the Mr. Fusion software.</p>



<h2 class="wp-block-heading">Flashing the MicroSD card with Mr. Fusion</h2>



<p>If you have your case on, you&#8217;ll notice that the SD card is a royal pain in the ass to get out easily.  If I just trimmed my fingernails, I end up having to use a tiny pliers to grab the card after I release it with a push (it&#8217;s a spring-loaded-grabber SD Card type, but when releasing the card it *barely* clears the case if at all).  This is another reason I want to avoid having to take the SD Card in and out of the kit, it&#8217;s too damn annoying.  This is why I&#8217;m thinking most people would want to SCP into their MiSTer, use USB memory cards, or use network shares instead of ever having to remove the microSD card every time they wanted to add something.  I&#8217;m going with the network mount for the purposes of this document.</p>



<p>So, if you haven&#8217;t yet, remove the SD Card and put it into your favorite PC.  I like to use <a href="https://www.balena.io/etcher" target="_blank" rel="noreferrer noopener nofollow">balenaEtcher</a>, so I grab that and the <a href="https://github.com/MiSTer-devel/mr-fusion/releases" target="_blank" rel="noreferrer noopener">latest Mr. Fusion release</a> (at time of writing, 2.7), and let the etcher do its thing.</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="802" height="511" src="https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-103639.png" alt="" class="wp-image-2243" srcset="https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-103639.png 802w, https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-103639-300x191.png 300w, https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-103639-768x489.png 768w, https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-103639-585x373.png 585w" sizes="(max-width: 802px) 100vw, 802px" /></figure>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="214" height="299" src="https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-103800.png" alt="" class="wp-image-2244"/><figcaption class="wp-element-caption">This is your goal.</figcaption></figure></div>


<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#1a6ad9;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>Having troubles getting a successfully validated flashing of the Mr. Fusion image?  I shut down my anti-virus temporarily, and made sure any Windows explorer windows weren&#8217;t open (I think the windows auto mounting of cards after the initial writing of the image causes some confusion when validating the image etching)</div></div>



<p></p>



<p>Putting this back into the MiSTer (the MicroSD card slot is on the bottom side of the Nano board, so you should make the gold contacts of the MicroSD face UP when you slide it in), we&#8217;re now finally ready to boot this thing up and configure some of the software.</p>



<h2 class="wp-block-heading">First boot</h2>



<p>If everything has gone okay (and why wouldn&#8217;t it, things never break or go wrong, right?), you&#8217;ll see this on your monitor:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-12-1024x576.png" alt="" class="wp-image-2247" width="768" height="432" srcset="https://krystof.io/wp-content/uploads/2023/04/image-12-1024x576.png 1024w, https://krystof.io/wp-content/uploads/2023/04/image-12-300x169.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-12-768x432.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-12-1536x864.png 1536w, https://krystof.io/wp-content/uploads/2023/04/image-12-1170x658.png 1170w, https://krystof.io/wp-content/uploads/2023/04/image-12-585x329.png 585w, https://krystof.io/wp-content/uploads/2023/04/image-12-1320x743.png 1320w, https://krystof.io/wp-content/uploads/2023/04/image-12.png 1920w" sizes="(max-width: 768px) 100vw, 768px" /><figcaption class="wp-element-caption">You made it!</figcaption></figure></div>


<p>This will reboot, and then come to a screen that at first, made me think the flashing didn&#8217;t work right.  I didn&#8217;t know what to expect, so don&#8217;t be alarmed, and in fact, you should expect see this:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="576" src="https://krystof.io/wp-content/uploads/2023/04/image-13-1024x576.png" alt="" class="wp-image-2252" srcset="https://krystof.io/wp-content/uploads/2023/04/image-13-1024x576.png 1024w, https://krystof.io/wp-content/uploads/2023/04/image-13-300x169.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-13-768x432.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-13-1536x864.png 1536w, https://krystof.io/wp-content/uploads/2023/04/image-13-1170x658.png 1170w, https://krystof.io/wp-content/uploads/2023/04/image-13-585x329.png 585w, https://krystof.io/wp-content/uploads/2023/04/image-13-1320x743.png 1320w, https://krystof.io/wp-content/uploads/2023/04/image-13.png 1920w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Everything is fine.  Seriously.  I&#8217;m not kidding. No /s here.  For reals.</figcaption></figure>



<p>All this means is that you&#8217;ve loaded up Mr. Fusion and are looking at a blank core menu because, well, the initial flashing doesn&#8217;t install <strong>any</strong> cores.  We&#8217;ll have to do that ourselves in a bit.  First things first.  Connectivity.  <strong>Well, one more thing first.  If the flashing static background starts annoying you, hit F1 on your keyboard to change it.  This also easily screws up encoding, as I was streaming his at the time and all of the static made the rest of the stream overlays pixelate.</strong></p>



<h2 class="wp-block-heading">Initial Network Connectivity</h2>



<p>If you&#8217;re hard wired in, you should already have an IP address.  If not, you should hit Escape,  which will bring up the system settings, and select the &#8216;Scripts&#8217; directory.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-14.png" alt="" class="wp-image-2255" width="387" height="316" srcset="https://krystof.io/wp-content/uploads/2023/04/image-14.png 773w, https://krystof.io/wp-content/uploads/2023/04/image-14-300x245.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-14-768x627.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-14-585x478.png 585w" sizes="(max-width: 387px) 100vw, 387px" /></figure></div>


<p>At the warning, type yes (since you do want to run the script), and select &#8216;wifi&#8217; and hit return.  Assuming you have a wifi dongle plugged in (and if not, you should just go hard wired with ethernet), you&#8217;ll see the list of SSIDs &#8211; select yours and enter your password.  After that point, you should get taken back to the main menu, but you&#8217;ll have a little &#8216;Wifi&#8217; signal icon in the upper bar of your menu now.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-15.png" alt="" class="wp-image-2256" width="384" height="311" srcset="https://krystof.io/wp-content/uploads/2023/04/image-15.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-15-300x243.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-15-585x474.png 585w" sizes="(max-width: 384px) 100vw, 384px" /></figure></div>


<p>Now we&#8217;re cooking.  Next steps are to download the well known &#8216;update_all&#8217; script (not the stock update script that comes with the install &#8211; which definitely works if you only want to use that) that downloads all the stuff that the update script does, as well as a lot of neat and/or experimental features <em>should you desire it</em> and performs general updates and downloading of additional scripts.  But first let&#8217;s go over where I&#8217;m storing all of the files the downloader is going to download.</p>



<h2 class="wp-block-heading">MiSTer file paths and network mount considerations</h2>



<p>MiSTer FPGA has a fairly standard directory structure it uses to look up files, be it cores or roms.  Whether it&#8217;s network storage or the SD Card itself, MiSTer mounts a well known directory structure referenced here: <a href="https://mister-devel.github.io/MkDocs_MiSTer/cores/paths" target="_blank" rel="noreferrer noopener">https://mister-devel.github.io/MkDocs_MiSTer/cores/paths</a></p>



<p><strong>to do any of the following, we need to login via SSH to our running MiSTer.</strong>  To see these directories in action, you can use <a href="https://www.putty.org/" target="_blank" rel="noreferrer noopener">PuTTY</a> to open up a terminal into your MiSTer.  The default account is root and the default password is 1.  (So&#8230; maybe we&#8217;ll change that later)</p>



<p>After you login, know that all of the directories MiSTer is going to care about are under /media.  The basic key directories are:</p>



<figure class="wp-block-table"><table><tbody><tr><td>/media/fat</td><td>The root of your SD Card.  If you were to shutdown the MiSTer and mount your card in your windows machine, the contents of that card would be here.</td></tr><tr><td>/media/fat/_Arcade</td><td>Arcade cores go here.  Cores are the systems, not the games, remember.</td></tr><tr><td>/media/fat/_Computer</td><td>Computer cores go here.  These are things like the Apple II, Commodore 64, etc.</td></tr><tr><td>/media/fat/_Console</td><td>Console cores go here &#8211; Nintendo, Genesis, etc.</td></tr><tr><td>/media/fat/config</td><td>Configuration files &#8211; generally for each core as you modify and save configurations.</td></tr><tr><td>/media/fat/games</td><td>These are where all your games go.  Generally subdirectories under here line up with cores, so /media/fat/games/c64 would be where you put your C64 disk/cart/program images.</td></tr></tbody></table></figure>



<p>You won&#8217;t have some of these directories yet because we haven&#8217;t downloaded anything with the update_all script yet (you&#8217;ll at least have a Scripts directory because we&#8217;ve already run files from there).  Previously I mentioned that I did NOT want to constantly remove the MicroSD card to add content to my MiSTer.  I would think most people don&#8217;t want to do this, especially with a case because getting those SD cards in and out easily is <strong>annoying</strong>.  So, I figure I had these options:</p>



<ul>
<li>Use the SD card for primary storage, let the update_all script download cores to the SD card, and use SCP/SSH to transfer files to the MicroSD card to my computer.  Doable, but slightly cumbersome</li>



<li>Use a USB Stick (which the MiSTer should automount according to the core paths page referenced in the github link above.  Here we can at least windows to do a little easier transfer, but we still have to move the stick between files.</li>



<li>Use a Samba share &#8211; You can enable the Samba (Windows file share) service on the MiSTer and expose your SDCard over the network as described here: <a href="https://mister-devel.github.io/MkDocs_MiSTer/setup/games/" target="_blank" rel="noreferrer noopener">https://mister-devel.github.io/MkDocs_MiSTer/setup/games/</a>  Also doable, but I prefer to not really use the SDCard except for booting up the MiSTer and storing some configuration data.</li>



<li>Use the CIFS mount scripts and download all cores and games onto my Synology NAS, and then have MiSTer mount those directories instead (even thinking it&#8217;s /media/fat, when it&#8217;s really talking to my NAS).  I liked this because virtually all files are on my NAS, so I can use that from windows more easily than SFTP, and I&#8217;m not constantly writing to the MiSTer SD Card.  <strong>This is the option this document will describe further down below</strong>.</li>
</ul>



<p>So, my goal is to create a NAS share, and have MiSTer mount the FPGA directories for cores, systems, etc. on the NAS, but making it think it&#8217;s still under /media/fat (reason being if anything we ever install assumes /media/fat is used, it will just work).  The primary directories we&#8217;ll leave on the SD card itself are /media/linux and /media/config, which are much more towards MiSTer even running things properly.  The cores and games, however, will live on my NAS.</p>



<p>So I created a share and made a dedicate user for it, this way it wasn&#8217;t going to see any other directories on the NAS and things are neatly organized.  For the CIFS mount to work, the directories must already exist, so I created the directories I needed by using a template.zip file from a forum thread I found on doing this exact thing, referenced <a href="https://misterfpga.org/viewtopic.php?t=3246" target="_blank" rel="noreferrer noopener">here</a>.  However, I found I needed to add a couple of directories to that template, so I&#8217;ve created my own, which you can grab here.  It&#8217;s just a zip file with empty directories to get you started.  All I did was just unzip it to the root of my NAS MiSTer share.</p>


<div class="sdm_download_item "><div class="sdm_download_item_top"><div class="sdm_download_thumbnail"></div><div class="sdm_download_title">MiSTer FPGA NAS Directory Template</div></div><div style="clear:both;"></div><div class="sdm_download_description"><p>This zip is a bunch of empty directories you unzip to the root of your NAS share dedicated to your MiSTer FPGA.  These directories should exist on the NAS share so when you run the cifs_mount.sh script, your MiSTer will see those /media/fat/ subdirectories, but they&#8217;ll actually point to the NAS and not your SD card.</p>
</div><div class="sdm_download_link"><span class="sdm_download_button"><a href="https://krystof.io/?sdm_process_download=1&download_id=2260" class="sdm_download green" title="MiSTer FPGA NAS Directory Template" target="_self">Download Now!</a></span><span class="sdm_download_item_count"><span class="sdm_item_count_number">1710</span><span class="sdm_item_count_string"> Downloads</span></span></div></div><div class="sdm_clear_float"></div>



<p>(The reason we do this is that those directories must exist to mount them on the MiSTer, otherwise when the download runs it will download files to the /media/fat/games directory on the SD CARD, not the network mount that we want.  We&#8217;re using CIFS to trick MiSTer into thinking /media/fat/games is on the SD card when it&#8217;s really on the network, remember.)</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="673" height="734" src="https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-104946.png" alt="" class="wp-image-2265" srcset="https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-104946.png 673w, https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-104946-275x300.png 275w, https://krystof.io/wp-content/uploads/2023/04/Screenshot-2023-04-07-104946-585x638.png 585w" sizes="(max-width: 673px) 100vw, 673px" /></figure>



<p>These are the empty directories included in the zip file.  (Ignore #recycle, that&#8217;s from my Synology NAS)</p>



<h2 class="wp-block-heading">Download and configure the CIFS_MOUNT scripts</h2>



<p>Now that we have those directories created, we need to tell the MiSTer how to mount them.  To do that, we&#8217;ll download to our /media/fat/Scripts directory (which will NOT be part of our NAS) the two scripts cifs_mount.sh and cifs_umount.sh from <a href="https://github.com/MiSTer-devel/Scripts_MiSTer" target="_blank" rel="noreferrer noopener">https://github.com/MiSTer-devel/Scripts_MiSTer</a>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd /media/fat/Scripts
wget https://raw.githubusercontent.com/MiSTer-devel/Scripts_MiSTer/master/cifs_mount.sh
wget https://raw.githubusercontent.com/MiSTer-devel/Scripts_MiSTer/master/cifs_umount.sh
</pre></div>


<p>Now, in that same directory, we need to create a cifs_mount.ini file.  Here&#8217;s mine, you&#8217;d obviously use a real IP address for your NAS, a real username, and real password.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
# NAS IP (If server name doesn&#039;t work, use IP)
SERVER=&quot;192.168.50.10&quot;

#The share name on the NAS
SHARE=&quot;mister&quot;
USERNAME=&quot;mister&quot;
PASSWORD=&quot;mister&quot;

#Local directory/directories where the share will be mounted.
LOCAL_DIR=&quot;*&quot;

#mfsymlinks most likely is necessary so the update_all ArcadeOrganizer download works.
ADDITIONAL_MOUNT_OPTIONS=&quot;vers=3.11,mfsymlinks&quot;

#&quot;true&quot; in order to wait for the CIFS server to be reachable;
#useful when using this script at boot time.
WAIT_FOR_SERVER=&quot;true&quot;

#&quot;true&quot; for automounting CIFS shares at boot time;
#it will create start/kill scripts in /etc/network/if-up.d and /etc/network/if-down.d.
MOUNT_AT_BOOT=&quot;true&quot;

#========= ADVANCED OPTIONS =========
BASE_PATH=&quot;/media/fat&quot;
#MISTER_CIFS_URL=&quot;https://github.com/MiSTer-devel/CIFS_MiSTer&quot;
KERNEL_MODULES=&quot;md4.ko|md5.ko|des_generic.ko|fscache.ko|cifs.ko&quot;
IFS=&quot;|&quot;
SINGLE_CIFS_CONNECTION=&quot;true&quot;
#Pipe &quot;|&quot; separated list of directories which will never be mounted when LOCAL_DIR=&quot;*&quot;
SPECIAL_DIRECTORIES=&quot;config|linux|System Volume Information|#recycle&quot;
</pre></div>


<p>You can see in the SPECIAL_DIRECTORIES section we ignore config and linux, which we&#8217;ll always want to leave on our SDCard for stability.  The rest of the directories are mounted from the NAS IF they exist on the NAS already.</p>



<p>So, saving that file, my scripts directory now looks like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
/media/fat/Scripts# ls -l
total 160
-rwxr-xr-x 1 root root   911 Apr  6 00:18 cifs_mount.ini
-rwxr-xr-x 1 root root 12993 Apr  6 00:17 cifs_mount.sh
-rwxr-xr-x 1 root root  1051 Apr  6 00:17 cifs_umount.sh
-rwxr-xr-x 1 root root  4662 Jan  1  1980 update.sh
-rwxr-xr-x 1 root root 10638 Jan  1  1980 wifi.sh

</pre></div>


<p>I then invoked the ./cifs_mount.sh command to make sure it worked, and voila, here was my output:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
./cifs_mount.sh
</pre></div>


<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-16.png" alt="" class="wp-image-2268" width="347" height="524" srcset="https://krystof.io/wp-content/uploads/2023/04/image-16.png 463w, https://krystof.io/wp-content/uploads/2023/04/image-16-199x300.png 199w" sizes="(max-width: 347px) 100vw, 347px" /></figure>



<p>And now, all of these new directories appear on /media/fat (but most of them are on our NAS!)</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-17.png" alt="" class="wp-image-2269" width="609" height="639" srcset="https://krystof.io/wp-content/uploads/2023/04/image-17.png 812w, https://krystof.io/wp-content/uploads/2023/04/image-17-286x300.png 286w, https://krystof.io/wp-content/uploads/2023/04/image-17-768x806.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-17-585x614.png 585w" sizes="(max-width: 609px) 100vw, 609px" /></figure>



<p>Now, if you&#8217;re ever unsure as to whether or not the directory you see under /media/fat is local to the SD card or not, check out the mounts by doing a cat /proc/mounts.  You&#8217;ll see output like this:</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="840" height="612" src="https://krystof.io/wp-content/uploads/2023/04/image-18.png" alt="" class="wp-image-2270" srcset="https://krystof.io/wp-content/uploads/2023/04/image-18.png 840w, https://krystof.io/wp-content/uploads/2023/04/image-18-300x219.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-18-768x560.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-18-585x426.png 585w" sizes="(max-width: 840px) 100vw, 840px" /></figure>



<p>You can see all of the directories that are actually mounted to the NAS.  These are the same directories our update_all script is going to download to (as well as config/linux/Scripts, but those stay local on the SD card because we&#8217;ve either ignored them or did not create a matching directory on the NAS).</p>



<p><strong>You should be able to reboot your MiSTer and SSH into it again and see these mounts are still there.</strong></p>



<h2 class="wp-block-heading">Download and run theypsilon&#8217;s update_all.sh script</h2>



<p>Finally, the moment we&#8217;ve all been waiting for&#8230; let&#8217;s get things updated and downloaded.</p>



<p>SSH back into your MiSTer if you rebooted, and in the Scripts directory download the update_all.sh script from theypsilon&#8217;s git hub.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd /media/fat/Scripts
wget https://raw.githubusercontent.com/theypsilon/Update_All_MiSTer/master/update_all.sh
</pre></div>


<p>Then, execute it.   The update_all.sh script takes a while to run &#8211; you may want to run it from the OSD on the MiSTer, or you can still run it via SSH if you prefer.  On the MiSTer OSD you&#8217;d see this (Hit ESC to get to the System Settings menu, then select Scripts):</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-19.png" alt="" class="wp-image-2272" width="387" height="311" srcset="https://krystof.io/wp-content/uploads/2023/04/image-19.png 773w, https://krystof.io/wp-content/uploads/2023/04/image-19-300x241.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-19-768x618.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-19-585x471.png 585w" sizes="(max-width: 387px) 100vw, 387px" /></figure></div>


<p>Select update_all and you&#8217;ll be greeted with a preamble.  If you want to use default download options, just let it go, otherwise, hit UP ARROW and you can configure to download optional items. (If you&#8217;re on Wifi, this may take a while, might be best to do an initial update via ethernet cable)</p>



<p> </p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-20.png" alt="" class="wp-image-2273" width="404" height="461" srcset="https://krystof.io/wp-content/uploads/2023/04/image-20.png 539w, https://krystof.io/wp-content/uploads/2023/04/image-20-263x300.png 263w" sizes="(max-width: 404px) 100vw, 404px" /></figure></div>


<p>I hit UP and was greeted to the main settings page.  Where I enabled this and that, but regardless it&#8217;s going to download the primary cores, scripts, and folder setup structure for /media/fat/games.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-21.png" alt="" class="wp-image-2274" width="452" height="260" srcset="https://krystof.io/wp-content/uploads/2023/04/image-21.png 603w, https://krystof.io/wp-content/uploads/2023/04/image-21-300x172.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-21-585x336.png 585w" sizes="(max-width: 452px) 100vw, 452px" /></figure></div>


<p>You can always just take the defaults, &#8216;Exit and Run update all&#8217;, and run it later if you want to download Disabled items.  </p>



<p>That runs for a looooooong time.</p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>Note &#8211; if you enabled the Arcade Organizer and run into an error regarding symlinks, make sure you look at the details of my cifs_mount.ini file &#8211; it attempts to address that in there, and once I made the change (mfsymlinks), I had no issues running update_all.</div></div>



<p>At the very end of the script, barring any issues, you&#8217;ll see this:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-22.png" alt="" class="wp-image-2275" width="332" height="336" srcset="https://krystof.io/wp-content/uploads/2023/04/image-22.png 663w, https://krystof.io/wp-content/uploads/2023/04/image-22-296x300.png 296w, https://krystof.io/wp-content/uploads/2023/04/image-22-585x593.png 585w" sizes="(max-width: 332px) 100vw, 332px" /></figure></div>


<p>Your MiSTer will now reboot, and we&#8217;re done with the initial downloading.  If you look at your NAS share now, you&#8217;ll see it holds plenty of files and takes up a bit more space:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2023/04/image-23.png" alt="" class="wp-image-2276" width="867" height="690" srcset="https://krystof.io/wp-content/uploads/2023/04/image-23.png 867w, https://krystof.io/wp-content/uploads/2023/04/image-23-300x239.png 300w, https://krystof.io/wp-content/uploads/2023/04/image-23-768x611.png 768w, https://krystof.io/wp-content/uploads/2023/04/image-23-585x466.png 585w" sizes="(max-width: 867px) 100vw, 867px" /></figure></div>


<h2 class="wp-block-heading">Rebooting and final touches</h2>



<p><strong>A note on starting up your MiSTer now that you&#8217;re mounting a bunch of folders on your NAS:</strong>  Now that you&#8217;re &#8216;tricking&#8217; MiSTer into thinking /media/fat/&lt;some of your directories&gt; are local and not on the NAS, you may be occasionally surprised if you menu under &#8216;Arcade&#8217;, &#8216;Console&#8217;, or &#8216;Computer&#8217; is empty when you first start up.  Don&#8217;t be.  Just go back to the root of the menu (hit that OSD button on your case, or just escape out), wait a tick for the cifs_mount.sh script to finish in the background, and then you&#8217;ll see your cores and games visible.  It&#8217;s just on the initial boot up, and usually only takes a few seconds after the menu shows up.</p>



<p>Once that was all said and done, I went to the Scripts directory again and executed the timezone script to set my timezone properly.</p>



<p>Now, that pretty much concludes this round documenting my initial setup.   Some good reference links:</p>



<p><strong>HotKeys:</strong> <a href="https://mister-devel.github.io/MkDocs_MiSTer/basics/hotkey/" target="_blank" rel="noreferrer noopener">https://mister-devel.github.io/MkDocs_MiSTer/basics/hotkey/</a></p>



<p><strong>Defining GamePads:</strong> <a href="https://mister-devel.github.io/MkDocs_MiSTer/setup/controller/" target="_blank" rel="noreferrer noopener">https://mister-devel.github.io/MkDocs_MiSTer/setup/controller/</a></p>



<p>MiSTer FPGA Documentation: <a href="https://mister-devel.github.io/MkDocs_MiSTer/" target="_blank" rel="noreferrer noopener">https://mister-devel.github.io/MkDocs_MiSTer/</a></p>



<p>MiSTer Wiki on GitHub: <a href="https://github.com/MiSTer-devel/Wiki_MiSTer/wiki" target="_blank" rel="noreferrer noopener">https://github.com/MiSTer-devel/Wiki_MiSTer/wiki</a></p>



<p>SMB/CIFS Mount Threads: <a href="https://misterfpga.org/viewtopic.php?t=3246&amp;start=30" target="_blank" rel="noreferrer noopener">https://misterfpga.org/viewtopic.php?t=3246&amp;start=30</a><a href="https://misterfpga.org/viewtopic.php?t=4972" target="_blank" rel="noreferrer noopener">https://misterfpga.org/viewtopic.php?t=4972</a></p>



<p>theypsilon&#8217;s Update_All_MiSTer repo: <a href="https://github.com/theypsilon/Update_All_MiSTer" target="_blank" rel="noreferrer noopener">https://github.com/theypsilon/Update_All_MiSTer</a></p>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/mister-fpga-initial-setup-and-network-mounting/">MiSTer FPGA Initial Setup and Network Mounting</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/mister-fpga-initial-setup-and-network-mounting/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[FPGAdventures]]></series:name>
	</item>
		<item>
		<title>Retro Gaming PC Build Log Part 3 : PC Games with GOG</title>
		<link>https://krystof.io/retro-gaming-pc-build-log-part-3-pc-games-with-gog/</link>
					<comments>https://krystof.io/retro-gaming-pc-build-log-part-3-pc-games-with-gog/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Fri, 19 Aug 2022 19:35:16 +0000</pubDate>
				<category><![CDATA[Retro Gaming]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Dos Box]]></category>
		<category><![CDATA[Build Log]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[MS-DOS]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1984</guid>

					<description><![CDATA[<p>Working through LaunchBox and DOSBOX / Windows configurations for GOG.com games</p>
<p>The post <a rel="nofollow" href="https://krystof.io/retro-gaming-pc-build-log-part-3-pc-games-with-gog/">Retro Gaming PC Build Log Part 3 : PC Games with GOG</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on August 26, 2022.</p>
<p>I felt the need to separate GOG game installs from DOS games I&#8217;ve got that I&#8217;ll be setting up manually or through Steam.  The great thing about GOG (Good Old Games) games is that they do a lot of the legwork for getting old games to run on modern systems.  However, they&#8217;re not always great &#8211; they sometimes have issues, or occasionally lack content I&#8217;ve got on my original CDs or floppy images I&#8217;ve saved off.  Plus, I may want to run these with a different version of DOSBox, since a lot of the GOG games come packaged with DOSBOX 0.74-XXX.  I&#8217;d like to try some of these with DOSBOX-X and take advantage of save states and shaders which seem to be better supported there.</p>



<p>Nevertheless, they&#8217;ve tweaked a lot of the DOSBOX settings for CPU cycles and such on their end already, so that should save me some heavy lifting and fine-tuning&#8230; hopefully.</p>



<p>Here are some of the software / utilities I used when bringing in some GOG games:</p>



<figure class="wp-block-table"><table><tbody><tr><td><a href="https://www.gog.com/galaxy" target="_blank" rel="noreferrer noopener">GOG Galaxy</a></td><td>This is effectively their management tool for installed games, referencing your GOG account&#8217;s purchases.</td></tr><tr><td><a href="https://dosbox-x.com" target="_blank" rel="noreferrer noopener">DOSBOX-X</a></td><td>Currently using 0.84.2  There&#8217;s a really nice <a href="https://dosbox-x.com/wiki/DOSBox%E2%80%90X%E2%80%99s-Feature-Highlights" target="_blank" rel="noreferrer noopener">feature list</a> where the X team has added functionality above and beyond the standard DOSBOX build.  Running Windows 9X from this version sounds interesting, I&#8217;m going to give that a shot sometime.  The primary reason I&#8217;m using this is for when I feel like adding some opengl shaders.  I went with the vsbuild-win64.  Inside that archive, I went with the SDL2 release.</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">GOG install and personal tweaks to GOG&#8217;s DOSBOX</h2>



<p>So, I installed GOG Galaxy, linked my account, and found the myriad of games I&#8217;ve purchased over the years.  First stop, a personal favorite &#8211; Heroes Of Might and Magic.  I&#8217;m going to focus on the first of the series, which uses DOSBOX.</p>



<p>Now, my personal flavors on DOSBOX gaming are that I&#8217;d like full screen (I&#8217;d prefer borderless window but that&#8217;s not something I&#8217;m sure I can do with DOSBOX) at the host machine&#8217;s resolution, so I don&#8217;t encounter a crap ton of resolution switching on my monitor if I want to look at manuals or reference cards.  </p>



<p>In the past, I would manually tweak  a GOG games unique DOSBOX config to my liking, with generally these settings:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91;sdl]
fullscreen=true
fullresolution=desktop
output=opengl

&#91;render]
aspect=true
</pre></div>


<p>GOG stores the main dosbox config for each game in the game&#8217;s <code>dosbox&lt;abbreviation&gt;.conf</code> file.  So for Heroes of Might and Magic 1, that ends up being <code>dosboxHOMM1.conf</code>.  I may automate some of these changes, but for now I&#8217;m manually doing these to see how things play out first.  In fact, each GOG game gets its own DOSBOX copy stored underneath the game&#8217;s main directory:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="670" height="280" src="https://krystof.io/wp-content/uploads/2022/08/image-26.png" alt="" class="wp-image-1993" srcset="https://krystof.io/wp-content/uploads/2022/08/image-26.png 670w, https://krystof.io/wp-content/uploads/2022/08/image-26-300x125.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-26-585x244.png 585w" sizes="(max-width: 670px) 100vw, 670px" /></figure></div>


<p>The game loads up fine, though I do find it annoying that if I alt-tab out to look up a page in the manual and go back, DOSBOX reverts to the window, I have to hit alt-enter to go back to full screen.  At least I don&#8217;t have the monitor itself changing resolutions on top of it.  DOSBOX-X, thankfully, doesn&#8217;t do that, but we&#8217;ve not converted our GOG HOMM to DOSBOX-X yet.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-25-1024x770.png" alt="" class="wp-image-1992" width="512" height="385" srcset="https://krystof.io/wp-content/uploads/2022/08/image-25-1024x770.png 1024w, https://krystof.io/wp-content/uploads/2022/08/image-25-300x226.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-25-768x578.png 768w, https://krystof.io/wp-content/uploads/2022/08/image-25-1170x880.png 1170w, https://krystof.io/wp-content/uploads/2022/08/image-25-585x440.png 585w, https://krystof.io/wp-content/uploads/2022/08/image-25-1320x993.png 1320w, https://krystof.io/wp-content/uploads/2022/08/image-25.png 1436w" sizes="(max-width: 512px) 100vw, 512px" /><figcaption>Nostalgia nosebleed!</figcaption></figure></div>


<h2 class="wp-block-heading" id="h-dosbox-x-install-and-initital-configuration">DOSBOX-X install and initital configuration</h2>



<p>Now, I&#8217;ve installed my generic DOSBOX-X copy in a single directory under my D:\Emulators path:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="725" height="470" src="https://krystof.io/wp-content/uploads/2022/08/image-27.png" alt="" class="wp-image-1994" srcset="https://krystof.io/wp-content/uploads/2022/08/image-27.png 725w, https://krystof.io/wp-content/uploads/2022/08/image-27-300x194.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-27-585x379.png 585w" sizes="(max-width: 725px) 100vw, 725px" /></figure></div>


<p>Now, as far as DOSBOX-X goes, I&#8217;ve edited the dosbox-x.conf that comes with the download and tweaked to my liking.  </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91;sdl]
output=opengl
fullscreen=true
autolock=true
autolock_feedback = none

&#91;render]
aspect         = true
aspect_ratio   = 4:3
glshader       = crt-lottes-krystof.glsl

</pre></div>


<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>While I used opengl, the default output of DOSBOX-X is &#8216;ttf&#8217;, which looks really, really cool, but totally breaks retro immersion. 🙂<br><br>Also, you&#8217;ll notice I&#8217;m now forcing everything to 4:3.  Will that bite me later? Maybe, and probably for specific games, we&#8217;ll see.</div></div>



<p>You may notice the glshader entry in there.  That&#8217;s a custom one I was tweaking &#8211; you can make your own or point to one of the built in defaults under the glshaders directory.  Definitely something to play around with.</p>



<h2 class="wp-block-heading">Swapping HOMM&#8217;s DOSBOX for my DOSBOX-X</h2>



<p>If I run dosbox-x.exe, it works, and everything is happy.  Now, the question I have&#8230; Can I somehow swap out the DOSBox that my GOG Heroes of Might and Magic usses to use my global DOSBox-X directly?  It leads me to other questions:</p>



<ul><li>How do we point a GOG game to use my dosbox-X under D:\emulators\dosbox-x?  What about configs?</li><li>If we can swap a GOG&#8217;s dosbox to dosbox-x, can one dosbox-x config handle all the GOG games? Probably not</li><li>How do we have a common config and allow overrides as needed with dosbox-x? </li><li>How can we take a GOG&#8217;s customized DOSBOX-.74 config and overlay them on top of my global DOSBOX-X config?</li></ul>



<p>First off, the manual approaches.  Even if this works for one game, that doesn&#8217;t mean it will work for all, so I anticipate having to come back and make changes.  Perhaps I can automate some of them.</p>



<p>HOMM GOG&#8217;s DOSBox has multiple configuration files:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-28.png" alt="" class="wp-image-1995" width="220" height="91"/></figure></div>


<p>The launcher link also calls this, and starts with the current directory set to <em> inside it&#8217;s local DOSBOX folder</em>:</p>



<p><code>"D:\GOG Galaxy\Games\HoMM\DOSBOX\DOSBox.exe" -conf "..\dosboxHOMM1.conf" -conf "..\dosboxHOMM1_single.conf" -noconsole -c "exit"</code></p>



<p>So we can see they&#8217;re already using overrides &#8211; the &#8216;single&#8217; conf file overrides their HOMM global config file.  We also have some relative paths in there, going to the parent directory (which is the HOMM install).  The &#8216;single&#8217; file seems to be more of the autoexec related work, and doesn&#8217;t try to override much in the way of rendering, though it does shut ipx off.</p>



<h3 class="wp-block-heading">Brute Force &#8211; Duplicate DOSBOX-X and use it against the GOG HOMM&#8217;s DOSBOX 0.74 configs</h3>



<p>How can I swap out the EXE?  I could just copy all of dosbox-x and duplicate a game-unique DOSBOX install inside HOMM&#8217;s dosbox directory, which is effectively what they do.  Let&#8217;s try that, and rename dosbox-x.exe to just dosbox.  This means we won&#8217;t have to change the shortcut.  I did that and to be sure, deleted any dosbox-x.config files in my HOMM dosbox copy.  So now we have the DOSBOX-X binary being executed, but using the dosboxHOMM config files, which we know target the original DOSBOX-0.74 version.  <strong>Just because we&#8217;re using DOSBOX-X binaries doesn&#8217;t mean we can assume DOSBOX 0.74 configs will just work 100% without flaw.</strong>  At least I wouldn&#8217;t think so.  Perhaps I have trust issues.</p>



<p><strong>Result?  Successful </strong><em>proof of concept</em>.  It worked &#8211; with a side note.  I had to click into the program and heard an audible &#8216;click&#8217; when I activated the window.  I don&#8217;t recall that being a thing.  But we aren&#8217;t taking advantage of any spiffy DOSBOX-X configs, and if there are any defaults in our global dosbox-x we set, we&#8217;re not picking them up, since we made a complete duplicate dosbox-x.  It&#8217;s not what I want long term.</p>



<h3 class="wp-block-heading">Next step &#8211; Overwrite dosboxHOMM1.conf with our dosbox-x global config contents.</h3>



<p>I tried this just to see if it would still load.  Now what this also means is that we would lose ANY HOMM specific dosbox configurations since we&#8217;re going to replace it with dosbox-x.  So things like CPU cycle settings, sound card configs, xms,ems settings, etc. that GOG curators put in there would be lost.  This probably won&#8217;t fly long term, just wanted to see how well it would work.  So, I wiped did a copy and paste of the file contents of my global dosbox-x.conf into the file dosboxHOMM1.conf.</p>



<p><strong>Result? Mixed but doable</strong>.  We did get the shader working, but a couple of oddities.  The mouse only worked in full screen mode.  In window mode (for dosbox x you toggle full screen with F11-F) I couldn&#8217;t get a mouse cursor anymore.  Switching back to fullscreen fixed that.  To solve this, I needed to change my dosbox-x.config:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91;sdl]
autolock=true
autolock_feedback = none
</pre></div>


<p>autolock_feedback set to none removes the &#8216;click&#8217; when dosbox locks the mouse (that same audible click I heard the first attempt).  Your call.  You can hit CTRL-F10 to unlock the mouse again.  </p>



<p>Dont&#8217;t forget, we <em>copied</em> our dosbox-x.conf contents into dosboxHOMM1.conf.  That&#8217;s not a good long term solution, we&#8217;re just doing proof of concept.</p>



<p>So, that worked, but it worked <em>this time.</em>.. I totally expect some games to not tolerate this, because something in the game specific DOSBOX config would be lost if we did this for each game.  You can see with the autolock we already had a deviation from the dosbox-x default, but in this case, I&#8217;m fine with changing it.  However, it won&#8217;t always be the case &#8211; what if a DOS game wants EMS memory setup but another DOS game crashes because of it?  I suspect I&#8217;ll have to handle those cases.</p>



<p>What would be useful is a program that parses dos box config files, looks for values that don&#8217;t match default or ignorable patterns, and reports just meaningful differences.   Then we can take those differences, put them in the override dosbox config (<code>e.g. dosboxHOMM1_single.conf</code>), and still use our generic dosbox-x.conf as the primary for <strong>all</strong> of our games.  That&#8217;d be great, because if we want a different shader, they automatically apply to all the games.  We can still use the override file if we want to change it for a specific game, too.</p>



<p>What about those .lnk (Windows Shortcut) files?  GOG is using those to launch from it&#8217;s launcher.  If I import GOG games into LaunchBox, it&#8217;s going to use those .lnk files as well.  I&#8217;d like to leave the link intact, but I may need to modify them if I want to try to make some global dosbox.config usable.  But say I could do that, what does that look like?</p>



<h2 class="wp-block-heading">Attempting to use a single DOSBOX-X install and base config for multiple GOG games</h2>



<p>Let&#8217;s see if this even works before I worry about modifying Windows Shortcut links.</p>



<p>Resetting our GOG HOMM from scratch again&#8230;(Backups backups backups)</p>



<p>Recall our initial .lnk shortcut pointed this way and starts with the current directory set to <em> inside it&#8217;s local DOSBOX folder</em>:</p>



<p><code>"D:\GOG Galaxy\Games\HoMM\DOSBOX\DOSBox.exe" -conf "..\dosboxHOMM1.conf" -conf "..\dosboxHOMM1_single.conf" -noconsole -c "exit"</code></p>



<p>That means <code>dosboxHOMM1_single.conf</code> is referencing paths from the standpoint of our GOG HOMM&#8217;s DOSBox directory.  So we must start our command there just like the link does.  But if we want to use a global DOSBOX config in our <code>D:\Emulators\dosbox-x</code>, we&#8217;re at a bit of an impasse.  </p>



<p>So, in a command line prompt, I switched to the GOG HOMM DOSBOX directory and ran this command line instead from the GOG HOMM DOSBOX dir:</p>



<p><code>D:\GOG Galaxy\Games\HoMM\DOSBOX&gt; d:\Emulators\dosbox-x\dosbox-x.exe -conf "d:\Emulators\dosbox-x\dosbox-x.conf" -conf "../dosboxHOMM1_single.conf"</code></p>



<p>This actually worked.  I was surprised, since I half expected it to not find my custom shader, but it looks like dosbox-x is looking in it&#8217;s folders appropriately.  But what about any DOSBOX junk in the GOG HOMM folder left over?  We&#8217;re not actually using that DOSBOX anymore, we&#8217;re just starting in that directory so the relative paths in our <code>dosboxHOMM1_single.conf </code>work. </p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="767" src="https://krystof.io/wp-content/uploads/2022/08/image-29-1024x767.png" alt="" class="wp-image-2001" srcset="https://krystof.io/wp-content/uploads/2022/08/image-29-1024x767.png 1024w, https://krystof.io/wp-content/uploads/2022/08/image-29-300x225.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-29-768x575.png 768w, https://krystof.io/wp-content/uploads/2022/08/image-29-1170x876.png 1170w, https://krystof.io/wp-content/uploads/2022/08/image-29-585x438.png 585w, https://krystof.io/wp-content/uploads/2022/08/image-29-1320x989.png 1320w, https://krystof.io/wp-content/uploads/2022/08/image-29.png 1442w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Nostalgia nosebleed with DOSBOX-X and custom shader</figcaption></figure></div>


<p>My current plan is as follows for each GOG game, and summarizes the plan based on our results above:</p>



<ul><li>Modify the .lnk to point to our DOSBox-X base config, but still utilize the game-specific override config<ul><li>I&#8221;ll look at this GitHub repo and maven artifact: <a href="https://github.com/DmitriiShamrikov/mslinks" target="_blank" rel="noreferrer noopener">https://github.com/DmitriiShamrikov/mslinks</a> which seems to allow me to edit windows shortcuts programmatically.</li><li>Using that, I now have some throwaway-ish Java code that does the following:<ul><li>Spin through GOG games via network share to my retro machine</li><li>Look for a shortcut in each game root folder</li><li>If shortcut has dosbox in its target, make backups of the GOG DOSBOX config files.</li><li>Point the first config in the shortcut to our dosbox-x global config under <code>D:\Emulators\dosbox-x</code> instead of the GOG game specific primary dosbox.config</li><li>Change the shortcut target to point to our dosbox-x.exe in <code>D:\Emulators\dosbox-x</code></li></ul></li></ul></li><li><strong>If a game doesn&#8217;t &#8216;just work&#8217; with DOSBox-X: </strong>Look at the now abandoned &#8216;GOG-specific&#8217; dosbox config and determine if anything unique to that GOG game needs to be put in the override config.  See if we can automate this looking for the most common reasons a DOSBox game would have issues (e.g. cpu cycles)<ul><li>I&#8217;ll have to find a DOSBox properties parser or roll my own.  We need to support [bracket] sections and retain linefeeds and comments.  <strong>I searched around a bit and </strong>though I found some INI file parsers, they didn&#8217;t handle the DOSBOX autoexec section very well (since they&#8217;re not key-value pairs).  Ended up rolling my own simple parsing mechanism that gets the job done.  </li></ul></li></ul>



<h2 class="wp-block-heading">Progressing through my GOG installs</h2>



<p>After figuring out how to do this for Heroes of Might and Magic 1 and 2 (the rest in the series are native windows apps from GOG), I continued on with my other GOG installs.  Anything of interest noted below:</p>



<h2 class="wp-block-heading">DOSBOX Settings I take from the GOG install and put into the override file before pointing a GOG game at DOSBOX-X</h2>



<p>My thought is that I only want to take certain settings out of GOG&#8217;s DOSBOX-0.74 config and put them into the override file.  If I take everything, it would overwrite full screen and shader settings that I want to utilize with the DOSBOX-X binaries and my global config.  </p>



<p>I thought it&#8217;d be an interesting exercise to look at ALL GOG DOSBOX configs at once and count occurrences of unique key value pairs.  Here&#8217;s the raw dump:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
Occurences of keys/values across all dosbox GOG configs:
83	 cpu.core.auto
4	 cpu.core.dynamic
3	 cpu.core.normal
9	 cpu.core.simple
1	 cpu.coretype.auto
5	 cpu.cputype.386_slow
5	 cpu.cputype.486_slow
86	 cpu.cputype.auto
1	 cpu.cputype.pentium_slow
3	 cpu.cycledown.100
88	 cpu.cycledown.1000
1	 cpu.cycledown.10000
2	 cpu.cycledown.20
1	 cpu.cycledown.50
2	 cpu.cycledown.500
2	 cpu.cycledown.5000
1	 cpu.cycles.10000
1	 cpu.cycles.100000
1	 cpu.cycles.11000
1	 cpu.cycles.15000
2	 cpu.cycles.19000
2	 cpu.cycles.20000
1	 cpu.cycles.300
1	 cpu.cycles.3000
1	 cpu.cycles.35000
1	 cpu.cycles.4000
3	 cpu.cycles.500
2	 cpu.cycles.5000
1	 cpu.cycles.50000
1	 cpu.cycles.7500
2	 cpu.cycles.8000
1	 cpu.cycles.80000
1	 cpu.cycles.9000
29	 cpu.cycles.auto
2	 cpu.cycles.auto limit 16000
1	 cpu.cycles.fixed 10000
1	 cpu.cycles.fixed 12500
2	 cpu.cycles.fixed 14000
1	 cpu.cycles.fixed 15000
2	 cpu.cycles.fixed 30000
1	 cpu.cycles.fixed 35000
1	 cpu.cycles.fixed 6000
1	 cpu.cycles.fixed 60000
1	 cpu.cycles.fixed 7000
1	 cpu.cycles.fixed 8000
33	 cpu.cycles.max
2	 cpu.cycleup.10
3	 cpu.cycleup.100
88	 cpu.cycleup.1000
1	 cpu.cycleup.10000
1	 cpu.cycleup.50
2	 cpu.cycleup.500
2	 cpu.cycleup.5000
1	 dos.automount.true
2	 dos.ems.false
97	 dos.ems.true
1	 dos.files.127
93	 dos.keyboardlayout.auto
6	 dos.keyboardlayout.none
99	 dos.umb.true
99	 dos.xms.true
98	 dosbox.captures.capture
98	 dosbox.language.
98	 dosbox.machine.svga_s3
1	 dosbox.machine.vesa_nolfb
83	 dosbox.memsize.16
9	 dosbox.memsize.30
3	 dosbox.memsize.32
3	 dosbox.memsize.63
1	 dosbox.memsize.8
1	 dosbox.vmemsize.4
1	 glide.glide.true
1	 glide.grport.600
1	 glide.lfb.full
3	 gus.dma1.3
3	 gus.dma2.3
96	 gus.gus.false
2	 gus.gus.true
96	 gus.gusbase.240
93	 gus.gusdma.3
93	 gus.gusirq.5
7	 gus.gusrate.22050
89	 gus.gusrate.44100
3	 gus.irq1.5
3	 gus.irq2.5
96	 gus.ultradir.C:\ULTRASND
1	 innova.innova.false
1	 innova.quality.0
1	 innova.samplerate.22050
1	 innova.sidbase.280
2	 ipx.Connection.0
2	 ipx.Enable.0
7	 ipx.ipx.false
98	 joystick.autofire.false
64	 joystick.buttonwrap.false
34	 joystick.buttonwrap.true
1	 joystick.joysticktype.2axis
97	 joystick.joysticktype.auto
95	 joystick.swap34.false
3	 joystick.swap34.true
6	 joystick.timed.false
92	 joystick.timed.true
1	 log.bios.true
1	 log.cpu.true
1	 log.dma_control.true
1	 log.dosmisc.true
1	 log.exec.true
1	 log.fcb.true
1	 log.files.true
1	 log.fpu.true
1	 log.gui.true
1	 log.int10.true
1	 log.io.true
1	 log.ioctl.true
1	 log.keyboard.true
1	 log.logfile.
1	 log.misc.true
1	 log.mouse.true
1	 log.paging.true
1	 log.pci.true
1	 log.pic.true
1	 log.pit.true
1	 log.sblaster.true
1	 log.vga.true
1	 log.vgagfx.true
1	 log.vgamisc.true
4	 midi.config.
4	 midi.device.default
94	 midi.midiconfig.
94	 midi.mididevice.default
98	 midi.mpu401.intelligent
1	 midi.mt32rate.auto
87	 mixer.blocksize.1024
10	 mixer.blocksize.2048
2	 mixer.blocksize.4096
98	 mixer.nosound.false
6	 mixer.prebuffer.20
3	 mixer.prebuffer.240
68	 mixer.prebuffer.25
1	 mixer.prebuffer.30
4	 mixer.prebuffer.40
1	 mixer.prebuffer.512
16	 mixer.prebuffer.80
5	 mixer.rate.22050
93	 mixer.rate.44100
1	 mixer.swapstereo.false
1	 ne2000.macaddr.AC:DE:48:88:99:AA
1	 ne2000.ne2000.true
1	 ne2000.nicbase.300
1	 ne2000.nicirq.3
1	 ne2000.realnic.list
1	 parallel.parallel1.disabled
1	 parallel.parallel2.disabled
1	 parallel.parallel3.disabled
1	 printer.docpath..
1	 printer.dpi.360
1	 printer.height.110
1	 printer.multipage.false
1	 printer.printer.true
1	 printer.printoutput.png
1	 printer.timeout.0
1	 printer.width.85
73	 render.aspect.false
26	 render.aspect.true
1	 render.char9.false
99	 render.frameskip.0
1	 render.linewise.false
1	 render.multiscan.false
1	 render.scaler.hardware2x
2	 render.scaler.none
96	 render.scaler.normal2x
1	 sblaster.dma.0
98	 sblaster.dma.1
1	 sblaster.hardwarebase.220
99	 sblaster.hdma.5
1	 sblaster.irq.10
33	 sblaster.irq.5
65	 sblaster.irq.7
4	 sblaster.mixer.true
4	 sblaster.oplemu.compat
89	 sblaster.oplemu.default
1	 sblaster.oplemu.old
96	 sblaster.oplmode.auto
2	 sblaster.oplmode.opl3
7	 sblaster.oplrate.22050
91	 sblaster.oplrate.44100
99	 sblaster.sbbase.220
94	 sblaster.sbmixer.true
93	 sblaster.sbtype.sb16
6	 sblaster.sbtype.sbpro1
98	 sdl.autolock.true
99	 sdl.fulldouble.false
5	 sdl.fullresolution.
74	 sdl.fullresolution.desktop
20	 sdl.fullresolution.original
99	 sdl.fullscreen.true
70	 sdl.mapperfile.mapper-0.74-2.map
16	 sdl.mapperfile.mapper-0.74.map
1	 sdl.mapperfile.mapper-SVN.map
2	 sdl.mapperfile.mapper.map
10	 sdl.mapperfile.mapper.txt
1	 sdl.output.OpenGL
5	 sdl.output.ddraw
1	 sdl.output.direct3d
5	 sdl.output.opengl
84	 sdl.output.overlay
3	 sdl.output.surface
1	 sdl.overscan.0
1	 sdl.pixelshader.none
98	 sdl.priority.higher,normal
95	 sdl.sensitivity.100
3	 sdl.sensitivity.500
98	 sdl.usescancodes.true
98	 sdl.waitonerror.true
99	 sdl.windowresolution.original
1	 serial.serial1.disabled
97	 serial.serial1.dummy
97	 serial.serial2.dummy
1	 serial.serial2.nullmodem port:23
98	 serial.serial3.disabled
98	 serial.serial4.disabled
1	 speaker.disney.false
97	 speaker.disney.true
9	 speaker.pcrate.22050
89	 speaker.pcrate.44100
98	 speaker.pcspeaker.true
98	 speaker.tandy.auto
9	 speaker.tandyrate.22050
89	 speaker.tandyrate.44100
1	 vsync.vsyncmode.off
1	 vsync.vsyncrate.75

</pre></div>


<p>I did this just to get a quick look at how many configs really change between all the GOG Games.  As I suspected, we find a wide variety of cpu section settings.  We had 2 that turned off EMS memory, and a few that changed the memsize.  Quite a few twists in the joystick section, and a few other oddities here and there.  So just by looking at this, I changed my program to take some additional overrides.</p>



<p>So, the little local snippet of code I wrote looks at my DOSBOX-X main config and each GOG&#8217;s DOSBOX config and compares the following, taking the GOG config and overriding just for that game.  </p>



<figure class="wp-block-table"><table><tbody><tr><td><strong>Section Name</strong></td><td><strong>Keys of Note</strong></td></tr><tr><td>[sdl],[render]</td><td>I don&#8217;t bring the GOG values into the game specific override, this is typically where we&#8217;re configuring my preferred aspect ratio and shader usage.</td></tr><tr><td>Any other sections, e.g. [cpu], [dos], [dosbox], [joystick], [sblaster], [midi], [mixer], [speaker],[gus]&#8230;.</td><td>I took all values from GOG&#8217;s game and put them in the override file.</td></tr></tbody></table></figure>



<p>While HOMM worked just fine without taking [cpu] settings, the next game I tried was Alone in the Dark, and with default DOSBox-X settings, it slowed to a crawl.  Turns out GOG had tweaked their primary Alone in the Dark DOSBOX-0.74 config:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
core -&gt; simple
cputype -&gt; pentium_slow
cycles -&gt; 11000
cycleup -&gt; 1000
cycledown -&gt; 1000
</pre></div>


<p>This is why [cpu] is one of the sections I take from GOG&#8217;s curated game-specific configuration.</p>



<h2 class="wp-block-heading">Game specific tweaks I had to make</h2>



<p>Here&#8217;s the log of games I installed and any interesting tweaks I had to make to convert them to use my DOSBox-X install.</p>



<figure class="wp-block-table"><table><tbody><tr><td><strong>Game</strong></td><td><strong>Notes</strong></td></tr><tr><td>Magic Carpet Plus</td><td>I manually override the cpu config and render to shut the shader off, makes it easier to see the minimap dots.<br>CPU Config:<br>cycles=fixed 70000<br>cycleup=5000<br>cycledown=5000<br><br>This is so we can use &#8216;high res&#8217; mode by hitting &#8216;R&#8217; when the game starts.  Until then, it runs extremely fast.  <br></td></tr></tbody></table></figure>



<p></p>



<p></p>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/retro-gaming-pc-build-log-part-3-pc-games-with-gog/">Retro Gaming PC Build Log Part 3 : PC Games with GOG</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/retro-gaming-pc-build-log-part-3-pc-games-with-gog/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Retro Gaming PC Build Log]]></series:name>
	</item>
		<item>
		<title>Retro Gaming PC Build Log Part 2 : Commodore 64</title>
		<link>https://krystof.io/retro-gaming-pc-build-log-part-2-commodore-64/</link>
					<comments>https://krystof.io/retro-gaming-pc-build-log-part-2-commodore-64/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Mon, 15 Aug 2022 01:10:25 +0000</pubDate>
				<category><![CDATA[Retro Gaming]]></category>
		<category><![CDATA[Commodore]]></category>
		<category><![CDATA[VICE]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Emulation]]></category>
		<category><![CDATA[Build Log]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1882</guid>

					<description><![CDATA[<p>Working through LaunchBox and VICE emulator configs for Commodore 64 game emulation</p>
<p>The post <a rel="nofollow" href="https://krystof.io/retro-gaming-pc-build-log-part-2-commodore-64/">Retro Gaming PC Build Log Part 2 : Commodore 64</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on September 8, 2022.</p>
<p>Figured I&#8217;d start off with my favorite system &#8211; The Commodore 64.  Here are the key software components I used:</p>



<figure class="wp-block-table"><table><tbody><tr><td><a href="https://c64preservation.com/dp.php?pg=nibtools" target="_blank" rel="noreferrer noopener">Nib Tools</a></td><td>Used to convert any images that are .nib format to .G64 format that VICE can read.  D64 images are for unprotected (no copy protection) disks, while  .g64 and .nib are two formats that retain all of the copy protection.  So we&#8217;re going from NIB -&gt; G64</td></tr><tr><td>VICE 3.6.1 (<a href="https://vice-emu.sourceforge.io/windows.html" target="_blank" rel="noreferrer noopener" class="broken_link">Windows 64-bit SDL version</a>)</td><td>VICE is the emulator I&#8217;m most familiar with from my Diorama project and RetroPie tinkering, so I&#8217;ll continue with that here, same reason for the SDL version over GTK3.  </td></tr></tbody></table></figure>



<h2 class="wp-block-heading" id="h-nibconv-and-nib-disks">Nibconv and .NIB disks</h2>



<p>I have some disk images that are already the D64 or G64 type, and some that are .NIB.  I need to convert those using the nibconv from the Nib Tools package first.  A simple batch file that worked for me (drop it in the folder where you have nibconv.exe and .NIB files and it will handle the rest.  It deletes the G64 file first since mine would lock if the file already existed.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
for %%f in (*.nib) do (
	del &quot;%%~nf.g64&quot;
	nibconv &quot;%%~nf.nib&quot; &quot;%%~nf.g64&quot;
)
pause
</pre></div>


<h2 class="wp-block-heading">VICE install</h2>



<p>VICE doesn&#8217;t install &#8211; it just unpacks into a directory.  I put mine in a common emulators folder D:\Emulators\SDL2VICE-3.6.1-win64.  Underneath there are all sorts of binaries and such but the primary one is x64sc, and that&#8217;s what I&#8217;ll be configuring as I test out some games.</p>



<h2 class="wp-block-heading">First LaunchBox import and adding VICE as an emulator</h2>



<p>I put my Bruce Lee G64 file in a temporary directory just to try this out.  I&#8217;m going to let LaunchBox manage the Commodore 64 ROM files necessary, so it will &#8216;move it&#8217; into the LaunchBox Games directory on import:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image.png" alt="" class="wp-image-1892" width="542" height="399" srcset="https://krystof.io/wp-content/uploads/2022/08/image.png 722w, https://krystof.io/wp-content/uploads/2022/08/image-300x221.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-585x431.png 585w" sizes="(max-width: 542px) 100vw, 542px" /></figure></div>

<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-1.png" alt="" class="wp-image-1893" width="545" height="404" srcset="https://krystof.io/wp-content/uploads/2022/08/image-1.png 727w, https://krystof.io/wp-content/uploads/2022/08/image-1-300x222.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-1-585x434.png 585w" sizes="(max-width: 545px) 100vw, 545px" /></figure></div>


<p>Now here is where I may deviate from most.  I like the <em>idea</em> of RetroArch, and perhaps I&#8217;ll revisit it in the future, but I found while I can create global configurations to be shared across multiple emulators, I really liked having features in the later versions of emulators that don&#8217;t have an updated RetroArch core, or the core has crippled some features I desire.  So in general, I rarely use RetroArch at this time.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-2.png" alt="" class="wp-image-1894" width="548" height="409" srcset="https://krystof.io/wp-content/uploads/2022/08/image-2.png 731w, https://krystof.io/wp-content/uploads/2022/08/image-2-300x224.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-2-585x436.png 585w" sizes="(max-width: 548px) 100vw, 548px" /><figcaption>This page REALLY messed me up.  It actually populated RetroArch into the Associated Platforms list of the &#8216;Manually Configured Emulator&#8217;.  So I had to wipe those out (read on to see how that was diagnosed)</figcaption></figure></div>

<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-3.png" alt="" class="wp-image-1928" width="549" height="413" srcset="https://krystof.io/wp-content/uploads/2022/08/image-3.png 732w, https://krystof.io/wp-content/uploads/2022/08/image-3-300x225.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-3-585x440.png 585w" sizes="(max-width: 549px) 100vw, 549px" /></figure></div>


<p>For starters, all I&#8217;m populating is the name (VICE 64) and the location to x64sc.exe (The VICE C64 binary)</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="564" height="111" src="https://krystof.io/wp-content/uploads/2022/08/image-4-edited.png" alt="" class="wp-image-1932" srcset="https://krystof.io/wp-content/uploads/2022/08/image-4-edited.png 564w, https://krystof.io/wp-content/uploads/2022/08/image-4-edited-300x59.png 300w" sizes="(max-width: 564px) 100vw, 564px" /></figure></div>


<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="732" height="176" src="https://krystof.io/wp-content/uploads/2022/08/image-6.png" alt="" class="wp-image-1934" srcset="https://krystof.io/wp-content/uploads/2022/08/image-6.png 732w, https://krystof.io/wp-content/uploads/2022/08/image-6-300x72.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-6-585x141.png 585w" sizes="(max-width: 732px) 100vw, 732px" /></figure>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="733" height="129" src="https://krystof.io/wp-content/uploads/2022/08/image-7.png" alt="" class="wp-image-1935" srcset="https://krystof.io/wp-content/uploads/2022/08/image-7.png 733w, https://krystof.io/wp-content/uploads/2022/08/image-7-300x53.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-7-585x103.png 585w" sizes="(max-width: 733px) 100vw, 733px" /></figure>



<p>I let it populate all the checkboxes for both LaunchBox and EMU Movies.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-8.png" alt="" class="wp-image-1936" width="548" height="410" srcset="https://krystof.io/wp-content/uploads/2022/08/image-8.png 731w, https://krystof.io/wp-content/uploads/2022/08/image-8-300x224.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-8-585x437.png 585w" sizes="(max-width: 548px) 100vw, 548px" /></figure></div>

<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-9.png" alt="" class="wp-image-1937" width="543" height="403" srcset="https://krystof.io/wp-content/uploads/2022/08/image-9.png 724w, https://krystof.io/wp-content/uploads/2022/08/image-9-300x223.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-9-585x434.png 585w" sizes="(max-width: 543px) 100vw, 543px" /></figure></div>


<p>I leave these options as default:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="549" height="309" src="https://krystof.io/wp-content/uploads/2022/08/image-10.png" alt="" class="wp-image-1938" srcset="https://krystof.io/wp-content/uploads/2022/08/image-10.png 549w, https://krystof.io/wp-content/uploads/2022/08/image-10-300x169.png 300w" sizes="(max-width: 549px) 100vw, 549px" /></figure></div>

<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="722" height="204" src="https://krystof.io/wp-content/uploads/2022/08/image-11.png" alt="" class="wp-image-1939" srcset="https://krystof.io/wp-content/uploads/2022/08/image-11.png 722w, https://krystof.io/wp-content/uploads/2022/08/image-11-300x85.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-11-585x165.png 585w" sizes="(max-width: 722px) 100vw, 722px" /></figure></div>


<p>After searching the online databases for media, I now show Bruce Lee in my LaunchBox main view:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="628" height="420" src="https://krystof.io/wp-content/uploads/2022/08/image-12.png" alt="" class="wp-image-1940" srcset="https://krystof.io/wp-content/uploads/2022/08/image-12.png 628w, https://krystof.io/wp-content/uploads/2022/08/image-12-300x201.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-12-585x391.png 585w, https://krystof.io/wp-content/uploads/2022/08/image-12-263x175.png 263w" sizes="(max-width: 628px) 100vw, 628px" /></figure></div>


<h2 class="wp-block-heading">Testing the first game &#8211; Failure and Fix</h2>



<p>Double clicking on Bruce Lee does&#8230; nothing.  I see nothing.  I got nothing.  What gives?</p>



<p>I decide to launch the emulator directly (x64sc.exe in the VICE directory) and it worked fine:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-13.png" alt="" class="wp-image-1943" width="338" height="272" srcset="https://krystof.io/wp-content/uploads/2022/08/image-13.png 676w, https://krystof.io/wp-content/uploads/2022/08/image-13-300x241.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-13-585x470.png 585w" sizes="(max-width: 338px) 100vw, 338px" /></figure></div>


<p>I then decided to load the G64 image directly through VICE, bypassing LaunchBox.  Result:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-14.png" alt="" class="wp-image-1944" width="336" height="268" srcset="https://krystof.io/wp-content/uploads/2022/08/image-14.png 671w, https://krystof.io/wp-content/uploads/2022/08/image-14-300x239.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-14-585x466.png 585w" sizes="(max-width: 336px) 100vw, 336px" /></figure></div>


<p>Okay.  So now I now there&#8217;s something up with LaunchBox dealing with VICE.  I&#8217;m actually used to loading VICE first on my RetroPie and loading the image directly.  So this means I&#8217;ve got a command line argument issue.  Turns out LaunchBox tried to force my hand with RetroArch even though I wanted to configure the emulator manually!</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="288" height="224" src="https://krystof.io/wp-content/uploads/2022/08/image-16.png" alt="" class="wp-image-1946"/><figcaption>I didn&#8217;t ask for this, and I don&#8217;t want it.  It also pre populated entries in the &#8216;Associated Platforms&#8217; screen which causes it to think it needs a -f parameter and a RetroArch core.  </figcaption></figure></div>


<p>Perhaps I should have set the emulator up first, but if you run into this, you&#8217;ll see in your emulator config under &#8216;associated platforms&#8217; a WIDE list of items, and they also populate well known RetroArch cores.  </p>



<p>I missed the little &#8216;pop up&#8217; that stated it populated RetroArch for me.  I wish it hadn&#8217;t done that, it caused me a small headache.  So I went back into my VICE config and wiped out ALL of the associated platforms, left that tab, went back to an empty one (so it doesn&#8217;t show the RetroArch core column), and added one entry for Commodore 64 like so:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="143" src="https://krystof.io/wp-content/uploads/2022/08/image-15-1024x143.png" alt="" class="wp-image-1945" srcset="https://krystof.io/wp-content/uploads/2022/08/image-15-1024x143.png 1024w, https://krystof.io/wp-content/uploads/2022/08/image-15-300x42.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-15-768x108.png 768w, https://krystof.io/wp-content/uploads/2022/08/image-15-585x82.png 585w, https://krystof.io/wp-content/uploads/2022/08/image-15.png 1164w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>After that, VICE finally launched from LaunchBox properly:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/image-17.png" alt="" class="wp-image-1947" width="669" height="514" srcset="https://krystof.io/wp-content/uploads/2022/08/image-17.png 669w, https://krystof.io/wp-content/uploads/2022/08/image-17-300x230.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-17-585x449.png 585w" sizes="(max-width: 669px) 100vw, 669px" /><figcaption>Finally!</figcaption></figure></div>


<h2 class="wp-block-heading">Configuring VICE on Windows</h2>



<p>Great, now we know we can launch at least one game from LaunchBox using VICE.  Now I need to configure it to my tastes.  First off, it&#8217;s a tiny window in the center of the screen, and not full screen.  There are plenty of other things I like to configure for VICE, and here is where I&#8217;ll record those &#8216;default&#8217; settings I immediately set into the VICE configuration when I first install VICE.  I may tweak this over time but the settings below are my current reference settings of choice.</p>



<p>First off, VICE by default is storing it&#8217;s settings in C:\Users\&lt;userid&gt;\AppData\Roaming\vice.  Underneath there is a sdl-vice.ini after saving the first time and vice.log for any interesting execution log statements.  Good to know.</p>



<p>Side note: Try out wireless gamepads for the PC (Like XBOX controllers).  Luna loves chewing cables.</p>



<p>Here are the highlights for my VICE 3.61 Windows SDL version&#8217;s settings that deviate from the known defaults.</p>



<ul><li>SDL audio instead of WMM &#8211; Things sounded horrendous otherwise.</li><li>NTSC Mode vs Pal- I had NTSC, but sometimes images I have require PAL.  So I set up both</li><li>I set the VICE snapshots directory to the Snapshots directory I created underneath my C64 LaunchBox game folder for easier visibility.</li><li>I set the drive sound emulation to 1.  It&#8217;s just music to my ears.</li><li>Joystick &#8211; I set by default, Joystick 2 to my game controller (a generic gamepad), and Joystick 1 to the numeric keypad.  VICE by default sets my A button to Joystick firing, B button to bring up the VICE menu.  I manually set the Y button to toggle WARP speed on and off, and the X button to &#8216;swap&#8217; the Joystick ports.  I also set the left trigger to the &#8216;Load snapshot&#8217; menu, and the right trigger to &#8216;Save snapshot&#8217; menu.</li></ul>



<p>What I ended up doing was creating two emulator profiles &#8211; one for NTSC and one for PAL.  The two config files allow me to tweak the two &#8216;versions&#8217; of C64 emulation differently, and sometimes I just need to do that for some games.</p>



<p>VICE 64 &#8211; NTSC setup example (points to NTSC config)</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="648" height="200" src="https://krystof.io/wp-content/uploads/2022/08/image-23.png" alt="" class="wp-image-1978" srcset="https://krystof.io/wp-content/uploads/2022/08/image-23.png 648w, https://krystof.io/wp-content/uploads/2022/08/image-23-300x93.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-23-585x181.png 585w" sizes="(max-width: 648px) 100vw, 648px" /></figure>



<p>VICE 64 PAL &#8211; PAL setup example (points to PAL config)</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="619" height="205" src="https://krystof.io/wp-content/uploads/2022/08/image-22.png" alt="" class="wp-image-1977" srcset="https://krystof.io/wp-content/uploads/2022/08/image-22.png 619w, https://krystof.io/wp-content/uploads/2022/08/image-22-300x99.png 300w, https://krystof.io/wp-content/uploads/2022/08/image-22-585x194.png 585w" sizes="(max-width: 619px) 100vw, 619px" /></figure>



<p>Current reference settings:</p>



<p><strong>sdl-vice-ntsc.ini:</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91;C64SC]
SDLStatusbar=1
SoundDeviceName=&quot;sdl&quot;
VirtualDevice1=1
MachineVideoStandard=2
IECReset=1
CIA1Model=0
CIA2Model=0
KernalRev=-1
VICIIFullscreen=1
VICIIModel=3
SidModel=0
JoyPort10Device=0
JoyPort9Device=0
JoyPort8Device=0
JoyPort7Device=0
JoyPort6Device=0
JoyPort5Device=0
JoyPort4Device=0
JoyPort3Device=0
JoyDevice1=4
EventSnapshotDir=&quot;D:\LaunchBox\Games\Commodore 64\Snapshots\&quot;
GlueLogic=0
DriveSoundEmulation=1

</pre></div>


<p><strong>sdl-vice-pal.ini:</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91;C64SC]
SDLStatusbar=1
SoundDeviceName=&quot;sdl&quot;
VirtualDevice1=1
IECReset=1
CIA1Model=0
CIA2Model=0
KernalRev=-1
VICIIFullscreen=1
VICIIModel=0
SidModel=0
JoyPort10Device=0
JoyPort9Device=0
JoyPort8Device=0
JoyPort7Device=0
JoyPort6Device=0
JoyPort5Device=0
JoyPort4Device=0
JoyPort3Device=0
JoyDevice1=4
EventSnapshotDir=&quot;D:\LaunchBox\Games\Commodore 64\Snapshots\&quot;
GlueLogic=0
DriveSoundEmulation=1

</pre></div>


<p>LaunchBox specific settings:</p>



<p>Command line parameters:</p>



<ul><li>-chdir &#8220;D:\LaunchBox\Games\Commodore 64&#8221;  (Sets the autostart image directory to our games folder)</li></ul>



<h2 class="wp-block-heading">Game Specific Settings</h2>



<p>Game specific tweaks and oddities</p>



<figure class="wp-block-table"><table><tbody><tr><td><strong>Game</strong></td><td><strong>Command Line</strong></td></tr><tr><td>Jingle Disks</td><td>Couldn&#8217;t fix this with command line alone.  Must manually Load &#8220;Jingle&#8221;,8,1 and go from there.</td></tr></tbody></table></figure>
<p>The post <a rel="nofollow" href="https://krystof.io/retro-gaming-pc-build-log-part-2-commodore-64/">Retro Gaming PC Build Log Part 2 : Commodore 64</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/retro-gaming-pc-build-log-part-2-commodore-64/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Retro Gaming PC Build Log]]></series:name>
	</item>
		<item>
		<title>Retro Gaming PC Build Log Part 1 : Host PC and Front End</title>
		<link>https://krystof.io/retro-gaming-pc-build-log-part-1-host-pc-and-front-end/</link>
					<comments>https://krystof.io/retro-gaming-pc-build-log-part-1-host-pc-and-front-end/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Sun, 14 Aug 2022 18:10:49 +0000</pubDate>
				<category><![CDATA[Retro Gaming]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[MS-DOS]]></category>
		<category><![CDATA[GOG]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Emulation]]></category>
		<category><![CDATA[Build Log]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1841</guid>

					<description><![CDATA[<p>A fresh install of Windows and software for emulating and playing old installs from my software collection and third parties like Steam and GOG</p>
<p>The post <a rel="nofollow" href="https://krystof.io/retro-gaming-pc-build-log-part-1-host-pc-and-front-end/">Retro Gaming PC Build Log Part 1 : Host PC and Front End</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on August 14, 2022.</p>
<h2 class="wp-block-heading" id="h-the-goal">The Goal</h2>



<p>It seems when I&#8217;m able to come anywhere near close to dusting off some retro gaming work, I boot up whatever RetroPie or Windows based system I&#8217;ve set up for some retro gaming years back and can&#8217;t for the life of me remember how I set things up from either a taxonomy standpoint, controller setup, emulator configurations, and more.  I&#8217;m using these build logs to document my thought processes at the time and &#8216;Figure it out&#8217;.</p>



<h2 class="wp-block-heading" id="h-the-hardware">The Hardware</h2>



<p>Now, I&#8217;m not a retro gaming purist.  I&#8217;m at best <em>retro gaming purist adjacent.</em>  This means I love playing games on the older hardware, but with limited space, I can&#8217;t set up <em>all the things.</em>  I can set up some retro systems here and there, but I can&#8217;t set up everything in one big retro corner.  I&#8217;ve taken up enough corners in this house with my hobbies.  In fact, I&#8217;m fresh out of corners.  So, I&#8217;m going to emulate quite a bit, whether it&#8217;s Stella for the Atari 2600 or DOSBOX for Ultima Underworld.  I very much enjoy playing games on the original hardware when I can &#8211; but when it comes to easily streaming live content or looking up videos and articles about the game, it is very much easier to do it on a PC running emulation software.  Plus, I get to compare how the emulators compare to the real deal at my leisure. </p>



<p>Most of the time you don&#8217;t need a fancy machine to emulate old retro games &#8211; look at <a href="https://retropie.org.uk" target="_blank" rel="noreferrer noopener">RetroPie </a>for example.  You can emulate a metric crap ton of games on a Raspberry Pi.  The machine I chose is a bit beefier than I would need, but that&#8217;s because it&#8217;s available to me.  Why not a Pi?  I have a lot of DOS and Windows games as part of my &#8216;<a href="https://krystof.io/bucket-list/">Bucket List</a>&#8216; which rules out the Pi right quick &#8211; the Pi is great for certain computer and console emulation, but starts to have some issues in retro libraries of later eras (like Windows 9X games).  Plus, some of those may require some video acceleration &#8211; and for that I&#8217;ve an NVIDIA card to take care of the heavy lifting.  It&#8217;s not for the latest and greatest, but it will do for the oldest and greatest just fine.</p>



<p>It&#8217;s a 2018 ASUS GR8 II-6GT024Z VR Ready Mini PC Gaming Desktop with Intel Core i7-7700 and GeForce GTX 1060 6G Video Card.  All things considered it&#8217;s a powerhouse when it comes to what I need for retro gaming, even if it&#8217;s not available for purchase anymore and won&#8217;t be supported by Windows 11.</p>



<div class="wp-block-group is-layout-flow"><div class="wp-block-group__inner-container">
<div class="wp-block-columns is-layout-flex wp-container-3">
<div class="wp-block-column is-layout-flow">
<figure class="wp-block-image size-full is-resized"><img decoding="async" loading="lazy" src="https://krystof.io/wp-content/uploads/2022/08/asus-retro-machine.jpg" alt="" class="wp-image-1858" width="255" height="440" srcset="https://krystof.io/wp-content/uploads/2022/08/asus-retro-machine.jpg 509w, https://krystof.io/wp-content/uploads/2022/08/asus-retro-machine-174x300.jpg 174w" sizes="(max-width: 255px) 100vw, 255px" /><figcaption>I&#8217;ll run your Windows 10, pal, but that&#8217;s about it.  My dial doesn&#8217;t go to 11.</figcaption></figure>
</div>



<div class="wp-block-column is-layout-flow">
<p>Here are the basic specs:</p>



<figure class="wp-block-table"><table><tbody><tr><th>Processor</th><td>‎4.2 GHz core_i7</td></tr><tr><th>RAM</th><td>‎16 GB DDR4</td></tr><tr><th>Hard Drive</th><td>‎1 TB SSD</td></tr><tr><th>Graphics Coprocessor</th><td>‎NVIDIA GeForce GTX 1060</td></tr><tr><th>Chipset Brand</th><td>‎NVIDIA</td></tr><tr><th>Card Description</th><td>‎Dedicated</td></tr><tr><th>Graphics Card Ram Size</th><td>‎6 GB</td></tr><tr><th>Wireless Type</th><td>‎802.11ab</td></tr><tr><th>Number of USB 3.0 Ports</th><td>‎4</td></tr></tbody></table></figure>
</div>
</div>
</div></div>



<p class="has-text-align-left">So, while I type this, I&#8217;m performing that fresh Windows 10 install to start from scratch and begin the documentation process.  While we wait for that, let&#8217;s talk about the <strong>primary</strong> front end I&#8217;ll be using.</p>



<h2 class="wp-block-heading">Don&#8217;t forget to pack your LaunchBox</h2>



<p>I&#8217;ve tried a few front ends over the years, and most of the time they&#8217;re targeting specific emulating systems (MAME for example, has plenty of front ends, but that&#8217;s assuming you&#8217;re primarily dealing with MAME things).  I really adored HyperSpin in the mid 2010s, but I haven&#8217;t checked it out lately.  I think I&#8217;ll still use HyperSpin for a dedicated MAME cabinet (Project Pedestal), but I&#8217;m not considering it for this round.</p>



<p>I played around with LaunchBox quite a few years ago when it was in the early years, and I&#8217;ve been enjoying seeing the updates and enhancements (like BigBox) since then.  With the inherent support for multiple platforms and the capability for me to examine the datafiles (they&#8217;re stored in XML files inside the LaunchBox directory) easily, I can use LaunchBox to store configurations for the various games and I can also export that data to my &#8216;<a href="https://krystof.io/bucket-list/">Bucket List</a>&#8216; database, and from there I can auto populate my Twitch stream with box art, game metadata, and my personal high scores and playtime.  </p>



<p>I also wanted to be able to have some custom data points, which LaunchBox supports.  For example:</p>



<ul><li>Series Index &#8211; I use a field I call Series Index to indicate what order I should play a game when it&#8217;s part of a series.  Sometimes the titles aren&#8217;t an indicator (looking at you, GoldBox RPGs), and while I could use release date, I liked having a dedicated data-point.</li><li>Port Indicator &#8211; I don&#8217;t do this for all the games, but for some where I want to try out different versions, like say &#8216;BurgerTime&#8217; on Atari 2600, Intellivision, Commodore 64, etc. &#8211; I use this to link together individual game/platform combinations together.</li></ul>



<p>LaunchBox also has created a database to pull a lot of metadata down for recognized games, along with <a href="https://emumovies.com" target="_blank" rel="noreferrer noopener">EmuMovies </a>integration for video and additional art.  We can also pull down manuals, which is a big help so I don&#8217;t have to find the ASCII text files or open my game boxes up needlessly.  </p>



<p>So, I head over to the <a href="https://www.launchbox-app.com" target="_blank" rel="noreferrer noopener">LaunchBox </a>site, purchased a lifetime license, and went to work on the install.  You can of course install the free version, but I purchased it a looooong time ago, so I&#8217;m going to use my permanent license.</p>



<p>I&#8217;m leaving some hard drive space for the OS, but most of my stuff will be installed on a D: drive so I can keep some parts separated from the main OS.  We&#8217;ll see how well that works &#8211; ideally nothing should FORCE me to stay on the C: drive but you never know.  Personal preference, really &#8211; I could do all this on C: if I really wanted to.</p>



<p>After launching LaunchBox, I attached my GOG profile and my EmuMovies account subscription for future game and metadata downloads.</p>



<p>That&#8217;s it for this round.  Next chapters will probably be platform specific as I set up emulators and related utilities.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/retro-gaming-pc-build-log-part-1-host-pc-and-front-end/">Retro Gaming PC Build Log Part 1 : Host PC and Front End</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/retro-gaming-pc-build-log-part-1-host-pc-and-front-end/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Retro Gaming PC Build Log]]></series:name>
	</item>
		<item>
		<title>DOSBox Shaders Comparison For Modern DOS Retro Gaming</title>
		<link>https://krystof.io/dosbox-shaders-comparison-for-modern-dos-retro-gaming/</link>
					<comments>https://krystof.io/dosbox-shaders-comparison-for-modern-dos-retro-gaming/#comments</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Sun, 28 Jun 2020 14:46:58 +0000</pubDate>
				<category><![CDATA[Retro Gaming]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Dos Box]]></category>
		<category><![CDATA[Emulation]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1524</guid>

					<description><![CDATA[<p>Let's compare different dosbox shaders and see if we can make modern gaming look old again.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/dosbox-shaders-comparison-for-modern-dos-retro-gaming/">DOSBox Shaders Comparison For Modern DOS Retro Gaming</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on September 26, 2022.</p>
<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#050597;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>I&#8217;ve recently switched to DOSBOX-X for a more modern DOSBOX build with shaders support.  See how I configured that in the build log! <a href="https://krystof.io/retro-gaming-pc-build-log-part-3-pc-games-with-gog/">Retro Gaming PC Build Log Part 3 : PC Games with GOG</a></div></div>



<p>The basic version of DOSBox does not contain support for &#8216;shaders&#8217;. Those little bits of code and configuration that can make a modern retro gaming screen look cell shaded, dotted like an old school CRT monitor, or even curved and blurred like an old TV tube. So how do I get shaders? We have to utilize a fork or variant of DOSBox.  Let&#8217;s run a comparison of these shaders in a MSDOS Retro Gaming screenshot session of DOOM.</p>



<p>I have plans for three dioramas.  One is complete &#8211; the <a href="https://krystof.io/diorama-64-part-1-overview/">C64 years</a>.  I still have an Atari 2600 and IBM PC diorama to do, and the latter is a bit more technically challenging when it comes to actually playing the games.  Not only do I have to worry about DOS games, but Windows 3.1, Windows 95, and even some Windows 98 gaming, and attempting to make all of those games work on one small PC that will host the actual gameplay.</p>



<h2 class="wp-block-heading">Why DosBox at all?</h2>



<p>Between the old copies of games I have on CD and floppy images (I saved a lot of crap digitally if not physically), the actual CDs themselves, and sites like GOG.com, I&#8217;ll be able to relive a lot of my old gaming days.  This is, of course, thanks in no small part to a little program called <a aria-label="undefined (opens in a new tab)" href="https://www.dosbox.com/" target="_blank" rel="noreferrer noopener nofollow">DOSBox</a>.</p>



<p>From their site to explain it best:  <em>DOSBox is an emulator that recreates a MS-DOS compatible environment (complete with Sound, Input, Graphics and even basic networking). This environment is complete enough to run many classic MS-DOS games completely unmodified. </em></p>



<p>It&#8217;s the de facto standard for running DOS games on modern hardware.  </p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>This article refers to functionality I utilized in a specific DOSBox variant known as DOSBox Optionals, compiled by Marty Shepard.  More info on that below.</div></div>



<p></p>



<h3 class="wp-block-heading">I am 32 flavors and then some</h3>



<p>To that end, there&#8217;s almost always a variant of DOSBox that gains popularity for a while because DOSBox &#8216;proper&#8217; doesn&#8217;t support every single feature a DOS gamer might want to utilize when playing a game (e.g. Voodoo 3Dfx support).  There are a decent number of variants that fall under the label of &#8216;SVN Builds&#8217;, you can check em all out here: <a aria-label="undefined (opens in a new tab)" href="https://www.dosbox.com/wiki/SVN_Builds" target="_blank" rel="noreferrer noopener nofollow">https://www.dosbox.com/wiki/SVN_Builds</a>.  </p>



<p>One of the most popular variants today is called <a label="undefined (opens in a new tab)" href="https://dosboxece.yesterplay.net/" target="_blank" rel="noreferrer noopener nofollow" class="broken_link">DOSBox ECE</a>, standing for Enhanced Community Edition.  It emulates 3Dfx hardware and supports up to 384 MB of ram, two things that the standard DOSBox build doesn&#8217;t cover.  </p>



<p>Remember that you don&#8217;t have to use one version of DOSBox for every single game you play, although if you <em>could</em>, that would be ideal from a configuration management standpoint,  as each variant may have different config file options available.</p>



<p>Now we have variants like DOSBox X, SVN Daum, ECE, and even CRT, which first caught my eye because, while I don&#8217;t always play with shaders (I dislike them on VICE), I wanted to see what the DOSBox world had to offer me.  However, I wanted a relatively recent version of DOSBox with shaders.   The hunt begins.</p>



<h3 class="wp-block-heading">DOSBox CRT is close but no cigar</h3>



<p><a aria-label="undefined (opens in a new tab)" href="https://mattiasgustavsson.itch.io/dosbox-crt" target="_blank" rel="noreferrer noopener nofollow">DOSBox CRT</a> fit the bill at first &#8211; it&#8217;s essentially DOSBox 0.74 with a custom shader to give that real CRT look and feel.  As much as I liked the inner screen rendering of it, this version essentially paints a CRT border around the screen that becomes part of your DOSBox window&#8230; I did not find this palatable:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="726" src="https://krystof.io/wp-content/uploads/2020/06/dosbox-crt-1024x726.jpg" alt="" class="wp-image-1538" srcset="https://krystof.io/wp-content/uploads/2020/06/dosbox-crt-1024x726.jpg 1024w, https://krystof.io/wp-content/uploads/2020/06/dosbox-crt-300x213.jpg 300w, https://krystof.io/wp-content/uploads/2020/06/dosbox-crt-768x545.jpg 768w, https://krystof.io/wp-content/uploads/2020/06/dosbox-crt-1170x830.jpg 1170w, https://krystof.io/wp-content/uploads/2020/06/dosbox-crt-585x415.jpg 585w, https://krystof.io/wp-content/uploads/2020/06/dosbox-crt.jpg 1437w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Go away monitor border&#8230; I didn&#8217;t ask for you.</figcaption></figure>



<p>Good job and a nod to Mattias Gustavsson for compiling his custom shader work into DOSBox.  It just wasn&#8217;t for me.  So our hunt continues.  I didn&#8217;t want to use Retroarch for this, and I wanted something a little more recently maintained&#8230;</p>



<h3 class="wp-block-heading">An Optionals requirement is found</h3>



<p>I stumbled across another DOSBox variant called <a aria-label="undefined (opens in a new tab)" href="https://github.com/MartyShepard/DOSBox-Optionals" target="_blank" rel="noreferrer noopener nofollow">DOSBox Optionals</a>, created by Marty Shepard with near latest enhancements of DOSBox ECE, standard DOSBox, and other patches people have released that aren&#8217;t incorporated into the &#8216;standard DOSBox&#8217; build.  Marty has done a fantastic job of grouping all of these enhancements into a single DOSBox build that also supported the shader patch by <a aria-label="undefined (opens in a new tab)" href="https://github.com/duganchen/dosbox_shaders" target="_blank" rel="noreferrer noopener nofollow">duganchen</a>.  VOGONS thread about that support <a aria-label="undefined (opens in a new tab)" href="https://www.vogons.org/viewtopic.php?f=41&amp;t=43068" target="_blank" rel="noreferrer noopener nofollow">here</a>.  </p>



<p>I downloaded and extracted DOSBox Optionals and opened up the dosbox.conf.  Yikes! The sheer number of options and documentation to each option compared to the normal DOSBox install was amazing.  I recommend trying it out &#8211; I&#8217;ve tried a handful of titles with it thus far and they&#8217;ve worked, though I did discover a speech pitch issue.  I&#8217;ll cover that later in this post.</p>



<h2 class="wp-block-heading">Throwing Shade&#8230;rs.</h2>



<p>So without any &#8216;shaders&#8217;&#8230; What does DOSBox Optionals look like?  Let&#8217;s compare shader to non shader.   Given that I&#8217;m scaling my screen up, my no-shader view will have a slight blurring to it &#8211; but that&#8217;s not the shader.</p>



<p>Using DOSBox Optionals I took a &#8216;before and after&#8217; screen shot of &#8216;<strong>no shader</strong>&#8216; and the &#8216;<strong>crt-lottes_mod</strong>&#8216; shader.  You can drag the vertical slider below with your mouse and immediately see a difference.</p>


<div id="twenty20-1" class="twenty20" style="width: 100% !important; clear: both;"><div class="twentytwenty-container twenty20-1 t20-hover"><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/no-shader.jpg" /><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/dos-crt-lottes_mod.jpg" /></div><script>jQuery( document ).ready(function( $ ) {$(".twentytwenty-container.twenty20-1[data-orientation!='vertical']").twentytwenty({default_offset_pct: 0.5,move_slider_on_hover: true});$(".twenty20-1 .twentytwenty-before-label").html("No Shader");$(".twenty20-1 .twentytwenty-after-label").html("crt-lottes_mod");});</script></div>



<p>Please note that the new defaults <strong>(scaler=none, aspect=on)</strong> are needed for the shaders to work as designed.</p>



<p>The results?   Immediate shift to a more &#8216;dot-based&#8217; look, a little darker and very much closer to a curved CRT.  Compare yourself &#8211; the left side is without any shader and the right side is with &#8216;crt-lottes_mod&#8217; selected.  Drag the line to move your comparison from left to right.</p>



<p>Let&#8217;s zoom in and see what it looks like:</p>


<div id="twenty20-2" class="twenty20" style="width: 100% !important; clear: both;"><div class="twentytwenty-container twenty20-2 t20-hover"><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/closeup-no-shader.jpg" /><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/closeup-crt-lottes_mod-shader.jpg" /></div><script>jQuery( document ).ready(function( $ ) {$(".twentytwenty-container.twenty20-2[data-orientation!='vertical']").twentytwenty({default_offset_pct: 0.5,move_slider_on_hover: true});$(".twenty20-2 .twentytwenty-before-label").html("No Shader");$(".twenty20-2 .twentytwenty-after-label").html("crt-lottes_mod");});</script></div>



<p>I&#8217;m impressed.  You really get a sense of the dots and CRT nature of the view, and the phrase &#8216;dot pitch&#8217;, which I haven&#8217;t thought about in probably a decade, comes right back like it was yesterday.  This isn&#8217;t just any simple scan-line filter.</p>



<h3 class="wp-block-heading">Quick rundown of 13 shaders in DOSBox and DOOM</h3>



<p>What about some of the other shaders?  Let&#8217;s take a look &#8211; you can use the compare slider to look at the same screen shot of DOS and the same screen shot area of DOOM and compare shaders.  I imagine one shader might be good for one game and one for another &#8211; or if you&#8217;re playing CGA, EGA, VGA, or ANSI text games, you very well might want a specific kind of shader for those resolutions and colors.</p>


<div id="twenty20-3" class="twenty20" style="width: 100% !important; clear: both;"><div class="twentytwenty-container twenty20-3 t20-hover"><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/dosbox-doom-scanline-examples.jpg" /><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/dosbox-msdos-scanline-examples.jpg" /></div><script>jQuery( document ).ready(function( $ ) {$(".twentytwenty-container.twenty20-3[data-orientation!='vertical']").twentytwenty({default_offset_pct: 0.5,move_slider_on_hover: true});$(".twenty20-3 .twentytwenty-before-label").html("DOOM");$(".twenty20-3 .twentytwenty-after-label").html("DOS Text");});</script></div>



<p>For me, I&#8217;ve really got my eye on crt-lottes_mod and crt-easymode.  GTU looks like a contender as well.  Some of these other shaders are just nuts &#8211; FixingPixelArt gives one hell of a blur for example, and the xbr (#4,#5) shaders give it a &#8216;behind stained-glass&#8217; feel to me.</p>



<h3 class="wp-block-heading">Modifying shaders for testing</h3>



<p>As much as I like crt-lottes_mod, I have some tweaks I&#8217;d like to make:</p>



<ul><li>I don&#8217;t like curvature shaders.  I know it&#8217;s trying to be more realistic, it&#8217;s just so damn off-putting to me, I&#8217;d like to disable it.</li><li>It&#8217;s a little too dark &#8211; I&#8217;d like to increase the brightness a little bit.</li></ul>



<p>I started to wonder &#8211; if I do this, does it end up looking like crt-easymode?  Let&#8217;s tweak it a bit and find out.</p>



<p>I&#8217;m going to head over to the SHADERS/crt-lottes_mod.frag file and tweak a few values:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
#define warpX 0.000 //0.021, 0.007
#define warpY 0.000 //0.045, 0.021 
#define brightboost 1.0
</pre></div>


<p>Let&#8217;s compare crt-easymode to my custom-mod-v1:</p>


<div id="twenty20-4" class="twenty20" style="width: 100% !important; clear: both;"><div class="twentytwenty-container twenty20-4 t20-hover"><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/doom-title-crt-easymode-shader.jpg" /><img class="skip-lazy" src="https://krystof.io/wp-content/uploads/2020/06/doom-title-crt-lottes_mod-mycustom-shader.jpg" /></div><script>jQuery( document ).ready(function( $ ) {$(".twentytwenty-container.twenty20-4[data-orientation!='vertical']").twentytwenty({default_offset_pct: 0.5,move_slider_on_hover: true});$(".twenty20-4 .twentytwenty-before-label").html("crt-easymode");$(".twenty20-4 .twentytwenty-after-label").html("crt-lottes_mod w/ my customization");});</script></div>



<p>Granted, you could spend all day playing around with parameters, and while I feel the lottes_mod definitely has a lot more in the way of customization options, I&#8217;m leaning towards crt-easymode even with the modifications I made to flatten lottes and brighten the screen.  This is just to get something going to see if I like it enough.  It&#8217;s also a little lighter on the GPU than lottes will be from what I gather, which is good since I won&#8217;t be playing my DOSBox titles on a super high end modern machine.</p>



<h2 class="wp-block-heading">DOSBox Optionals comes with free Chipmunks</h2>



<p>Once I found a shader setting I wanted to try out for a bit, I needed to test a few titles on DOSBox Optionals to make sure it worked for my gaming tastes.  Optionals comes packaged with a demo for DUNE2, one of the first Real Time Strategy games, and a Westwood classic.</p>



<p>I fired up the demo and as soon as the voice synthesis came on, I could tell something was just a bit&#8230; chipmunky.  This was with default settings that come with the DOSBox Optionals install.  Listen to this:</p>



<figure class="wp-block-audio"><audio controls src="https://krystof.io/wp-content/uploads/2020/06/dune-intro-chipmunk.mp3"></audio></figure>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="800" height="492" src="https://krystof.io/wp-content/uploads/2020/06/dune-chipmunk.jpg" alt="" class="wp-image-1568" srcset="https://krystof.io/wp-content/uploads/2020/06/dune-chipmunk.jpg 800w, https://krystof.io/wp-content/uploads/2020/06/dune-chipmunk-300x185.jpg 300w, https://krystof.io/wp-content/uploads/2020/06/dune-chipmunk-768x472.jpg 768w, https://krystof.io/wp-content/uploads/2020/06/dune-chipmunk-585x360.jpg 585w" sizes="(max-width: 800px) 100vw, 800px" /><figcaption>I DID NOT SIGN UP FOR THIS</figcaption></figure>



<p>This did *not* happen running the same DUNE 2 demo on regular DOSBox, so I knew it was something specific to Optionals.  But what?  What patch is inserting Alvin into my games?  I found this <a aria-label="undefined (opens in a new tab)" href="https://www.vogons.org/viewtopic.php?t=33896" target="_blank" rel="noreferrer noopener nofollow">VOGONS thread</a> referencing elevated pitch in DOSBox, calling out this code in particular:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="415" src="https://krystof.io/wp-content/uploads/2020/06/image-1024x415.png" alt="" class="wp-image-1569" srcset="https://krystof.io/wp-content/uploads/2020/06/image-1024x415.png 1024w, https://krystof.io/wp-content/uploads/2020/06/image-300x121.png 300w, https://krystof.io/wp-content/uploads/2020/06/image-768x311.png 768w, https://krystof.io/wp-content/uploads/2020/06/image-1536x622.png 1536w, https://krystof.io/wp-content/uploads/2020/06/image-1170x474.png 1170w, https://krystof.io/wp-content/uploads/2020/06/image-585x237.png 585w, https://krystof.io/wp-content/uploads/2020/06/image.png 1702w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>I found a reference to Goldplay while searching the DOSBox Optionals repository:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="893" height="400" src="https://krystof.io/wp-content/uploads/2020/06/image-1.png" alt="" class="wp-image-1570" srcset="https://krystof.io/wp-content/uploads/2020/06/image-1.png 893w, https://krystof.io/wp-content/uploads/2020/06/image-1-300x134.png 300w, https://krystof.io/wp-content/uploads/2020/06/image-1-768x344.png 768w, https://krystof.io/wp-content/uploads/2020/06/image-1-585x262.png 585w" sizes="(max-width: 893px) 100vw, 893px" /></figure>



<p>Snippet pulled from <a href="https://github.com/MartyShepard/DOSBox-Optionals/blob/master/dosbox/tOptionals/src/hardware/sblaster.cpp" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">https://github.com/MartyShepard/DOSBox-Optionals/blob/master/dosbox/tOptionals/src/hardware/sblaster.cpp</a> at the time of this writing.</p>



<p>So, Goldplay.  We&#8217;re now just a bit above my pay grade &#8211; it&#8217;s DMA transfers, sample rates, and IRQ programming.  Nevertheless, I set <code>goldplay = true</code> in the dosbox.conf and voila:</p>



<figure class="wp-block-audio"><audio controls src="https://krystof.io/wp-content/uploads/2020/06/dune-intro-normal.mp3"></audio><figcaption>Good bye, Alvin.  The sands of Arrakis have finally rid us of your presence.</figcaption></figure>



<p>I&#8217;ll have to keep that configuration option in mind in the future if something seems off in Speech.  But between DUNE2, the demo and the game, along with Ultima Underworld, I needed to have this setting set to true for speech to sound proper.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>Got some shader settings you like?  I&#8217;d love to know if there&#8217;s a favorite preset or game/app you use a particular shader for.  I&#8217;ll probably stick with crt-easymode for now, though I might look at the shader configuration and tweak a few things and see what happens.  That&#8217;s what shader configs are all about &#8211; experimentation &#8211; because if a shader just isn&#8217;t doing anything for you, and it&#8217;s not reminding you of the monitor model you played that game on &#8211; tweak it!</p>



<h2 class="wp-block-heading">References</h2>



<ul><li><a href="https://github.com/MartyShepard/DOSBox-Optionals">https://github.com/MartyShepard/DOSBox-Optionals</a> &#8211; DOSBox Optionals Repo</li><li><a href="https://github.com/duganchen/dosbox_shaders">https://github.com/duganchen/dosbox_shaders</a> &#8211; Duganchen&#8217;s shaders included in DOSBox Optionals</li><li><a href="https://mattiasgustavsson.itch.io/dosbox-crt">https://mattiasgustavsson.itch.io/dosbox-crt</a> &#8211; DOSBox CRT Build</li><li><a href="https://www.vogons.org/viewtopic.php?t=33896">https://www.vogons.org/viewtopic.php?t=33896</a> &#8211; VOGONs thread regarding sample rate and DMA for SoundBlaster devices</li><li><a aria-label="undefined (opens in a new tab)" href="http://filthypants.blogspot.com/2015/04/more-crt-shaders.html" target="_blank" rel="noreferrer noopener nofollow">http://filthypants.blogspot.com/2015/04/more-crt-shaders.html</a> &#8211; A good article referencing example shots of these shaders utlized in other emulators like RetroArch.</li><li><a href="https://emulation.gametechwiki.com/index.php/CRT_Shaders">https://emulation.gametechwiki.com/index.php/CRT_Shaders</a> &#8211; General Shaders article &#8211; references a lot of shaders converted over to DOSBox (Duganchen&#8217;s build) and included in DOSBox Optionals.</li><li><a href="https://scalibq.wordpress.com/2017/03/12/dma-activation/">https://scalibq.wordpress.com/2017/03/12/dma-activation/</a> lots of technical information but references SoundBlaster GoldPlay</li></ul>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/dosbox-shaders-comparison-for-modern-dos-retro-gaming/">DOSBox Shaders Comparison For Modern DOS Retro Gaming</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/dosbox-shaders-comparison-for-modern-dos-retro-gaming/feed/</wfw:commentRss>
			<slash:comments>18</slash:comments>
		
		<enclosure url="https://krystof.io/wp-content/uploads/2020/06/dune-intro-chipmunk.mp3" length="184621" type="audio/mpeg" />
<enclosure url="https://krystof.io/wp-content/uploads/2020/06/dune-intro-normal.mp3" length="184621" type="audio/mpeg" />

			</item>
		<item>
		<title>MJPG-Streamer on a Raspberry Pi Zero W with a USB Webcam Streaming Setup</title>
		<link>https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/</link>
					<comments>https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/#comments</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Thu, 14 May 2020 16:58:46 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Featured]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1467</guid>

					<description><![CDATA[<p>Last Updated on October 5, 2022. After my recent move, the streaming and &#8216;workshop/den/laboratory&#8217; setup has been a lot of work from the ground up on the computer system side.&#8230;</p>
<p>The post <a rel="nofollow" href="https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/">MJPG-Streamer on a Raspberry Pi Zero W with a USB Webcam Streaming Setup</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on October 5, 2022.</p>
<p>After my recent move, the streaming and &#8216;workshop/den/laboratory&#8217; setup has been a lot of work from the ground up on the computer system side.  I used to have a Raspberry PI 4 used as a remote webcam that covered my old place&#8217;s 3D printing area.  While that worked, I never liked the idea of dedicating a whole Raspberry Pi 4 to that &#8211; I wanted to try a Raspberry Pi Zero W and see if it could handle the load.  Utilizing the popular MJPG-Streamer package, I was able to get that installed and running, though I had a few hiccups which I&#8217;ll reference at the bottom.</p>



<p>The article is a combination of various articles I found on the web, referencing older versions of one part or another, and this is a reference for my setup should I need to rebuild it.</p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>This article targets Raspberry PI Bullseye, Version dated 10-30-2021.</div></div>



<h2 class="wp-block-heading" id="h-hardware">Hardware</h2>



<ul><li>Raspberry Pi Zero W &#8211; Purchased one of those <a rel="noreferrer noopener" href="https://www.amazon.com/Vilros-Raspberry-Starter-Power-Premium/dp/B0748MPQT4" target="_blank">kits </a>on Amazon and it came with various cases and cables I needed, so I was happy with it.</li><li>Logitech USB Webcam</li><li>Power/HDMI/USB</li><li>Keyboard/Mouse</li></ul>



<h2 class="wp-block-heading" id="h-fresh-raspbian-install">Fresh Raspbian Install</h2>



<p>I&#8217;m utilizing the latest version of Raspbian as of this writing, which was released around February, 2020.  Flashing that to a simple 16 GB Micro SD Card for a blank slate:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="796" height="478" src="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47.png" alt="" class="wp-image-1472" srcset="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47.png 796w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47-300x180.png 300w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47-768x461.png 768w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_8-20-47-585x351.png 585w" sizes="(max-width: 796px) 100vw, 796px" /><figcaption>Always fresh, never frozen</figcaption></figure>



<p>Assuming you&#8217;re relatively familiar with the Pi, here&#8217;s the minimum I&#8217;m generally doing as post boot up task work:</p>



<ul><li>Changing default password</li><li>Setting Up Wifi</li><li>Enabling SSH</li><li>Setting Hostname</li><li>Setting Locale/Internationalization Options</li><li>Rebooting</li></ul>



<p>After that, the obligatory &#8216;update&#8217; install:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt update
sudo apt upgrade
</pre></div>


<p>I can now SSH into the Pi Zero W, disconnect the keyboard, and move along with the install.</p>



<h2 class="wp-block-heading" id="h-build-dependencies">Build Dependencies</h2>



<p>We need to download some things first before we can build mjpg-streamer.  I found some references to articles that pulled from the SVN repo to retrieve and compile, but I ended up getting a large amount of compile errors that look like some library was swapped but the source wasn&#8217;t updated.  It&#8217;s the <code>'redefinition of ‘struct statx_timestamp’'</code> error.</p>



<p>Instead of pulling the SVN version, I&#8217;m going to be pulling the Git repo of mjpg-streamer that was created by <a rel="noreferrer noopener" href="https://github.com/jacksonliam" target="_blank">jacksonliam</a>.  This (<a href="https://github.com/jacksonliam/mjpg-streamer" target="_blank" rel="noreferrer noopener">https://github.com/jacksonliam/mjpg-streamer</a>) is the &#8216;official&#8217; successor to the now abandoned SVN version at <a href="https://sourceforge.net/projects/mjpg-streamer/" target="_blank" rel="noreferrer noopener" class="broken_link">https://sourceforge.net/projects/mjpg-streamer/</a>.</p>



<p>We&#8217;ll now install our dependencies before we download and compile mjpg-streamer code:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt-get install build-essential libjpeg9-dev imagemagick libv4l-dev cmake git -y
</pre></div>


<h2 class="wp-block-heading" id="h-git-make-install">Git, Make, Install</h2>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
mkdir ~/mjpg-streamer
cd ~/mjpg-streamer

git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental

make
sudo make install
</pre></div>


<p>The make install will copy binaries, libraries and the www pages to the /usr/local/ directory structure:</p>



<ul><li><code>/usr/local/bin/mjpg_streamer</code> &#8211; The primary binary</li><li><code>/usr/local/lib/mjpg-streamer/</code> &#8211; The directory of input/output modules</li><li><code>/usr/local/share/mjpg-streamer/www</code> &#8211; The www server interface</li></ul>



<h2 class="wp-block-heading" id="h-test-the-build">Test The Build</h2>



<p>I&#8217;m going to test the build by plugging in a webcam into the Pi Zero W&#8217;s lone USB port.  Executing dmesg shows that it was loaded properly:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
&#91; 1275.662775] usb 1-1: New USB device found, idVendor=046d, idProduct=082d, bcdDevice= 0.11
&#91; 1275.662796] usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=1
&#91; 1275.662806] usb 1-1: Product: HD Pro Webcam C920
</pre></div>


<p>Let&#8217;s test by trying to run mjpg-streamer against the input_uvc.so plugin, since I&#8221;m not using a Raspi-Camera, but a USB one instead.  (<strong>See notes at the bottom about Raspberry Pi Bullseye and Raspi-Cameras</strong>).  I&#8217;ll also output using the http plugin.  So my testing command line looks like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
/usr/local/bin/mjpg_streamer -i &quot;input_uvc.so -f 15 -r 640x480&quot; \
 -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
</pre></div>


<p>Executing that line gives us a dump of data &#8211; here&#8217;s the relevant info:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
MJPG Streamer Version: git rev: 5a6e0a2db163e6ae9461552b59079870d0959340
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: 15
 i: Format............: JPEG
 i: TV-Norm...........: DEFAULT
 o: www-folder-path......: /usr/local/share/mjpg-streamer/www/
 o: HTTP TCP port........: 8080
 o: HTTP Listen Address..: (null)
 o: username:password....: disabled
 o: commands.............: enabled
</pre></div>


<p>Our key variables to tweak are <strong>-f for frame rate</strong>, and <strong>-r for resolution</strong>. I&#8217;ll change those later, but for a quick test I head on out to my browser and point it at the www server at http://cam-pi-zero.local:8080/</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="801" height="706" src="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40.png" alt="" class="wp-image-1477" srcset="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40.png 801w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40-300x264.png 300w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40-768x677.png 768w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-08-40-585x516.png 585w" sizes="(max-width: 801px) 100vw, 801px" /><figcaption>I always feel like&#8230; somebody&#8217;s watching me&#8230;</figcaption></figure>



<p>Not only do we see the web interface, but a snapshot of the web cam, which was, clearly, laying down on a workbench behind me while I tried this out.</p>



<p>Validating the stream worked (by clicking &#8216;Stream&#8217;) and turning around, I could see myself moving:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="734" height="706" src="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38.png" alt="" class="wp-image-1478" srcset="https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38.png 734w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38-300x289.png 300w, https://krystof.io/wp-content/uploads/2020/05/2020-05-14_11-09-38-585x563.png 585w" sizes="(max-width: 734px) 100vw, 734px" /><figcaption>Hello you&#8230; come here often?</figcaption></figure>



<p>You can now hit CTRL-C in your SSH window (or terminal) and quit the stream.  After this point, I could delete the build files I downloaded.</p>



<h2 class="wp-block-heading" id="h-tweaking-configuration">Tweaking configuration</h2>



<p>I wanted to run my camera at its intended resolution and at least a frame rate of 30fps.  To do that I modified my command line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#30fps, 1080 HD
/usr/local/bin/mjpg_streamer -i &quot;input_uvc.so -f 30 -r 1920x1080&quot; \
 -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
</pre></div>


<p>I then loaded my own stream up in VLC by opening the direct network path to the stream:</p>



<p>http://cam-pi-zero.local:8080?action=stream</p>



<p>That worked, and I get about a 1-2 second delay from Pi to VLC.  So I wouldn&#8217;t use this with audio feeds unless I was planning on creating a sync delay.  I&#8217;m using this to monitor 3D prints, or watch birds outside, so my use case does <strong>not</strong> demand low latency.  Is it exactly 30 frames per second?  No&#8230;. NO it&#8217;s not.</p>



<p>At 1280&#215;720, it seemed closer, but at 1920&#215;1080, when set at 30fps, it definitely wasn&#8217;t even close.  I&#8217;d guess more like 15.</p>



<p>The PI wasn&#8217;t maxed out on CPU, but it could just be the nature of USB 2.0 at this point.  I&#8217;m not sure how I can tell if it&#8217;s overloaded there or not, but, once again, this is a light monitoring video stream, I don&#8217;t care too much about latency.  It could be WiFi as well.  Someday I may dig in a bit more and find out where the bottleneck is.</p>



<p>I think you could probably choose either 1920&#215;1080 15fps or 1280&#215;720 30fps routes and be okay.</p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>Be careful about frames and resolution &#8211; Watch your CPU, but also make sure you don&#8217;t see messages about fps being &#8216;coerced&#8217; down or up.  Your mileage may vary, and you may have to tweak format, fps, and resolution settings further, check out the mjpg-streamer headquarters on their git hub page (see references down below).  You can also see the different modes available to your camera by using this command:</div></div>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
v4l2-ctl --list-formats-ext
</pre></div>


<h2 class="wp-block-heading" id="h-running-on-startup">Running On Startup</h2>



<p>I liked<a rel="noreferrer noopener" href="https://jacobsalmela.com/2014/05/31/raspberry-pi-webcam-using-mjpg-streamer-over-internet/" target="_blank" class="broken_link"> Jacob Salmela</a>&#8216;s script &#8211; all I did was change it for my command line on the stop and restart section for my resolution and frame-rate.  Save the following script by doing a sudo vi:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
sudo vi /etc/init.d/livestream.sh
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#!/bin/sh
# /etc/init.d/livestream.sh
### BEGIN INIT INFO
# Provides:          livestream.sh
# Required-Start:    $network
# Required-Stop:     $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: mjpg_streamer for webcam
# Description:       Streams /dev/video0 to http://IP/?action=stream
### END INIT INFO
f_message(){
        echo &quot;&#91;+] $1&quot;
}

# Carry out specific functions when asked to by the system
case &quot;$1&quot; in
        start)
                f_message &quot;Starting mjpg_streamer&quot;
                /usr/local/bin/mjpg_streamer -b -i &quot;input_uvc.so -f 15 -r 1920x1080&quot; -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
                sleep 2
                f_message &quot;mjpg_streamer started&quot;
                ;;
        stop)
                f_message &quot;Stopping mjpg_streamer…&quot;
                killall mjpg_streamer
                f_message &quot;mjpg_streamer stopped&quot;
                ;;
        restart)
                f_message &quot;Restarting daemon: mjpg_streamer&quot;
                killall mjpg_streamer
                /usr/local/bin/mjpg_streamer -b -i &quot;input_uvc.so -f 15 -r 1920x1080&quot; -o &quot;output_http.so -w /usr/local/share/mjpg-streamer/www&quot;
                sleep 2
                f_message &quot;Restarted daemon: mjpg_streamer&quot;
                ;;
        status)
                pid=`ps -A | grep mjpg_streamer | grep -v &quot;grep&quot; | grep -v mjpg_streamer. | awk ‘{print $1}’ | head -n 1`
                if &#91; -n &quot;$pid&quot; ];
                then
                        f_message &quot;mjpg_streamer is running with pid ${pid}&quot;
                        f_message &quot;mjpg_streamer was started with the following command line&quot;
                        cat /proc/${pid}/cmdline ; echo &quot;&quot;
                else
                        f_message &quot;Could not find mjpg_streamer running&quot;
                fi
                ;;
        *)
                f_message &quot;Usage: $0 {start|stop|status|restart}&quot;
                exit 1
                ;;
esac
exit 0
</pre></div>


<p>Then we enable this on startup by performing:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo chmod 755 /etc/init.d/livestream.sh
sudo update-rc.d livestream.sh defaults
</pre></div>


<p>Now you can reboot your pi, or use commands like &#8216;sudo service livestream start&#8217;   I rebooted my pi, and my fed was running, and running a status command on my service yields:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
pi@cam-pi-zero:~ $ sudo service livestream status
● livestream.service - LSB: mjpg_streamer for webcam
   Loaded: loaded (/etc/init.d/livestream.sh; generated)
   Active: active (running) since Thu 2020-05-14 11:46:09 CDT; 2min 51s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 411 ExecStart=/etc/init.d/livestream.sh start (code=exited, status=0/SUCCESS)
   Memory: 2.2M
   CGroup: /system.slice/livestream.service
           └─416 /usr/local/bin/mjpg_streamer -b -i input_uvc.so -f 15 -r 1920x1080 -o output_http.so

May 14 11:46:07 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: TV-Norm...........: DEFAUL
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: www-folder-path......: /us
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: HTTP TCP port........: 808
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: HTTP Listen Address..: (nu
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: username:password....: dis
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: commands.............: ena
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: starting input plugin inpu
May 14 11:46:08 cam-pi-zero.local mjpg_streamer&#91;416]: MJPG-streamer &#91;416]: starting output plugin: ou
May 14 11:46:09 cam-pi-zero.local livestream.sh&#91;411]: &#91;+] mjpg_streamer started
May 14 11:46:09 cam-pi-zero.local systemd&#91;1]: Started LSB: mjpg_streamer for webcam.

</pre></div>


<h2 class="wp-block-heading" id="h-conclusion">Conclusion</h2>



<p>Using the Raspberry Pi for video streams is good enough if we&#8217;re looking for low frame rate monitoring without audio.  I&#8217;ve yet to find anything that really gives me the frame rate and audio (regardless of latency) that a standard USB webcam directly into my OBS machine would give.  Maybe if NDI ever makes it on to the raspberry Pi, or if there is ever SLDP support.</p>



<p>Have you tried streaming across the network on a Raspberry Pi with a USB webcam?  Did you fare better than I?  Let me know!</p>



<p>Nevertheless, with that, I&#8217;m done!  I can now embed this into OBS via the VLC media source or anything that can handle an HTTP Motion JPEG video stream.  I won&#8217;t have audio, but that&#8217;s okay for what I&#8217;m using this for.</p>



<h2 class="wp-block-heading" id="h-raspi-cameras-libcamera-is-in-raspivid-is-out-in-bullseye">Raspi-Cameras (libcamera is in, raspivid is out in Bullseye)</h2>



<p>Mjpg-Streamer won&#8217;t have the raspicam input module anymore if you compile on Bullseye, because I believe the headers don&#8217;t exist as the Bullseye version is going the way of libcamera.  While I was able to hack around that and build it, I got HORRIBLE artifacts using a raspberry pi camera with the h264 codec and libcamera.  I tried switching codecs to MJPEG instead of H264 and had less artifacts, but worse frame rate.  So for now I decided to go with gstreamer instead of mjpg-streamer at 1280&#215;720 for a nice 30fps solution.</p>



<p>For me, what worked was to enable the legacy raspi-camera support (so we&#8217;re not using libcamera, we&#8217;re using v4l2).</p>



<p>Here are the rough steps:</p>



<ul><li>Started out with Bullseye, latest install with sudo apt update/sudo apt upgrade executed.</li><li>Edit /boot/config.txt and change the following:<ul><li>start_x=1 //add this line</li><li>gpu_mem=128  //probably no higher</li><li>#camera_auto_detect=1 //Comment this line out</li></ul></li><li>Restart</li><li>Installs:</li></ul>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt-get install gstreamer1.0-tools gstreamer1.0-plugins-base \
     gstreamer1.0-plugins-good gstreamer1.0-plugins-bad
</pre></div>


<p>Then execute this on the command line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
/usr/bin/gst-launch-1.0 v4l2src ! video/x-h264,width=1280,height=720,framerate=30/1 ! h264parse config-interval=1 ! matroskamux streamable=true ! tcpserversink host=::0 port=9000 sync=false sync-method=2
</pre></div>


<p>Once that&#8217;s up and running, I ran VLC against it using :network-caching=250 and a URL of tcp://&lt;yourhostname&gt;:9000 and was able to get a decent stream.  That&#8217;s about the extent I&#8217;ve been pushing the raspi-cameras as I typically use the USB side.  I did notice it was nice and fluid, along with less power consumption by a 100 milliamps or so, so I think I&#8217;ll use this as a portable battery powered wireless camera to use around the house on streams.  Hmmm, I may need to look at getting a microphone on here somehow and streaming audio with gstreamer as well.</p>



<h2 class="wp-block-heading" id="h-references">References</h2>



<ul><li><a href="https://einar.slaskete.net/2018/08/16/using-a-raspberry-pi-as-a-surveillance-camera-in-home-assistant/" target="_blank" rel="noreferrer noopener">https://einar.slaskete.net/2018/08/16/using-a-raspberry-pi-as-a-surveillance-camera-in-home-assistant/</a></li><li><a href="https://picamera.readthedocs.io/en/release-1.12/fov.html" target="_blank" rel="noreferrer noopener" class="broken_link">https://picamera.readthedocs.io/en/release-1.12/fov.html</a></li><li><a href="https://qengineering.eu/install-gstreamer-1.18-on-raspberry-pi-4.html" target="_blank" rel="noreferrer noopener">https://qengineering.eu/install-gstreamer-1.18-on-raspberry-pi-4.html</a></li><li><a rel="noreferrer noopener" href="https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md" target="_blank" class="broken_link">https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md</a> &#8211; Raspberry Pi Document on WIFI Setup</li><li><a rel="noreferrer noopener" href="https://www.amazon.com/Vilros-Raspberry-Starter-Power-Premium/dp/B0748MPQT4" target="_blank">https://www.amazon.com/Vilros-Raspberry-Starter-Power-Premium/dp/B0748MPQT4</a> &#8211; The Raspberry Pi Zero W kit I purchased</li><li><a href="https://sourceforge.net/projects/mjpg-streamer" rel="noreferrer noopener" target="_blank" class="broken_link">https://sourceforge.net/projects/mjpg-streamer </a>&#8211; The original source forge project.</li><li><a href="https://github.com/jacksonliam/mjpg-streamer" rel="noreferrer noopener" target="_blank">https://github.com/jacksonliam/mjpg-streamer</a> &#8211; The successor to the abandoned Sourceforge project.</li><li><a href="https://jacobsalmela.com/2014/05/31/raspberry-pi-webcam-using-mjpg-streamer-over-internet/" class="broken_link">https://jacobsalmela.com/2014/05/31/raspberry-pi-webcam-using-mjpg-streamer-over-internet/</a> &#8211; Reference for build information</li><li><a href="https://www.acmesystems.it/video_streaming">https://www.acmesystems.it/video_streaming</a> &#8211; Another build reference</li><li><a href="https://qiita.com/xeno14/items/e32e52c688d969d182e2">https://qiita.com/xeno14/items/e32e52c688d969d182e2</a> &#8211; Another build reference</li></ul>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/">MJPG-Streamer on a Raspberry Pi Zero W with a USB Webcam Streaming Setup</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/mjpg-streamer-on-a-raspberry-pi-zero-w-with-a-usb-webcam-streaming-setup/feed/</wfw:commentRss>
			<slash:comments>41</slash:comments>
		
		
			</item>
		<item>
		<title>Patching the VICE emulator to light up floppy drive LEDs</title>
		<link>https://krystof.io/patching-the-vice-emulator-to-light-up-floppy-drive-leds/</link>
					<comments>https://krystof.io/patching-the-vice-emulator-to-light-up-floppy-drive-leds/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Sat, 15 Feb 2020 17:03:24 +0000</pubDate>
				<category><![CDATA[Retro Gaming]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Commodore]]></category>
		<category><![CDATA[VICE]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[Emulation]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1379</guid>

					<description><![CDATA[<p>To make the miniature floppy drive LED light up when VICE is using the virtual disk image, we need to patch VICE source code and write some new code to pass instructions on to the PI and toggle the LED activity light.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/patching-the-vice-emulator-to-light-up-floppy-drive-leds/">Patching the VICE emulator to light up floppy drive LEDs</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on March 17, 2023.</p>
<p>In a previous article of the <a href="https://krystof.io/series/diorama-64">Diorama 64</a> series, we <a href="https://krystof.io/installing-the-vice-commodore-emulator-for-console-mode-on-a-fresh-raspberry-pi-4/">installed VICE 3.4</a>, unmodified, on our Raspberry Pi 4.  I didn&#8217;t cover any customization of <a rel="noreferrer noopener" label="VICE  (opens in a new tab)" href="http://vice-emu.sourceforge.net/" target="_blank" class="broken_link">VICE </a>in that article because I wanted to &#8216;walk before I run&#8217;.  However, our goal is to take a miniature floppy drive model, shove a LED into it, and have our VICE emulator control when the LED blinks on or off, mirroring the Commodore 1541 disk drive activity LED.  This article won&#8217;t cover the circuit itself (that&#8217;s a later article), but it is focused on modifying the VICE source code, and using some Python to transfer data from VICE and drive the Raspberry PI&#8217;s GPIO pins, which would later drive an LED light.</p>



<p>While the circuit details will come in a later article, here&#8217;s a little visual of the circuit setup &#8211; a Raspberry Pi 4 with GPIO pins attached to a breakout board, attached to a breadboard.  The top breadboard is used to drive a separate power source for the LEDs, but you can see the green &#8216;power&#8217; LEDs and one of the red &#8216;activity&#8217; LEDs light up there, that&#8217;s all driven by the Raspberry PI and VICE.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="866" height="506" src="https://krystof.io/wp-content/uploads/2020/02/vice-python-test-circuit.jpg" alt="" class="wp-image-1385" srcset="https://krystof.io/wp-content/uploads/2020/02/vice-python-test-circuit.jpg 866w, https://krystof.io/wp-content/uploads/2020/02/vice-python-test-circuit-300x175.jpg 300w, https://krystof.io/wp-content/uploads/2020/02/vice-python-test-circuit-768x449.jpg 768w, https://krystof.io/wp-content/uploads/2020/02/vice-python-test-circuit-585x342.jpg 585w" sizes="(max-width: 866px) 100vw, 866px" /><figcaption class="wp-element-caption">Pretend those LEDs are inside tiny disk drive models. </figcaption></figure>



<h2 class="wp-block-heading" id="h-high-level-design">High Level Design</h2>



<p>Since VICE is an open source project (thank goodness!), I figured I&#8217;d need to get in that code and see if I can detect when the virtual floppy drives are being used.  If I could do that, I&#8217;d want to send that data to a different program that would be responsible for driving the Raspberry Pi GPIO pins, which then drive the LEDs.  I purposefully did not want to drive the LEDs directly from VICE itself &#8211; I wanted to affect the actual emulator process as little as possible.  Just enough to get the data out of VICE.  After that, some other process takes the data and controls the circuit.  The secondary program would be written in Python, primarily because it&#8217;s very easy to interface with the Raspberry PI with the Python GPIO libraries.  VICE, of course, is written in C.</p>



<p>So I&#8217;d have a C program that gathers data, and a Python program that does something with it.  We typically call that a <strong>Publisher/Subscriber</strong> scenario.  VICE is the <em><strong>Publisher</strong></em> as it is sourcing data, and making it available (publishing) for other processes to use, and VICE isn&#8217;t getting any data back &#8211; this is a one-sided conversation.  Our Python program will be one of the <strong><em>Subscribers</em></strong><em> </em>as it will poll for new &#8216;messages&#8217; or changes in state.  The Python program will then, in turn, send signals via the GPIO library and Raspberry PI GPIO pins to the Darlington Array, which controls individual LEDs, namely our Commodore 1541 Floppy Disk Drive Activity Lights.  Here&#8217;s a high level flow:</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="576" src="https://krystof.io/wp-content/uploads/2020/02/2020-02-06_15-28-45-1024x576.jpg" alt="" class="wp-image-1387" srcset="https://krystof.io/wp-content/uploads/2020/02/2020-02-06_15-28-45-1024x576.jpg 1024w, https://krystof.io/wp-content/uploads/2020/02/2020-02-06_15-28-45-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/02/2020-02-06_15-28-45-768x432.jpg 768w, https://krystof.io/wp-content/uploads/2020/02/2020-02-06_15-28-45-1170x658.jpg 1170w, https://krystof.io/wp-content/uploads/2020/02/2020-02-06_15-28-45-585x329.jpg 585w, https://krystof.io/wp-content/uploads/2020/02/2020-02-06_15-28-45.jpg 1440w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">High level design flow &#8211; in this article we cover VICE and Python.</figcaption></figure>



<p>The first real question I pondered was how I&#8217;d get a C program and a Python program on a Raspberry PI to share data, even if the conversation is one-sided.  I figured I had four options off the top of my head:</p>



<ol>
<li><strong>Datafile access</strong> &#8211; Vice writes to a file that the Python program constantly reads from to determine drive status.  While this is definitely feasible, I wanted to avoid constant file-system access, OS caching or not.  The LED is meant to blink on and off rapidly, that&#8217;s a lot of file updates to apply on a SD card.</li>



<li><strong>Networking Channel</strong> &#8211; UDP or TCP, some sort of client/server or packet broadcast.  This would be necessary if the diorama was remote (an interesting idea), but ultimately the emulator and the consumer are on the same machine, so I wanted to keep the communications channel a little tighter.</li>



<li><strong>UNIX Sockets</strong> &#8211; Since the Raspberry Pi 4 is running Raspbian, it supports UNIX style sockets for a simple IPC (Inter-process Communication) channel between the VICE and Python processes.  However, it&#8217;s still a lot of code to inject into VICE.</li>



<li><strong><em>The Winner</em> &#8211; Shared Memory</strong> &#8211; I finally decided on a shared memory solution to avoid a lot of unnecessary and potentially harmful patching to VICE with any networking related code (the less I&#8217;m in VICE the less I affect its processing), along with Python recently getting support for shared memory between disparate processes with Python 3.8 and above.  </li>
</ol>



<p>While we are calling this a &#8216;Publisher/Subscriber&#8217; model, it&#8217;s a very loose fit &#8211; there&#8217;s no middle-ware here handling message flow &#8211; it&#8217;s a bit bucket we poll for state changes every few milliseconds.  Therefore, I hesitate to apply the terminology of &#8216;Publisher/Subscriber&#8217; without a few grains of salt.   Thy key point: VICE is decoupled from the consuming process(es).</p>



<h2 class="wp-block-heading" id="h-patching-vice">Patching VICE</h2>



<p>Remember where we compiled <a href="https://krystof.io/installing-the-vice-commodore-emulator-for-console-mode-on-a-fresh-raspberry-pi-4/">VICE on the command line</a>?  Even if a binary was available, the reason why I wanted to compile VICE was because I knew I&#8217;d be tinkering with the source code.  To that end, I downloaded their SVN source and started searching through the code for key strings like &#8216;1541&#8217;, &#8216;drive&#8217;, &#8216;floppy&#8217;, etc. until I found drive.c and drive.h.  I won&#8217;t include the whole pieces here, but this part is what I found particularly interesting &#8211; I wanted to find some place to initialize the shared memory, and some place to write to it so we can &#8216;publish&#8217; our floppy drive status updates.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
/* Initialize the hardware-level drive emulation (should be called at least
   once before anything else).  Return 0 on success, -1 on error.  */
int drive_init(void)
{
    unsigned int dnr;
    drive_t *drive;

    if (rom_loaded) {
        return 0;
    }

//..... More
}
</pre></div>


<p>Great!  <em>drive_init</em> sounds like a good hook method &#8211; we don&#8217;t want to constantly be creating shared memory segments, create it once, but write to it many times.  Here&#8217;s where I figured I&#8217;d place the &#8216;publishing&#8217; code:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
static void drive_led_update(drive_t *drive, drive_t *drive0)
{
    int my_led_status = 0;
    CLOCK led_period;
    unsigned int led_pwm;

    /* Actually update the LED status only if the `trap idle&#039;
       idling method is being used, as the LED status could be
       incorrect otherwise.  */

    if (drive0-&gt;idling_method != DRIVE_IDLE_SKIP_CYCLES) {
        my_led_status = drive-&gt;led_status;
    }

//More.....
}
</pre></div>


<p>So now, we know the two spots that sound like they&#8217;d be great for initialization and continuous updates of our shared memory with drive status.  Let&#8217;s look at the modifications necessary, then.   Our goal is to allocate some shared memory (just enough to hold drive status for drive devices 8 through 11), and when VICE is updating it&#8217;s UI LED, we want to update shared memory with that status, a simple 1 or 0 toggle will suffice.  That&#8217;s a pretty straightforward hook!</p>



<h3 class="wp-block-heading" id="h-modifications-for-drive-c"><strong>Modifications for drive.c</strong></h3>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
#include &lt;fcntl.h&gt;
#include &lt;sys/shm.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;sys/mman.h&gt;
#include &lt;unistd.h&gt;

const char *led_shm_name = &quot;vice-drive-led-shm&quot;;

void *viceDriveLedShmPointer;

void init_drive_led_shm(void) {

	int shm_fd;

	const int SIZE = 16;

	/* create the shared memory object */
	shm_fd = shm_open(led_shm_name, O_CREAT | O_RDWR, 0666);

	/* configure the size of the shared memory object */
	ftruncate(shm_fd, SIZE);

	/* memory map the shared memory object */
	viceDriveLedShmPointer = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);

	sprintf(viceDriveLedShmPointer, &quot;%s&quot;, &quot;80900010&quot;);
}

void update_shm_drive_status(unsigned int driveNumber,
		int driveLedStatus) {
//      Uncomment for some simple and extreme debugging
//	log_warning(drive_log, &quot;Hey! Drive %d Status : %d&quot;, driveNumber,
//			driveLedStatus);

	if (drive_init_was_called) {
		((char*) viceDriveLedShmPointer)&#91;(driveNumber * 2) + 1] = (
				driveLedStatus == 0 ? &#039;0&#039; : &#039;1&#039;);
	}
}

//  Call our initialization method from drive_init
init_drive_led_shm();

//  Add this to update our status in the existing function drive_led_update
update_shm_drive_status(drive-&gt;mynumber, my_led_status);
</pre></div>


<h3 class="wp-block-heading" id="h-modifications-to-drive-h"><strong>Modifications to drive.h</strong></h3>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
extern void init_drive_led_shm(void);
extern void update_shm_drive_status(unsigned int driveNumber, int driveLedStatus);
</pre></div>


<h3 class="wp-block-heading" id="h-modifications-for-compilation"><strong>Modifications for compilation</strong></h3>



<p>There&#8217;s not much else to this &#8211; all I needed to add  (and this was a quite a bit of stumbling around on my part as I&#8217;m not comfortable or familiar with automake/autoconf) was adding the system libraries to work with shared memory to the configuration file configure.proto, around line 3316, before references to GFXOUTPUT_DRIVERS</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
dnl Patch to add -lrt for shared memory IPC work
echo &quot;Patch to add -lrt for shared memory IPC work&quot;
old_LIBS=&quot;$LIBS&quot;
LIBS=&quot;$LIBS -lrt&quot;
</pre></div>


<h3 class="wp-block-heading" id="h-github-repo">Github repo</h3>



<p>Of course, you don&#8217;t have to copy these and paste them yourselves.  I put a GitHub repo for my modifications here:</p>



<p><a href="https://github.com/erkrystof/vice">https://github.com/erkrystof/vice</a></p>



<p>You&#8217;ll want to check the tags for &#8216;pure VICE&#8217; and tags for my modifications to see deltas or pull the version you desire.</p>



<p>When I wrote this &#8211; there was one tag that represented my modifications and VICE 3.4 combined:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
git clone --single-branch --branch 3.4-Modded-1.0 https://github.com/erkrystof/vice
</pre></div>


<h2 class="wp-block-heading" id="h-running-vice-with-our-patch">Running VICE with our patch</h2>



<p>After running the same build commands as I did when installing basic VICE, executing the binary should have no discernible difference (unless you un-comment that log statement) in the logs for the way VICE handles.</p>



<p>However, you should now notice there&#8217;s a piece of shared memory  you can see, and that you can read, given that everything in *nix is a file.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
pi@vice-pi:/dev/shm $ ls -l
total 4
-rw-r--r-- 1 pi pi 16 Feb  9 09:16 vice-drive-led-shm
pi@vice-pi:/dev/shm $ cat vice-drive-led-shm
80900010
pi@vice-pi:/dev/shm $

</pre></div>


<p>Excellent, we now know it&#8217;s working!  If I loop over that in an SSH console, just to see, and run VICE and load a floppy, you should see the second byte (0/1 &#8211; the drive 8 status LED) flip between 1 and 0.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
for i in {1..10000}; do cat vice-drive-led-shm; echo ... Counter: $i; done
#Sample output:
80900010... Counter: 43
80900010... Counter: 44
80900010... Counter: 45
81900010... Counter: 46  &lt;----- We have activity on drive 8
81900010... Counter: 47
81900010... Counter: 48
81900010... Counter: 49
</pre></div>


<p>Looking good so far.  So VICE is essentially done &#8211; it&#8217;s &#8216;publishing&#8217; drive status to an area in shared memory that we&#8217;ll now want to read from and drive the LEDs connected to the Raspberry Pi GPIO pins.</p>



<h2 class="wp-block-heading" id="h-reading-the-1541-drive-status-with-python">Reading the 1541 drive status with Python</h2>



<p>We&#8217;re halfway there &#8211; the next step is to work on a separate process &#8211; our subscriber that reads the VICE drive status and sends commands to the Raspberry Pi&#8217;s GPIO pins to drive our LEDs.  I could have done this in C, matching how we read shared memory that we&#8217;re writing to in VICE, but I wasn&#8217;t familiar with driving a Raspberry Pi&#8217;s GPIO pins from C.  I am a bit more comfortable with the GPIO libraries available in Python, however, though the question of reading shared memory needed an answer.</p>



<p>Granted, I could probably just read from <code>/dev/shm/vice-drive-led-shm</code>, but I really wanted to keep this semi-portable in the sense that I wanted to use the available shared-memory libraries instead of  a known *nix-specific file behavior.  After doing some research on Python and shared memory, it turns out we need a more recent version of Python than may come with your default Raspbian install &#8211; Python 3.8 or greater.</p>



<h3 class="wp-block-heading" id="h-python-3-8-or-greater-and-rpi-gpio-libraries">Python 3.8 or greater and RPi.GPIO libraries</h3>



<p>For that installation, I&#8217;m going to divert away from this article to a separate one that&#8217;s not necessarily part of the series as reference if you need it &#8211; <a href="https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/">How to install Python 3.8 on the Raspberry Pi</a>. </p>



<p>If you already have Python 3.8 or greater, you&#8217;ll just need to make sure you have the RPi GPIO library installed:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo python3.8 -m pip install RPi.GPIO
</pre></div>


<h3 class="wp-block-heading" id="h-a-simple-python-client">A simple Python client</h3>



<p>The latest source code for the Python piece is available on <a rel="noreferrer noopener" aria-label="GitHub (opens in a new tab)" href="https://github.com/erkrystof/diorama-64-1541-status-consumer-gpio-led-driver" target="_blank">GitHub</a>, although I&#8217;ll go over this roughly below.  </p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>I&#8217;m not a Python programmer by trade &#8211; this was just enough to illustrate the point of reading shared memory and routing commands to the Raspberry Pi, not a gold standard of Python coding.</div></div>



<h4 class="wp-block-heading" id="h-initialization">Initialization</h4>



<p>Let&#8217;s look at the first chunk, primarily initialization and some structure:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
powerLedsPin = 23
drive8ActivityPin = 27
drive9ActivityPin = 22

DRIVE_8_ACTIVITY_INDEX = 1
DRIVE_9_ACTIVITY_INDEX = 3

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(&#91;powerLedsPin,drive8ActivityPin,drive9ActivityPin],
        GPIO.OUT, initial=GPIO.HIGH)
</pre></div>


<p>My diorama has four &#8216;devices&#8217; &#8211; two 1541 floppy drives, a Commodore keyboard, and a Commodore monitor.  We use one pin for all green &#8216;power&#8217; LEDs, since I didn&#8217;t feel like controlling power LEDs separately, it&#8217;s all the same output.  For the floppy drive activity LEDs, however, I needed them controlled separately, so I created a drive 8 and drive 9 pin and reserved them to pins 27 and 22, respectively.</p>



<p>After that I&#8217;m setting up the state to be HIGH &#8211; initialize all LEDs as on.</p>



<h4 class="wp-block-heading" id="h-load-the-shared-memory-reference">Load the shared memory reference</h4>



<p>Our primary code must first initialize the reference to shared memory:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
try:
    print (&quot;Consumix Python version starting up.&quot;)

    while (True):
        try:
            shm_vice = shared_memory.SharedMemory(name=&quot;vice-drive-led-shm&quot;, create=False, size=16)
            break;
        except Exception as e:
            print (e)
            print (&quot;Error Trying to Open Shared Memory... Trying again in a bit.&quot;)
            time.sleep(.5)
            continue

    print (&quot;Shared memory found, let&#039;s read it.&quot;)
</pre></div>


<p> We&#8217;re using the same shared memory name we used in VICE, and we say &#8216;create=False&#8217; since VICE is responsible for creating the shared memory object &#8211; we are just reading 16 bytes worth.  In the case that the Python program starts before VICE, we catch the exception and try again in a little bit.  I had to add that slightly fault tolerant try/catch loop as this Python client ends up staring <em>before</em> VICE when I startup my Raspberry Pi.</p>



<h4 class="wp-block-heading" id="h-read-shared-write-led">Read Shared, Write LED</h4>



<p>Now that we&#8217;ve loaded our shared memory reference, we read from the shared memory, place it into a character array, and update the LEDs with a loop and a function:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
while (True):
        driveData = array.array(&#039;b&#039;,shm_vice.buf&#91;:8])
        driveDataString = driveData.tostring().decode(&quot;utf-8&quot;)
        updateLEDLighting(driveDataString)
        time.sleep(0.025)

#... more stuff after....
#update function for reference:

def updateLEDLighting(driveDataString):
    if (driveDataString&#91;DRIVE_8_ACTIVITY_INDEX] == &#039;1&#039;):
        GPIO.output(drive8ActivityPin,GPIO.HIGH)
    else:
        GPIO.output(drive8ActivityPin,GPIO.LOW)

    if (driveDataString&#91;DRIVE_9_ACTIVITY_INDEX] == &#039;1&#039;):
        GPIO.output(drive9ActivityPin,GPIO.HIGH)
    else:
        GPIO.output(drive9ActivityPin,GPIO.LOW)
</pre></div>


<p>It&#8217;s a pretty simple program overall &#8211; but it does the job.  Since I only ended up wiring up two drives, I only read the drive 8 and 9 data, and ignore 10 and 11.</p>



<h3 class="wp-block-heading" id="h-a-note-on-python-shared-memory">A note on Python shared memory</h3>



<p>This isn&#8217;t as fault tolerant as I&#8217;d like though &#8211; if you quit your Python client, the shared memory reference seems to be <strong><em>destroyed</em></strong> &#8211; which completely baffles me.  The creator of a resource is in charge of closing it, not some other process.  So if VICE is creating the shared memory, I could understand if my Python client needs to open and close a <em>reference</em>, but not the shared memory itself.  </p>



<p>Regardless, when I close my Python client, it destroys the shared memory object completely, even if I try to &#8216;close&#8217; the reference ahead of time.  Perhaps I&#8217;ve wired something up wrong here &#8211; but i think, based on some of these links referencing the shared-memory usage in Python 3.8, that I&#8217;m not entirely crazy.</p>



<p><a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://bugs.python.org/issue38119" target="_blank">https://bugs.python.org/issue38119</a></p>



<p>Now, I&#8217;m not really worried about this myself &#8211; but it could be an interesting read for others &#8211; as far as my Python client goes, I don&#8217;t need to restart it, so it shouldn&#8217;t start closing the shared memory VICE created on me.  What I may need to do now and then is restart VICE, however, and this setup handles that just fine (my patched-VICE simply uses the existing shared-memory object and the Python client keeps reading happily).</p>



<h2 class="wp-block-heading" id="h-the-outcome">The outcome</h2>



<p>Load up VICE and the Python client, and watch your GPIO pins toggle high and low with drive activity.  You can debug by tailing the shared memory object as we did above, you could use an oscilloscope or multimeter to watch some voltage changes on the GPIO pins, or you could do what I did &#8211; have some LEDs on the pins and watch them blink on and off &#8211; which is exactly what I&#8217;m looking for.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="576" src="https://krystof.io/wp-content/uploads/2020/02/20200105_141239-1024x576.jpg" alt="" class="wp-image-1417" srcset="https://krystof.io/wp-content/uploads/2020/02/20200105_141239-1024x576.jpg 1024w, https://krystof.io/wp-content/uploads/2020/02/20200105_141239-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/02/20200105_141239-768x432.jpg 768w, https://krystof.io/wp-content/uploads/2020/02/20200105_141239-1536x864.jpg 1536w, https://krystof.io/wp-content/uploads/2020/02/20200105_141239-scaled.jpg 2048w, https://krystof.io/wp-content/uploads/2020/02/20200105_141239-1170x658.jpg 1170w, https://krystof.io/wp-content/uploads/2020/02/20200105_141239-1920x1080.jpg 1920w, https://krystof.io/wp-content/uploads/2020/02/20200105_141239-585x329.jpg 585w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Green Power LEDs are go, and drive 8 is active (Red LED lit)</figcaption></figure>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/patching-the-vice-emulator-to-light-up-floppy-drive-leds/">Patching the VICE emulator to light up floppy drive LEDs</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/patching-the-vice-emulator-to-light-up-floppy-drive-leds/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Diorama 64]]></series:name>
	</item>
		<item>
		<title>Installing Alternative Python Versions on Raspberry Pi</title>
		<link>https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/</link>
					<comments>https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/#respond</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Sat, 15 Feb 2020 13:42:49 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1408</guid>

					<description><![CDATA[<p>Installing an alternative version of python on the raspberry pi.  This is primarily used when the stock version is lower than the python version you desire.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/">Installing Alternative Python Versions on Raspberry Pi</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on May 21, 2021.</p>
<p>In my <a href="https://krystof.io/series/diorama-64">Commodore 64 Diorama series</a>, I used Python to read shared memory segments that we wrote to from VICE.  However, the version of Python at the time of that Raspbian install was less than the version I needed &#8211; 3.8 or higher.  Here&#8217;s how I installed an alternative version of Python, along with making it the default version and using PIP in a version-specific manner.</p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><span class="dashicon dashicons dashicons-info"></span></div><div>This document is a combination from a few different resources and for Python 3.8.  Ideally later versions would work in a similar fashion.</div></div>



<h2 class="wp-block-heading" id="h-downloading-and-updating">Downloading and Updating</h2>



<p>The obligatory apt update/apt upgrade, along with installing dependencies:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd ~

sudo apt update
sudo apt upgrade
sudo apt-get install -y build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev tar wget vim

wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz
</pre></div>


<h2 class="wp-block-heading" id="h-compile-and-install">Compile and Install</h2>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
tar zxf Python-3.8.0.tgz
cd Python-3.8.0
./configure --enable-optimizations
make -j 4
sudo make altinstall
</pre></div>


<h2 class="wp-block-heading" id="h-validation">Validation</h2>



<p>Executing this on the command line should work just fine and return the version installed:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
pi@vice-pi:~ $ python3.8 -V
Python 3.8.0
</pre></div>


<h2 class="wp-block-heading" id="h-making-our-install-the-default-version">Making our install the default version</h2>



<p>I prefer to do this by adding the alias to a (potentially new) file .bash_aliases in your home directory by adding this line to the file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
alias python=&#039;/usr/local/bin/python3.8&#039;
</pre></div>


<h2 class="wp-block-heading" id="h-example-pip-updating">Example PIP updating</h2>



<p>Based on some current reading it looks like it&#8217;s a good practice to use the python version specific pip for the version you&#8217;re running instead of assuming any default.  Here&#8217;s the example I used to update the python package manager and installing the RPi.GPIO library.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo python3.8 -m pip install --upgrade pip
sudo python3.8 -m pip install RPi.GPIO
</pre></div>


<h2 class="wp-block-heading" id="h-references">References</h2>



<ul><li><a rel="noreferrer noopener" aria-label="https://www.scivision.dev/compile-install-python-beta-raspberry-pi/ (opens in a new tab)" href="https://www.scivision.dev/compile-install-python-beta-raspberry-pi/" target="_blank">https://www.scivision.dev/compile-install-python-beta-raspberry-pi/</a></li><li><a rel="noreferrer noopener" aria-label="https://installvirtual.com/how-to-install-python-3-8-on-raspberry-pi-raspbian/ (opens in a new tab)" href="https://installvirtual.com/how-to-install-python-3-8-on-raspberry-pi-raspbian/" target="_blank">https://installvirtual.com/how-to-install-python-3-8-on-raspberry-pi-raspbian/</a></li><li><a rel="noreferrer noopener" label="https://www.ramoonus.nl/2019/10/23/how-to-install-python-3-8-on-raspberry-pi/ (opens in a new tab)" href="https://www.ramoonus.nl/2019/10/23/how-to-install-python-3-8-on-raspberry-pi/" target="_blank" class="broken_link">https://www.ramoonus.nl/2019/10/23/how-to-install-python-3-8-on-raspberry-pi/</a></li><li><a href="https://stackoverflow.com/questions/2812520/dealing-with-multiple-python-versions-and-pip" target="_blank" rel="noreferrer noopener" label="https://stackoverflow.com/questions/2812520/dealing-with-multiple-python-versions-and-pip (opens in a new tab)" class="broken_link">https://stackoverflow.com/questions/2812520/dealing-with-multiple-python-versions-and-pip</a></li></ul>



<p></p>
<p>The post <a rel="nofollow" href="https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/">Installing Alternative Python Versions on Raspberry Pi</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/installing-alternative-python-versions-on-raspberry-pi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display</title>
		<link>https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/</link>
					<comments>https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/#comments</comments>
		
		<dc:creator><![CDATA[Eric R. Krystof]]></dc:creator>
		<pubDate>Wed, 15 Jan 2020 16:13:13 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[LCD Displays]]></category>
		<category><![CDATA[Featured]]></category>
		<guid isPermaLink="false">https://krystof.io/?p=1126</guid>

					<description><![CDATA[<p>I needed a small display for my Commodore diorama that mirrors the output of my Raspberry Pi - I found one with this 1.3 inch ST7789 driven LCD display.  Trouble was, mirroring this wasn't as straight forward as I would have liked.</p>
<p>The post <a rel="nofollow" href="https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/">Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="post-modified-info">Last Updated on May 30, 2021.</p>
<p>My Commodore 64 Diorama project was well underway.  After installing VICE on the console of a Raspberry Pi 4, the next step was to make sure I could get a tiny display that would fit some sort of &#8216;tiny monitor&#8217; I&#8217;d have to create further into the project.    I shopped around a few different places, but I ended up really liking two, both available from Adafruit.    Either way, we&#8217;re mirroring the Raspberry Pi to a ST7789 driven LCD display. </p>



<p><a href="https://krystof.io/installing-the-vice-commodore-emulator-for-console-mode-on-a-fresh-raspberry-pi-4/">Previously in the series</a>, we installed VICE on our Raspberry Pi and made sure it worked.  Now we want to mirror the HDMI output to our tiny LCD for the <a href="https://krystof.io/series/diorama-64/">diorama</a>.</p>



<p>Here&#8217;s our video that covers this article at a high level:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display" width="1170" height="658" src="https://www.youtube.com/embed/1zTZgx9ilWU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<h2 class="wp-block-heading" id="h-two-lcds-enter-one-lcd-leaves">Two LCDs enter, One LCD leaves</h2>



<p>The <a rel="noreferrer noopener" aria-label="OLED Breakout Board - 16-bit Color 0.96&quot; w/microSD holder (opens in a new tab)" href="https://www.adafruit.com/product/684" target="_blank">OLED Breakout Board &#8211; 16-bit Color 0.96&#8243; w/microSD holder</a> was a contender.  At about 1/12 scale this would have worked out nicely, though it felt a little &#8216;wide screen&#8217; compared to the monitors I knew of my youth.  I was also concerned with resolution, as it supports  96&#215;64, a far cry from the <a rel="noreferrer noopener" aria-label="Commodore 64's 320x200 (opens in a new tab)" href="http://www.studiostyle.sk/dmagic/gallery/gfxmodes.htm" target="_blank">Commodore 64&#8217;s 320&#215;200</a>.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="970" height="728" src="https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display.jpg" alt="" class="wp-image-1130" srcset="https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display.jpg 970w, https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display-300x225.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/oled-.96inch.display-768x576.jpg 768w" sizes="(max-width: 970px) 100vw, 970px" /><figcaption>Image from Adafruit&#8217;s Product Page</figcaption></figure>



<p>The other, and my ultimate winner &#8211; the <a rel="noreferrer noopener" aria-label="Adafruit 1.3&quot; 240x240 Wide Angle TFT LCD Display with MicroSD - ST7789 (opens in a new tab)" href="https://www.adafruit.com/product/4313" target="_blank">Adafruit 1.3&#8243; 240&#215;240 Wide Angle TFT LCD Display with MicroSD &#8211; ST7789</a> at least got me closer with 240&#215;240, though it was a touch larger.  To that end, I&#8217;d try both with the Raspberry Pi and compare.  Once I plugged in the 240&#215;240 display and saw the Commodore 64 Ready screen, I was sold.  Even though you&#8217;d be able to make out what I was playing on the OLED display mirroring my HDMI output, with the 240&#215;240 you can actually read a good amount of text, as well.  <em>We have a winner.</em></p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="970" height="728" src="https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display.jpg" alt="" class="wp-image-1131" srcset="https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display.jpg 970w, https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display-300x225.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/tftlcd-1.3inch.display-768x576.jpg 768w" sizes="(max-width: 970px) 100vw, 970px" /><figcaption>Image from Adafruit&#8217;s Product Page</figcaption></figure>



<h2 class="wp-block-heading" id="h-a-couple-of-quests-for-the-chosen-one">A Couple of Quests for the Chosen One</h2>



<p>Adafruit has a great page in terms of how to wire this up to an Arduino and Raspberry Pi located <a rel="noreferrer noopener" aria-label="here (opens in a new tab)" href="https://learn.adafruit.com/adafruit-1-3-and-1-54-240-x-240-wide-angle-tft-lcd-displays?view=all" target="_blank">here</a>. It&#8217;s where I learned that the ST7789 chip is used to drive two different LCD displays &#8211; 240&#215;240 and 320&#215;240.  This becomes important later as I struggle with getting that working on the Raspberry Pi.  Regardless of what display I chose &#8211; I knew I needed to have the following requirements satisfied:</p>



<ul><li>The LCD should mirror HDMI output &#8211; I didn&#8217;t want this to be the primary display, but a <em><strong>mirrored</strong></em> display.</li><li>The LCD screen needed to be in a specific orientation &#8211; <strong><em>pins on the bottom</em></strong> &#8211; so they could more easily hide inside the 3D printed monitor &#8216;bottom&#8217;</li></ul>



<h3 class="wp-block-heading" id="h-wire-before-you-fire">Wire Before You Fire</h3>



<p>The display doesn&#8217;t come with header pins pre-soldered, so after remembering which end of the soldering iron is the hot end, I was able to move forward by placing the display into my breadboard:</p>



<figure class="wp-block-image size-full"><img decoding="async" loading="lazy" width="804" height="226" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55.jpg" alt="" class="wp-image-1149" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55.jpg 804w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55-300x84.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_7-22-55-768x216.jpg 768w" sizes="(max-width: 804px) 100vw, 804px" /></figure>



<p>I followed the basic Adafruit directions for wiring the ST7789 driven 240&#215;240 display into my Raspberry Pi.  Key points:</p>



<ul><li>This is an SPI mode device.  We&#8217;re using the Raspi&#8217;s SPI0 mode, so that some of the LCD pins need to wire up to specific Raspberry Pi Pins.  More on SPI here.</li><li>We have a choice on the LCD&#8217;s reset pin, we went with a loose default of 24 on the Pi.</li><li>We have a choice on the D/C pin, we went with a loose default of GPIO 25 on the Pi.</li></ul>



<p>Here&#8217;s from Adafruit&#8217;s page specific to our ST7789 driven LCD display: <em><strong>(Editors Note &#8211; If you compare this to Adafruit&#8217;s wiring page, you may notice I swapped my RST and D/C pins &#8211; Adafruit uses 24/25 and I&#8217;m using 25/24 &#8211; It&#8217;s fine as long as you&#8217;re consistent with your physical pins and the command line options you&#8217;ll use later.  Thanks, Thomas!)</strong></em></p>



<ul><li><strong>Vin</strong>&nbsp;connects to the Raspberry Pi&#8217;s&nbsp;<strong>3V</strong>&nbsp;pin</li><li><strong>GND</strong>&nbsp;connects to the Raspberry Pi&#8217;s&nbsp;<strong>ground</strong></li><li><strong>CLK</strong>&nbsp;connects to SPI clock. On the Raspberry Pi, thats&nbsp;<strong>SCLK</strong></li><li><strong>MOSI</strong>&nbsp;connects to SPI MOSI. On the Raspberry Pi, thats also&nbsp;<strong>MOSI</strong></li><li><strong>CS</strong>&nbsp;connects to our SPI Chip Select pin. We&#8217;ll be using&nbsp;<strong>CE0</strong></li><li><strong>RST</strong>&nbsp;connects to our Reset pin. We&#8217;ll be using&nbsp;<strong>GPIO 25</strong>&nbsp;but this can be changed later. </li><li><strong>D/C</strong>&nbsp;connects to our the data/command pin. We&#8217;ll be using&nbsp;<strong>GPIO 24</strong>, but this can be changed later as well.</li></ul>



<hr class="wp-block-separator"/>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div><em>&#8220;But I looked at Adafruit&#8217;s page and they reference CS AND D/C as SPI Chip Select?&#8221;</em>  I noticed that too&#8230; and it was confusing to me.  It seems there are variations in how SPI works, and here&#8217;s a simple summary of the same question on Adafruit&#8217;s site:  <a rel="noreferrer noopener" label=" (opens in a new tab)" href="https://forums.adafruit.com/viewtopic.php?f=47&amp;t=51949" target="_blank" class="broken_link">https://forums.adafruit.com/viewtopic.php?f=47&amp;t=51949</a>.  Also, found a great summary here on <a rel="noreferrer noopener" aria-label="particle.io (opens in a new tab)" href="https://community.particle.io/t/ssd1306-via-hardware-spi/8448/4" target="_blank">particle.io</a>:<br><br><em>The DC or D/C pin is needed by some devices to distinguish between commands or data for the controler.<br>Since SPI only pushes out anonymous bitsreams the user code has to “tell” the controler if this will be a command (e.g. D/C LOW) or a data (e.g. D/C HIGH) bitstream. And so D/C is not actually an SPI pin, but this gives you freedom which Core pin to choose.</em><br></div></div>



<hr class="wp-block-separator"/>



<p>Remember that the Raspberry PI has numerous GPIO pins, but GPIO pin 24 doesn&#8217;t mean pin 24 on the pin-out diagram &#8211; always refer to some cheat sheet like this one from <a rel="noreferrer noopener" label="RaspberryPi.org (opens in a new tab)" href="https://www.raspberrypi.org/documentation/usage/gpio/" target="_blank" class="broken_link">RaspberryPi.org</a> shown below.  Also, another great Raspberry Pi pin-out page that&#8217;s interactive is made available by <a rel="noreferrer noopener" aria-label="Gadgetoid (opens in a new tab)" href="https://pinout.xyz/" target="_blank">Gadgetoid</a>.</p>



<div class="wp-block-envira-envira-gallery"><div class="envira-gallery-feed-output"><img class="envira-gallery-feed-image" tabindex="0" src="https://krystof.io/wp-content/uploads/2020/01/GPIO-Pinout-Diagram-2-1024x588.png" title="GPIO-Pinout-Diagram-2" alt="" /></div></div>



<p>Okay, so we&#8217;ve got it wired now, and there&#8217;s a promising backlight barely illuminating the LCD when we turn the PI on.  We&#8217;re one step closer to mirroring our Raspberry Pi to the ST7789 driven LCD Display.  Now what?</p>



<h2 class="wp-block-heading" id="h-lcd-driver-powers-activate-form-of-a-mirrored-display">LCD Driver Powers activate! Form of a mirrored display</h2>



<p>While I could have used Python to draw some Commodore images, screenshots, and other static media on the display, I want to actually mirror the display.  What shows on the HDMI output should show on the LCD, but I need the mirror scaled.  My monitor I&#8217;ll play games on doesn&#8217;t support 320&#215;240 as a resolution, the bare minimum is 800&#215;600 to make it work well enough.  So I searched around the internet and found a couple of solutions that did NOT turn the LCD into the only display or require me to overwrite with a new image.</p>



<p>This is where things might get a little confusing.  Both solutions I&#8217;m presenting here involve taking the HDMI display output and doing a little frame-buffer copy and manipulation magic.</p>



<hr class="wp-block-separator"/>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>Keep in mind that as the time of this writing, I&#8217;m using the Raspbian Buster Lite image on a Raspberry Pi 4.  Mileage may vary in the future.</div></div>



<hr class="wp-block-separator"/>



<ol><li>Notro&#8217;s <strong>fbtft</strong> LCD device drivers, which create an LCD frame buffer at /dev/fb1, then utilizing tasanakorn&#8217;s <strong>fbcp</strong> program which copies /dev/fb0 (HDMI output) to /dev/fb1 (LCD output), effectively mirroring the display.</li><li>juj&#8217;s <strong>fbcp-ili9341</strong> display driver that effectively does the same thing as #1, though it doesn&#8217;t technically create it&#8217;s own framebuffer, and it&#8217;s not just for ili9341 displays (it supports my ST7789!)</li></ol>



<p>Which one to use?  Well, if only one works for you, choose that one.  Otherwise, I found that  the second, <strong>fbcp-ili9341</strong> worked the best, but it does utilize a little more CPU, so you may very well want to test both (the Raspberry Pi 4 handled it fine)</p>



<p>The primary issues I had with both of these solutions involved rotation.  My requirements for either solution were to have the header pins aligned with the bottom of the display so I could more easily hide them in the mini-LCD monitor&#8217;s bottom piece.  </p>



<h3 class="wp-block-heading" id="h-option-1-fbtft-and-fbcp">Option 1 &#8211; fbtft and fbcp</h3>



<h4 class="wp-block-heading" id="h-the-journey-to-a-working-lcd-mirror">The Journey to a working LCD mirror</h4>



<p>Notro&#8217;s <a rel="noreferrer noopener" aria-label="fbtft driver (opens in a new tab)" href="https://github.com/notro/fbtft" target="_blank">fbtft driver</a> repo seems to be still a good reference point but may not be forever.  There&#8217;s a lot of discussion around the future of this project, as part of it has been brought into the Linux staging structure, and that it may stay there forever stagnating based on some discussions on the <a rel="noreferrer noopener" aria-label="development page (opens in a new tab)" href="https://github.com/notro/fbtft/wiki/Development" target="_blank">development page</a>.  Nevertheless, it did end up working.</p>



<p>There&#8217;s a lot of good information to sift through on that wiki, but I&#8217;ll keep this page more towards my journey in getting it working.</p>



<p>I saw some references in the staging code base to the ST7789 driver, so it felt promising:</p>



<p><a href="https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c</a></p>



<p>Now, the key here is that if these drivers are effectively already part of my Raspbian install, I should be able to use the Linux modprobe commands to load these modules in.  By looking at other sample modprobe commands I tried this against my Raspberry Pi with the LCD on the breadboard:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#Screen mirrors but inverted colors and rotation
sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 gpios=reset:25,dc:24
</pre></div>


<p>The command above loads the <em>fbtft_device</em> module with a custom configuration based on the provided driver <em>fb_st7789v</em>.  Notice that we didn&#8217;t have to declare the standard SPI pins but we need to reference our two custom GPIO pins from the wiring section &#8211; reset and dc.</p>



<p><em>Remember that this command just creates a framebuffer for the LCD at /dev/fb1, it doesn&#8217;t actively mirror the display.  We need the fbcp program for that.</em>  I just run fbcp as a background process and voila.  The LCD came to life &#8230; but it&#8217;s a little off.  (Also, don&#8217;t worry, the full setup steps are at the end)</p>



<p>Here&#8217;s the result when I ran &#8216;htop&#8217;:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="578" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-1024x578.jpg" alt="" class="wp-image-1161" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-1024x578.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06-768x434.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-11_20-50-06.jpg 1220w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>I want none of this.</figcaption></figure></div>



<p>If you don&#8217;t know what that <strong>should</strong> look like, I can tell you that display screen is rotated 180 degrees off my desired layout (pins on the bottom), and the screen color is &#8216;negative&#8217;.  It should be a black screen with white text.</p>



<p>Now I&#8217;m off to figure out how to rotate and how to invert the colors.  I dug around the issues page on the wiki and found this reference:</p>



<p><a href="https://github.com/notro/fbtft/issues/425">https://github.com/notro/fbtft/issues/425</a></p>



<p>Github user <a rel="noreferrer noopener" aria-label="tr1p1ea  (opens in a new tab)" href="https://github.com/tr1p1ea" target="_blank">tr1p1ea </a>references an init string argument you can also pass along in the modprobe argument, which probably was setting some ST7789 specific codes I needed to set.</p>



<pre class="wp-block-code"><code>init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3</code></pre>



<p>What is all this crap?  These are initialization parameters you can send directly to your LCD driver chipset.  Notro&#8217;s page has some information there, but understanding the specifics for your LCD require the datasheet.  Nevertheless, I tried it out and we got farther&#8230;</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="579" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-1024x579.jpg" alt="" class="wp-image-1167" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-1024x579.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-300x170.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49-768x434.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_7-21-49.jpg 1222w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Okay, color looks good, now let&#8217;s rotate it.</figcaption></figure></div>



<p>The fbtft_device page on the wiki references other parameters &#8211; one of them being rotate:</p>



<pre class="wp-block-code"><code>rotate
Angle to rotate display counter clockwise: 0, 90, 180, 270 </code></pre>



<p>Okay, so we rotate with our updated command &#8211; I figured 180 degrees to start.</p>



<pre class="wp-block-code"><code>sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 rotate=180 gpios=reset:25,dc:24 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3</code></pre>



<p>Which now leaves us with something completely different &#8211; I thought I saw rotation but couldn&#8217;t tell easily &#8211; so I ran VICE and saw it fill up only part of the screen!</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="580" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-1024x580.jpg" alt="" class="wp-image-1173" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-1024x580.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-300x170.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31-768x435.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-32-31.jpg 1220w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>What fresh hell is this?</figcaption></figure>



<p>During my research on fbtft and fbcp, I ran across that the ST7789 driver chip supported 320&#215;240 <strong><em>and</em></strong> 240&#215;240 displays.  So it looked like to me that my 240&#215;240 lcd was acting as a viewport into the &#8216;opposite end&#8217; of the video ram that stores the 240&#215;240 image as configured by our modprobe command.</p>



<p>I had a rough idea now of what I was looking for &#8211; I need to &#8216;scroll&#8217; up about 320-240 = 80 pixels.  How the **** am I supposed to do this?  At this point I started looking for the ST7789 data sheet so I could see if there was some &#8216;mode&#8217; or related setting.  After perusing this for a while, I found something quite interesting in the <a rel="noreferrer noopener" aria-label="PDF (opens in a new tab)" href="https://www.rhydolabz.com/documents/33/ST7789.pdf" target="_blank">PDF</a>:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="535" height="622" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-39-58.jpg" alt="" class="wp-image-1174" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-39-58.jpg 535w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-39-58-258x300.jpg 258w" sizes="(max-width: 535px) 100vw, 535px" /><figcaption>This looks promising!</figcaption></figure></div>



<p>At this point it looked like I wanted to add to our init string.  Something with instruction 37h, with 2 parameters.  I defaulted the first to zero and the second to the number of pixels I wanted to &#8216;scroll&#8217;.  I wasn&#8217;t sure if my rotation settings &#8216;inverted&#8217; the pixel count so I just started with the difference of 320-240 = 80.  Of course, we&#8217;re dealing with hex, so thats 0x50.  The full piece of the initialization string I inserted after the 0x36 instruction follows:</p>



<pre class="wp-block-preformatted">-1,0x37,0x00,0x50
<strong>-1</strong> (break for new instruction)
<strong>0x37</strong> Instruction for Vertical Scroll Start Address Of RAM
<strong>0x00</strong> First Parameter  (defaulted this to 0)
<strong>0x50</strong> Second Parameter (set this to 80 pixels, converted to hex)</pre>



<p>So now my init string, with the extra 37h instruction added, yielded this result:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="577" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-1024x577.jpg" alt="" class="wp-image-1175" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-1024x577.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06-768x433.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-12_15-47-06.jpg 1226w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Holy crap, it actually worked.</figcaption></figure></div>



<h4 class="wp-block-heading" id="h-install-instructions-for-option-1-fbtft-and-fbcp">Install Instructions for Option 1 &#8211; fbtft and fbcp</h4>



<p>So, we at least have something working.  That was the entire goal of this first stage &#8211; just get the LCD mirroring the HDMI output of my Raspberry Pi with VICE.  Good to go!  So let&#8217;s finish off option 1 by building the list of instructions.</p>



<p>Since fbtft drivers are already part of Raspbian Buster, all we really need to do is download and copy fbcp, and basing the instructions off that GitHub page: <a rel="noreferrer noopener" aria-label="https://github.com/tasanakorn/rpi-fbcp (opens in a new tab)" href="https://github.com/tasanakorn/rpi-fbcp" target="_blank">https://github.com/tasanakorn/rpi-fbcp</a></p>



<hr class="wp-block-separator"/>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>This option is here to best describe the journey &#8211; I ended up going with Option 2 &#8211; FBCP-ILI9341</div></div>



<hr class="wp-block-separator"/>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
mkdir ~/fbcp-src
cd ~/fbcp-src

git clone https://github.com/tasanakorn/rpi-fbcp.git
cd rpi-fbcp/

mkdir build
cd build
cmake ..
make
</pre></div>


<p>After that point, a new <em><strong>fbcp</strong></em> binary now exists in the build directory we just made.</p>



<p>To just test the general execution of these two, I&#8217;ll enter the commands into the shell.  Afterwards I&#8217;d see the LCD activate and mirror the screen properly.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
#start LCD Driver - create fb1 frame buffer
sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 rotate=180 gpios=reset:25,dc:24 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x37,0x00,0x50,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3
</pre></div>


<p>Then, we need to run fbcp so it can copy the framebuffer from HDMI (/dev/fb0) to the LCD (/dev/fb1) &#8211; run this from your fbcp&#8217;s build directory you created earlier:</p>



<pre class="wp-block-preformatted">./fbcp &amp;</pre>



<p>What if we want this to run on start up?  There are numerous ways to do that, here&#8217;s a simple one &#8211; pop it into rc.local.  We&#8217;ll cover alternate methods later in the series, this article is just about getting the LCD going.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#Copy fbcp and start it up and the fbtft drivers  (run from your fbcp build dir)
sudo cp fbcp /usr/bin 
sudo chmod +x /usr/bin/fbcp

sudo nano /etc/rc.local
</pre></div>


<p>Add the following lines to rc.local before &#8216;exit 0&#8217;.  Remember the sudo modprobe is <em>all one single line</em>.</p>



<pre class="wp-block-code"><code>sudo modprobe --first-time fbtft_device name=fb_st7789v custom width=240 height=240 speed=32000000 rotate=180 gpios=reset:25,dc:24 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x37,0x00,0x50,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3

#
#Add a little sleep before starting fbcp to allow fbtft to initialize
#(your display might stay blank otherwise)
#
sleep 2

/usr/bin/fbcp &amp;</code></pre>



<p>Reboot and you should see the screen mirror after the boot process initializes some.  If you don&#8217;t have your HDMI output active, VICE may not load (it doesn&#8217;t get a good hook into /dev/fb0) &#8211; so you may need to edit your /boot/config.txt and add:</p>



<pre class="wp-block-code"><code>hdmi_force_hotplug=1</code></pre>



<h3 class="wp-block-heading" id="h-option-2-fbcp-ili9341">Option 2 &#8211; fbcp-ili9341</h3>



<h4 class="wp-block-heading" id="h-a-faster-alternative-to-fbtft-fbcp-that-uses-a-little-more-cpu">A faster alternative to fbtft/fbcp that uses a little more CPU</h4>



<p>I was initially happy with option 1 &#8211; I wasn&#8217;t planning on playing games using the tiny LCD, just mirror it so the diorama looked alive.  However, I still perused a few other search threads and found out about this other option called <strong>fbcp-ili9341</strong>, and while the name may be confusing (it doesn&#8217;t create a framebuffer, and it&#8217;s not just for the ili9341 driver), I was able to get it working with our ST7789 1.3&#8243; LCD display.  </p>



<p><strong>Why did I try it out?</strong> Turns out, SPI doesn&#8217;t have the inherent bandwidth as it stands with libtft and fbcp &#8211; and since I&#8217;m playing games, which inherently implies video as opposed to text, I noticed the refresh rate on the LCD was always a little stuttered while playing C64 games and demos.  Through some optimizations and shortcuts, the author juj has created an alternative that is faster than our option 1, all the way to 60fps.  Ohhhhh yeah.</p>



<p>So here&#8217;s the journey to making that work.  A little easier, and a bit nicer payoff.  This option, while using a little more CPU (Our Raspi has 4 cores, so it&#8217;s not a big deal), is <strong><em>fast</em></strong>.  In fact, it says so on it&#8217;s <a rel="noreferrer noopener" aria-label="GitHub page (opens in a new tab)" href="https://github.com/juj/fbcp-ili9341" target="_blank">GitHub page</a>, so you know it&#8217;s true!</p>



<p>Since the name is also confusing, here&#8217;s <em>why</em> it&#8217;s named the way it is:</p>



<p><em>The&nbsp;<code>fbcp</code>&nbsp;part in the name means&nbsp;framebuffer copy; specifically for the ILI9341 controller. fbcp-ili9341 is not actually a framebuffer copying driver, it does not create a secondary framebuffer that it would copy bytes across to from the primary framebuffer. It is also no longer a driver only for the ILI9341 controller. A more appropriate name might be&nbsp;userland-raspi-spi-display-driver&nbsp;or something like that, but the original name stuck. </em></p>



<p>So I downloaded the source and compiled it, and there&#8217;s effectively just one execution line since this takes the place of fbtft and fbcp &#8211; in fact, you can&#8217;t run both at the same time &#8211; test with Option 1 or Option 2 separately.</p>



<p>The <strong>cmake</strong> command to the build takes a few options in, and I chose these as my initial settings so I could see what it would do:</p>



<pre class="wp-block-preformatted"><strong>-DST7789=ON</strong> 
There's built in support for our chip set, so this was a natural choice.
<strong>-DGPIO_TFT_DATA_CONTROL=24</strong>
Same as option 1 - our custom pin we chose for data control.
<strong>-DGPIO_TFT_RESET_PIN=25</strong>
Same as option 1 - our custom pin for LCD display reset.
<strong>-DSPI_BUS_CLOCK_DIVISOR=30</strong>
My sensible default based on the GitHub page - lower is more responsive but may cause screen artifacts on LCDs.</pre>



<p>Compiling with those options successfully, I now had a fbcp-ili9341 binary to execute.  Survey says&#8230;</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="578" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-1024x578.jpg" alt="" class="wp-image-1191" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-1024x578.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04-768x433.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-25-04.jpg 1225w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Rotated 90 degrees off, and looks like some debugging info at the &#8216;top&#8217;.</figcaption></figure></div>



<p>Okay, we can fix this.  Reading up on a reported issue in the project&#8217;s GitHub issues list, I found reference to a couple of items to change in the code:</p>



<pre class="wp-block-preformatted"><strong>define DISPLAY_OUTPUT_LANDSCAPE</strong> - If we comment this out, we'll rotate the display 90 degrees - which way though?  Let's try and find out what happens.</pre>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="491" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-1024x491.jpg" alt="" class="wp-image-1192" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-1024x491.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-300x144.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45-768x369.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-30-45.jpg 1440w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Getting closer&#8230;</figcaption></figure></div>



<p>So we&#8217;re rotated properly, but we&#8217;re reversed.  The text should be on the left.  So we need to reverse the image, not just a simple rotation.  Here&#8217;s the next changes I tried:</p>



<pre class="wp-block-preformatted"><strong>madctl ^= MADCTL_COLUMN_ADDRESS_ORDER_SWAP;</strong>  - Adding this line into another file will mirror image the display - Sold!

<strong>-DSTATISTICS=0</strong> Remove that debug information</pre>



<p>So, we try this change and rebuild, and we now have&#8230;</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="578" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-1024x578.jpg" alt="" class="wp-image-1195" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-1024x578.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-300x169.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03-768x434.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-36-03.jpg 1224w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>The proper orientation, but &#8230; slightly squeezed.  Like an 8-bit orange.</figcaption></figure>



<p>Now we&#8217;re getting there!  We&#8217;re oriented in the right way, and the image reads left to right.  Only thing now is to change the scaling, which is how my research led to this option:</p>



<pre class="wp-block-preformatted"><strong>-DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON</strong> - I expected something like this because our display is 240 wide, so it's scaling 180 on the vertical to maintain aspect ratio.  Let's just make it fill the whole thing so we don't have the black bars of doom.</pre>



<p>And now&#8230;.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="491" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-1024x491.jpg" alt="" class="wp-image-1196" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-1024x491.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-300x144.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22-768x369.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_15-56-22.jpg 1440w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>We&#8217;re done!</figcaption></figure>



<p>So now I&#8217;ve got both options working in the same fashion.  There are differences though, and we&#8217;ll cover that in the next section below, after the &#8216;install instructions&#8217;</p>



<h4 class="wp-block-heading" id="h-install-instructions-for-option-2-fbcp-ili9341">Install Instructions for Option 2 &#8211; fbcp-ili9341</h4>



<p>Our goal is to download fbcp-ili9341, perform some quick modifications to the code, set our options, compile, and execute it.</p>



<div data-padding="10" class="wp-block-simple-blocks-info-block" style="background-color:#000000;color:#ffffff;padding:10px"><div data-iconsize="20" data-iconspace="20" class="icon" style="margin-right:20px"><svg aria-hidden="true" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewbox="0 0 20 20" class="dashicon dashicons-info"><path d="M10 2c4.42 0 8 3.58 8 8s-3.58 8-8 8-8-3.58-8-8 3.58-8 8-8zm1 4c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zm0 9V9H9v6h2z"></path></svg></div><div>If you are running Option 1 on start up of your PI, you should disable that first.  Option 1 and Option 2 are mutually exclusive.</div></div>



<p>If necessary, download the dependencies required:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt-get install cmake
</pre></div>


<p>Then let&#8217;s download our source code:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
mkdir ~/fbcp-ili9341
cd ~/fbcp-ili9341
git clone https://github.com/juj/fbcp-ili9341.git
</pre></div>


<p>This creates and downloads the source to /home/pi/fbcp-ili9341/fbcp-ili9341  (Yeah, it&#8217;s a double directory, I always make my own root directories for compilation work)</p>



<p>Before we compile, we need to make the edits referenced in our previous section on figuring out how Option 2 was going to work.  </p>



<p>Edit your config.h file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
nano ~/fbcp-ili9341/fbcp-ili9341/config.h
</pre></div>


<p>Comment out the line below (the example is already commented out)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
//#define DISPLAY_OUTPUT_LANDSCAPE
</pre></div>


<p>Next, we&#8217;ll edit our ST7789 (actually it&#8217;s a file that handles a couple of ST-made chips) specific file to do the &#8216;mirroring&#8217; swap.  Edit the following:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
nano ~/fbcp-ili9341/fbcp-ili9341/st7735r.cpp
</pre></div>


<p>and add the following line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
madctl ^= MADCTL_COLUMN_ADDRESS_ORDER_SWAP;
</pre></div>


<p>somewhere before this line:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
SPI_TRANSFER(0x36/MADCTL: Memory Access Control/, madctl);
</pre></div>


<p><strong>Optional Gamma Change: </strong>I&#8217;ve also, over time, discovered that I like the screen a little darker, primarily because I have a camera pointed at it at the Twitch stream and it causes some overexposure of the screen compared to the diorama itself.  So you can make the gamma 1.0 by changing this line in the same file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
SPI_TRANSFER(0x26/Gamma Curve Select/, 0x04/Gamma curve 3 (2.5x if GS=1, 2.2x otherwise)/);
</pre></div>


<p>Change the 0x04 to 0x08:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
SPI_TRANSFER(0x26/Gamma Curve Select/, 0x08/Gamma curve 3 (2.5x if GS=1, 2.2x otherwise)/);
</pre></div>


<p>That&#8217;s it for file editing, let&#8217;s get back to the compile.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd ~/fbcp-ili9341/fbcp-ili9341
mkdir build
cd build
cmake -DST7789=ON -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DSPI_BUS_CLOCK_DIVISOR=30 -DSTATISTICS=0 -DDISPLAY_BREAK_ASPECT_RATIO_WHEN_SCALING=ON ..
make -j
</pre></div>


<p>This will create the <strong>fbcp-ili9341</strong> binary in the build directory.  Try it out by running it and hitting CTRL-C when you&#8217;re done.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo ./fbcp-ili9341
</pre></div>


<p>If that works nicely for you, you could also make a quick hack to your /etc/rc.local file and make it boot on startup.  (This is a quick hack)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#Copy fbcp-ili9341 and start it up on boot
sudo cp ./fbcp-ili9341 /usr/bin 
sudo chmod +x /usr/bin/fbcp-ili9341

sudo nano /etc/rc.local
</pre></div>


<p>Add the following line to rc.local before &#8216;exit 0&#8217;.  </p>



<pre class="wp-block-code"><code>sudo /usr/bin/fbcp-ili9341 &amp;</code></pre>



<h2 class="wp-block-heading" id="h-comparing-mirroring-options">Comparing Mirroring Options</h2>



<p>You may notice right off the bat that the default initialization of our option 1 vs option 2 have a stark difference in brightness.  I didn&#8217;t investigate further in making the first option brighter, because I was just so happy with option 2 as a whole I never looked back.</p>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="590" src="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-1024x590.jpg" alt="" class="wp-image-1222" srcset="https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-1024x590.jpg 1024w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-300x173.jpg 300w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03-768x443.jpg 768w, https://krystof.io/wp-content/uploads/2020/01/2020-01-13_19-27-03.jpg 1199w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Option 2 may seem almost too bright from the photo, but it&#8217;s actually not bad for me in person.</figcaption></figure>



<p>Option 2, as you can see in the video segment at the beginning of this article, has a much higher frame rate as promised.  While I did try two different arguments to the <strong>SPI_BUS_CLOCK_DIVISOR</strong> option (30 and 8), I really didn&#8217;t see much of a difference in my eyes.  The big difference is between fbtft/fbcp being much slower than fbcp-ili9341.  </p>



<p>What&#8217;s the trade-off?  As you see in the video, there&#8217;s about a 20-40% spike in one of my Pi&#8217;s cores on FBCP-ILI9341 vs regular old FBCP.  Given I&#8217;m using a beefy Raspberry Pi, I detected no issues in game play.  Your mileage may vary.</p>



<p>So we&#8217;ve now got part of our diorama circuitry working &#8211; we successfully mirrored the Raspberry Pi HDMI output to the ST7789 driven LCD display, showing whatever we play on our VICE Commodore emulator&#8217;s HDMI output.  There&#8217;s more to come, though!  Remember those 1541 disk drives that Commodore computers utilized?  Well, we need to make sure that the LEDs we plan on putting in those floppy drives <strong>light up according to activity in VICE</strong>.  To do that, we&#8217;ll need to create a custom VICE build (we&#8217;ll be doing a small bit of C programming) so we can drive LED activity and power LEDs based on whatever VICE is doing.  That will be the next article in the series, coming soon.</p>



<h2 class="wp-block-heading" id="h-references-and-further-reading">References and Further Reading</h2>



<p><strong>SPI &#8211; Serial Peripheral Interface</strong></p>



<p><a rel="noreferrer noopener" aria-label="https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all (opens in a new tab)" href="https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all" target="_blank">https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all</a><br><a rel="noreferrer noopener" aria-label="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface (opens in a new tab)" href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface" target="_blank">https://en.wikipedia.org/wiki/Serial_Peripheral_Interface</a><br><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md" class="broken_link">https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md</a><br><a rel="noreferrer noopener" aria-label="https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices (opens in a new tab)" href="https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices" target="_blank">https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/spi-sensors-devices</a></p>



<p><strong>Option 1 &#8211; FBTFT/FBCP</strong></p>



<p><a href="https://github.com/notro/fbtft" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/notro/fbtft</a></p>



<p><a href="https://github.com/notro/fbtft/wiki/Development" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/notro/fbtft/wiki/Development</a></p>



<p><a href="https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/torvalds/linux/blob/master/drivers/staging/fbtft/fb_st7789v.c</a></p>



<p><a href="https://github.com/notro/fbtft/issues/425" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://github.com/notro/fbtft/issues/425</a></p>



<p><a href="https://www.rhydolabz.com/documents/33/ST7789.pdf" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">https://www.rhydolabz.com/documents/33/ST7789.pdf</a></p>



<p><a rel="noreferrer noopener" aria-label=" (opens in a new tab)" href="https://github.com/tasanakorn/rpi-fbcp" target="_blank">https://github.com/tasanakorn/rpi-fbcp</a></p>



<p><strong>Option 2 &#8211; FBCP-ILI9341</strong></p>



<p><a href="https://github.com/juj/fbcp-ili9341">https://github.com/juj/fbcp-ili9341</a></p>



<p><strong>Raspberry Pi GPIO Information</strong></p>



<p><a href="https://www.raspberrypi.org/documentation/usage/gpio/" target="_blank" rel="noreferrer noopener" label=" (opens in a new tab)" class="broken_link">https://www.raspberrypi.org/documentation/usage/gpio/</a></p>



<p><strong>Adafruit</strong></p>



<p><a rel="noreferrer noopener" aria-label=".96&quot; OLED Product Page (opens in a new tab)" href="https://www.adafruit.com/product/684" target="_blank">.96&#8243; OLED Product Page</a> (Not the display I ended up going with for resolution reasons, otherwise it&#8217;s very nice.)</p>



<p><a rel="noreferrer noopener" aria-label="1.3&quot; 240x240 TFT LCD Product Page (opens in a new tab)" href="https://www.adafruit.com/product/4313" target="_blank">1.3&#8243; 240&#215;240 TFT LCD Product Page</a> (My ultimate choice for this diorama)</p>



<p><a href="https://learn.adafruit.com/adafruit-1-3-and-1-54-240-x-240-wide-angle-tft-lcd-displays?view=all">Tutorial/Learning Page for the 1.3&#8243; display</a> (wiring, python, etc.)</p>



<p><strong>VICE</strong></p>



<p><a href="https://csdb.dk/release/?id=179123" target="_blank" rel="noreferrer noopener" aria-label="The Elder Scrollers Demo by Booze Design (opens in a new tab)">The Elder Scrollers Demo by Booze Design</a></p>
<p>The post <a rel="nofollow" href="https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/">Mirroring Raspberry Pi HDMI Video to a ST7789 1.3 inch LCD Display</a> appeared first on <a rel="nofollow" href="https://krystof.io">Krystof.IO</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://krystof.io/mirroring-raspberry-pi-hdmi-video-to-a-st7789-1-3-inch-lcd-display/feed/</wfw:commentRss>
			<slash:comments>23</slash:comments>
		
		
		
		<series:name><![CDATA[Diorama 64]]></series:name>
	</item>
	</channel>
</rss>
