𑇢^^^°< Technical stuff https://www.schnappy.xyz/ Thu, 23 Mar 2023 02:27:07 +0100 Thu, 23 Mar 2023 02:27:07 +0100 Pico GNU/Linux - Udev & systemd - Running a graphic environment when a USB device is plugged in <h1>GNU/Linux - Udev &amp; systemd - Running a graphic environment when a USB device is plugged in</h1> <h2>Summary :</h2> <p>At a GNU/Linux console prompt, no GUI. When a USB device of type <a href="https://en.wikipedia.org/wiki/Human_interface_device">HID</a> (keyboard/mouse mainly) is plugged in, we want the X server to start and launch VLC's graphical interface, fullscreen, no borders. When this device is removed, VLC is shut down and the X server too, and we end up back at the console prompt.</p> <h3>Proposed solution:</h3> <ol> <li><a href="https://wiki.archlinux.org/title/Udev">Udev</a> rules are triggered when the USB device is plugged/unplugged to create a file in '/tmp' named '.vlc_gui'.</li> <li>A systemd <a href="https://wiki.archlinux.org/title/Systemd/User">user</a> service starts a script on startup.</li> <li>This script uses <a href="https://man.archlinux.org/man/inotifywait.1">inotifywait</a> to monitor a file's creation/deletion in the '/tmp' folder, and act accordingly;</li> <li>Start/close a minimal graphical environment with <a href="http://openbox.org/">openbox</a> running <a href="https://videolan.org">VLC</a>.</li> </ol> <h2>1. Udev configuration</h2> <h3>Run script on USB HID (mouse/kb) connect</h3> <p>We want a rule that triggers when a device has SUBSYSTEM=="usb" and DRIVER=="usbhid". </p> <p>In '/etc/udev/rules.d/01-vlc_gui.rules' : </p> <pre><code># On plug ACTION=="add" SUBSYSTEM=="usb", DRIVER=="usbhid", RUN+="/usr/bin/touch /tmp/.vlc_gui" # On un-plug ACTION=="remove" SUBSYSTEM=="usb", RUN+="/usr/bin/rm -f /tmp/.vlc_gui"</code></pre> <p>The rules above create a '.vlc_gui' file in '/tmp' when a usbhid device is plugged in, and removes it when unplugged.</p> <h3>Change read permissions on tty7</h3> <p>By default, permissions on '/dev/tty*' are 0620 (<code>crw--w----</code>). So members of group <code>tty</code> can write, but not read to ttys. This will be a problem for the X server, so we need to change those permissions to have read writes for our group too. </p> <p>Let's change the permissions on the tty that we need to 0660 (<code>crw-rw----</code>) so that we can run our X session on it. </p> <p>Inspect how udev sees your TTY (tty7 here): </p> <p><code>udevadm info --attribute-walk --path=/sys/class/tty/tty7</code></p> <pre><code>looking at device '/devices/virtual/tty/tty7': KERNEL=="tty7" SUBSYSTEM=="tty" DRIVER=="" ATTR{power/control}=="auto" ATTR{power/runtime_active_time}=="0" ATTR{power/runtime_status}=="unsupported" ATTR{power/runtime_suspended_time}=="0</code></pre> <p>So we want a rule that matches 'KERNEL=="tty7"' and 'SUBSYSTEM=="tty"' and set it to mode '0660': </p> <p><code>SUBSYSTEM=="tty", KERNEL=="tty7", MODE:="0660"</code></p> <p>Notice the <a href="https://www.freedesktop.org/software/systemd/man/udev.html#Operators">immutable operator</a> ":=" for "MODE"; it makes shure this won't be changed by another rule. </p> <p><a href="https://forums.opensuse.org/t/udev-rules-priority-disallow-change-by-other-rules-with-operator/100210">Udev rules order read</a> </p> <p>Test which rules are triggered by a specific device with : </p> <p><code>udevadm test /class/tty/tty7</code></p> <p>Reload and apply the new rules with : </p> <pre><code>udevadm control --reload-rules udevadm trigger</code></pre> <p>Of course, don't forget to add your user to the 'tty' group :</p> <p><code>sudo adduser USERNAME tty</code></p> <p>On some system, you might have to use usermod :</p> <p><code>sudo usermod -a -G tty USERNAME</code></p> <p>then log out/in and check with <code>groups</code> that 'tty' appears in the listed groups. </p> <h2>2. Systemd user unit</h2> <p>We can create <a href="https://wiki.archlinux.org/title/systemd/User">user units</a> in '~/.config/systemd/user/', e.g : </p> <p><code>nano ~/.config/systemd/user/vlc_gui.service</code></p> <pre><code class="language-yaml">[Unit] Description=VLC GUI launcher service [Service] # %h specifier resolves to user home (~ equivalent) ExecStart="%h"/vlc_gui.sh Restart=always [Install] WantedBy=default.target</code></pre> <p>Reload the units with <code>systemctl --user daemon-reload</code><br /> and start/enable the service with<br /> <code>systemctl --user start vlc_gui.service</code> / <code>systemctl --user enable vlc_gui.service</code>. </p> <p>More about systemd specifiers:<br /> <a href="https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers">https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers</a> </p> <h3>Starting a user unit as root</h3> <p>If running <a href="https://github.com/systemd/systemd/blob/28795f2c138203fb700fc394f0937708af886116/NEWS#L2809">systemd version &gt;= 248 (2021-03)</a>, you can <a href="https://www.freedesktop.org/software/systemd/man/systemctl.html#-M">start a user unit as root</a>, i.e ;<br /> using <code>sudo systemctl</code> or in a root shell, with e.g: </p> <p><code>sudo systemctl --user --machine USERNAME@ start foo.service</code></p> <p>On prior versions, you have to use either<br /> <code>su - USERNAME -c 'systemctl --user start foo.service'</code> or<br /> <code>runuser -l USERNAME -c 'systemctl --user start foo.service'</code> instead. </p> <h2>3. inotifywait : watch for a file's creation/deletion</h2> <h3>Install the tool :</h3> <p><code>sudo apt-get install inotify-tools</code></p> <h3>Create the script :</h3> <p>In '~/vlc_gui.sh' :</p> <pre><code class="language-bash">#!/usr/bin/env bash inotifywait -m /tmp -e create -e delete | while read directory action file; do if [[ "$file" == ".vlc_gui" ]]; then if [[ "$action" == "CREATE" ]]; then echo "Starting VLC GUI." # Start X environment on tty7 DISPLAY=:0 startx -- vt7 &amp; elif [[ "$action" == "DELETE" ]]; then echo "Killing VLC GUI" pkill vlc fi fi done</code></pre> <p>Don't forget to set execution bit : <code>sudo chmod +x ~/vlc_gui.sh</code></p> <h2>4. Minimal X environment &amp; Launching VLC</h2> <p>Install the following packages : </p> <p><code>sudo apt-get install -y --no-install-recommends --no-install-suggests xinit xserver-xorg xserver-xorg-core xserver-xorg-input-evdev xserver-xorg-input-kbd openbox feh</code></p> <h3>Xinit config</h3> <p>We start the X environment with <code>startx</code>, which sources "~/.xinitrc".<br /> Let's start openbox session there. </p> <p><code>cp /etc/X11/xinit/xinitrc ~/.xinitrc</code></p> <p>Then in "~/.xinitrc" : </p> <pre><code class="language-bash">#!/bin/sh # /etc/X11/xinit/xinitrc # # global xinitrc file, used by all X sessions started by xinit (startx) # invoke global X session script . /etc/X11/Xsession exec openbox-session</code></pre> <p>Set execution bit : </p> <p><code>sudo chmod +x ~/.xinitrc</code></p> <h3>Openbox configuration</h3> <p>Now Openbox config files are in '~/.config/openbox' and there are two of them :</p> <h4>autostart.sh</h4> <p>In '~/.config/openbox/autostart.sh' :</p> <pre><code class="language-bash">#!/bin/bash # Exit openbox when VLC is closed vlc --vout=gles2 &amp;&amp; openbox --exit # on rpi with 3d kms driver, can be --vout=drm_vout </code></pre> <p>Set execution bit : </p> <p><code>sudo chmod +x ~/.config/openbox/autostart.sh</code></p> <h4>rc.xml</h4> <p><code>cp /etc/xdg/openbox/rc.xml ~/.config/openbox/</code></p> <p>We want the VLC gui launching fullscreen, with no window decoration. In openbox's <a href="http://openbox.org/wiki/Help:Applications">&lt;applications></a> section of '~/.config/openbox/rc.xml', l.656, add: </p> <pre><code class="language-markup"> &lt;application name="vlc" role="vlc-main"&gt; &lt;decor&gt;no&lt;/decor&gt; &lt;maximized&gt;yes&lt;/maximized&gt; &lt;/application&gt;</code></pre> <h2>Troubleshooting</h2> <h3>Udev rules</h3> <p>You can increase udev's log verbosity with <code>sudo udevadm control --log-priority=debug</code><br /> then run <code>journalctl -f</code> to see if an error message comes up when plugging/unplugging the USB HID.</p> <h3>Xserver</h3> <p>You can see what's going on by launching <code>journalctl -f</code> in a SSH session, then plug/unplug the USB HID.<br /> If you encounter an error with the X server complaining about permission to tty7 like this </p> <pre><code>(EE) xf86OpenConsole: Cannot open virtual console 7 (Permission denied)</code></pre> <p>try rebooting. </p> <h3>Slow mouse cursor</h3> <p>If you experience laggy mouse cursor movements, you can try adding <code>usbhid.mousepoll=0</code> to '/boot/cmdline.txt'.</p> <p>Other values you might want to try are :</p> <table> <thead> <tr> <th style="text-align: center;">value</th> <th style="text-align: center;">speed</th> </tr> </thead> <tbody> <tr> <td style="text-align: center;">0</td> <td style="text-align: center;">device request</td> </tr> <tr> <td style="text-align: center;">X</td> <td style="text-align: center;">1000/X Hz</td> </tr> </tbody> </table> <p>source: <a href="https://peppe8o.com/fixing-slow-mouse-with-raspberry-pi-os/">https://peppe8o.com/fixing-slow-mouse-with-raspberry-pi-os/</a> </p> Thu, 19 Jan 2023 01:00:00 +0100 https://www.schnappy.xyz/?UDEV_systemd_start_x_environment_usb_plugging https://www.schnappy.xyz/?UDEV_systemd_start_x_environment_usb_plugging Rpi config.txt - Safe overclocking values <h1>Rpi config.txt - Safe overclocking values</h1> <p>To get a little boost out of your RPI while being conservative for applications where you need reliability and avoid data corruption, I found these values to do the job. </p> <p>This goes in '/boot/config.txt' : </p> <pre><code># SD card reader OC (expect 20% rio improvement) # Samsung Pro/Evo+ is recommended # default value : 50 # value needs to be an int divisor of core_freq # NEEDS A UHS-1/Class10 SD CARD ! # dtparam=sd_overclock=100 # To check the sd card clock once booted : cat /sys/kernel/debug/mmc0/ios | grep 'actual clock' [pi4] # Run as fast as firmware / board allows arm_boost=1 dtoverlay=disable-bt dtoverlay=vc4-kms-v3d max_framebuffers=2 # Apply to rpi3, rpi3+, cm3 [pi3] # Safe OC values # gpu_freq : Sets core_freq, h264_freq, isp_freq, v3d_freq and hevc_freq together # default values : # arm_freq 1200 # gpu_freq 400 # sdram_freq 450 arm_freq=1300 gpu_freq=462 sdram_freq=500 over_voltage=3 # NEEDS A UHS-1/Class10 SD CARD ! dtparam=sd_overclock=66 # Disable bluetooth dtoverlay=disable-bt # Enable DRM VC4 V3D driver dtoverlay=vc4-kms-v3d max_framebuffers=2 # Override OC values for 3+ models [pi3+] # Defaults values : # arm_freq 1400 # gpu_freq 400 # sdram_freq 500 arm_freq=1500 sdram_freq=550 [pi1] # default values # arm_freq 700 # gpu_freq 250 # sdram_freq 400 arm_freq=1000 gpu_freq=400 sdram_freq=500 over_voltage=6 [all] # This much is needed for 1080p playback gpu_mem=64 # Force HDMI Full HD hdmi_group=1 hdmi_mode=16 # fullHD@60 # Avoid SD card corruption boot_delay=1 # Disable rainbow splash and power warnings avoid_warnings=1 disable_splash=1</code></pre> <h2>Some links</h2> <ul> <li>RPI's official doc on overclocking : <a href="https://www.raspberrypi.com/documentation/computers/config_txt.html#overclocking-options">https://www.raspberrypi.com/documentation/computers/config_txt.html#overclocking-options</a></li> <li>SD overclocking guide : <a href="https://www.jeffgeerling.com/blog/2016/how-overclock-microsd-card-reader-on-raspberry-pi-3">https://www.jeffgeerling.com/blog/2016/how-overclock-microsd-card-reader-on-raspberry-pi-3</a></li> <li>SD card benchmarks : <a href="https://www.pidramble.com/wiki/benchmarks/microsd-cards">https://www.pidramble.com/wiki/benchmarks/microsd-cards</a></li> </ul> Thu, 12 Jan 2023 01:00:00 +0100 https://www.schnappy.xyz/?Rpi_config_txt_safe_oc_values https://www.schnappy.xyz/?Rpi_config_txt_safe_oc_values Rpi 3A+/3B+/4B wifi - BCM4345 and CTRL-EVENT-ASSOC-REJECT <h1>Rpi 3A+/3B+/4B wifi - BCM4345 and CTRL-EVENT-ASSOC-REJECT when using handshake offloading</h1> <p>I encountered an issue with the wifi on my 3A+/4B not willing to connect to my AP, while my 3B was perfectly happy with it. Turns out it's a driver issue with 'brcmfmac' and the BCM4345 chipset that's in newer RPI models.<br /> I'm using <strong>raspios bullseye (2022-09-22-raspios-bullseye-arm64-lite.img.xz)</strong>. </p> <p><code>wpa_supplicant</code> kept insisting that <code>CTRL-EVENT-ASSOC-REJECT</code>, i.e: </p> <pre><code>sudo wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant.conf -iwlan0 Successfully initialized wpa_supplicant wlan0: Trying to associate with **:**:**:**:**:** (SSID='foo' freq=2417 MHz) wlan0: CTRL-EVENT-ASSOC-REJECT bssid=**:**:**:**:**:** status_code=16 wlan0: Trying to associate with **:**:**:**:**:** (SSID='foo' freq=2417 MHz) wlan0: CTRL-EVENT-ASSOC-REJECT bssid=**:**:**:**:**:** status_code=16 wlan0: Trying to associate with **:**:**:**:**:** (SSID='foo' freq=2417 MHz) wlan0: CTRL-EVENT-ASSOC-REJECT bssid=**:**:**:**:**:** status_code=16 [etc]</code></pre> <h2>Why is this happening ?</h2> <p>After a <strong>LOT</strong> of troubleshooting and tests, and web searching, I stumbled upon several interesting pages and bug reports : </p> <ul> <li>A wiki page in <a href="https://iwd.wiki.kernel.org/start">IWD</a>'s wiki kernel.org : <a href="https://iwd.wiki.kernel.org/offloading">https://iwd.wiki.kernel.org/offloading</a>- <a href="https://web.archive.org/web/20221129112439/https://iwd.wiki.kernel.org/offloading">mirror</a> with an explanation as to why this happens</li> <li>A bug report linked in the page above : <a href="https://lore.kernel.org/linux-wireless/e1ff2a8eef465eaa76e8d00503d04e0fdd61a878.camel@gmail.com/">https://lore.kernel.org/linux-wireless/e1ff2a8eef465eaa76e8d00503d04e0fdd61a878.camel@gmail.com/</a> - <a href="https://web.archive.org/web/20220704011121/https://lore.kernel.org/linux-wireless/e1ff2a8eef465eaa76e8d00503d04e0fdd61a878.camel@gmail.com/">mirror</a> </li> <li>Another bug report on launchpad.net <a href="https://bugs.launchpad.net/raspbian/+bug/1929746">https://bugs.launchpad.net/raspbian/+bug/1929746</a> - <a href="https://web.archive.org/web/20230107122421/https://bugs.launchpad.net/raspbian/%20bug/1929746">mirror</a></li> </ul> <p>From the wiki linked above :</p> <blockquote> <p>Certain drivers support offloading the 4-way handshake as well as SAE/WPA3 into the firmware. For drivers which do not support user space driven Authenticate/Associate frames this is the only way to enable features such as SAE/WPA3 or Fast Transition roaming. Handshake offloading (both WPA2 and WPA3) is enabled in IWD by default for drivers which advertise support. The driver support, however, can be disabled on brcmfmac which will be discussed further. Handshake offloading has only been tested on the brcmfmac driver, and this wiki page assumes this driver is being used. </p> </blockquote> <blockquote> <p>If you are using brcmfmac and are experiencing problems such as not being able to connect to a network which you previously could, you may want to disable handshake offloading.</p> </blockquote> <blockquote> <p>The brcmfmac driver has a module parameter called 'feature_disable'. It expects a hex value (bitmask) where each bit corresponds to a feature [...]. The features we care about here are 'SAE' and 'FWSUP'. These features (when enabled) are listed in /sys/kernel/debug/ieee80211/<phy>/features so you can first see if your card even supports these before trying to debug further. </p> </blockquote> <p>On the <strong>rpi 3A+ and 4B</strong>, here'is what <code>/sys/kernel/debug/ieee80211/&lt;phy&gt;/features</code> gives us : </p> <pre><code># cat /sys/kernel/debug/ieee80211/phy0/features Features: 001428d6 MCHAN PNO P2P TDLS SCAN_RANDOM_MAC MFP FWSUP DOT11H FWAUTH Quirks: 00000000</code></pre> <blockquote> <p>To turn off offloading you need to remove the brcmfmac module, then reinsert it with the feature_disable option:</p> </blockquote> <pre><code>sudo rmmod brcmfmac sudo modprobe brcmfmac feature_disable=0x82000</code></pre> <blockquote> <p>This will disable both SAE (0x80000) and FWSUP (0x02000). You could disable just one, but this is not suggested due to a bug which prevents EAPoL frames from being forwarded after offloading is used for the first time.</p> </blockquote> <h2>The workaround</h2> <p>You can resolve the issue by using only <code>feature_disable=0x02000</code> if you're sure you won't ever have a WPA3/SAE AP around, but due to the bug mentionned above, you might want to be on the safe side and disable SAE as well while this bug exists.</p> <pre><code>sudo rmmod brcmfmac sudo modprobe brcmfmac roamoff=1 feature_disable=0x82000</code></pre> <h2>Driver options on boot</h2> <p>If that fixes things for you and you want to make this setting persistent, you can create a file with these options in '/etc/modprobe.d', e.g ; </p> <pre><code>echo 'options brcmfmac roamoff=1 feature_disable=0x82000' | sudo tee /etc/modprobe.d/brcmfmac.conf</code></pre> <p>This will make sure the settings are applied when the driver loads. </p> <p>The 3A+/3B+/4B are equipped with a BCM4345 chipset so this should solve wifi issues with those models. </p> Sat, 07 Jan 2023 01:00:00 +0100 https://www.schnappy.xyz/?Rpi_wifi_-_BCM4345_and_CTRL-EVENT-ASSOC-REJECT https://www.schnappy.xyz/?Rpi_wifi_-_BCM4345_and_CTRL-EVENT-ASSOC-REJECT Rpi pico - SHA1ving the yack with micropython RP2040 <h1>Rpi pico - SHA1ving the yack with micropython RP2040</h1> <p>So for those of you wondering how to get sha1 back in (u)hashlib on the rp2 port, it can be enabled by defining <code>MICROPY_PY_UHASHLIB_SHA1</code> in '<a href="https://github.com/micropython/micropython/blob/master/ports/rp2/mpconfigport.h">ports/rp2/mpconfigport.h</a>', after the <code>#include</code> directives (l.36)<br /> , i.e : </p> <pre><code class="language-c">[...] #include "pico/multicore.h" #include "mpconfigboard.h" #define MICROPY_PY_UHASHLIB_SHA1 (1) // alternatively, use // #define MICROPY_PY_NETWORK (1) // for a full network stack ( adds ~145KB to firmware file size ) // Board and hardware specific configuration [...]</code></pre> <p>then compile according to the instructions in <a href="https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-python-sdk.pdf">raspberry-pi-pico-python-sdk.pdf</a>, chapter 1.3. </p> <p>The resulting filesize with only SHA1 enabled is ~10KB more. </p> <p>For convenience, a pre-compiled firmware for the Rpi Pico with sha1 available in hashlib is hosted here : </p> <p><a href="https://www.schnappy.xyz/assets/MicroPython_v1.19.1-782-g699477d12-dirty_2022-12-23.uf2">MicroPython_v1.19.1-782-g699477d12-dirty_2022-12-23.uf2</a><br /> sha1sum : 079d695acfbaec80261b9e2c6127f63580ebe25e<br /> sha256sum : 9cfc1013015096f71420b56339aa3405d1f5ae6cd563149a6e9db06af4adeb10<br /> md5sum : 85d433f5d0516b411ee28bf14d27fe11 </p> <p><strong><a href="https://www.computerworld.com/article/3173616/the-sha1-hash-function-is-now-completely-unsafe.html">Of course, don't use SHA1 for new stuff as it's deprecated, etc.</a></strong></p> Fri, 23 Dec 2022 01:00:00 +0100 https://www.schnappy.xyz/?Rpi_pico_-_SHA1ving_the_yack_with_micropython_RP2040 https://www.schnappy.xyz/?Rpi_pico_-_SHA1ving_the_yack_with_micropython_RP2040 PS4 - Remote play without a PSN account <h1>PS4 - Remote play without a PSN account</h1> <p>For whatever reason, some genius at Sony thought it would make sense to make having an activated PSN account mandatory in order to be able to use remote play.<br /> Since firmware 7.0, you must provide your PSN account ID, which is a unique 8 bytes identifier tied to your PSN account. </p> <p>I don't want to offer Sony my private data just for the privilege to use remote play on my lan, so I was glad to find that you can avoid creating a PSN account and still be able to register new devices. </p> <p><strong>It does need your PS4 to be jailbroken for at least a few minutes though</strong>, and generating a fake account ID, which I guess if you ever plan on using a real PSN account, could have unforeseen consequences. You've been warned.</p> <h2>Steps</h2> <ul> <li><a href="https://invidious.fdn.fr/watch?v=yVFbo23BCK4&amp;list=PLn7ji3VsPy3Gryq_sCOMp6H87jXywCMPI&amp;index=0">Jailbreak your PS4</a></li> <li>Install <a href="https://github.com/bucanero/apollo-ps4">Apollo Save Tool</a> (also available via the <a href="https://github.com/LightningMods/PS4-Store/releases">HB store</a></li> <li>Open 'Apollo Save Tool', then go to 'User tools', 'Activate fake account'. You should see something like :</li> </ul> <pre><code>Activate Offline Account YourUserName (0000000000000000)</code></pre> <p><img src="https://www.schnappy.xyz/assets/ps4-apollo_1.jpg" alt="Apollo fake account registration" /> <img src="https://www.schnappy.xyz/assets/ps4-apollo_2.jpg" alt="Apollo fake account registration" /> <img src="https://www.schnappy.xyz/assets/ps4-apollo_3.jpg" alt="Apollo fake account registration" /></p> <ul> <li>Close then re-open 'Apollo', go back to 'User tools' and write down the generated ID (the hexadecimal string between the parenthesis)</li> <li>You then have to convert this 16 characters hexadecimal string to int, then to base64. Here is a python one liner :</li> </ul> <pre><code class="language-python">python -c 'import base64;print( "Your 8 bytes, base64 encoded account ID is : " + base64.b64encode(int( "1a2b3c4d5e6f7a8b", 16 ).to_bytes(8, "little")).decode())'</code></pre> <p><strong>Make sure to replace <code>1a2b3c4d5e6f7a8b</code> with your generated ID</strong><br /> The base64 ID will look like that : <code>i3pvXk08Kxo=</code>. Alternatively, use the following script :<br /> <a href="https://gist.github.com/ABelliqueux/30f03a6bd8dcc087c4319a529d934b1b">https://gist.github.com/ABelliqueux/30f03a6bd8dcc087c4319a529d934b1b</a><br /> or run it online:<br /> <a href="https://trinket.io/python3/352d094d9c">https://trinket.io/python3/352d094d9c</a> </p> <ul> <li>Install and launch <a href="https://sr.ht/~thestr4ng3r/chiaki/">Chiaki</a></li> <li>On your PS4, go to Settings &gt; Remote play connection settings &gt; Add device <img src="https://www.schnappy.xyz/assets/ps4-register_dev.jpg" alt="Register device" /> <img src="https://www.schnappy.xyz/assets/ps4-register_pin.jpg" alt="Register PIN" /></li> <li>Back in chiaki, connec to your PS4, and when asked to register, enter the base64 account ID you found earlier and the 8 digits PIN number that's displayed by your PS4. </li> <li>Enjoy.</li> </ul> <h2>Bonus : Fix Android's broken Dualshock 4 layout</h2> <p>What I wanted to achieve was use the libre software <a href="https://f-droid.org/packages/com.metallic.chiaki/">chiaki</a> on my old android tablet. While the client works great, it looks like the default layout for the Dualshock 4 on android is sub-optimal, not to say sucky. At least you can connect your DS4 via bluetooth as a regular gamepad, and not need a 3rd party app like for the DS3, so there's progress there. </p> <p>To fix the layout, you need to own your hardware, which means it has to be rooted, since we'll be accessing some system files.<br /> You also have to <a href="https://developer.android.com/studio/debug/dev-options">enable developer mode and USB debugging</a>, and <a href="https://www.xda-developers.com/install-adb-windows-macos-linux/">install ADB</a> on your computer. </p> <p>You then have to put a file with the correct layout in <code>/system/usr/keylayout</code>. </p> <h3>Steps</h3> <ul> <li>Download the layout file from <a href="https://www.schnappy.xyz/assets/android-dualshock4-layout.zip">here</a> and extract the two kl layout files it contains.</li> <li>Connect your android device to your computer</li> <li>Copy the .kl files from your computer to your device with your file browser, for example in your download folder ; <code>/storage/emulated/0/Download</code> </li> <li>In a terminal/cmd, launch and ADB shell on your device with :<pre><code>adb shell</code></pre> </li> <li>Switch to super user by typing:<pre><code>su</code></pre> </li> <li>Remount <code>/system</code> with read-write permissions :<pre><code>mount -o remount,rw /system</code></pre> </li> <li>Copy the new layout files to the <code>/system/usr/keylayout</code> folder :<pre><code>cp /storage/emulated/0/Download/*.kl /system/usr/keylayout/</code></pre> </li> <li>Make sure the permissions on the files are correct :<pre><code>chmod 644 /system/usr/keylayout/Vendor_054c*.kl</code></pre> </li> <li>Reboot your device<pre><code>reboot</code></pre> </li> </ul> <p>Your DS4 should now be mapped correctly.</p> <h2>Sources &amp; More</h2> <p>Pics : <a href="https://www.digitaltrends.com/gaming/how-to-stream-from-your-ps4-to-your-pc/">https://www.digitaltrends.com/gaming/how-to-stream-from-your-ps4-to-your-pc/</a><br /> Android keylayout : <a href="https://forum.xda-developers.com/t/root-dualshock-4-correct-keymaps-controller-bug-fix-kl-file.2817223/page-2">https://forum.xda-developers.com/t/root-dualshock-4-correct-keymaps-controller-bug-fix-kl-file.2817223/page-2</a><br /> MODDED WARFARE's tutorial series on PS4 jailbreak : <a href="https://invidious.fdn.fr/playlist?list=PLn7ji3VsPy3Gryq_sCOMp6H87jXywCMPI">https://invidious.fdn.fr/playlist?list=PLn7ji3VsPy3Gryq_sCOMp6H87jXywCMPI</a><br /> Real PSN account ID script : <a href="https://github.com/thestr4ng3r/chiaki/issues/158">https://github.com/thestr4ng3r/chiaki/issues/158</a> </p> Sun, 06 Mar 2022 01:00:00 +0100 https://www.schnappy.xyz/?PS4-remote_play_without_psn_account https://www.schnappy.xyz/?PS4-remote_play_without_psn_account Making your Vibram 5 fingers last - Update <h1>Making your Vibram 5 Fingers last - Update</h1> <p>As I mentionned in my <a href="/?making_your_vibram_5fingers_last">previous article</a>, here comes the time to get back to this rubber insole hack with some numbers. </p> <p>So here is the result after <strong>355km</strong> in them insoles, <strong>~1600km</strong> total for the shoes :</p> <p><img src="https://www.schnappy.xyz/assets/insole_after_350km.jpg" alt="inside" /> <img src="https://www.schnappy.xyz/assets/outsole_after_350km.jpg" alt="out" /></p> <p>That's not bad as it means this makes the shoes last about <strong>1/3rd</strong> of their typical mileage longer. I can no longer use the left shoe though, as the little finger has become separated from its siblings :( </p> <p><img src="https://www.schnappy.xyz/assets/ohno.jpg" alt="sad" /></p> Sat, 05 Feb 2022 01:00:00 +0100 https://www.schnappy.xyz/?making_your_vibram_5fingers_last_update https://www.schnappy.xyz/?making_your_vibram_5fingers_last_update Making your Vibram 5 fingers last <h1>Making your Vibram 5 Fingers last</h1> <p><img src="https://www.schnappy.xyz/assets/vibram5f-holes.jpg" alt="Notice a pattern ?" /></p> <p>I noticed that after ~1000km, my V-trails 's soles tend to develop holes around the metatarsal heads area.<br /> Wether it's due to a slight over-suppination on my part or thiner material in this particular spot, all ten pairs I owned had this particular outcome. </p> <p>These have around 1200km in them ; <img src="https://www.schnappy.xyz/assets/hole-y-molly.jpg" alt="1200km on the clock" /></p> <p>Clocking roughly 2500km/year, this means I wear out two pairs a year. That's a lot of money at ~150€ / pair, and more importantly, a lot of waste in the long run (pun intended). It recently occured to me (about time...) that I could do something to further increase the usability of my gear.</p> <h2>Custom, tailor-made, pure synthetic rubber insoles</h2> <p>Using a salvaged wheelbarrow innertube, I traced the shape of my feet on the rubber and cut insoles, that I was able to fit in the shoes quite easily.</p> <p><img src="https://www.schnappy.xyz/assets/newshoe.jpg" alt="new insoles" /></p> <p>I was worried the insole would fold in the shoe while running, but this did not occur during my last runs so I guess this is viable.<br /> I expect this solution to increase usability by a few hundred kilometers. <a href="/?making_your_vibram_5fingers_last_update">And it did</a></p> Fri, 24 Dec 2021 01:00:00 +0100 https://www.schnappy.xyz/?making_your_vibram_5fingers_last https://www.schnappy.xyz/?making_your_vibram_5fingers_last Bookeen Cybook Orizon : Tear Down and Serial IO <h1>Hacking with the Bookeen Cybook Orizon Tear down and Serial connection</h1> <p>Let's connect via Serial to this device, setup the wireless card, and enable an ssh server on it.</p> <h2>Connecting SIO</h2> <p>The serial connection is on the debug connector JA901 at the bottom left of the board :</p> <p><img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_cybook_orizon_ja901_debug_connector.jpg" alt="JA901 location on mb" /></p> <p>Pinout is (right to left with the battery on bottom) :</p> <table> <thead> <tr> <th>Pin</th> <th>Usage</th> </tr> </thead> <tbody> <tr> <td>1 TX1</td> <td>UNUSED</td> </tr> <tr> <td>2 RX1</td> <td>UNUSED</td> </tr> <tr> <td>3 TX0</td> <td><strong>SERIAL TX</strong></td> </tr> <tr> <td>4 RX0</td> <td><strong>SERIAL RX</strong></td> </tr> <tr> <td>5 TX3</td> <td>UNUSED</td> </tr> <tr> <td>6 RX3</td> <td>UNUSED</td> </tr> <tr> <td>7-13</td> <td>?</td> </tr> <tr> <td>14-16 GND</td> <td><strong>SERIAL GND</strong></td> </tr> <tr> <td>16-18 VDD</td> <td><strong>SERIAL VCC (3.3V)</strong></td> </tr> </tbody> </table> <p><img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_cybook_orizon_serial_ttl.jpg" alt="JA901 pinout" /></p> <p>You can then use minicom to login :</p> <pre><code class="language-bash">sudo minicom -b 115200 -D /dev/ttyUSB0</code></pre> <p>Login : root </p> <pre><code class="language-bash">FnX Bootloader for s3c2416 build on confucius version master_6376fd19638ef062_b360 Build time "Mon, 11 Oct 2010 14:15:38 +0200" Copyright (C) 2010 Bookeen Detected: Bookeen Cybook Orizon, A00/A01/A022;FnX - Bookeen Cybook Orizon - Terminal Battery level: [==================================== ] Info: Battery condition reasonable Info: Reset/boot due to Software reset I0: 00000000... Starting: Uncompressing Linux.......................................................................... ***: Cybook Linux Starting... ***: Prepare filesystem... ***: Does software want to update? No ***: Check if user want to update... ***: Verify partitions... fsck 1.41.9 (22-Aug-2009) rootfs: clean, 1177/38456 files, 120508/153600 blocks boot: clean, 15/3840 files, 9958/15360 blocks (check deferred; on battery) privatefs: recovering journal privatefs: clean, 66/2560 files, 1516/10240 blocks (check deferred; on battery) ***: Continue booting..... ***: Doing critical nasty things...... ***: Starting BooReader... Welcome to your Cybook Orizon! CybookOrizon login: root login[872]: root login on 'ttySAC0' [root@CybookOrizon ~]#</code></pre> <h2>Keep the device awake</h2> <p>You need to either power the device via micro USB, or kill processes <code>ebrmain</code> and <code>boordr</code> :</p> <pre><code class="language-bash">pkill ebrmain pkill boordr </code></pre> <h2>Wifi connection</h2> <h3>Firmware loading</h3> <p>You can load the wifi firmware and enable the wifi interface (which will apear as 'eth0') with the init script that's in <code>/etc/init.d</code> :</p> <pre><code class="language-bash">/etc/init.d/wireless start [root@CybookOrizon ~]# ifconfig eth0 Link encap:Ethernet HWaddr 00:27:13:F7:E3:F7 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:58 (58.0 B) TX bytes:0 (0.0 B) </code></pre> <h3>Connecting to a network</h3> <p>You can use <code>iwlist scan</code> to search for your network, which you can then connect to using <code>wpa_supplicant</code>.</p> <p>Edit <code>/etc/network/interfaces</code> and add the following lines :</p> <pre><code>auto eth0 iface eth0 inet dhcp</code></pre> <p>Create the file <code>/etc/wpa_supplicant.conf</code> that should contain :</p> <pre><code>network={ ssid="yourSSID" psk="yourPSK" }</code></pre> <p>Then run <code>wpa_supplicant -Dwext -ieth0 -c/etc/wpa_supplicant.conf &amp;</code> and once connected, use the network init script :</p> <pre><code>/etc/init.d/network start</code></pre> <p>You should now be connected to your Wireless AP.</p> <h3>SSH connection</h3> <p>By default the root account has no password, so you should change it in order to be able to connect via SSH :</p> <pre><code>passwd # then type your password two times</code></pre> <p>Finally, you can start the dropbear ssh server with <code>/etc/init.d/dropbear start</code>.</p> <p>As this is quite an old version of dropbear, the generating utility <code>dropbearkey</code> only comes with rsa/dss, and the only available key exchange algorithm is SHA-1, which was disabled in openssh 8.8.</p> <p>If you plan on using an ssh key to login, you'll have to re-enable those algorithms :</p> <pre><code>ssh -o KexAlgorithms=diffie-hellman-group1-sha1 -o HostkeyAlgorithms=ssh-rsa -i .ssh/bookeen_rsa_key root@</code></pre> <p>Have fun :)</p> <h2>CPU info</h2> <pre><code>cat /proc/cpuinfo Processor : ARM926EJ-S rev 5 (v5l) BogoMIPS : 199.47 Features : swp half thumb fastmult edsp java CPU implementer : 0x41 CPU architecture: 5TEJ CPU variant : 0x0 CPU part : 0x926 CPU revision : 5 Cache type : write-back Cache clean : cp15 c7 ops Cache lockdown : format C Cache format : Harvard I size : 16384 I assoc : 4 I line length : 32 I sets : 128 D size : 16384 D assoc : 4 D line length : 32 D sets : 128 Hardware : Cybook Orizon Revision : 0100 Serial : 0000000000000000</code></pre> <h2>Hardware components</h2> <p>SOC : <a href="https://elinux.org/S3C2416">S3C2416</a><br /> Screen: <a href="https://wiki.mobileread.com/wiki/SiPix">Sipix</a> AUO 6" 800x600 A0608E02<br /> Display controller : AUO K-1900<br /> Video DRAM : Etron Tech EM686165VE-7H<br /> Wifi/Bluetooth : <a href="https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;ved=0CCwQFjAA&amp;url=http%3A%2F%2Fmr2857gb.googlecode.com%2Fsvn%2Ftrunk%2Fdata%2520sheet%2Fwifi%2FWM-BN-BM-01_PRD_v2.3%252020091221.pdf&amp;ei=97esUYSvJ6PT0QWqjYGYDQ&amp;usg=AFQjCNGDYlpKc_9zgodMOIT3pAZfGHf7eQ&amp;bvm=bv.47244034,d.d2k">USI WM-BN-BM-01-0</a><br /> Storage : Hynnix H26M210010AR e-NAND 2GB Flash<br /> Memory : 32MB<br /> CPU : 200 Mhz </p> <h2>Misc</h2> <h3>bootsplash screen</h3> <p>The boot splash picture is in <code>/boot/</code> and is a 600x800 greyscale, indexed 16 colors bmp file (filesize 240,1 KB). </p> <p><strong>If using gimp to edit it, make sure to check the compatibility option "Do not write colorspace information".</strong> </p> <p>Then, to replace it, you first have to mount <code>/boot</code> as rw ;</p> <pre><code>mount /boot mount -o remount,rw /boot</code></pre> <p>then edit your boot splash pic, and put it on the device as <code>/boot/bootsplash.bmp</code> via ssh:</p> <pre><code>scp bootsplash.bmp CybookOrizonIP:/boot/</code></pre> <p><img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_bootsplash.jpg" alt="Custom bootsplash" /></p> <h3>Screensaver and thumbnail file formats</h3> <p>The file format is <code>t4b</code>, and you can find some scripts to convert from an to this format here : </p> <p><a href="https://github.com/ABelliqueux/t4b-tools">https://github.com/ABelliqueux/t4b-tools</a> </p> <p>The default screen saver pictures are in <code>/mnt/app/res/ds</code>.<br /> Most UI assets are in <code>/mnt/app/res/img</code>.</p> <h3>Wifi + SSH at boot</h3> <p>In order to enable Wireless, connect to your AP and start the SSH server automatically at boot, you can create a script in <code>/etc/init.d</code> with this content :</p> <pre><code># Start ALL the things ! # case "$1" in start) echo "Killing useless processes..." pkill ebrmain pkill boordr echo "Enabling wireless" /etc/init.d/wireless start echo "Connecting to AP..." wpa_supplicant -B -Dwext -ieth0 -c/etc/wpa_supplicant.conf sleep 3 echo "Init network" /etc/init.d/network stop /etc/init.d/network start echo "Starting SSH..." /etc/init.d/dropbear start ;; stop) echo -n "Stopping all the things !" /etc/init.d/dropbear stop /etc/init.d/network stop /etc/init.d/wireless stop ;; restart|reload) "$0" stop "$0" start ;; *) echo $"Usage: $0 {start|stop|restart}" exit 1 esac exit $?</code></pre> <p>Make sure the script has the right owner/permissions :</p> <pre><code>chmod 755 /etc/init.d/* chown default:default /etc/init.d/*</code></pre> <p>Then, remove/backup the existing symlinks in <code>/etc/rc.d</code> : </p> <pre><code>rm /etc/rc.d/*</code></pre> <p>and create a new one to your script :</p> <pre><code>ln -s /etc/init.d/custom /etc/rc.d/S05custom</code></pre> <h3>Input</h3> <p>The Cybook's physical buttons (up, left, down, right, middle and on/off/sleep) can be accessed from <code>/dev/cyio</code><br /> Pressing a button triggers the following packets :</p> <table> <thead> <tr> <th>Button</th> <th>Packet content HEX</th> <th>ASCII</th> </tr> </thead> <tbody> <tr> <td>Left</td> <td>6B 80 10 6C</td> <td>l</td> </tr> <tr> <td>Up</td> <td>6B 80 10 75</td> <td>u</td> </tr> <tr> <td>Right</td> <td>6B 80 10 72</td> <td>r</td> </tr> <tr> <td>Down</td> <td>6B 80 10 64</td> <td>d</td> </tr> <tr> <td>Center</td> <td>6B 80 10 65</td> <td>e</td> </tr> <tr> <td>Sleep</td> <td>6B 80 10 6F</td> <td>o</td> </tr> </tbody> </table> <p><img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/cyio.png" alt="Cybook IO" /> </p> <h2>Pictures</h2> <p><img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-01.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-02.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-03.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-04.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-05.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-06.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-07.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-08.jpg" alt="screen_A0608E02 connector" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-09.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-10.jpg" alt="bookeen orizon tear up" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-11.jpg" alt="AUO K1900 - Etrontech EM686165VE-7H" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-12.jpg" alt="AUO K1900" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_orizon-13.jpg" alt="unpopuated USB" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_cybook_orizon_screen_A0608E02.jpg" alt="screen_A0608E02" /><br /> <img src="https://www.schnappy.xyz/assets/bidouille/demontage_d_un_bookeen_orizon/bookeen_cybook_orizon_hynnix_H26M210010AR.jpg" alt="_hynnix_H26M210010AR" /> </p> <h2>Links</h2> <p><a href="http://wiki.mobileread.com/wiki/Cybook_Orizon">http://wiki.mobileread.com/wiki/Cybook_Orizon</a><br /> <a href="https://www.e-ink-info.com/why-did-bookeen-use-sipix-and-not-e-ink-their-upcoming-orizon-reader">https://www.e-ink-info.com/why-did-bookeen-use-sipix-and-not-e-ink-their-upcoming-orizon-reader</a><br /> <a href="https://web.archive.org/web/20101203015220/http://www.fwma.de/pmwiki/pmwiki.php?n=Main.OYO">https://web.archive.org/web/20101203015220/http://www.fwma.de/pmwiki/pmwiki.php?n=Main.OYO</a><br /> <a href="https://shkspr.mobi/blog/2013/04/disassembling-an-ereader/">https://shkspr.mobi/blog/2013/04/disassembling-an-ereader/</a><br /> <a href="https://wiki.techinc.nl/OYO_Hacking">https://wiki.techinc.nl/OYO_Hacking</a><br /> <a href="https://web.archive.org/web/20141218033547/http://ownyo.de/">https://web.archive.org/web/20141218033547/http://ownyo.de/</a><br /> <a href="https://p2k.unkris.ac.id/IT/2-3065-2962/Qisda-ES900_21112_p2k-unkris.html">https://p2k.unkris.ac.id/IT/2-3065-2962/Qisda-ES900_21112_p2k-unkris.html</a> </p> Fri, 19 Nov 2021 01:00:00 +0100 https://www.schnappy.xyz/?hacking_with_bookeen_cybook_orizon https://www.schnappy.xyz/?hacking_with_bookeen_cybook_orizon RE: Pseudo-reflections in TRII on Psx - the code part II <h1>RE: Pseudo-reflections in TRII on Psx - the code part II</h1> <p>Following up on my <a href="https://www.schnappy.xyz/?tr2_not_shaders-follow_up">follow-up</a> to <a href="https://schnappy.xyz/?tr2_not_shaders">an article</a> about a pseudo-reflection effect in the Tomb Raider I &amp; II games on psx, picking up where we left of ; </p> <blockquote> <p>In this pic, you can see that Lara's reflection looks cloudy. This <em>could be</em> because a second primitive with semi-transparency is drawn above the one doing the reflection. </p> </blockquote> <p><img src="https://www.schnappy.xyz/assets/tr2-wall-1.jpg" alt="TR2 on Psx : The Great Wall level" /></p> <p>Now this might sound a bit expensive to draw two primitives instead of one, but it's not really. In fact, you can do the calculations once, and apply the resulting coordinates to 2 different primitives.</p> <pre><code class="language-c">// cast nextpri as POLY_GT3 poly[0] = (POLY_GT3 *)nextpri; poly[1] = (POLY_GT3 *)nextpri+sizeof(POLY_GT3); // Initialize the primitives SetPolyGT3(poly[0]); SetPolyGT3(poly[1]); // Reflection Cube // This cube has its UVs mapped directly to VRAM coordinates // We're using the framebuffers as a texture (0,0 and 0,256) // Get 256x256 texture page that's at x0, y0 poly[1]-&gt;tpage = getTPage( 2, stpRate, 0, !(db) * 256 // Here, we're using db's value that can be either 0 or 1 to determine the texture page Y coordinate. ); // Set STP SetSemiTrans(poly[1], stpFlag); // Map coordinates from drawarea (320x240) to texture size (256x240) in fixed point math // x = x * (256 / 320) =&gt; ( x * ( 256 * 4096 ) / 320 ) / 4096 =&gt; x * 3276 &gt;&gt; 12 // y = y * (240 / 240) =&gt; ( y * ( 240 * 4096 ) / 240 ) / 4096 =&gt; y * 4096 &gt;&gt; 12 == y setUV3( poly[1], (poly[1]-&gt;x0 * normH) &gt;&gt; 12, poly[1]-&gt;y0 - (!(db) * 16) , // We're using db's value again to add a 16 pixels offset to the Y's coordinates of the UVs (poly[1]-&gt;x1 * normH) &gt;&gt; 12, poly[1]-&gt;y1 - (!(db) * 16), // We have to do that because the buffer is 240 high, whereas our texture page is 256, hence 256 - 240 == 16 (poly[1]-&gt;x2 * normH) &gt;&gt; 12, poly[1]-&gt;y2 - (!(db) * 16) ); // Draw "container" cube // This cube has a texture with transparent areas. // STP bit is set on PNG's alpha channel : img2tim -usealpha -org 320 0 -o cube.tim cube.png poly[0]-&gt;tpage = getTPage( timImages[0].mode&amp;0x3, stpRate, timImages[0].prect-&gt;x, timImages[0].prect-&gt;y ); // If 8/4bpp, load CLUT to vram if ( (timImages[0].mode &amp; 0x3) &lt; 2 ) { setClut( poly[0], timImages[0].crect-&gt;x, timImages[0].crect-&gt;y ); } // Set UV coordinates setUV3(poly[0], modelCube.u[i].vx, modelCube.u[i].vy, modelCube.u[i+2].vx, modelCube.u[i+2].vy, modelCube.u[i+1].vx, modelCube.u[i+1].vy ); // Rotate, translate, and project the vectors and output the results into a primitive // curTriangle, +1, +2 point to the vertices index of the triangle we're drawing. OTz = RotTransPers(&amp;modelCube_mesh[ modelCube_index[ curTriangle[0] ] ] , ( long * ) &amp;poly[1]-&gt;x0, &amp;p, &amp;Flag); OTz += RotTransPers(&amp;modelCube_mesh[ modelCube_index[ curTriangle[0] + 2] ], ( long*) &amp;poly[1]-&gt;x1, &amp;p, &amp;Flag); OTz += RotTransPers(&amp;modelCube_mesh[ modelCube_index[ curTriangle[0] + 1] ], ( long * ) &amp;poly[1]-&gt;x2, &amp;p, &amp;Flag); // Instead of doing the same calculations for the "prism" cube, use results from above directly poly[0]-&gt;x0 = poly[1]-&gt;x0; poly[0]-&gt;y0 = poly[1]-&gt;y0; poly[0]-&gt;x1 = poly[1]-&gt;x1; poly[0]-&gt;y1 = poly[1]-&gt;y1; poly[0]-&gt;x2 = poly[1]-&gt;x2; poly[0]-&gt;y2 = poly[1]-&gt;y2;</code></pre> <p>And there you have it :</p> <p><img src="https://www.schnappy.xyz/assets/double_prim.gif" alt="Double primitive with transparency" /></p> <p>Here's a pic that hopefully shows a bit more :</p> <p><img src="https://www.schnappy.xyz/assets/double_prim.jpg" alt="Double primitive with transparency" /></p> <p>You can see the two cubes with the right one being the "reflection"... </p> <p>You can easily get various graphical result by tweaking the colors/depth/size of the primitives !</p> <p><img src="https://www.schnappy.xyz/assets/cell-shading.jpg" alt="Double primitive with transparency" /></p> <h2>Full code and more infos</h2> <p>The full code is available at <a href="https://github.com/ABelliqueux/nolibgs_hello_worlds/tree/main/hello_fx">https://github.com/ABelliqueux/nolibgs_hello_worlds/tree/main/hello_fx</a> </p> <p>You can find more details about semi-transparency and primitive transparency on the PSX here : </p> <p><a href="https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/STP">https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/STP</a> </p> <p><a href="https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM#transparency">https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM#transparency</a></p> <hr /> <h2>Links and notes</h2> <p>Original articles : </p> <p><a href="https://www.schnappy.xyz/?tr2_not_shaders">https://www.schnappy.xyz/?tr2_not_shaders</a><br /> <a href="https://www.schnappy.xyz/?tr2_not_shaders-follow_up">https://www.schnappy.xyz/?tr2_not_shaders-follow_up</a></p> <p>Thanks to psxdev users gwald and sicklebrick, and to <a href="https://twitter.com/cnhyv">Paul Douglas</a> for their time and answers.</p> Thu, 18 Nov 2021 01:00:00 +0100 https://www.schnappy.xyz/?tr2_not_shaders-part3 https://www.schnappy.xyz/?tr2_not_shaders-part3 PSXDEV: Change the debug font appearance and color <h1>Change the debug font appearance and color</h1> <p><img src="https://www.schnappy.xyz/assets/debug_font.gif" alt="Funky!" /></p> <p>Changing the debug font face and color can be useful if you don't want or don't have time to implement a full-fledged font atlas solution, but still want to be able to customize the default font a bit.</p> <h2>Basics</h2> <p>According to PsyQ's doc, the <code>FntLoad()</code> function is in charge of loading the texture and <a href="https://www.computerhope.com/jargon/c/clut.htm">CLUT</a> in the PSX vram.<br /> By default it will load a 128x32 image to xy coordinates <code>960, 0</code>, and its clut will be loaded at <code>960,0+128</code>.</p> <p>Using a custom debug font is then a simple matter of loading an image into vram at those coordinates, and/or altering the clut.</p> <h2>Color</h2> <p><img src="https://www.schnappy.xyz/assets/debug_font_color.png" alt="A custom debug font color" /></p> <p>The CLUT is loaded at <code>x,y+128</code> ( 960,128 by default ) and consists of two horizontal pixels for the default font; the first is black (RGB 0,0,0) and is the background colour.<br /> The second one is white (RGB 255,255,255) and is the foreground (or text) colour. You can use the <code>ClearImage()</code> function to draw a colored rectangle anywhere in vram, so why not draw a 1x1 pixel at 961,128 and see the result ? </p> <p><strong>Note that setting the pixel at 960x128 to a different color overides <code>FntOpen()</code>'s <code>isbg</code> value.</strong></p> <pre><code class="language-c">// Used for font texture position in vram #define FONTX 960 #define FONTY 0 // Two color vectors R,G,B CVECTOR fntColor = { 255, 0, 0 }; CVECTOR fntColorBG = { 0, 0, 0 }; void FntColor(CVECTOR fgcol, CVECTOR bgcol ) { // The debug font clut is at tx, ty + 128 // tx = bg color // tx + 1 = fg color // We can override the color by drawing a rect at these coordinates // // Define 1 pixel at 960,128 (background color) and 1 pixel at 961, 128 (foreground color) RECT fg = { FONTX+1, FONTY + 128, 1, 1 }; RECT bg = { FONTX, FONTY + 128, 1, 1 }; // Set colors ClearImage(&amp;fg, fgcol.r, fgcol.g, fgcol.b); ClearImage(&amp;bg, bgcol.r, bgcol.g, bgcol.b); }</code></pre> <p>All you have to do after that is calling <code>FntColor()</code> after <code>FntLoad()</code> and <code>FntOpen()</code> :</p> <pre><code class="language-c">FntLoad(FONTX, FONTY); // Load font to vram at FONTX,FONTY FntOpen(100, 100, 48, 20, 0, 12 ); // FntOpen(x, y, width, height, black_bg, max. nbr. chars) FntColor(fntColor, fntColorBG);</code></pre> <p>You can check in a vram viewer that the pixels at those coordinates have the new colors ;</p> <p><img src="https://www.schnappy.xyz/assets/debug_font_vram.png" alt="the debug font texture in VRAM" /></p> <h2>Fontface</h2> <p>Changing the font face allows you to use customized 7x7 pixels glyph and a full 4bpp CLUT, that's quite nice ! The latin aphabet debug font has 64 glyphs ; 4 lines, 16 glyphs per line in this order : </p> <p><strong>Notice that the first glyph on the first line is empty</strong></p> <pre><code> !"#$%&amp;'()*+,-./ 0123456789:;&lt;=^? @ABCDEFGHIJKLMNO PQRSTUVWXYZ[\]&gt;</code></pre> <p>The fontface should be a 128x32, 16 colors palettized image with each glyphs taking 7x7 pixels :</p> <p><img src="https://www.schnappy.xyz/assets/debug_font_tpl.png" alt="template" /></p> <p>For reference, here is an example : </p> <p><img src="https://www.schnappy.xyz/assets/debug_font_spr.png" alt="template" /></p> <p>Gimp or Aseprite are tools that would do the trick.</p> <h3>Converting the image to TIM</h3> <p>Using Lameguy64's <code>img2tim</code> utility, convert the image to <a href="https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM">tim</a> :</p> <pre><code>img2tim -b -usealpha -org 960 0 -plt 960 128 -bpp 4 -o output.tim input.png</code></pre> <h3>Including the tim file</h3> <p>If using nugget+psyq, as described <a href="https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/(Archived)--Embedding-binary-data-in-your-psx-executable">here</a>, you have to add the tim file to your <code>SRCS</code>, then add these conversion instructions in your makefile :</p> <pre><code class="language-mk">%.o: %.tim $(PREFIX)-objcopy -I binary --set-section-alignment .data=4 --rename-section .data=.rodata,alloc,load,readonly,data,contents -O elf32-tradlittlemips -B mips $&lt; $@</code></pre> <p>To access the data in code, use the following declarations :</p> <pre><code>extern unsigned long _binary_output_tim_start[]; extern unsigned long _binary_output_tim_end[]; extern unsigned long _binary_output_tim_length;</code></pre> <h3>Loading the image to vram</h3> <p>Using a nice function written by Lameguy64 ;</p> <pre><code class="language-c">extern unsigned long _binary_fnt_tim_start[]; extern unsigned long _binary_fnt_tim_end[]; extern unsigned long _binary_fnt_tim_length; // Loading an image to vram. See https://github.com/ABelliqueux/nolibgs_hello_worlds/blob/main/hello_sprt/hello_sprt.c#L42 TIM_IMAGE fontface; void LoadTexture(u_long * tim, TIM_IMAGE * tparam){ OpenTIM(tim); ReadTIM(tparam); LoadImage(tparam-&gt;prect, tparam-&gt;paddr); DrawSync(0); if (tparam-&gt;mode &amp; 0x8){ // check 4th bit LoadImage(tparam-&gt;crect, tparam-&gt;caddr); DrawSync(0); } }</code></pre> <p>Then in <code>main()</code>, call it once after init:</p> <pre><code class="language-c">LoadTexture(_binary_fnt_tim_start, &amp;fontface);</code></pre> <h2>Full code</h2> <p>A full example is available here : <a href="https://github.com/ABelliqueux/nolibgs_hello_worlds/tree/main/hello_font">https://github.com/ABelliqueux/nolibgs_hello_worlds/tree/main/hello_font</a> </p> <h2>Doc &amp; Sources</h2> <ul> <li><code>FntLoad()</code> ref : <a href="http://psx.arthus.net/sdk/Psy-Q/DOCS/LibRef47.pdf">http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf</a>, p.292 </li> <li>Nolibgs wiki TIM page : <a href="https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM">https://github.com/ABelliqueux/nolibgs_hello_worlds/wiki/TIM</a> </li> </ul> Mon, 25 Oct 2021 02:00:00 +0200 https://www.schnappy.xyz/?psxdev-change_font_color https://www.schnappy.xyz/?psxdev-change_font_color