𑇢^^^°< Technical stuff https://www.schnappy.xyz/ Mon, 24 Jan 2022 04:49:28 +0100 Mon, 24 Jan 2022 04:49:28 +0100 Pico 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. I'll update this article when I have some numbers.</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@10.10.10.10</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 PSXDEV: NuggetQ : Changing the Load Address of a PSX exe <h1>NuggetQ : Changing the Load Address of a PSX exe</h1> <p>In order to change the Load Memory Address (LMA) of your psx executable, you should use one of those solutions ;</p> <pre><code class="language-bash">$ file hello_poly.ps-exe hello_poly.ps-exe: Sony Playstation executable PC=0x8001f000, .text=[0x8001f000,0x1c000], Stack=0x801fff00, ()</code></pre> <h2>From the command line</h2> <p>When compiling, use the following command :</p> <pre><code class="language-bash">LDFLAGS ="-Xlinker --defsym=TLOAD_ADDR=0x80010000" make</code></pre> <h2>From the Makefile</h2> <p>In the project's makefile, add the following line :</p> <pre><code class="language-mk">LDFLAGS += -Xlinker --defsym=TLOAD_ADDR=0x80010000</code></pre> <h2>With an ld script</h2> <p>In the project's Makefile, add a line to include the ld script:</p> <pre><code class="language-mk">OVERLAYSCRIPT ?= script.ld</code></pre> <p>in the linked script, add the following lines :</p> <pre><code>TLOAD_ADDR = 0x8001f000; /*Changes the PC*/ __heap_base = 0x8001f000; /* Build fails if not provided */</code></pre> <h2>Source</h2> <p><a href="https://discord.com/channels/642647820683444236/646781091252011058/791255427990945823">https://discord.com/channels/642647820683444236/646781091252011058/791255427990945823</a><br /> <a href="https://discord.com/channels/642647820683444236/663664210525290507/894235813657837569">https://discord.com/channels/642647820683444236/663664210525290507/894235813657837569</a> </p> Sun, 03 Oct 2021 02:00:00 +0200 https://www.schnappy.xyz/?psxdev-nuggetQ_change_load_address https://www.schnappy.xyz/?psxdev-nuggetQ_change_load_address PSXDEV: Generate a PSX disk image with lua-interface <h1>Generate a PSX disk image with lua-interface</h1> <h2>PSX image</h2> <p>Get <code>lua-interface</code> here : <a href="http://static.grumpycoder.net/pixel/lua-interface-distrib/">http://static.grumpycoder.net/pixel/lua-interface-distrib/</a> . </p> <h3>Script</h3> <p>Create a <code>master.lua</code> file with this content :</p> <pre><code class="language-lua">function main() loadmodule "lualibs" loadmodule "luahandle" loadmodule "luacd" iso_file = Output "myiso.bin" iso = isobuilder(iso_file) pvd = PVD() pvd.sysid = "PLAYSTATION" pvd.volid = "MYISO" pvd.pubid = "YOURNAME" pvd.appid = "YOURAPP" root = iso:setbasics(pvd) root:setbasicsxa() iso:createfile(root, "PSX.EXE", Input "your.psexe"):setbasicsxa() falsesect = {} for i = 1, 148, 1 do iso:createsector(falsesect, MODE2) end iso:close() end</code></pre> <p>Use the <code>master.lua</code> script , changing l.15 'your.psexe' value to reflect your psx exe 's filename : </p> <pre><code>./lua-interface.exe -e "main()" master.lua</code></pre> <h2>Generate your audio tracks with ffmpeg</h2> <pre><code>ffmpeg -i input.file -f s16le -acodec pcm_s16le track.bin</code></pre> <h2>Create the Cue file</h2> <p>The cue file should follow this format :</p> <pre><code>FILE "psxfile.bin" BINARY TRACK 01 MODE2/2352 INDEX 01 00:00:00 FILE "audio1.bin" BINARY TRACK 02 AUDIO INDEX 01 00:00:00 FILE "audio2.bin" BINARY TRACK 03 AUDIO INDEX 00 00:00:00 INDEX 01 00:02:00</code></pre> <p>'psxfile.bin' should be the file generated by the lua script. 'audio1.bin', etc. should be the files generated with ffmpeg. </p> <h2>Source</h2> <p><a href="https://discord.com/channels/642647820683444236/663664210525290507/796078666148610089">https://discord.com/channels/642647820683444236/663664210525290507/796078666148610089</a><br /> <a href="https://discord.com/channels/642647820683444236/642848592754901033/891744067933831200">https://discord.com/channels/642647820683444236/642848592754901033/891744067933831200</a> </p> Sun, 26 Sep 2021 02:00:00 +0200 https://www.schnappy.xyz/?psxdev-generate_disk_image_lua https://www.schnappy.xyz/?psxdev-generate_disk_image_lua PSXDEV: Change the PSX's boot logo <h1>Creating a custom psx boot logo</h1> <p><img src="https://www.schnappy.xyz/assets/hblogo.png" alt="A custom psx boot logo!" /></p> <h2>Needed tools :</h2> <ul> <li>PsyQ's <a href="http://psx.arthus.net/sdk/Psy-Q/PSXGraphicStudio.zip">utilities</a> : <code>dxf2rsd.exe</code>, <code>RSDLINK.EXE</code> and <code>rsdtool.exe</code> (aternatively, Lameguy64's <a href="https://github.com/Lameguy64/smxtool"><code>smxtool</code></a> ) </li> <li><a href="https://www.dosbox.com/">Dosbox</a> to run the dos program above.</li> <li>Blender and optionnaly <a href="https://github.com/Lameguy64/Blender-RSD-Plugin">Lameguy64's Blender RSD plugin</a> </li> <li>BootEdit2 available here : <a href="http://psx.arthus.net/tools/bootedit2.zip">http://psx.arthus.net/tools/bootedit2.zip</a> </li> </ul> <h2>Steps</h2> <h3>Blender model creation</h3> <p>Create a model in blender. Keep your polycount low. For reference, the original psx logo has 560 triangles.<br /> Make sure you only have one mesh in your object !</p> <p><img src="https://www.schnappy.xyz/assets/bootedit-blender.png" alt="Logo in blender" /></p> <h4>Set shading to "Flat"</h4> <p>Tab into "Edit mode" with your object selected, and make sur your object's faces are set to "Flat" in "Shading". </p> <h4>Use vertex paint for colors</h4> <p>Either use vertex painting directly, or bake the object's materials to vertex color :</p> <ol> <li>In the "Material" tab, "Shading" section, check "Shadeless" for each material<br /> <img src="https://www.schnappy.xyz/assets/blender279_bake_mat_to_vertex_col_1.png" alt="Set materials to shadeless" /> </li> <li>In the "Data" tab, add a Vertex Color layer in the "Vertex colors" section<br /> <img src="https://www.schnappy.xyz/assets/blender279_bake_mat_to_vertex_col_2.png" alt="Add vertex color layer" /> </li> <li>In the "Render" tab, "Bake" section, check "Bake to Vertex Color", then hit "Bake" after making sure your object is selected.<br /> <img src="https://www.schnappy.xyz/assets/blender279_bake_mat_to_vertex_col_3.png" alt="Check &#039;Bake to Vertex Color&#039; and Bake" /> </li> </ol> <p>You can check this worked by switching to Vertex Paint mode. </p> <h4>Exporting using the RSD plugin</h4> <p>Make sure you apply transformations to your object before exporting.<br /> In object mode, that's <code>Ctrl</code> + <code>A</code>, 'Location', 'Rotation &amp; Scale'. </p> <p>Ideally, your object should be at <code>0,0,0</code>, and have X and Y dimensions of ~18 blender units.<br /> Your object's front should point towards Blender's <code>-Y</code> axis (that's toward your eye by default). </p> <p><img src="https://www.schnappy.xyz/assets/boot_logo_size.png" alt="Object&#039;s rough size, orientation and location" /> </p> <p>Then, export your object using <a href="https://github.com/Lameguy64/Blender-RSD-Plugin">Lameguy64's RSD plugin</a> and proceed to the "RSD to TMD conversion" step. </p> <h4>Exporting using the DXF plugin</h4> <p><strong>This method is not recommended as Color information is lost</strong> </p> <h5>Object orientation</h5> <p>The psx space coordinates is Y-UP, so you might have to make it so the top of your object points towards the positive Y axis in Blender (that's the green axis, pointing away from you).<br /> <img src="https://www.schnappy.xyz/assets/blender_yup_object.png" alt="Rotating the object" /><br /> The key sequence to do that in Blender is <code>Tab</code> into edit mode, hit <code>A</code> key, hit <code>R</code> key, hit <code>X</code> key, hit <code>-</code>, <code>9</code>, <code>0</code> then hit <code>Enter</code>. </p> <ol> <li> <p>Export from blender as dxf with the <a href="https://archive.blender.org/wiki/index.php/Extensions:2.6/Py/Scripts/Import-Export/DXF_Exporter/">"Export Autocad DXF"</a> plugin.</p> </li> <li> <p>Use psyq's <code>dxf2rsd.exe</code> utility with dosbox to convert the DXF to RSD using the <code>-back</code> option to flip normals:</p> <pre><code>DXF2RSD.EXE -o logo.rsd -back model.dxf</code></pre> </li> <li> <p>Edit the RSD file with PsyQ's old <code>rsdtool</code> or use the modern <a href="https://github.com/Lameguy64/smxtool"><code>smxtool</code></a> to add colors and save as RSD.</p> </li> </ol> <p><img src="https://www.schnappy.xyz/assets/bootedit-smxtool.png" alt="Logo in smxtool" /></p> <h4>Checking the MAT file</h4> <p>You have to make sure the final <code>.MAT</code> file generated has every line's columns 2 to 4 look has these values ; <code>2 F C</code>. E.g :</p> <pre><code>x 2 F C rrr ggg bbb</code></pre> <p><code>x</code> is the vertex index.<br /> <code>2</code> &gt; 0x2 (0010) means 'Light-source calculations performed' and 'Double-faced polygon.'<br /> <code>F</code> means flat shaded<br /> <code>C</code> means color and <code>rrr ggg bbb</code> is the color value. </p> <p>See the '[Flag]' section in <a href="http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf">http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf</a>, p.56 for more details on these values.</p> <h3>RSD to TMD conversion</h3> <p>Convert the RSD to TMD using psyq's <code>RSDLINK.EXE</code> tool with dosbox :</p> <pre><code>RSDLINK.EXE -s XXX.X -o logo.tmd logo.rsd</code></pre> <p>Here <code>-s XXX.X</code> is needed so that the model is scaled to the correct size. </p> <p><strong>The scale factor is not the same if you used DXF vs RSD export.</strong> </p> <p>If using the DXF export plugin, scale factor is <code>240.0</code>. </p> <p>If using the RSD export plugin, scale factor is <code>60.0</code>. </p> <h3>Patching the disk image</h3> <p>Patch your disk image with <a href="http://psx.arthus.net/tools/bootedit2.zip"><code>BootEdit.exe</code></a> by selecting your bin file, then the new tmd file.</p> <p>You can also change the license text; These are two 32 characters field with pre-determined spaces. </p> <p>Apply the patch and voila !</p> <p><img src="https://www.schnappy.xyz/assets/bootedit-patch.png" alt="Patch disk image" /></p> <h2>Logos to download</h2> <p>You can download the TMDs and corresponding blend for logos I made here : </p> <p><a href="http://psx.arthus.net/homebrew/assets/boot_logos/">http://psx.arthus.net/homebrew/assets/boot_logos/</a> </p> <p><img src="https://www.schnappy.xyz/assets/hblogo.png" alt="Homebrew logo" /><br /> <img src="https://www.schnappy.xyz/assets/hb_chs.png" alt="32bit logo" /> <img src="https://www.schnappy.xyz/assets/32blogo.png" alt="32bit logo" /></p> <h2>Tips and infos</h2> <h3>Original PSX logo</h3> <p>For reference, the original psx logo ranges from XYZ (-611, -775, -943) to (608, 231, 594) and has 560 triangles.</p> <p><img src="https://www.schnappy.xyz/assets/tmdinfo-psx.png" alt="PSX&#039;s logo specs" /></p> <p>You can check a tmd file with the <code>TMDINFO.EXE</code> utility:</p> <pre><code>TMDINFO.EXE logo.tmd</code></pre> <h4>Original logo colors</h4> <p>The original colors in the logo are : </p> <table> <thead> <tr> <th>Color</th> <th>HEX</th> <th>RGB</th> </tr> </thead> <tbody> <tr> <td><span style="background-color:#82D2C8;padding:0.2em;">Green</span></td> <td>82D2C8</td> <td>130, 210, 200</td> </tr> <tr> <td><span style="background-color:#8BADD7;padding:0.2em;">Blue</span></td> <td>8BADD7</td> <td>139, 173, 215</td> </tr> <tr> <td><span style="background-color:#FBDF00;padding:0.2em;">Yellow</span></td> <td>FBDF00</td> <td>251, 223, 0</td> </tr> <tr> <td><span style="background-color:#FF3232;padding:0.2em;">Red</span></td> <td>FF3232</td> <td>255, 50 , 50</td> </tr> </tbody> </table> <h3>MAT file</h3> <p>To reduce filesize, one can use a range to specify color/shading/flags in one line :</p> <pre><code>0-256 0 F C 200 200 200 # Use light-source, flat shaded, grey for vertices 0 to 256</code></pre> <p>This would result in a stylish grey logo... </p> <p><img src="https://www.schnappy.xyz/assets/bootedit-bw.png" alt="Style" /> </p> <h3>Run Dos program from Linux CLI</h3> <p>You can ran a DOS program directly from CLI :</p> <pre><code class="language-bash">dosbox -c "rsdlink.exe -s 60.0 B:\input.rsd -o B:\output.tmd"</code></pre> <p>Here, <code>B:\</code> is mapped to the folder that contains the input and ouptu files :</p> <p>In <code>dosbox.conf</code> 'z <code>[autoexec]</code> section :</p> <pre><code>MOUNT B ~/path/to/files</code></pre> <h4>Bash script</h4> <p>Here is a small bash wrapper to convert rsd to tmd :</p> <pre><code class="language-bash">#!/bin/bash if [ "$1" == "-h" ] || [ "$1" == "" ]; then echo "Usage : rsd2tmd.sh scale output.tmd input.rsd" fi dosbox -c "rsdlink.exe -s ${1} -o B:\\$2 B:\\$3" -c "exit"</code></pre> <h2>Converting TMD back to an OBJ file</h2> <p>A small java utility is available that can convert TMDs back to Wavefront OBJ files : <a href="https://github.com/ABelliqueux/tmd2obj">https://github.com/ABelliqueux/tmd2obj</a>. </p> <h2>Doc &amp; Sources</h2> <ul> <li>PSXDEV.net topic : <a href="www.psxdev.net/forum/viewtopic.php?t=156&amp;sid=fa6e4327893620c1a1b5a5e548879685">www.psxdev.net/forum/viewtopic.php?t=156&amp;sid=fa6e4327893620c1a1b5a5e548879685</a> </li> <li>Original Darsel engineering tutorial : <a href="https://web.archive.org/web/20041229035553/http://www.fortunecity.com/greenfield/wolf/51/ETMDv10.htm">https://web.archive.org/web/20041229035553/http://www.fortunecity.com/greenfield/wolf/51/ETMDv10.htm</a> - mirror : <a href="http://psx.arthus.net/docs/bootedit-tut-mirror.html">http://psx.arthus.net/docs/bootedit-tut-mirror.html</a> </li> <li>TMD and RSD file formats are documented here : <a href="http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf">http://psx.arthus.net/sdk/Psy-Q/DOCS/FileFormat47.pdf</a>, p.49 </li> <li>Usage of PsyQ utitlies are documented here : <a href="http://psx.arthus.net/sdk/Psy-Q/DOCS/Devrefs/Dataconv.pdf">http://psx.arthus.net/sdk/Psy-Q/DOCS/Devrefs/Dataconv.pdf</a> p.81, 117 &amp; 127 </li> </ul> Sun, 26 Sep 2021 02:00:00 +0200 https://www.schnappy.xyz/?psxdev-change_psx_boot_logo https://www.schnappy.xyz/?psxdev-change_psx_boot_logo PSXDEV: .bss VS .data <h2>.bss VS .data</h2> <p><code>.bss</code> is a "section [that] is guaranteed to be all zeros when the program is loaded into memory". That's a section that will always contain 0s when loaded, hence its content does not have to be stored. </p> <p><code>.data</code> is a section that's stored in the ELF, and need to be read upon loading.</p> <h3>Moving values to .data</h3> <p>Initializing a global variable with something else than <code>0</code> means moving it from <code>.bss</code> to <code>.data</code>.</p> <p>So if you're doing; e.g:</p> <pre><code class="language-c">static int8_t buffer[1024] = {1};</code></pre> <p>what you're actually doing is moving it from <code>.bss</code> to <code>.data</code>. </p> <p>A reason to do that would be to ensure that the data gets initialized to 0s even if <code>.bss</code> initialization is skipped, which you could be willing to do if this section's initialization was really slow on some hardware.</p> <h3>Implications on PSX</h3> <p>On PSX, <code>.bss</code> initialization is slow : </p> <p><strong>Nicolas Noble:</strong></p> <blockquote> <p>DMA (.data) versus a byte-wise memset (.bss) ; a byte-wise memset that's running off the bios ROM, that takes about 20 cycles per instructions therefore takes about 40 cycles per byte to set to 0. </p> </blockquote> <p>On the other hand, initializating from <code>.data</code>, you have to take into account the PSX's slow CDROM speed.</p> <h2>Source</h2> <p><a href="https://discord.com/channels/642647820683444236/663664210525290507/868225849202208838">https://discord.com/channels/642647820683444236/663664210525290507/868225849202208838</a><br /> <a href="https://stackoverflow.com/a/16557776">https://stackoverflow.com/a/16557776</a> </p> Mon, 02 Aug 2021 02:00:00 +0200 https://www.schnappy.xyz/?psxdev-.bss_vs_.data https://www.schnappy.xyz/?psxdev-.bss_vs_.data Using a RPI as a 4G/LTE modem <h1>Using a RPI as a 4G/LTE modem</h1> <h2>Hardware :</h2> <ul> <li>any RPI with GPIO headers</li> <li><a href="https://sixfab.com/product/raspberry-pi-base-hat-3g-4g-lte-minipcie-cards/">Sixfab's 4g lte base hat</a> + <a href="https://sixfab.com/product/quectel-ec25-mini-pcie-4g-lte-module/">Quectel EC25 mini PCIe module</a></li> <li>sd card, power supply, keyboard, lan cables, hdmi display, etc.</li> </ul> <h3>Optional hardware</h3> <ul> <li><a href="https://www.amazon.com/UGREEN-Network-Ethernet-Supports-Nintendo/dp/B00MYTSN18">USB 3.0 to ethernet Gigabit adapter</a></li> <li><a href="https://www.reichelt.de/en/en/mimo-lte-aerial-delock-88931-p153258.html">LTE antenna + cable</a></li> </ul> <h2>Base setup</h2> <p>Download and flash the last version of <a href="https://www.raspberrypi.org/software/operating-systems/">RaspiOS lite</a>. Plug, boot to command prompt. </p> <h3>Disable bluetooth and wifi</h3> <pre><code class="language-bash">echo -e "dtoverlay=disable-wifi\ndtoverlay=disable-bt" | sudo tee -a /boot/config.txt </code></pre> <h3>Update Upgrade</h3> <pre><code class="language-bash">sudo apt-get update sudo apt-get upgrade -y</code></pre> <h3>Install dependencies</h3> <pre><code class="language-bash">sudo apt-get install --no-install-recommends git raspberrypi-kernel-headers dnsmasq iptables-persistent vnstat</code></pre> <h2>Sixfab LTE hat</h2> <h3>Install driver module</h3> <p><strong>Make sure to do it with no hat connected</strong></p> <pre><code class="language-bash">wget https://raw.githubusercontent.com/sixfab/Sixfab_RPi_3G-4G-LTE_Base_Shield/master/tutorials/QMI_tutorial/qmi_install.sh sudo chmod +x qmi_install.sh sudo ./qmi_install.sh</code></pre> <h3>Install the auto-reconnect service</h3> <pre><code class="language-bash">wget https://raw.githubusercontent.com/sixfab/Sixfab_RPi_3G-4G-LTE_Base_Shield/master/tutorials/QMI_tutorial/install_auto_connect.sh sudo chmod +x install_auto_connect.sh sudo ./install_auto_connect.sh</code></pre> <h2>WWAN to ethernet</h2> <h3>Fixed IP</h3> <p>Edit <code>/etc/dhcpcd.conf</code> and set your LAN settings by uncommenting and adapting lines 44 to 48 :</p> <pre><code>interface eth0 static ip_address=192.168.xx.1/24 static ip6_address=fd51:42f8:caae:d92e::ff/64 static routers=192.168.xx.1 static domain_name_servers=192.168.xx.1 8.8.8.8 fd51:42f8:caae:d92e::1</code></pre> <p><strong>Remember to edit <code>192.168.xx.1</code> to a valid range.</strong></p> <h3>DHCP server : dnsmasq</h3> <p>Edit <code>/etc/dnsmasq.conf</code> and set your dhcp server's address by adding:</p> <pre><code>listen-address=192.168.xx.1</code></pre> <p>Create <code>/etc/dnsmasq.d/090_lan.conf</code> :</p> <pre><code>interface=eth0 dhcp-range=eth0,192.168.xx.0,192.168.xx.50,255.255.255.0,12h # optionnal - add fixed lease # dhcp-host=00:11:22:33:44:55,192.168.xx.xx #DNS servers server=8.8.8.8 server=4.4.4.4 log-dhcp log-queries dhcp-option=6,8.8.8.8,4.4.4.4 log-facility=/tmp/dnsmasq.log conf-dir=/etc/dnsmasq.d # Use custom resolv.conf # resolv-file=/path/to/custom/resolv.conf</code></pre> <h3>Routing and IP masquerading</h3> <p>These steps allow clients on <code>eth0</code> to access computers on the <code>wwan0</code> network, and from there the internet. Begin by enabling IP forwarding with the following commands:</p> <pre><code>echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/90_wwantolan.conf &gt; /dev/null sudo sysctl -p /etc/sysctl.d/90_wwantolan.conf sudo /etc/init.d/procps restart</code></pre> <p>To enable traffic between clients on the LAN and the internet, we add two <code>iptables</code> network address translation (NAT) "masquerade" firewall rules. Create these rules and persist them with the following:</p> <pre><code>sudo iptables -t nat -A POSTROUTING -j MASQUERADE sudo iptables -t nat -A POSTROUTING -s 192.168.xx.xx/24 ! -d 192.168.xx.xx/24 -j MASQUERADE sudo iptables-save | sudo tee /etc/iptables/rules.v4</code></pre> <p><strong><code>192.168.xx.xx/24</code> should match the network range you set in your dhcpcd config.</strong></p> <h2>Optionnal steps</h2> <h3>OpenVPN</h3> <p>Optionally, you may install OpenVPN, enabling <code>openvpn-client</code> service:</p> <pre><code>sudo apt-get install openvpn sudo systemctl enable openvpn-client@client</code></pre> <p>Put your openvpn config and auth files in <code>/etc/openvpn/client</code>. After that, you can use :</p> <pre><code class="language-bash">sudo systemctl start openvpn-client@configfile.service</code></pre> <p>to use the VPN connection that corresponds to <code>/etc/openvpn/client/configfile</code>. </p> <h3>Ad blocking</h3> <p>Download the block list :</p> <pre><code class="language-bash">sudo wget https://github.com/notracking/hosts-blocklists/raw/master/dnsmasq/dnsmasq.blacklist.txt -O /etc/dnsmasq.blacklist.txt</code></pre> <p>Add the following line to your <code>dnsmasq.conf</code> :</p> <pre><code class="language-bash">conf-file=/etc/dnsmasq.blacklist.txt</code></pre> <h4>Use cronjob to update the list automatically</h4> <pre><code class="language-bash">#write out current crontab crontab -l &gt; mycron #echo new cron into cron file # run at 3am every sunday echo "00 3 * * 7 wget https://github.com/notracking/hosts-blocklists/raw/master/dnsmasq/dnsmasq.blacklist.txt -O /etc/dnsmasq.blacklist.txt" &gt;&gt; mycron #install new cron file crontab mycron rm mycron</code></pre> <h3>One-liner public IP and Current month total data comsumption</h3> <p>Should be run on the Rpi. If you want to be able to run it from your station, you can put the following command in a bash script, set the execution bit on that, and run it via <code>ssh</code>; e.g : <code>ssh foo@ltemodemIP /path/to/the/script.sh</code><br /> In the following command, <code>date +"%Y-%m-10"</code> will result in the current year and month, followed by whatever value you put. You should edit the <code>10</code> to reflect the actual day of the month your data plan is reset to 0. </p> <pre><code class="language-bash">wget http://ipecho.net/plain -O - -q ; echo &amp;&amp; echo " | " &amp;&amp; vnstat -i wwan0 -d --begin `date +"%Y-%m-10"` --end `date +"%Y-%m-10" -d "next month"` | tail -1 | awk '{print $(NF-2),$(NF-1)}'</code></pre> <h2>Links and notes</h2> <p><a href="https://docs.sixfab.com/page/qmi-interface-internet-connection-setup-using-sixfab-shield-hat">https://docs.sixfab.com/page/qmi-interface-internet-connection-setup-using-sixfab-shield-hat</a> </p> <p><a href="https://docs.raspap.com/manual/">https://docs.raspap.com/manual/</a> </p> Sun, 01 Aug 2021 02:00:00 +0200 https://www.schnappy.xyz/?rpi_as_lte_modem https://www.schnappy.xyz/?rpi_as_lte_modem RE: Pseudo-reflections in TRII on Psx - the code <h1>RE: Pseudo-reflections in TRII on Psx - the code</h1> <p>Remember that article : <a href="https://schnappy.xyz/?tr2_not_shaders">https://schnappy.xyz/?tr2_not_shaders</a> ? </p> <p>That concluded on the somewhat disappointing statement that I didn't know exactly how it's done...<br /> Well after a year and a half of PSX development, I think I've got what it takes to explain it in more details.<br /> Obviously, you should read the first part if you want to know what I'm on about. </p> <h2>Pseudo-reflection needs framebuffer</h2> <p>As was <a href="http://www.psxdev.net/forum/viewtopic.php?f=48&amp;t=976#p10721">pointed out by @sickle</a> and <a href="https://twitter.com/cnhyv">Paul Douglas</a>, it's a trick with the framebuffer that allows this nice effect. </p> <h3>The PSX vram</h3> <p>Basically, the VRAM on the psx is a 1024x512 pixels image where you can load graphical stuff like textures, palettes and fontmaps. You also have to reserve and area where you will draw the final image that appears on the screen. </p> <p>On the PSX you can use values from 256x240 to 640x480. But as you can guess, the more space you take for your drawing area, the less space you have in vram to load stuff. </p> <p>The drawing area is defined by a <code>DRAWENV</code> and the display area (which defines what portion of the vram should be displayed) is defined by a <code>DISPENV</code>. </p> <h3>Double-buffering setup</h3> <p>Declaring the buffers: </p> <pre><code class="language-c">DISPENV disp[2]; DRAWENV draw[2]; short db = 0; // Will flip between values 0 and 1</code></pre> <p>Setting the double buffers : </p> <pre><code class="language-c">// Set a dispenv at 0,0 and at 0,240 SetDefDispEnv(disp[0], 0, 0, 320, 240); SetDefDispEnv(disp[1], 0, 240, 320, 240); // Set a drawenv at 0,240 and at 0,0 SetDefDrawEnv(draw[0], 0, 240, 320, 240); SetDefDrawEnv(draw[1], 0, 0, 320, 240);</code></pre> <p>and switching the buffers: </p> <pre><code class="language-c">while(1){ PutDispEnv(disp[db]); PutDrawEnv(draw[db]); // Flip db value if 0 = 1, if 1 = 0 db = !db; }</code></pre> <p>Double buffering is a way of interverting the DRAWENV and the DISPENV positions in vram, so that one is displayed, while the other one is drawn. </p> <p>Here is the content of the vram : </p> <p><img src="https://www.schnappy.xyz/assets/db.png" alt="PSX db" /> </p> <p>As you can see, two similar frames are stacked on the leftmost of it, and these are the draw areas. You can also see that some text is apparent on only one of the frames, and that is because the debug font will only display on the current display area. </p> <p>The funny stuff on the rigth are textures and the debug fontmap. </p> <p><em>Quick note : Coordinates in vram are Top Left 0,0, Bottom Right 1024,512.</em></p> <p>So this helps us determine that at this point in execution, the current <code>DISPENV</code> has it's vram coordinates to 0,0, and the <code>DRAWENV</code> has it at 0,256. </p> <h3>Using textures</h3> <p>On PSX, textures are applied on primitives by using UV coordinates. This means that for each vertex that has 3D coordinates in the 3D world you're simulating, you specify a 2D coordinate in vram. That way, you 3D object will map to your 2D texture image. </p> <p>For example in the following image, you can guess that the texture used on the wall is the one you can see in that pink rectangle on the right ; </p> <p><img src="https://www.schnappy.xyz/assets/db-tex.png" alt="PSX db" /> </p> <p>So what if instead of giving the textures coordinates, we gave arbitrary coordinates in the vram ? We could use the current <code>DRAWENV</code> as a texture for example ? </p> <p><img src="https://www.schnappy.xyz/assets/db-tex-1.png" alt="PSX db" /> </p> <p>Yup, that's exactly what we're going to do !<br /> There is one problem with that approach though.<br /> The vram is cut in 256x256 pixels pieces called Texture Pages in PsyQ world, so if you want to access a texture that's at 0,320, then a texture that's at 256,640, you have to change the current texture page, which takes time. </p> <p>Plus, a TPage is only 256 pixels wide, whereas our DISP/DRAW envs are 320 pixels wide, so we have a problem on the X axis ! </p> <p>Instead of switching TPage, which is slow, we'll re-scale the values that span from 0 to 320 between 0 and 256. </p> <p>Mapping an area to a smaller one in fixed point math can be done with :<br /> <code>( xcoord * ( smallerAreaWidth * scaleValue ) / greaterAreaWidth ) / scaleValue</code><br /> which in our case gives :<br /> <code>( xcoord * ( 256 * 4096 ) / 320 ) / 4096</code>.<br /> We'll be using bitshift's <code>&gt;&gt;12</code> as equivalent to <code>/4096</code>. </p> <p>On the Y axis, another problem arises : it's fine for the first TPage, that spans from 0 to 240, but what about the ne that spans from 240 to 480 ?<br /> We're going to have a 16 pixels offset that will make the reflection appear jumpy, which is not good.<br /> In order to solve that one, we're going to have to add a 16px offset <strong>only</strong> when the bottom area is used as <code>DRAWENV</code>. Fortunately, we can know when it is by checking <code>db</code>'s value. </p> <h2>The code</h2> <p>Texturing a primitive with PsyQ's libraries is basically:</p> <pre><code class="language-c">// Set primitive SetPolyGT3(primitive); // Change texture page : in the example above, tpage is at 0, 640 in vram primitive-&gt;tpage = getTPage( texture.mode, 0, texture.prect-&gt;x, // 0 texture.prect-&gt;y // 640 ); // We should load the CLUT to vram here if needed. // Set UV coordinates for 3 vertices setUV3( primitive, texture.vx, texture.vy, // Vertex 1 texture.vx, texture.vy, // Vertex 2 texture.vx, texture.vy // Vertex 3 ); }</code></pre> <p>So that's pretty straight forward. Changing the texture to the current <code>DRAWENV</code> would mean doing:</p> <pre><code class="language-c">// Change TPage to current DRAWENV - here 'db' is a value that flips between 0 and 1 and is used as the DISPENV/DRAWENV array's index. setTPage( poly4, 2, 0, 0, !(*db)&lt;&lt;8); // Map coordinates from drawarea (320x240) to texture page size (256x256) in fixed point math // x = x * (256 / 320) =&gt; ( x * ( 256 * 4096 ) / 320 ) / 4096 =&gt; x * 3277 &gt;&gt; 12 // y = y * (240 / 256) =&gt; ( y * ( 240 * 4096 ) / 256 ) / 4096 =&gt; y * 3840 &gt;&gt; 12 setUV3( primitive, // Scale coordinates on X axis (primitive-&gt;x0 * 3277) &gt;&gt; 12, // Scale coordinates on Y axis, and add offset when !db ((primitive-&gt;y0 * 3840) &gt;&gt; 12) - (!(*db) &lt;&lt; 4), (primitive-&gt;x1 * 3277) &gt;&gt; 12, ((primitive-&gt;y1 * 3840) &gt;&gt; 12) - (!(*db) &lt;&lt; 4), (primitive-&gt;x2 * 3277) &gt;&gt; 12, ((primitive-&gt;y2 * 3840) &gt;&gt; 12) - (!(*db) &lt;&lt; 4) );</code></pre> <p>With this trick, we already have a nice kinda-refracting-looking effect : </p> <p><img src="https://www.schnappy.xyz/assets/db-refrac.png" alt="Result!" /></p> <p>Now we'd like to add a color hue to it, to have that nice blue crystal look.<br /> Well instead of using the vertex colors that are stored in the level for this specific object, we'll use a custom one, and perform the local color operations on that : </p> <pre><code class="language-c"> // Add color tint - nice blue color CVECTOR prismCol = {0x40,0x40,0xff,0x0}; // work color vectors CVECTOR outCol, outCol1, outCol2; // Find local color from normal and prismCol gte_NormalColorDpq3( primitive-&gt;n.vx, primitive-&gt;n.vz, primitive-&gt;n.vy, &amp;prismCol, primitive-&gt;p, &amp;outCol, &amp;outCol1, &amp;outCol2 ); // Set colors setRGB0(poly, outCol.r, outCol.g , outCol.b); setRGB1(poly, outCol1.r, outCol1.g, outCol1.b); setRGB2(poly, outCol2.r, outCol2.g, outCol2.b);</code></pre> <p>And voilà : </p> <p><img src="https://www.schnappy.xyz/assets/db-blue.png" alt="Result!" /></p> <h2>Semi-transparency</h2> <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. This is further described in this article :</p> <p><a href="https://schnappy.xyz/?tr2_not_shaders-part3">https://schnappy.xyz/?tr2_not_shaders-part3</a> </p> <p><img src="https://www.schnappy.xyz/assets/tr2-wall-1.jpg" alt="TR2 on Psx : The Great Wall level" /></p> <hr /> <h2>Links and notes</h2> <p>Original article : <a href="https://wiki.arthus.net/?tr2_not_shaders">https://wiki.arthus.net/?tr2_not_shaders</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> Wed, 28 Jul 2021 02:00:00 +0200 https://www.schnappy.xyz/?tr2_not_shaders-follow_up https://www.schnappy.xyz/?tr2_not_shaders-follow_up