diff options
| author | Pinapelz <yukais@pinapelz.com> | 2026-05-27 00:53:18 -0700 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2026-05-27 00:55:26 -0700 |
| commit | 36e053f4f0a2f63c08f7c28b9492c067f1ca42bc (patch) | |
| tree | c28973073c8e26775ee4d18d1016df44afdfeceb /micro.pinapelz.com/posts | |
| parent | a01e0666fd66c367745cdaff76fcd6ea7568c31c (diff) | |
migrate pinapelz.moe -> pinapelz.com
Diffstat (limited to 'micro.pinapelz.com/posts')
27 files changed, 7717 insertions, 0 deletions
diff --git a/micro.pinapelz.com/posts/2025-12-01-hello-world/index.html b/micro.pinapelz.com/posts/2025-12-01-hello-world/index.html new file mode 100644 index 0000000..51eb74c --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-01-hello-world/index.html @@ -0,0 +1,501 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Hello World - Why This | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Hello World - Why This</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-01T20:11:57-08:00"> + Monday, December 1, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-01-hello-world/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/default">default</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/default" class="p-category">default</a> + + </span></div><div class="e-content"> + <p>I think having control of your own data is great. The same is true for decentralized social media. I’ve always been a primary user of microblog platforms (like Twitter/X). Having experienced both the traditional and “decentralized” approaches to microblogs, they both have some particular shortcoming in terms of what I want to get out of “social media”.</p> +<h2 id="twitterx">Twitter/X</h2> +<p>This is fairly self explanatory. The rebranding of Twitter to X and Musk’s new ownership of the platform shifted the direction of the platform to be ever more political. X Premium boosting visibility is also something I wasn’t a particular fan of. You can’t view anything without signing in either, so goodbye viewing stuff anonymously. There’s just a lot of “features” here I’m not a fan of. Needless to say, there’s a lot of reasons to not post stuff there.</p> +<h2 id="fediverse">Fediverse</h2> +<p>I initially moved to the <code>Fediverse</code> (on Misskey/Sharkey). Interoperability between different platforms is very cool, and the wide variety of platforms to choose from means that picking any platform never made me feel like “missing out” elsewhere.</p> +<p>However, this in itself has a problem. If you create an account on someone else’s instance, you are a part of their <em>walled garden</em>. Now I’m sure that they are a wonderful person who equally values data ownership/agency, however it doesn’t change the fact that someone else holds your content/data and you rely on them for that service.</p> +<p>So then the alternative here is self-hosting a single person instance. This solves everything, <strong>BUT</strong> the fact that its quite expensive to pay for the bandwidth + storage if you are a small instance and end up federating with a lot of instances. This wasn’t a compromise I wanted, since the name of the game with the Fediverse is being able to connect cross-platform. Great if you have the resources, but not particularly worth it for a single person starting fresh. There’s not really a good way to handle this right now, which is why federation with a very large platform like Threads is limited.</p> +<h2 id="bluesky">Bluesky</h2> +<p><code>Bluesky</code> is one of the drop-in alternatives for Twitter. Its built on the AT-Protocol, which does actually solve a lot of the problems of ActivityPub (Fediverse) in terms of handling small self-hosted instance with large ones. +AtProto allows you to host a <code>PDS (Personal Data Server)</code> which stores all your own posts, profile info, and follows. This boils down to meaning that you really only need to be responsible for serving your own content, which you also own on your own machine. There’s also a lot of fine-grain features that help with not getting overwhelmed by firehose traffic.</p> +<p>While this is great, the issue is that the service is not truly “federated” (yet?). Its still early days for the platform and protocol, Most people are still on <code>bsky.social</code>. This means that to get anything to read at all you’d still need to pull from the big central relay. Even if we were successful in this, its not entirely clear what the costs would be for running all these components together (is it even worth it for a single person?). I think AtProto is promising, but its still early days and who knows where it’ll go…</p> +<h1 id="now-what">Now What</h1> +<p>Its time to try something new. From a surface view the idea of <a href="https://indieweb.org/">IndieWeb</a> is a good solution from the perspective of creating the content. You basically just build a website/blog (which nowadays is dirt cheap to host something static), you then just add some special HTML (<a href="https://indieweb.org/microformats">microformats</a>) and now you’ve got a common protocol similar to a post (only now you can leverage the power of HTML/CSS and customize it however you want). Then implemtning <a href="https://indieweb.org/Webmention">webmentions</a> gives the ability for other people to interact with your content. Using a bridging/syndication service like <a href="https://fed.brid.gy/">Bridgy Fed</a> you can post to the Fediverse and Bluesky as well as allow others from there to interact with your post.</p> +<p>So that’s what this is. Let’s see how it goes.</p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-01-hello-world\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-02-china-town-fair/gloves.webp b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/gloves.webp Binary files differnew file mode 100644 index 0000000..fd42b6c --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/gloves.webp diff --git a/micro.pinapelz.com/posts/2025-12-02-china-town-fair/index.html b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/index.html new file mode 100644 index 0000000..8c6ccfb --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/index.html @@ -0,0 +1,506 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>China Town Fair | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">China Town Fair</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-02T00:22:32-08:00"> + Tuesday, December 2, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-02-china-town-fair/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/life">life</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/arcade" class="p-category">arcade</a> + + </span></div><div class="e-content"> + <p>Visited New York during the Thanksgiving break and had a chance to stopped by one of the most legendary landmarks North American arcade gaming history.</p> +<figure><img src="/posts/2025-12-02-china-town-fair/outside-ctf.webp" + alt="China Town Fair Outside"> +</figure> + +<p>Also yep you’re reading that right, it indeed once home to a <a href="https://davidpotorti.substack.com/p/the-dancing-chicken">dancing chicken as well as one that played tic tac toe</a>.</p> +<p>But apart from just being an old arcade, it was also home to one of the largest competitive arcade game fighting scene (Marvel vs Capcom, Street Fighter, etc.). Many of NAs top players frequented this arcade. However, as we all already know video arcades began to die down during the early 2000s and China Town Fair was no exception having closed in 2011.</p> +<p>Then it re-opened under new management and became a complete shell of its former self. These days its pretty much all redemption slop in there. Very few actual “games” in there; there’s a DDR A3 cab, PIU, a singular jubeat with a broken audio mod, a fully broken down SDVX Nemsys, and 3 Wangan 5DX+ (not sure what happened to the 4th one).</p> +<figure><img src="/posts/2025-12-02-china-town-fair/inside-ctf.webp" + alt="China Town Fair Inside"> +</figure> + +<p>Anyways, its pretty tiny in there and feels like its not doing amazing. A single credit for jubeat was like 3-4 USD I think, and one of the machines to reload cards was fully broken down (tbh just go to Round1 and play).</p> +<p>If you want some actual rhythm games though, walk like 6 minutes and the newly opened “Akiba House” store has private networked maimai DX, WACCA (modded), and CHUNITHM.</p> +<figure><img src="/posts/2025-12-02-china-town-fair/gloves.webp" + alt="Chinese maimai gloves" width="300"> +</figure> + +<p>Also I was absolutely not ready for the New York winter temps. Thankfully I always keep my rhythm game gloves on me which saved my hands from freezing.</p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-02-china-town-fair\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-02-china-town-fair/inside-ctf.webp b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/inside-ctf.webp Binary files differnew file mode 100644 index 0000000..d08d15f --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/inside-ctf.webp diff --git a/micro.pinapelz.com/posts/2025-12-02-china-town-fair/outside-ctf.webp b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/outside-ctf.webp Binary files differnew file mode 100644 index 0000000..aacc4e2 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-02-china-town-fair/outside-ctf.webp diff --git a/micro.pinapelz.com/posts/2025-12-02-power-bank-recall/index.html b/micro.pinapelz.com/posts/2025-12-02-power-bank-recall/index.html new file mode 100644 index 0000000..d0e5ac6 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-02-power-bank-recall/index.html @@ -0,0 +1,499 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>INIU Power Bank Gets Recall | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">INIU Power Bank Gets Recall</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-02T19:45:01-08:00"> + Tuesday, December 2, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-02-power-bank-recall/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/default">default</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/default" class="p-category">default</a> + + </span></div><div class="e-content"> + <p>It would seem that I, along with what seems like the entirety of <a href="https://www.reddit.com/r/amazonprime/comments/1pcq5ug/how_to_get_customer_support_for_recall_iniu/">Reddit</a> bought the same cheap 10000mAh power bank and now its getting recalled.</p> +<p>I wonder if it has anything to do with the poor quality they found in that viral <a href="https://www.lumafield.com/first-article/posts/whats-hiding-inside-haribos-power-bank-and-headphones">Haribo Powerbank</a>. Not sure since I’ve had this one for a long time. I guess I really got what I paid for, shame cause it really is super slim and works well.</p> +<p><strong>But I’d definetly prefer for it not to blow up on me</strong></p> +<p>Here’s the full notice:</p> +<blockquote> +<p>Dear Amazon Customer,</p> +<p>We have learned of a potential safety issue regarding certain product(s) that our records indicate you purchased through the Amazon.com website.</p> +<p>For more details on what you should do, please contact INIU at <a href="mailto:recall@iniu.shop">recall@iniu.shop</a>.</p> +<p>Product: INIU Portable Charger, Slimmest 10000mAh 5V/3A Power Bank, USB C in&out High-Speed Charging Battery Pack, External Phone Powerbank Compatible with iPhone 16 15 14 13 12 Samsung S22 S21 Google iPad etc</p> +<p>If you made this purchase for someone else, please notify the recipient immediately and provide them with the information.</p> +<p>We regret any inconvenience this may cause you but trust you will understand that the safety and satisfaction of our customers is our highest priority.</p> +</blockquote> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-02-power-bank-recall\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-03-04-yt-music-rewind/index.html b/micro.pinapelz.com/posts/2025-12-03-04-yt-music-rewind/index.html new file mode 100644 index 0000000..d389cdc --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-03-04-yt-music-rewind/index.html @@ -0,0 +1,492 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>YouTube Music Recap 2025 | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">YouTube Music Recap 2025</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-03T19:38:52-08:00"> + Wednesday, December 3, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-03-04-yt-music-rewind/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/default">default</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/anime" class="p-category">anime</a> + + </span></div><div class="e-content"> + <p>Its all Bandori. At least 75% of that MyGO!!!!! listening time was probably Haruhikage since I came back to Bandori and had to catch up before watching Ave Mujica anime.</p> +<figure><img src="https://files.catbox.moe/tsquqc.jpg" + alt="YouTube Music Recap Top 5 Artists In Order: MyGO!!!!!, Yumenokessho, Ave Mujica, KMNZ, Roselia" width="300"> +</figure> + + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-03-04-yt-music-rewind\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-04-procon2-hid-tool/index.html b/micro.pinapelz.com/posts/2025-12-04-procon2-hid-tool/index.html new file mode 100644 index 0000000..7d1a70f --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-04-procon2-hid-tool/index.html @@ -0,0 +1,634 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Enable HID Mode on Nintendo Pro Controller 2 | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Enable HID Mode on Nintendo Pro Controller 2</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-04T23:19:29-08:00"> + Thursday, December 4, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-04-procon2-hid-tool/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/tools">tools</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/code" class="p-category">code</a> + + #<a href="/tags/nintendo" class="p-category">nintendo</a> + + </span></div><div class="e-content"> + <p>Switch 2 Pro Controller is very comfy in my hands, but unfortunately it didn’t work out of box on PC (Linux) for me like it’s predacessor. Until there’s actual better driver support for this thing in the kernel (or Valve does something), here’s a hacky Python script to initialize HID-mode on the controller</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># I only tested this script on Linux w/ Steam but in theory it shoud work on Windows?</span> +</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> usb.core <span style="color:#75715e"># install pyusb first: pip install pyusb</span> +</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> usb.util +</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> time +</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sys +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>VENDOR_ID <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x057E</span> +</span></span><span style="display:flex;"><span>PRODUCT_IDS <span style="color:#f92672">=</span> { +</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2066</span>: <span style="color:#e6db74">"Joy-Con (L)"</span>, +</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2067</span>: <span style="color:#e6db74">"Joy-Con (R)"</span>, +</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2069</span>: <span style="color:#e6db74">"Pro Controller"</span>, +</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2073</span>: <span style="color:#e6db74">"GCN Controller"</span> +</span></span><span style="display:flex;"><span>} +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>USB_INTERFACE_NUMBER <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span>INIT_COMMAND_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0d</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>]) +</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x07 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x16 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x16</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>REQUEST_CONTROLLER_MAC <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0e</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>]) +</span></span><span style="display:flex;"><span>LTK_REQUEST <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x11</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>]) +</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x15_ARG_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x09 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>IMU_COMMAND_0x02 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x27</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x11 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x11</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x0A <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x14</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0x35</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x46</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>IMU_COMMAND_0x04 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x27</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>ENABLE_HAPTICS <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x10 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x10</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x01 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x0A_ALT <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>]) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">send_usb_data</span>(ep_out, ep_in, data, description<span style="color:#f92672">=</span><span style="color:#e6db74">""</span>): +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>: +</span></span><span style="display:flex;"><span> ep_out<span style="color:#f92672">.</span>write(data) +</span></span><span style="display:flex;"><span> time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">0.01</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>: +</span></span><span style="display:flex;"><span> response <span style="color:#f92672">=</span> ep_in<span style="color:#f92672">.</span>read(<span style="color:#ae81ff">32</span>, timeout<span style="color:#f92672">=</span><span style="color:#ae81ff">100</span>) +</span></span><span style="display:flex;"><span> hex_resp <span style="color:#f92672">=</span> <span style="color:#e6db74">" "</span><span style="color:#f92672">.</span>join([<span style="color:#e6db74">f</span><span style="color:#e6db74">"</span><span style="color:#e6db74">{</span>x<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">"</span> <span style="color:#66d9ef">for</span> x <span style="color:#f92672">in</span> response]) +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Response: </span><span style="color:#e6db74">{</span>hex_resp<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> e<span style="color:#f92672">.</span>errno <span style="color:#f92672">==</span> <span style="color:#ae81ff">110</span>: +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] No response (Timeout)"</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">else</span>: +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Read Error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Write Error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">raise</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">set_player_leds</span>(ep_out, ep_in, led_mask): +</span></span><span style="display:flex;"><span> command <span style="color:#f92672">=</span> [ +</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, +</span></span><span style="display:flex;"><span> led_mask, +</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span> +</span></span><span style="display:flex;"><span> ] +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, bytes(command), <span style="color:#e6db74">f</span><span style="color:#e6db74">"Set LED Mask: 0x</span><span style="color:#e6db74">{</span>led_mask<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">connect_usb</span>(): +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">"Searching for Nintendo Switch Controllers..."</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">match_device</span>(dev): +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> dev<span style="color:#f92672">.</span>idVendor <span style="color:#f92672">==</span> VENDOR_ID <span style="color:#f92672">and</span> dev<span style="color:#f92672">.</span>idProduct <span style="color:#f92672">in</span> PRODUCT_IDS +</span></span><span style="display:flex;"><span> dev <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>find(custom_match<span style="color:#f92672">=</span>match_device) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> dev <span style="color:#f92672">is</span> <span style="color:#66d9ef">None</span>: +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">raise</span> <span style="color:#a6e22e">ValueError</span>(<span style="color:#e6db74">"Device not found"</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> product_name <span style="color:#f92672">=</span> PRODUCT_IDS<span style="color:#f92672">.</span>get(dev<span style="color:#f92672">.</span>idProduct, <span style="color:#e6db74">"Unknown Device"</span>) +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Found </span><span style="color:#e6db74">{</span>product_name<span style="color:#e6db74">}</span><span style="color:#e6db74"> (ID: </span><span style="color:#e6db74">{</span>dev<span style="color:#f92672">.</span>idProduct<span style="color:#e6db74">:</span><span style="color:#e6db74">04x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">)"</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> dev<span style="color:#f92672">.</span>is_kernel_driver_active(USB_INTERFACE_NUMBER): +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>: +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">"Detaching kernel driver..."</span>) +</span></span><span style="display:flex;"><span> dev<span style="color:#f92672">.</span>detach_kernel_driver(USB_INTERFACE_NUMBER) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Could not detach kernel driver: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>: +</span></span><span style="display:flex;"><span> dev<span style="color:#f92672">.</span>set_configuration() +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">"Configuration set."</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Error setting configuration: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>: +</span></span><span style="display:flex;"><span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>claim_interface(dev, USB_INTERFACE_NUMBER) +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Interface </span><span style="color:#e6db74">{</span>USB_INTERFACE_NUMBER<span style="color:#e6db74">}</span><span style="color:#e6db74"> claimed."</span>) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Could not claim interface: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> cfg <span style="color:#f92672">=</span> dev<span style="color:#f92672">.</span>get_active_configuration() +</span></span><span style="display:flex;"><span> intf <span style="color:#f92672">=</span> cfg[(USB_INTERFACE_NUMBER,<span style="color:#ae81ff">0</span>)] +</span></span><span style="display:flex;"><span> ep_out <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>find_descriptor( +</span></span><span style="display:flex;"><span> intf, +</span></span><span style="display:flex;"><span> custom_match <span style="color:#f92672">=</span> <span style="color:#66d9ef">lambda</span> e: usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>endpoint_direction(e<span style="color:#f92672">.</span>bEndpointAddress) <span style="color:#f92672">==</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>ENDPOINT_OUT) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> ep_in <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>find_descriptor( +</span></span><span style="display:flex;"><span> intf, +</span></span><span style="display:flex;"><span> custom_match <span style="color:#f92672">=</span> +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">lambda</span> e: usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>endpoint_direction(e<span style="color:#f92672">.</span>bEndpointAddress) <span style="color:#f92672">==</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>ENDPOINT_IN +</span></span><span style="display:flex;"><span> ) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> ep_out: +</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">"Could not find OUT endpoint"</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Found Endpoint OUT: 0x</span><span style="color:#e6db74">{</span>ep_out<span style="color:#f92672">.</span>bEndpointAddress<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">"Starting Initialization Sequence..."</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>: +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, INIT_COMMAND_0x03, <span style="color:#e6db74">"Init 0x03"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x07, <span style="color:#e6db74">"Unknown 0x07"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x16, <span style="color:#e6db74">"Unknown 0x16"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, REQUEST_CONTROLLER_MAC, <span style="color:#e6db74">"Req MAC"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, LTK_REQUEST, <span style="color:#e6db74">"Req LTK"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x15_ARG_0x03, <span style="color:#e6db74">"Unknown 0x15"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x09, <span style="color:#e6db74">"Unknown 0x09"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, IMU_COMMAND_0x02, <span style="color:#e6db74">"IMU 0x02"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x11, <span style="color:#e6db74">"OUT Unknown 0x11"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x0A, <span style="color:#e6db74">"Unknown 0x0A"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, IMU_COMMAND_0x04, <span style="color:#e6db74">"IMU 0x04"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, ENABLE_HAPTICS, <span style="color:#e6db74">"Enable Haptics"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x10, <span style="color:#e6db74">"OUT Unknown 0x10"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x01, <span style="color:#e6db74">"OUT Unknown 0x01"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x03, <span style="color:#e6db74">"OUT Unknown 0x03"</span>) +</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x0A_ALT, <span style="color:#e6db74">"OUT Unknown 0x0A Alt"</span>) +</span></span><span style="display:flex;"><span> set_player_leds(ep_out, ep_in, <span style="color:#ae81ff">0x0F</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">"Controller initialization sequence complete! All LEDs should be on."</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Error during sequence: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">"__main__"</span>: +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>: +</span></span><span style="display:flex;"><span> connect_usb() +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">ValueError</span> <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> print(e) +</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e: +</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">"Unexpected error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">"</span>) +</span></span></code></pre></div><p><strong>Steps</strong></p> +<ol start="0"> +<li>(Optional) First Create a virtual environment</li> +<li>Install pyusb via <code>pip install pyusb</code></li> +<li>Plug your Pro Controller 2 in via USB</li> +<li>Run the script</li> +</ol> +<p>If all 4 of the player indicator LEDs light up (the square ones near the charging port), then that means you should be good to go!</p> +<p>You’ll need to re-run this script each time you plug/unplug or restart your machine.</p> +<p>This is pretty much a copy of the <a href="https://handheldlegend.github.io/procon2tool/">online Procon 2 Enabler Tool</a> but WebHID is dodgy on the Firefox fork I’m using, plus its annoying having to open this page each time.</p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-04-procon2-hid-tool\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/18.webp b/micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/18.webp Binary files differnew file mode 100644 index 0000000..83768f7 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/18.webp diff --git a/micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/index.html b/micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/index.html new file mode 100644 index 0000000..0d0594a --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/index.html @@ -0,0 +1,496 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>First MXM 18 Cleared! | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">First MXM 18 Cleared!</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-06T22:33:23-08:00"> + Saturday, December 6, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/games">games</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/arcade" class="p-category">arcade</a> + + </span></div><div class="e-content"> + <p>Cleared my first 18 difficulty chart in + +<a href="https://micro.pinapelz.com//tags/sdvx" class="p-category">#sdvx</a> +</p> +<p>Albeit its not a very difficult one, but I think I’m finally starting to chip away at the 17-18 difficulty wall. +<figure><img src="/posts/2025-12-06-first-sdvx-18/18.webp" + alt="Sound Voltex Enchant 6 Clear" width="500"> +</figure> +</p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-06-first-sdvx-18\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/cab1.webp b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/cab1.webp Binary files differnew file mode 100644 index 0000000..6f30510 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/cab1.webp diff --git a/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/cab2.webp b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/cab2.webp Binary files differnew file mode 100644 index 0000000..6b5f02f --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/cab2.webp diff --git a/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/danevo.webp b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/danevo.webp Binary files differnew file mode 100644 index 0000000..c15d1f5 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/danevo.webp diff --git a/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/index.html b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/index.html new file mode 100644 index 0000000..28b63d0 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/index.html @@ -0,0 +1,537 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Arcade Monsters | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Arcade Monsters</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-18T21:38:23-08:00"> + Thursday, December 18, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/games">games</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/arcade" class="p-category">arcade</a> + + </span></div><div class="e-content"> + <p>If you live in Socal and are also into arcade gaming (both retro and modern), one of the great weekend day-trips I’ve found is taking the Pacific Surfliner train down to San Diego.</p> +<h1 id="getting-there">Getting There</h1> +<p>There are a number of departures in the morning, and while not as fast as a car when there’s no traffic, you can save your energy and do other stuff on the train. The timetable also works nicely since you can pretty much get there around opening if you want to beat the crowds.</p> +<p>Once you get there, you can either take the trolley or walk 20 minutes to the arcade. I prefer the walk since you can grab some food/coffee on the way.</p> +<p>Plus the view is excellent.</p> +<p><figure><img src="/posts/2025-12-18-07-arcade-monsters-sd/view1.webp" + alt="Ocean view from the Pacific Surfliner" width="700"> +</figure> + +<figure><img src="/posts/2025-12-18-07-arcade-monsters-sd/view2.webp" + alt="Ocean view from the Pacific Surfliner" width="700"> +</figure> +</p> +<h1 id="value">Value</h1> +<p>So is this trip worth it and what is the cost?</p> +<p>Arcade Monsters games operate all on “Free Play”, you pay a set fee for entry and can stay for as long as you’d like. Its $25 to enter, or $35 if you want to be able to leave and come back.</p> +<p>Since there aren’t exactly a lot of “retro” arcades anymore, I’ll compare the value proposition here to Round1:</p> +<p>At Round1 a standard rhythm games is roughly 8.6 credits per play. If we estimate the value of a Round1 credit to be around $0.15 (assuming standard non-member $120 package for 777 credits), this would put 1 play at around $1.29. This means it takes roughly 20 plays to hit $25.</p> +<p>Let’s also say that a single play at any rhythm game takes roughly 10 minutes. Assuming you continuously played games This means $25 of Round1 credits would last you roughly 3.3 hours. So just this on its own, without considering anything else I’d say that this is great value just on its own.</p> +<p>But if you were to include transportation costs, assuming around $60 for a round-trip ticket via train, it becomes a little more difficult to justify since for the same price since you’d be able to play 46 rounds of something else at Round1.</p> +<p>However, with the variety of games in there (even rarer ones), I’d say this is still an excellent trip. I personally could easily stay 5+ hours in there (cause I’m a degenerate and they also sell food + drinks in there).</p> +<figure><img src="/posts/2025-12-18-07-arcade-monsters-sd/cab1.webp" + alt="Arcade Cabinets" width="500"> +</figure> + +<h1 id="quality">Quality</h1> +<p>Most of the retro stuff is very well maintained and in great working condition. Also many of the modern games are networked and have card saving features.</p> +<p>However, it’d be dishonest to say that these cabs are in excellent condition:</p> +<ul> +<li>The Sound Voltex knobs are basically falling off, the switches don’t feel great</li> +<li>The pads ghosts on Dancerush and the navigation keys are broken</li> +<li>FutureTomTom drums have sensitivity issues</li> +<li>Small things like how the stool for Ongeki doesn’t match the height of the standard seat.</li> +</ul> +<p>Also it gets busy in there and is also a popular spot for families (kids get loud).</p> +<figure><img src="/posts/2025-12-18-07-arcade-monsters-sd/cab2.webp" + alt="Arcade Cabinets" width="500"> +</figure> + +<h1 id="conclusion">Conclusion</h1> +<p>Overall, as a once in a while its great value. You get to try out a ton of games, some of which are even considered rare to come by in Japan. If you also just want to go in and hardcore grind out some CHUNITHM, I can see that as a pretty good option too.</p> +<p>Check out the list of games <a href="https://zenius-i-vanisher.com/v5.2/arcade.php?id=9155&section=games#games">here</a></p> +<figure><img src="/posts/2025-12-18-07-arcade-monsters-sd/danevo.webp" + alt="Arcade Cabinets" width="500"> +</figure> + + + +<a href="https://micro.pinapelz.com//tags/arcade" class="p-category">#arcade</a> + + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-18-07-arcade-monsters-sd\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/view1.webp b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/view1.webp Binary files differnew file mode 100644 index 0000000..b7463ba --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/view1.webp diff --git a/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/view2.webp b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/view2.webp Binary files differnew file mode 100644 index 0000000..21956d9 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/view2.webp diff --git a/micro.pinapelz.com/posts/2025-12-19-08-ffxiv-patch-7-4/index.html b/micro.pinapelz.com/posts/2025-12-19-08-ffxiv-patch-7-4/index.html new file mode 100644 index 0000000..dbe44e6 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-19-08-ffxiv-patch-7-4/index.html @@ -0,0 +1,520 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Playlog: FFXIV Dawntrail Patch 7.4 Thoughts (spoilers) | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Playlog: FFXIV Dawntrail Patch 7.4 Thoughts (spoilers)</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-19T22:15:50-08:00"> + Friday, December 19, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-19-08-ffxiv-patch-7-4/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/games">games</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/playlog" class="p-category">playlog</a> + + </span></div><div class="e-content"> + <p><em>This is primarily focused on the content of the patch, not so much the features they’ve added.</em></p> +<h1 id="story">Story</h1> +<ul> +<li>Mistwake Dungeon was a good difficulty. Although I’m not a fan of the electricity star AOEs, very hard to read for no apparent reason. Please just stick with the old one.</li> +<li>Cutscene quality def. got better. As in animations and uniqueness.</li> +<li>Love the look and feel (Treno). There’s a ton of good spots for “gpose-ing”. Music is nice too.</li> +<li>Seriously Krile? You parents were the ones who dropped you into the Source. I don’t think they’d care if you wanted to stay in the Source (just make up your mind) -> well glad that got sorted out</li> +<li>“Hell on Rails” Trial (Doomtrain) is very nicely designed. Its got some nice unique mechanics, the “sucking” mechanic definetly trips you up the first time because the distance to move back + timing has been tuned so that you need to pre-position for it.</li> +<li>The transition from inside the engine to outside was really cool!!! This is probably one of my top normal trials now.</li> +<li>The instance battle was well done too. The roleplaying part was on point, and when it was finally time to fight a real boss you get to play as yourelf (I think this is the best flow). Love the idea using the spriggan to avoid Behemoth’s meteor.</li> +<li>Cool so we just get to keep the key. If this were any bit realistic, we’ve surely learned that no one this powerful should be allowed to keep the key on themsleves 24/7. Because surely the WoL being the most powerful being will never run rogue with a interdimensional travel capable tool. Then again, seeing how stuff gets stolen all the time in the story… Well I guess it can go either way.</li> +<li>I’m guessing this key is gonna be how the writers justify being able to travel to new worlds for post-Zodiark/Hydaelyn story. Its fine I guess, but a little disappointing it isn’t something more unique.</li> +<li>And what do you know. Ascians. I hope we get something unqiue for 8.0… I guess thats fine but please lets not have it just be SHB all over again.</li> +</ul> +<h1 id="raid">Raid</h1> +<ul> +<li>“Feral Fandom” -> Yep thats FF14 NA playerbase for you.</li> +<li>Heavyweight 1 (Vamp Fatale) Raid was cool and unique, but a bit too flashy imo. That Half Moon is needlessly large, wish we’d stop with mechanics that are designed to trick people even when read correctly.</li> +<li>Heavyweight 2 (Xtremes) I take it back, this is the one with the blinding effects MY EYES. Fire and water one after another. This is a pretty hard normal fight actually (the first time you run it blind). Really punishing for bad AOE placement positions since you can effectively be cut off from the team.</li> +<li>Holy wow these cutscenes are in serious need of voice acting. Its a good story but so dry and awkward without it.</li> +<li>Heavyweight 3 (Tyrant). Really? Behemoth again, double dipping from the instance battle. There’s so many other cool FF monsters. I like the arena, it fits the guy well, all about history of the Arcadion/tradition. Fight is underwhelming and too easy imo, apart from 1 single trick mechanic that can cause a wipe…</li> +<li>Heavyweight 4 (Lindwurm). EVERYTHING BURNS. This fight was honestly too easy, zero deaths everything can be read. 2nd phase was underhelming.</li> +<li>Overall the story here while not as in depth and relevant to the story as Endwalker raids, still had a nice little twist at the end I def did not expect. Enjoyed it!</li> +</ul> +<h1 id="misc">Misc</h1> +<ul> +<li>The new Frontline map is “dangerous”. Overall the new capturing point system is far better than a non-interruptable interact like in Onsal Hakir. The snowman and aurora events are also good, and I think they come in right when they’re needed too (to spice things up/allow for a turning point).</li> +<li>The map design however is far too complex, all these bridges and everywhere and invisible walls. It does add a lot of chokepoints but also makes it difficult to navigate from point A -> B (but partially I guess this is done cause the map does feel smaller than Onsal).</li> +</ul> + + +<a href="https://micro.pinapelz.com//tags/ffxiv" class="p-category">#ffxiv</a> + + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-19-08-ffxiv-patch-7-4\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2025-12-31-09-dbox-review/index.html b/micro.pinapelz.com/posts/2025-12-31-09-dbox-review/index.html new file mode 100644 index 0000000..643ed74 --- /dev/null +++ b/micro.pinapelz.com/posts/2025-12-31-09-dbox-review/index.html @@ -0,0 +1,497 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>DBOX Movie Seats | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">DBOX Movie Seats</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2025-12-31T22:03:51-08:00"> + Wednesday, December 31, 2025 + </time> + - <a href="https://micro.pinapelz.com/posts/2025-12-31-09-dbox-review/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/default">default</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/default" class="p-category">default</a> + + </span></div><div class="e-content"> + <p>There’s a thing here in Canada where certain theaters have these special seats that rumble and move in motion with whats happening on screen.</p> +<p>I recently saw the new Avatar (Fire and Ash) in one of these seats. It wasn’t a bad experience but given the markup, I don’t think its worth it:</p> +<ul> +<li>First it is fun (sometimes). For example when they were flying through the air, the seat would tilt in the motion of them flying. Or when there was an explosion/gunfire, the seat would rumble</li> +<li>However, for me I think they overdid it at times, literately the seat would move and rumble for the smallest things. So it was kind of like a constant thing throughout the whole film. For me its a bit annoying</li> +<li>For the $10-15 extra (I think I paid a bit more cause the movie was also in 3D), I’d much rather just go to a theater that has the big comfy recliner seats</li> +<li>I think for the right movie (maybe something heavy on action or horror) this could be a solid purchase if its a movie you’re really looking forward to</li> +<li>Or I also know that some people see movies multiple times, so maybe this can be a good option for a 2nd viewing?</li> +</ul> +<p>Generally, though… I think I’ll live without them.</p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2025-12-31-09-dbox-review\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2026-02-19-10-discord-rant/index.html b/micro.pinapelz.com/posts/2026-02-19-10-discord-rant/index.html new file mode 100644 index 0000000..53119e9 --- /dev/null +++ b/micro.pinapelz.com/posts/2026-02-19-10-discord-rant/index.html @@ -0,0 +1,501 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Discord Rant | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Discord Rant</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2026-02-19T19:17:04-08:00"> + Thursday, February 19, 2026 + </time> + - <a href="https://micro.pinapelz.com/posts/2026-02-19-10-discord-rant/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/default">default</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/default" class="p-category">default</a> + + </span></div><div class="e-content"> + <p>We’ve seen time and time again that there is “no such thing as a free lunch”. The same is true for Discord.</p> +<ol> +<li>Offer a service that is much better than all the competitors</li> +<li>Attract a bunch of users</li> +<li>Burn VC money</li> +<li>Repeat 1-3 until its time to pay them back</li> +<li>Figure out how to make money</li> +</ol> +<p>Nitro doesn’t fund the platform, hosting free voice and screenshare is more expensive than you think. Ultimately, any choice of software for me boils down to “what value do I get out of it”.</p> +<p>Look, free is free, and nothing can and will ever beat the value of free. There’s still plenty of reasons to move even if you are a free user, but that’s not the point of this. What I want to take a look at is what value you are actually getting as a paying user.</p> +<p>If you wanted to take advantage of ALL of Discord’s features, such as the higher quality screen share + audio or vanity for servers; you need to buy Nitro and boost your server. Nitro comes out to $99.99 a year for Nitro and around $490 a year for the 14 boosts to Tier 3. For me, it feels like the company if scavenging for opportunities to make money, making features like server banners and vanity links paid (which I suppose is how capitalism works, but for what you get at that price point it seems ridiculous). Even if we lower it down to no Nitro and just 2 boosts to get the additional custom emoji slots on a server, <strong>that’s still around $6 a month</strong>.</p> +<p>Let’s say you do opt for this $6 price point. Is it good value? I suppose it depends. I can spin up Teamspeak 6 and Matrix on a CPX11 for 6 Euros a month from Hetzner. Services that give me all the features from the start without all the paywalling BS. In fact, Discord can capture this as well if they changed their pricing model, but I believe their too deep into this situation where they now have to fund the free users or risk everyone migrating elsewhere.</p> +<p>Not to mention, the Discord client has gotten progressively worse over the years, all these accessories and animations do is lag out the client which they don’t even seem to understand the codebase of anymore.</p> +<p>What Discord sells is convenience, regardless of the Face ID or data collection, the value is not there and hasn’t been there from a “running a small community” perspective. There’s much better options where you have much more agency over your data, as well as have more fine-grain control over optimizing cost. I suppose you can think of it as going to McDonalds or actually making dinner.</p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2026-02-19-10-discord-rant\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/index.html b/micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/index.html new file mode 100644 index 0000000..c702832 --- /dev/null +++ b/micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/index.html @@ -0,0 +1,516 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Playlog: Hundred Lines Last Defense Academy | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Playlog: Hundred Lines Last Defense Academy</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2026-03-17T17:19:03-07:00"> + Tuesday, March 17, 2026 + </time> + - <a href="https://micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/games">games</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/playlog" class="p-category">playlog</a> + + </span></div><div class="e-content"> + <p>After about a year of playing on and off, I’ve finally finished all 100 (and 1, counting the first one). In total it took roughly 105 hours or so. +<figure><img src="/posts/2026-03-17-11-hundred-lines-last-defense-playlog/playtime.png" + alt="105 hours or more played"> +</figure> +</p> +<h2 id="core-mechanics">Core Mechanics</h2> +<ul> +<li>This is basically a visual novel, there’s very little fun to be had if you are a “cutscene skipper”. If you enjoyed Kodaka’s other works like Danganronpa then you’ll be right at home.</li> +<li>There’s a bunch of smaller “minigames” but are mostly a one-off thing, they feel mostly like an afterthought (+25)</li> +</ul> +<h2 id="structure">Structure</h2> +<ul> +<li>There’s 2 main parts of the game, the battling and the story itself</li> +<li>The battling itself has a decent amount of strategy to it, and you can in fact easily lose if you’re not careful for some of them</li> +<li>In my opinion though given how little variety there is it kinda gets old fast, luckily the 2nd half of the game lets you skip battles you’ve already done</li> +<li>As far as the story goes, its standard visual novel stuff but with a Kodaka twist. Each ending belongs to a particular “route” which is centered around a particular storyline, each one is also explicitly named in the game’s flowchart. (+20)</li> +</ul> +<h2 id="content">Content</h2> +<ul> +<li>The story itself is quite good, but not all the routes are really worth doing if you just want what I consider to be the “core” of the plot. Some of them basically lead to nothing and are there just for fun.</li> +<li>Everyone has to play through <code>Last Defense Academy 1</code> which basically acts as a very long prologue for the actual game</li> +<li><strong>Not Necessary:</strong> Serial Battles Route (PLEASE skip this one, the game forces you to play unskippable battles and it forshadows literately the tiniest thing), Box of Blessings, Conspiracy (does nothing but is very quick to do), Romance, Comedy, V’ehxness Route (mainly character building), Reset Route</li> +<li>I would recommend playing through the prologue, then explicitly following a guide for the <code>Last Defense Academy 2nd Scenario</code>, then if you still want more start the S.F Route and follow a guide to unlock the pre-requisite routes while you progress through that. Everything else is largely optional IMO and is just for world-building. (12)</li> +</ul> +<h2 id="technical-execution">Technical Execution</h2> +<p>Its fine overall. You can def. tell they didn’t have as big of a budget as Danganronpa to work with. There were some issues with leaving the game in suspense for too long on Switch but no major performance issues (+15)</p> +<h2 id="presentation">Presentation</h2> +<p>Was good since I’m a Danganronpa fan. I would’ve liked to see a few more tracks or at least variations in boss fights. It does get a bit repetitive after 100 times… Still a surprising number of lines were voiced so props to them! (+14)</p> +<p><strong>(86/100)</strong></p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2026-03-17-11-hundred-lines-last-defense-playlog\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/playtime.png b/micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/playtime.png Binary files differnew file mode 100644 index 0000000..bde1097 --- /dev/null +++ b/micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/playtime.png diff --git a/micro.pinapelz.com/posts/2026-04-26-12-april-playlog/index.html b/micro.pinapelz.com/posts/2026-04-26-12-april-playlog/index.html new file mode 100644 index 0000000..cbdfcb5 --- /dev/null +++ b/micro.pinapelz.com/posts/2026-04-26-12-april-playlog/index.html @@ -0,0 +1,574 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Playlog: April 2026 (No Sleep for Kaname Date, Xenoblade 1 DE, Catherine Full Body) | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Playlog: April 2026 (No Sleep for Kaname Date, Xenoblade 1 DE, Catherine Full Body)</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2026-04-26T18:20:09-07:00"> + Sunday, April 26, 2026 + </time> + - <a href="https://micro.pinapelz.com/posts/2026-04-26-12-april-playlog/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/games">games</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/playlog" class="p-category">playlog</a> + + </span></div><div class="e-content"> + <p>I’ve gotten quite good at actually making progress on my backlog. Turns out the answer was to just uninstall all social media and get rid of doom scrolling. I invested in a rudimentary capture card as well so that I can have my Switch games show up as an application on my PC rather than having to swap display inputs (which makes it easy to get up and running for a quick session).</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mirror-switch <span style="color:#f92672">()</span> <span style="color:#f92672">{</span> +</span></span><span style="display:flex;"><span> dev<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>1<span style="color:#66d9ef">:-</span>/dev/video6<span style="color:#e6db74">}</span> +</span></span><span style="display:flex;"><span> nohup ffplay -f v4l2 -framerate <span style="color:#ae81ff">100</span> -video_size 1920x1080 -i <span style="color:#e6db74">"</span>$dev<span style="color:#e6db74">"</span> <span style="color:#ae81ff">\ +</span></span></span><span style="display:flex;"><span> -fflags nobuffer -flags low_delay -framedrop >/dev/null 2>&<span style="color:#ae81ff">1</span> & +</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span> +</span></span></code></pre></div><p>The delay is actually pretty good, I’m able to play something like Fall Guys on it just fine! Now onto the playlog.</p> +<h1 id="no-sleep-for-kaname-date--from-ai-the-somnium-files">No Sleep for Kaname Date – From AI: The Somnium Files</h1> +<p>This is a spin-off game that takes place in between the first and second AI: The Somnium Files game. Its relatively short.</p> +<p> +<figure> + <img src="https://files.catbox.moe/8rhr2j.jpg" alt="" /> +</figure> + + +</p> +<h2 id="1-core-mechanics">1. Core Mechanics</h2> +<p>The game has a similar style to the first and second game, where you enter Sommnium (the dream world) of people to uncover some truth. However, it also introduces an escape room mechanic where you need to solve puzzles to escape a given room. This is essentially the same mechanic as what’s in the “Zero Escape” series, so much so that each escape room opens with the same “Seek a way out” screen.</p> +<p> +<figure> + <img src="https://files.catbox.moe/hz2jxm.img" alt="" /> +</figure> + + +</p> +<p>For the puzzle solving, that’s just entirely dependent on how good you are at reading between the lines. For most of them, once you eventually do figure out how to do it you’ll feel dumb not noticing earlier. The Sommnium exploration segment though is still in my opinion plagued with the issue of where you are sort of just “guessing and checking” based on very loose clues. I suppose that’s intended, but I wish that the correct options to pick become a bit more apparent not just from exploring around Sommnium but also from clues in the real outside world. (+32)</p> +<h2 id="2-structure">2. Structure</h2> +<p>The progression of the story is near identical to the first and second game. You read through the story visual novel style, then jump into Sommnium. Only now it alternates between Sommnium and an escape room. The challenges in both are well designed and interesting, but I personally felt that some of the escape rooms were a bit random? I mean the rooms bared little relevance to the AI The Sommnium world for the most part (which I wish it did). (+20)</p> +<h2 id="3-content">3. Content</h2> +<p>The game follows Kaname Date and AIBA the AI-Ball, who are investigating a new case where Iris Sagan (from the first game) goes missing. A mysterious figure named Akemi tells Iris that she is participating in the “Third Eye Game”.</p> +<p>The story explains some details of what’s been going on between the first and second game. Even the tiny details. The story is pretty self-contained for the most part, and its sorta like a mini-adventure. There is indeed an actual twist like every Uchikoshi game so pay attention to your surroundings. Very enjoyable to play through (+15)</p> +<h2 id="4-technical-execution-15">4. Technical Execution (15)</h2> +<p>No issues here, plays great on the Switch 2. (+15)</p> +<h1 id="5-presentation-15">5. Presentation (15)</h1> +<p>In my opinion, the game is a bit on the short side considering the price point. The content is good though. I’d say grab it if its on sale for 40 USD rather than 50 USD (+13)</p> +<p><strong>92/100</strong></p> +<hr> +<h1 id="xenoblade-1-de">Xenoblade 1: DE</h1> +<p>Covers the base game, not including the DLC.</p> +<p> +<figure> + <img src="https://files.catbox.moe/2hfxo4" alt="" /> +</figure> + + +</p> +<h2 id="1-core-mechanics-1">1. Core Mechanics</h2> +<p>Combat is much more simple than the second game and for me it sorta gets repetitive quick. Found myself avoiding monsters towards the end of the game. I’d say definetly try playing different characters to keep things fresh. The friendship tree thing is kind of useless and confusing, same with the gemstones. It just feels like they aren’t really needed and just add onto the things to do. In my opinion they should’ve kept it to just upgrading gear and obtaining arts. (+28)</p> +<h2 id="2-structure-1">2. Structure</h2> +<p>This game is grindy. Doesn’t matter what people say, you do need to stop and kill stuff as well as do side quests otherwise the enemy level outpaces you fast. This kinda got old for me so what I did was I would grind levels on casual mode and then switch back to normal mode when progressing through the story. Other than that the progression in the game is fairly linear and follows a central plot. The one side quest that may be worth doing is restoring Colony 6 which sorta acts like a big sidequest spanning multiple chapters in the story. Other than just for world building, much of the sidequests are just fetch-quests and are kind of drab. (+15)</p> +<h2 id="3-content-1">3. Content</h2> +<p>I thought the story was just alright for me. It does end up being quite “anime”, I would say it only really ramps up towards the last couple chapters. Before that we’re largely just adventures, adventuring around. It does provide good context for the second game. Shulk as a character definetly has some serious plot armor, even in some cases he just sorta comes back from the dead. Still, I do think the story is worth seeing (+15)</p> +<h2 id="4-technical-execution">4. Technical Execution</h2> +<p>No issues here, plays great on the Switch 2. (+15)</p> +<h1 id="5-presentation">5. Presentation</h1> +<p>The voice acting and dialogue… it certainly leaves something to be desired. Well the second game sorta suffered the same issue. I played on full English though. YMMV. (+10)</p> +<p><strong>83/100</strong></p> +<hr> +<h1 id="catherine-full-body">Catherine Full Body</h1> +<p>It’s a puzzle game. But more erotic.</p> +<p> +<figure> + <img src="https://files.catbox.moe/o1169e.jpg" alt="" /> +</figure> + + +</p> +<h2 id="1-core-mechanics-2">1. Core Mechanics</h2> +<p>Absolutely no qualms here. Its a genius little puzzle game with lots of strategy involved. You’d really have to watch some footage of it to understand how it works. (+35)</p> +<p> +<figure> + <img src="https://files.catbox.moe/7atzn3.png" alt="" /> +</figure> + + +</p> +<h2 id="2-structure-2">2. Structure</h2> +<p>For me, the puzzles aren’t too repetitive. There’s a nice break in between each one, and each night (after a set of puzzles) you get to watch a bit more of the story. Most of the game outside of the puzzle takes place in the “stray sheep” bar, the best way I can describe it is like Persona 3/4/5 “Free Time” where you can go around talking to your friends or others in the bar. Despite the small area there’s a fair amount of extra lore here, since you’ll start noticing that many of the people you talk to are also the ones appearing in your nightmare.</p> +<p>The only thing I didn’t like is that it wasn’t really clear who you had to talk to if you wanted to “progress time”. It may seem a bit confusing, but essentially once you have done everything in the bar, people get up and leave and new people walk in (this effectively progresses the night in free-time). (+23)</p> +<h2 id="3-content-2">3. Content</h2> +<p>The story of the game revolves around the main character <em>Vincent</em>. Its a short game about dealing with societal pressures. I say that but the game is quite funny, and it doesn’t take too long to beat. Vincent himself is a bit of a bozo, most of the game is linear and decided for you up until the very end. Essentially the game has you answer questions that make you reflect on your personal morals, then at the end this decides which ending you get. I don’t think this is a bad thing, but I would’ve liked to see more player agency at different points of the game rather than only at the end. Not a huge deal though (+13).</p> +<h2 id="4-technical-execution-1">4. Technical Execution</h2> +<p>The only thing that annoyed me was that for some reason the spike blocks are kinda laggy on the Switch 2? Not sure why. (+14)</p> +<h2 id="5-presentation-1">5. Presentation</h2> +<p>Based on the start of the game I thought this game would be extremely “goon-bait” but actually it wasn’t. Very fun with lots of replayability (in terms of challenge yourself to puzzles + multiplayer) (+15)</p> +<p>If you see this game on sale, definelty give it a try. Not sure if its worth at full-price but when its on sale for less than 10 bucks its a steal!</p> +<p><strong>95/100</strong></p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2026-04-26-12-april-playlog\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/2026-04-29-13-dac-vs-wireless-dap/index.html b/micro.pinapelz.com/posts/2026-04-29-13-dac-vs-wireless-dap/index.html new file mode 100644 index 0000000..c6c0c37 --- /dev/null +++ b/micro.pinapelz.com/posts/2026-04-29-13-dac-vs-wireless-dap/index.html @@ -0,0 +1,541 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Portable Audio: Phone, Wireless DAC, or DAP | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + + + <main> + <article class="h-entry"> + <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a> + <h1 class="p-name">Portable Audio: Phone, Wireless DAC, or DAP</h1> + <div hidden><div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> +</div> + + + <div><b> + <time class="dt-published" datetime="2026-05-03T03:16:09-07:00"> + Sunday, May 3, 2026 + </time> + - <a href="https://micro.pinapelz.com/posts/2026-04-29-13-dac-vs-wireless-dap/" class="u-url u-uid" >Permalink</a> + </b></div> + <div class="article-meta"><span class="categories"> + Categories: + + <a href="/categories/default">default</a> + + </span>--<span class="tags"> + Tags: + + #<a href="/tags/default" class="p-category">default</a> + + </span></div><div class="e-content"> + <p>Supposedly, there’s been a <a href="https://www.facebook.com/APNews/videos/secondhand-sales-of-apple-ipods-are-surging-four-years-after-it-was-killed-off-w/1278247987103509/">resurgence in the popularity of the iPod</a> in the recent months for all sorts of reasons. While I’m well aware of “MP3 Players”, such as the original iPod and the old Sony Walkman, these are not devices I grew up using. As a “new-gen” audiophile myself, getting a DAP (Dedicated Audio Player, its the new term for these sort of devices as they can play much more than just MP3s) was certainly an interesting idea. However, modern day audiophiles now have an arsenal of methods to enjoy music, even when it comes to portable playback.</p> +<blockquote> +<p><strong>PREFACE</strong></p> +<p>I’ll assume that you already have some basic audiophile knowledge, and that you have your own reasons for maintaining an audio library independent of streaming services.</p> +</blockquote> +<p>I’ve reduced it down to 3 main categories: 1. Using your phone with a dongle DAC (Digital to Analog Converter), 2. Wireless DAC (via Bluetooth), 3. Dedicated DAP. Now that I own one of each, I’d like to share my opinions on each one.</p> +<h1 id="phone-with-dongle-dac">Phone with Dongle DAC</h1> +<p>This is probably something most people are familiar with so I won’t go into too much detail.</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span><span style="color:#a6e22e">+ easy access to streaming services +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ excellent user interface (software) +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ excellent audio quality so long as you don't buy a SUPER cheap dongle +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- distractions whether from notifications or having to fiddle with app +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- drains your battery +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- dongles/cables are annoying when tethered to your phone +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- if you maintain your own music library, it will take up additional storage/use data (especially for FLACs) +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- minimal physical button media controls +</span></span></span></code></pre></div><h1 id="wireless-dac">Wireless DAC</h1> +<p>A wireless DAC is exactly what it sounds like. Rather than a traditional dongle DAC that plugs into your phone, a wireless DAC connects to your phone over Bluetooth. Your headphones/IEMs then plug into the DAC itself which is what makes it a wireless experience.</p> +<p>This effectively allows you to use any IEM or Headphone as a wireless one, and provides a largely tangle free experience since you’re free to leave the DAC in your pocket while you take your phone out to do things.</p> +<p>For reference I have the FiiO BTR7, so most of the points below will be focused on that.</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span><span style="color:#a6e22e">+ connects to phone, so easy streaming, great UI +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ largely tangle-free, you can take your phone in and out of your pockets without the dongle getting in the way +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ can also be used as a wired DAC with PC or phone +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ EQ customization, even if your phone doesn't support it software-wise +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ support for high bit-rate coding technologies (such as Sony's LDAC which supports up to 990kbps) (1) +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ drives high-impedance headphones +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- still drains your battery a lot +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- have to charge it, or else its no better than a dongle DAC +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- better physical button media controls, but for most DACs its minimal +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- can get pricey (relatively to what you are getting) +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- you still need to use data/storage whether you are streaming or listening to files +</span></span></span></code></pre></div><p><code>(1) If you're on iOS only AAC is supported, thanks Apple (250-260kbps)</code></p> +<p>This option alone has been excellent for using my IEMs on the go just for the sake of not having to fiddle with a dongle. Usually the battery life on these things are fantastic, and they last a really long time. Most streaming services also likely won’t exceed 990kbps regardless, so its not a huge compromise either.</p> +<p>The biggest caveat here is that it suffers from a lot of the same issues with battery and data/storage usage that listening from a smartphone has.</p> +<h1 id="dedicated-audio-player">Dedicated Audio Player</h1> +<p>There is a wide variety of DAPs out there. Some of them even run Android which almost makes them a phone. I’ll focus more on a budget option, that being the Snowsky Echo Mini.</p> +<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-diff" data-lang="diff"><span style="display:flex;"><span><span style="color:#a6e22e">+ distraction free listening, hassle free in terms of tangling +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ physical buttons to control media + volume +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ stores your music, doesn't take up storage +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ EQ customization +</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">+ looks cool :) +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- need to charge it or else its a brick +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- can get pricey as well, but lots of budget friendly options +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- you'll probably have to buy a micro-sd or equiv. to expand the storage on it +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- need to manually add music to it (duh...) +</span></span></span><span style="display:flex;"><span><span style="color:#f92672">- doesn't do streaming (2) +</span></span></span></code></pre></div><blockquote> +<p>Side Note</p> +<p>Depending on how expensive your DAP is it may have other limitations such as only supporting a certain bit depth or not supporting ReplayGain. If you don’t have a decently organized library this can be annoying to work around</p> +</blockquote> +<p><code>(2) Some DAPs also have the option to do music streaming, although in my opinion that largely defeats the whole purpose since it would probably be more worth it to pick up a cheap phone just for that</code></p> +<p>Another benefit of the Echo Mini is that it can also be used as a dongle DAC if necessary. The main caveat here is that you need to be good about maintaining/tagging your audio library, and of course you don’t get any audio from your phone (although that’s a plus in terms of cutting out distractions for me, if I need to take a call I’ll just use the built-in speaker as is)</p> +<h1 id="conclusion">Conclusion</h1> +<p>I find myself using my DAP the most, since it doesn’t drain my phone’s battery and has been helpful in training my patience in terms of not doomscrolling (since I literately will not be able to hear the audio). Although I do usually bring the wireless DAP along too on most days in case I want to watch a video or something. Both devices are tiny so its no big deal.</p> + + </div> + + + + + + + <section id="comments" class="webmentions"> + <h2 class="wm-title">Webmentions</h2> + <div id="mentions" class="wm-list">Loading…</div> +</section> + +<style> +.webmentions { + margin-top: 2.5rem; + padding-top: 1rem; + border-top: 2px dashed var(--hrcolor); +} + +.webmentions .wm-title { + color: var(--titlecolor); + margin-bottom: 1rem; +} + +.wm-list { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + + +.wm-reactions { + margin-bottom: 1.5rem; +} + +.wm-reaction-group { + margin-bottom: 1rem; +} + +.wm-reaction-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.wm-avatar-grid { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; +} + +.wm-avatar { + position: relative; + display: inline-block; +} + +.wm-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + border: 2px solid var(--hrcolor); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.wm-avatar:hover img { + transform: scale(1.1); + box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4); +} + +.wm-avatar-tooltip { + position: absolute; + bottom: 120%; + left: 50%; + transform: translateX(-50%); + background: var(--blockquotecolor); + color: var(--titlecolor); + padding: 4px 8px; + border-radius: 4px; + font-size: 0.8rem; + white-space: nowrap; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 10; + border: 1px solid var(--hrcolor); +} + +.wm-avatar:hover .wm-avatar-tooltip { + opacity: 1; +} + + +.wm-comments-header { + font-size: 1.1rem; + font-weight: 600; + color: var(--titlecolor); + margin-bottom: 0.5rem; + margin-top: 1rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + + +.wm-regular { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.wm { + display: flex; + gap: 0.6rem; + padding: 0.6rem 0.75rem; + border-radius: 10px; + background: var(--alertbgcolor); + border: 1px solid var(--hrcolor); + box-shadow: 0 0 6px rgba(255, 180, 220, 0.22); +} + +.wm-author img { + width: 32px; + height: 32px; + border-radius: 50%; + box-shadow: 0 0 4px rgba(255, 140, 200, 0.35); +} + +.wm-body { + flex: 1; + font-size: 0.9rem; +} + +.wm-author-name a { + font-weight: 600; + color: var(--linkcolor); +} + +.wm-type { + font-size: 0.8rem; + margin-top: 2px; + color: var(--titlecolor); +} + +.wm-content { + margin-top: 4px; + padding: 6px 8px; + font-size: 0.9rem; + background: var(--blockquotecolor); + border-left: 3px solid var(--hrcolor); + border-radius: 6px; +} + +.wm-meta { + margin-top: 3px; + font-size: 0.75rem; + opacity: 0.7; +} + +.wm-meta a { + color: var(--linkcolor); +} + + +@media (max-width: 600px) { + .wm-avatar img { + width: 32px; + height: 32px; + } + + .wm-avatar-grid { + gap: 3px; + } + + .wm-reaction-title { + font-size: 1rem; + } + + .wm-comments-header { + font-size: 1rem; + } +} +</style> + +<script> +const PAGE_URL = "https:\/\/micro.pinapelz.com\/posts\/2026-04-29-13-dac-vs-wireless-dap\/"; + +async function loadMentions() { + const url = + "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.com&token=hdjQAqlZwgJmSuPSiU8h8w"; + + const res = await fetch(url); + const data = await res.json(); + + const container = document.getElementById("mentions"); + container.innerHTML = ""; + + + const mentions = data.children.filter(m => { + const t = m["wm-target"]; + const inReply = m["in-reply-to"]; + const likeOf = m["like-of"]; + const repostOf = m["repost-of"]; + const mentionOf = m["mention-of"]; + + return ( + t === PAGE_URL || + inReply === PAGE_URL || + likeOf === PAGE_URL || + repostOf === PAGE_URL || + mentionOf === PAGE_URL + ); + }); + + if (!mentions.length) { + container.innerHTML = "<p>No webmentions yet.</p>"; + return; + } + + + const likes = mentions.filter(m => m["wm-property"] === "like-of"); + const reposts = mentions.filter(m => m["wm-property"] === "repost-of"); + const replies = mentions.filter(m => m["wm-property"] === "in-reply-to"); + const regularMentions = mentions.filter(m => + !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"]) + ); + + + const reactionsDiv = document.createElement("div"); + reactionsDiv.className = "wm-reactions"; + + + if (reposts.length > 0) { + const repostGroup = document.createElement("div"); + repostGroup.className = "wm-reaction-group"; + + const repostTitle = document.createElement("div"); + repostTitle.className = "wm-reaction-title"; + repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`; + + const repostGrid = document.createElement("div"); + repostGrid.className = "wm-avatar-grid"; + + reposts.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + repostGrid.appendChild(avatarDiv); + }); + + repostGroup.appendChild(repostTitle); + repostGroup.appendChild(repostGrid); + reactionsDiv.appendChild(repostGroup); + } + + + if (likes.length > 0) { + const likeGroup = document.createElement("div"); + likeGroup.className = "wm-reaction-group"; + + const likeTitle = document.createElement("div"); + likeTitle.className = "wm-reaction-title"; + likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`; + + const likeGrid = document.createElement("div"); + likeGrid.className = "wm-avatar-grid"; + + likes.forEach(mention => { + const author = mention.author || {}; + const avatarDiv = document.createElement("div"); + avatarDiv.className = "wm-avatar"; + + avatarDiv.innerHTML = ` + <a href="${author.url || "#"}" target="_blank"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" /> + </a> + <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div> + `; + + likeGrid.appendChild(avatarDiv); + }); + + likeGroup.appendChild(likeTitle); + likeGroup.appendChild(likeGrid); + reactionsDiv.appendChild(likeGroup); + } + + + if (reactionsDiv.children.length > 0) { + container.appendChild(reactionsDiv); + } + + + const regularMentionsToShow = [...replies, ...regularMentions]; + + if (regularMentionsToShow.length > 0) { + + const commentsHeader = document.createElement("div"); + commentsHeader.className = "wm-comments-header"; + commentsHeader.textContent = "Comments"; + container.appendChild(commentsHeader); + + const regularDiv = document.createElement("div"); + regularDiv.className = "wm-regular"; + + regularMentionsToShow.forEach(m => { + const div = document.createElement("div"); + div.className = "wm"; + + const author = m.author || {}; + const content = m.content || {}; + const type = + m["wm-property"] === "in-reply-to" ? "replied đź’¬" : + "mentioned this"; + + div.innerHTML = ` + <div class="wm-author"> + <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}"> + </div> + + <div class="wm-body"> + <div class="wm-author-name"> + <a href="${author.url || "#"}" target="_blank"> + ${author.name || "Unknown"} + </a> + </div> + + <div class="wm-type">${type}</div> + + ${content.text ? `<div class="wm-content">${content.text}</div>` : ""} + + <div class="wm-meta"> + <a href="${m.url}" target="_blank">source</a> • + ${m["wm-received"] + ? new Date(m["wm-received"]).toLocaleString() + : ""} + </div> + </div> + `; + regularDiv.appendChild(div); + }); + + container.appendChild(regularDiv); + } + + + if (container.children.length === 0) { + container.innerHTML = "<p>No webmentions yet.</p>"; + } +} + +loadMentions(); +</script> + + </article> + </main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/index.html b/micro.pinapelz.com/posts/index.html new file mode 100644 index 0000000..953da2d --- /dev/null +++ b/micro.pinapelz.com/posts/index.html @@ -0,0 +1,551 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Posts | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + <link rel="alternate" type="application/rss+xml" href="/posts/index.xml" title="micro.pinapelz.com"> + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + +<main class="content-list"> + + + <div> + + <h1> + Posts + +<a href="/posts/index.xml"><img style="height:1.5rem; display: inline;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='RSS' role='img' viewBox='0 0 512 512'%3E%3Cpath d='M0 0h512v512H0' fill='%23f80'/%3E%3Cpath d='M109 271A132 133 0 0 1 241 403h60A192 193 0 0 0 109 211v-54A246 247 0 0 1 355 403h60A306 307 0 0 0 109 97m35 235a35 35 0 1 0 2 0' fill='%23fff'/%3E%3C/svg%3E" alt="RSS icon" /></a> + + + </h1> + + + </div> + + + <div class="h-feed"> + + + + + + + + + + + </ul> + </div> + + <div> + <h3>May 2026</h3> + <ul> + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2026-05-03T03:16:09-07:00">03</time>: + + <a href="https://micro.pinapelz.com/posts/2026-04-29-13-dac-vs-wireless-dap/" class="u-url p-name title"> + Portable Audio: Phone, Wireless DAC, or DAP + </a> + </div> + </li> + + + + + + + + + + + + </ul> + </div> + + <div> + <h3>April 2026</h3> + <ul> + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2026-04-26T18:20:09-07:00">26</time>: + + <a href="https://micro.pinapelz.com/posts/2026-04-26-12-april-playlog/" class="u-url p-name title"> + Playlog: April 2026 (No Sleep for Kaname Date, Xenoblade 1 DE, Catherine Full Body) + </a> + </div> + </li> + + + + + + + + + + + + </ul> + </div> + + <div> + <h3>March 2026</h3> + <ul> + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2026-03-17T17:19:03-07:00">17</time>: + + <a href="https://micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/" class="u-url p-name title"> + Playlog: Hundred Lines Last Defense Academy + </a> + </div> + </li> + + + + + + + + + + + + </ul> + </div> + + <div> + <h3>February 2026</h3> + <ul> + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2026-02-19T19:17:04-08:00">19</time>: + + <a href="https://micro.pinapelz.com/posts/2026-02-19-10-discord-rant/" class="u-url p-name title"> + Discord Rant + </a> + </div> + </li> + + + + + + + + + + + + </ul> + </div> + + <div> + <h3>December 2025</h3> + <ul> + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-31T22:03:51-08:00">31</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-31-09-dbox-review/" class="u-url p-name title"> + DBOX Movie Seats + </a> + </div> + </li> + + + + + + + + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-19T22:15:50-08:00">19</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-19-08-ffxiv-patch-7-4/" class="u-url p-name title"> + Playlog: FFXIV Dawntrail Patch 7.4 Thoughts (spoilers) + </a> + </div> + </li> + + + + + + + + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-18T21:38:23-08:00">18</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/" class="u-url p-name title"> + Arcade Monsters + </a> + </div> + </li> + + + + + + + + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-06T22:33:23-08:00">06</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/" class="u-url p-name title"> + First MXM 18 Cleared! + </a> + </div> + </li> + + + + + + + + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-04T23:19:29-08:00">04</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-04-procon2-hid-tool/" class="u-url p-name title"> + Enable HID Mode on Nintendo Pro Controller 2 + </a> + </div> + </li> + + + + + + + + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-03T19:38:52-08:00">03</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-03-04-yt-music-rewind/" class="u-url p-name title"> + YouTube Music Recap 2025 + </a> + </div> + </li> + + + + + </ul> + </div> + </div> + + <div> + +1 of 2 + + <a href="/posts/page/2/">Next Page</a> + +</div> + +</main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> diff --git a/micro.pinapelz.com/posts/index.xml b/micro.pinapelz.com/posts/index.xml new file mode 100644 index 0000000..bf543b5 --- /dev/null +++ b/micro.pinapelz.com/posts/index.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title>Posts on micro.pinapelz.com</title> + <link>https://micro.pinapelz.com/posts/</link> + <description>Recent content in Posts on micro.pinapelz.com</description> + <generator>Hugo</generator> + <language>en-us</language> + <managingEditor>yukais@pinapelz.com (Pinapelz)</managingEditor> + <webMaster>yukais@pinapelz.com (Pinapelz)</webMaster> + <lastBuildDate>Sun, 03 May 2026 03:16:09 -0700</lastBuildDate> + <atom:link href="https://micro.pinapelz.com/posts/index.xml" rel="self" type="application/rss+xml" /> + <item> + <title>Portable Audio: Phone, Wireless DAC, or DAP</title> + <link>https://micro.pinapelz.com/posts/2026-04-29-13-dac-vs-wireless-dap/</link> + <pubDate>Sun, 03 May 2026 03:16:09 -0700</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2026-04-29-13-dac-vs-wireless-dap/</guid> + <description><p>Supposedly, there&rsquo;s been a <a href="https://www.facebook.com/APNews/videos/secondhand-sales-of-apple-ipods-are-surging-four-years-after-it-was-killed-off-w/1278247987103509/">resurgence in the popularity of the iPod</a> in the recent months for all sorts of reasons. While I&rsquo;m well aware of &ldquo;MP3 Players&rdquo;, such as the original iPod and the old Sony Walkman, these are not devices I grew up using. As a &ldquo;new-gen&rdquo; audiophile myself, getting a DAP (Dedicated Audio Player, its the new term for these sort of devices as they can play much more than just MP3s) was certainly an interesting idea. However, modern day audiophiles now have an arsenal of methods to enjoy music, even when it comes to portable playback.</p></description> + </item> + <item> + <title>Playlog: April 2026 (No Sleep for Kaname Date, Xenoblade 1 DE, Catherine Full Body)</title> + <link>https://micro.pinapelz.com/posts/2026-04-26-12-april-playlog/</link> + <pubDate>Sun, 26 Apr 2026 18:20:09 -0700</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2026-04-26-12-april-playlog/</guid> + <description><p>I&rsquo;ve gotten quite good at actually making progress on my backlog. Turns out the answer was to just uninstall all social media and get rid of doom scrolling. I invested in a rudimentary capture card as well so that I can have my Switch games show up as an application on my PC rather than having to swap display inputs (which makes it easy to get up and running for a quick session).</p></description> + </item> + <item> + <title>Playlog: Hundred Lines Last Defense Academy</title> + <link>https://micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/</link> + <pubDate>Tue, 17 Mar 2026 17:19:03 -0700</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/</guid> + <description><p>After about a year of playing on and off, I&rsquo;ve finally finished all 100 (and 1, counting the first one). In total it took roughly 105 hours or so.
<figure><img src="https://micro.pinapelz.com/posts/2026-03-17-11-hundred-lines-last-defense-playlog/playtime.png"
 alt="105 hours or more played">
</figure>
</p>
<h2 id="core-mechanics">Core Mechanics</h2>
<ul>
<li>This is basically a visual novel, there&rsquo;s very little fun to be had if you are a &ldquo;cutscene skipper&rdquo;. If you enjoyed Kodaka&rsquo;s other works like Danganronpa then you&rsquo;ll be right at home.</li>
<li>There&rsquo;s a bunch of smaller &ldquo;minigames&rdquo; but are mostly a one-off thing, they feel mostly like an afterthought (+25)</li>
</ul>
<h2 id="structure">Structure</h2>
<ul>
<li>There&rsquo;s 2 main parts of the game, the battling and the story itself</li>
<li>The battling itself has a decent amount of strategy to it, and you can in fact easily lose if you&rsquo;re not careful for some of them</li>
<li>In my opinion though given how little variety there is it kinda gets old fast, luckily the 2nd half of the game lets you skip battles you&rsquo;ve already done</li>
<li>As far as the story goes, its standard visual novel stuff but with a Kodaka twist. Each ending belongs to a particular &ldquo;route&rdquo; which is centered around a particular storyline, each one is also explicitly named in the game&rsquo;s flowchart. (+20)</li>
</ul>
<h2 id="content">Content</h2>
<ul>
<li>The story itself is quite good, but not all the routes are really worth doing if you just want what I consider to be the &ldquo;core&rdquo; of the plot. Some of them basically lead to nothing and are there just for fun.</li>
<li>Everyone has to play through <code>Last Defense Academy 1</code> which basically acts as a very long prologue for the actual game</li>
<li><strong>Not Necessary:</strong> Serial Battles Route (PLEASE skip this one, the game forces you to play unskippable battles and it forshadows literately the tiniest thing), Box of Blessings, Conspiracy (does nothing but is very quick to do), Romance, Comedy, V’ehxness Route (mainly character building), Reset Route</li>
<li>I would recommend playing through the prologue, then explicitly following a guide for the <code>Last Defense Academy 2nd Scenario</code>, then if you still want more start the S.F Route and follow a guide to unlock the pre-requisite routes while you progress through that. Everything else is largely optional IMO and is just for world-building. (12)</li>
</ul>
<h2 id="technical-execution">Technical Execution</h2>
<p>Its fine overall. You can def. tell they didn&rsquo;t have as big of a budget as Danganronpa to work with. There were some issues with leaving the game in suspense for too long on Switch but no major performance issues (+15)</p></description> + </item> + <item> + <title>Discord Rant</title> + <link>https://micro.pinapelz.com/posts/2026-02-19-10-discord-rant/</link> + <pubDate>Thu, 19 Feb 2026 19:17:04 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2026-02-19-10-discord-rant/</guid> + <description><p>We&rsquo;ve seen time and time again that there is &ldquo;no such thing as a free lunch&rdquo;. The same is true for Discord.</p>
<ol>
<li>Offer a service that is much better than all the competitors</li>
<li>Attract a bunch of users</li>
<li>Burn VC money</li>
<li>Repeat 1-3 until its time to pay them back</li>
<li>Figure out how to make money</li>
</ol>
<p>Nitro doesn&rsquo;t fund the platform, hosting free voice and screenshare is more expensive than you think. Ultimately, any choice of software for me boils down to &ldquo;what value do I get out of it&rdquo;.</p></description> + </item> + <item> + <title>DBOX Movie Seats</title> + <link>https://micro.pinapelz.com/posts/2025-12-31-09-dbox-review/</link> + <pubDate>Wed, 31 Dec 2025 22:03:51 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-31-09-dbox-review/</guid> + <description><p>There&rsquo;s a thing here in Canada where certain theaters have these special seats that rumble and move in motion with whats happening on screen.</p>
<p>I recently saw the new Avatar (Fire and Ash) in one of these seats. It wasn&rsquo;t a bad experience but given the markup, I don&rsquo;t think its worth it:</p>
<ul>
<li>First it is fun (sometimes). For example when they were flying through the air, the seat would tilt in the motion of them flying. Or when there was an explosion/gunfire, the seat would rumble</li>
<li>However, for me I think they overdid it at times, literately the seat would move and rumble for the smallest things. So it was kind of like a constant thing throughout the whole film. For me its a bit annoying</li>
<li>For the $10-15 extra (I think I paid a bit more cause the movie was also in 3D), I&rsquo;d much rather just go to a theater that has the big comfy recliner seats</li>
<li>I think for the right movie (maybe something heavy on action or horror) this could be a solid purchase if its a movie you&rsquo;re really looking forward to</li>
<li>Or I also know that some people see movies multiple times, so maybe this can be a good option for a 2nd viewing?</li>
</ul>
<p>Generally, though&hellip; I think I&rsquo;ll live without them.</p></description> + </item> + <item> + <title>Playlog: FFXIV Dawntrail Patch 7.4 Thoughts (spoilers)</title> + <link>https://micro.pinapelz.com/posts/2025-12-19-08-ffxiv-patch-7-4/</link> + <pubDate>Fri, 19 Dec 2025 22:15:50 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-19-08-ffxiv-patch-7-4/</guid> + <description><p><em>This is primarily focused on the content of the patch, not so much the features they&rsquo;ve added.</em></p>
<h1 id="story">Story</h1>
<ul>
<li>Mistwake Dungeon was a good difficulty. Although I&rsquo;m not a fan of the electricity star AOEs, very hard to read for no apparent reason. Please just stick with the old one.</li>
<li>Cutscene quality def. got better. As in animations and uniqueness.</li>
<li>Love the look and feel (Treno). There&rsquo;s a ton of good spots for &ldquo;gpose-ing&rdquo;. Music is nice too.</li>
<li>Seriously Krile? You parents were the ones who dropped you into the Source. I don&rsquo;t think they&rsquo;d care if you wanted to stay in the Source (just make up your mind) -&gt; well glad that got sorted out</li>
<li>&ldquo;Hell on Rails&rdquo; Trial (Doomtrain) is very nicely designed. Its got some nice unique mechanics, the &ldquo;sucking&rdquo; mechanic definetly trips you up the first time because the distance to move back + timing has been tuned so that you need to pre-position for it.</li>
<li>The transition from inside the engine to outside was really cool!!! This is probably one of my top normal trials now.</li>
<li>The instance battle was well done too. The roleplaying part was on point, and when it was finally time to fight a real boss you get to play as yourelf (I think this is the best flow). Love the idea using the spriggan to avoid Behemoth&rsquo;s meteor.</li>
<li>Cool so we just get to keep the key. If this were any bit realistic, we&rsquo;ve surely learned that no one this powerful should be allowed to keep the key on themsleves 24/7. Because surely the WoL being the most powerful being will never run rogue with a interdimensional travel capable tool. Then again, seeing how stuff gets stolen all the time in the story&hellip; Well I guess it can go either way.</li>
<li>I&rsquo;m guessing this key is gonna be how the writers justify being able to travel to new worlds for post-Zodiark/Hydaelyn story. Its fine I guess, but a little disappointing it isn&rsquo;t something more unique.</li>
<li>And what do you know. Ascians. I hope we get something unqiue for 8.0&hellip; I guess thats fine but please lets not have it just be SHB all over again.</li>
</ul>
<h1 id="raid">Raid</h1>
<ul>
<li>&ldquo;Feral Fandom&rdquo; -&gt; Yep thats FF14 NA playerbase for you.</li>
<li>Heavyweight 1 (Vamp Fatale) Raid was cool and unique, but a bit too flashy imo. That Half Moon is needlessly large, wish we&rsquo;d stop with mechanics that are designed to trick people even when read correctly.</li>
<li>Heavyweight 2 (Xtremes) I take it back, this is the one with the blinding effects MY EYES. Fire and water one after another. This is a pretty hard normal fight actually (the first time you run it blind). Really punishing for bad AOE placement positions since you can effectively be cut off from the team.</li>
<li>Holy wow these cutscenes are in serious need of voice acting. Its a good story but so dry and awkward without it.</li>
<li>Heavyweight 3 (Tyrant). Really? Behemoth again, double dipping from the instance battle. There&rsquo;s so many other cool FF monsters. I like the arena, it fits the guy well, all about history of the Arcadion/tradition. Fight is underwhelming and too easy imo, apart from 1 single trick mechanic that can cause a wipe&hellip;</li>
<li>Heavyweight 4 (Lindwurm). EVERYTHING BURNS. This fight was honestly too easy, zero deaths everything can be read. 2nd phase was underhelming.</li>
<li>Overall the story here while not as in depth and relevant to the story as Endwalker raids, still had a nice little twist at the end I def did not expect. Enjoyed it!</li>
</ul>
<h1 id="misc">Misc</h1>
<ul>
<li>The new Frontline map is &ldquo;dangerous&rdquo;. Overall the new capturing point system is far better than a non-interruptable interact like in Onsal Hakir. The snowman and aurora events are also good, and I think they come in right when they&rsquo;re needed too (to spice things up/allow for a turning point).</li>
<li>The map design however is far too complex, all these bridges and everywhere and invisible walls. It does add a lot of chokepoints but also makes it difficult to navigate from point A -&gt; B (but partially I guess this is done cause the map does feel smaller than Onsal).</li>
</ul>


<a href="https://micro.pinapelz.com//tags/ffxiv" class="p-category">#ffxiv</a></description> + </item> + <item> + <title>Arcade Monsters</title> + <link>https://micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/</link> + <pubDate>Thu, 18 Dec 2025 21:38:23 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-18-07-arcade-monsters-sd/</guid> + <description><p>If you live in Socal and are also into arcade gaming (both retro and modern), one of the great weekend day-trips I&rsquo;ve found is taking the Pacific Surfliner train down to San Diego.</p>
<h1 id="getting-there">Getting There</h1>
<p>There are a number of departures in the morning, and while not as fast as a car when there&rsquo;s no traffic, you can save your energy and do other stuff on the train. The timetable also works nicely since you can pretty much get there around opening if you want to beat the crowds.</p></description> + </item> + <item> + <title>First MXM 18 Cleared!</title> + <link>https://micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/</link> + <pubDate>Sat, 06 Dec 2025 22:33:23 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/</guid> + <description><p>Cleared my first 18 difficulty chart in 

<a href="https://micro.pinapelz.com//tags/sdvx" class="p-category">#sdvx</a>
</p>
<p>Albeit its not a very difficult one, but I think I&rsquo;m finally starting to chip away at the 17-18 difficulty wall.
<figure><img src="https://micro.pinapelz.com/posts/2025-12-06-first-sdvx-18/18.webp"
 alt="Sound Voltex Enchant 6 Clear" width="500">
</figure>
</p></description> + </item> + <item> + <title>Enable HID Mode on Nintendo Pro Controller 2</title> + <link>https://micro.pinapelz.com/posts/2025-12-04-procon2-hid-tool/</link> + <pubDate>Thu, 04 Dec 2025 23:19:29 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-04-procon2-hid-tool/</guid> + <description><p>Switch 2 Pro Controller is very comfy in my hands, but unfortunately it didn&rsquo;t work out of box on PC (Linux) for me like it&rsquo;s predacessor. Until there&rsquo;s actual better driver support for this thing in the kernel (or Valve does something), here&rsquo;s a hacky Python script to initialize HID-mode on the controller</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># I only tested this script on Linux w/ Steam but in theory it shoud work on Windows?</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> usb.core <span style="color:#75715e"># install pyusb first: pip install pyusb</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> usb.util
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> time
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sys
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>VENDOR_ID <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x057E</span>
</span></span><span style="display:flex;"><span>PRODUCT_IDS <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2066</span>: <span style="color:#e6db74">&#34;Joy-Con (L)&#34;</span>,
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2067</span>: <span style="color:#e6db74">&#34;Joy-Con (R)&#34;</span>,
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2069</span>: <span style="color:#e6db74">&#34;Pro Controller&#34;</span>,
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2073</span>: <span style="color:#e6db74">&#34;GCN Controller&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>USB_INTERFACE_NUMBER <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>INIT_COMMAND_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0d</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>])
</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x07 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x16 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x16</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>REQUEST_CONTROLLER_MAC <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0e</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>])
</span></span><span style="display:flex;"><span>LTK_REQUEST <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x11</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>])
</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x15_ARG_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x09 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>IMU_COMMAND_0x02 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x27</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x11 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x11</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x0A <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x14</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0x35</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x46</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>IMU_COMMAND_0x04 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x27</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>ENABLE_HAPTICS <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x10 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x10</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x01 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x0A_ALT <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">send_usb_data</span>(ep_out, ep_in, data, description<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>):
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span> ep_out<span style="color:#f92672">.</span>write(data)
</span></span><span style="display:flex;"><span> time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">0.01</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span> response <span style="color:#f92672">=</span> ep_in<span style="color:#f92672">.</span>read(<span style="color:#ae81ff">32</span>, timeout<span style="color:#f92672">=</span><span style="color:#ae81ff">100</span>)
</span></span><span style="display:flex;"><span> hex_resp <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34; &#34;</span><span style="color:#f92672">.</span>join([<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{</span>x<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#66d9ef">for</span> x <span style="color:#f92672">in</span> response])
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Response: </span><span style="color:#e6db74">{</span>hex_resp<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> e<span style="color:#f92672">.</span>errno <span style="color:#f92672">==</span> <span style="color:#ae81ff">110</span>:
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] No response (Timeout)&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Read Error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Write Error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">raise</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">set_player_leds</span>(ep_out, ep_in, led_mask):
</span></span><span style="display:flex;"><span> command <span style="color:#f92672">=</span> [
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>,
</span></span><span style="display:flex;"><span> led_mask,
</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>
</span></span><span style="display:flex;"><span> ]
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, bytes(command), <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Set LED Mask: 0x</span><span style="color:#e6db74">{</span>led_mask<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">connect_usb</span>():
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Searching for Nintendo Switch Controllers...&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">match_device</span>(dev):
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> dev<span style="color:#f92672">.</span>idVendor <span style="color:#f92672">==</span> VENDOR_ID <span style="color:#f92672">and</span> dev<span style="color:#f92672">.</span>idProduct <span style="color:#f92672">in</span> PRODUCT_IDS
</span></span><span style="display:flex;"><span> dev <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>find(custom_match<span style="color:#f92672">=</span>match_device)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> dev <span style="color:#f92672">is</span> <span style="color:#66d9ef">None</span>:
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">raise</span> <span style="color:#a6e22e">ValueError</span>(<span style="color:#e6db74">&#34;Device not found&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> product_name <span style="color:#f92672">=</span> PRODUCT_IDS<span style="color:#f92672">.</span>get(dev<span style="color:#f92672">.</span>idProduct, <span style="color:#e6db74">&#34;Unknown Device&#34;</span>)
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Found </span><span style="color:#e6db74">{</span>product_name<span style="color:#e6db74">}</span><span style="color:#e6db74"> (ID: </span><span style="color:#e6db74">{</span>dev<span style="color:#f92672">.</span>idProduct<span style="color:#e6db74">:</span><span style="color:#e6db74">04x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">)&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> dev<span style="color:#f92672">.</span>is_kernel_driver_active(USB_INTERFACE_NUMBER):
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Detaching kernel driver...&#34;</span>)
</span></span><span style="display:flex;"><span> dev<span style="color:#f92672">.</span>detach_kernel_driver(USB_INTERFACE_NUMBER)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Could not detach kernel driver: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span> dev<span style="color:#f92672">.</span>set_configuration()
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Configuration set.&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Error setting configuration: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>claim_interface(dev, USB_INTERFACE_NUMBER)
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Interface </span><span style="color:#e6db74">{</span>USB_INTERFACE_NUMBER<span style="color:#e6db74">}</span><span style="color:#e6db74"> claimed.&#34;</span>)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Could not claim interface: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span> cfg <span style="color:#f92672">=</span> dev<span style="color:#f92672">.</span>get_active_configuration()
</span></span><span style="display:flex;"><span> intf <span style="color:#f92672">=</span> cfg[(USB_INTERFACE_NUMBER,<span style="color:#ae81ff">0</span>)]
</span></span><span style="display:flex;"><span> ep_out <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>find_descriptor(
</span></span><span style="display:flex;"><span> intf,
</span></span><span style="display:flex;"><span> custom_match <span style="color:#f92672">=</span> <span style="color:#66d9ef">lambda</span> e: usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>endpoint_direction(e<span style="color:#f92672">.</span>bEndpointAddress) <span style="color:#f92672">==</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>ENDPOINT_OUT)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> ep_in <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>find_descriptor(
</span></span><span style="display:flex;"><span> intf,
</span></span><span style="display:flex;"><span> custom_match <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">lambda</span> e: usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>endpoint_direction(e<span style="color:#f92672">.</span>bEndpointAddress) <span style="color:#f92672">==</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>ENDPOINT_IN
</span></span><span style="display:flex;"><span> )
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> ep_out:
</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">&#34;Could not find OUT endpoint&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Found Endpoint OUT: 0x</span><span style="color:#e6db74">{</span>ep_out<span style="color:#f92672">.</span>bEndpointAddress<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Starting Initialization Sequence...&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, INIT_COMMAND_0x03, <span style="color:#e6db74">&#34;Init 0x03&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x07, <span style="color:#e6db74">&#34;Unknown 0x07&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x16, <span style="color:#e6db74">&#34;Unknown 0x16&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, REQUEST_CONTROLLER_MAC, <span style="color:#e6db74">&#34;Req MAC&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, LTK_REQUEST, <span style="color:#e6db74">&#34;Req LTK&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x15_ARG_0x03, <span style="color:#e6db74">&#34;Unknown 0x15&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x09, <span style="color:#e6db74">&#34;Unknown 0x09&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, IMU_COMMAND_0x02, <span style="color:#e6db74">&#34;IMU 0x02&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x11, <span style="color:#e6db74">&#34;OUT Unknown 0x11&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x0A, <span style="color:#e6db74">&#34;Unknown 0x0A&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, IMU_COMMAND_0x04, <span style="color:#e6db74">&#34;IMU 0x04&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, ENABLE_HAPTICS, <span style="color:#e6db74">&#34;Enable Haptics&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x10, <span style="color:#e6db74">&#34;OUT Unknown 0x10&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x01, <span style="color:#e6db74">&#34;OUT Unknown 0x01&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x03, <span style="color:#e6db74">&#34;OUT Unknown 0x03&#34;</span>)
</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x0A_ALT, <span style="color:#e6db74">&#34;OUT Unknown 0x0A Alt&#34;</span>)
</span></span><span style="display:flex;"><span> set_player_leds(ep_out, ep_in, <span style="color:#ae81ff">0x0F</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Controller initialization sequence complete! All LEDs should be on.&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Error during sequence: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span> connect_usb()
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">ValueError</span> <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> print(e)
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e:
</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Unexpected error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
</span></span></code></pre></div><p><strong>Steps</strong></p></description> + </item> + <item> + <title>YouTube Music Recap 2025</title> + <link>https://micro.pinapelz.com/posts/2025-12-03-04-yt-music-rewind/</link> + <pubDate>Wed, 03 Dec 2025 19:38:52 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-03-04-yt-music-rewind/</guid> + <description><p>Its all Bandori. At least 75% of that MyGO!!!!! listening time was probably Haruhikage since I came back to Bandori and had to catch up before watching Ave Mujica anime.</p>
<figure><img src="https://files.catbox.moe/tsquqc.jpg"
 alt="YouTube Music Recap Top 5 Artists In Order: MyGO!!!!!, Yumenokessho, Ave Mujica, KMNZ, Roselia" width="300">
</figure></description> + </item> + <item> + <title>INIU Power Bank Gets Recall</title> + <link>https://micro.pinapelz.com/posts/2025-12-02-power-bank-recall/</link> + <pubDate>Tue, 02 Dec 2025 19:45:01 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-02-power-bank-recall/</guid> + <description><p>It would seem that I, along with what seems like the entirety of <a href="https://www.reddit.com/r/amazonprime/comments/1pcq5ug/how_to_get_customer_support_for_recall_iniu/">Reddit</a> bought the same cheap 10000mAh power bank and now its getting recalled.</p>
<p>I wonder if it has anything to do with the poor quality they found in that viral <a href="https://www.lumafield.com/first-article/posts/whats-hiding-inside-haribos-power-bank-and-headphones">Haribo Powerbank</a>. Not sure since I&rsquo;ve had this one for a long time. I guess I really got what I paid for, shame cause it really is super slim and works well.</p></description> + </item> + <item> + <title>China Town Fair</title> + <link>https://micro.pinapelz.com/posts/2025-12-02-china-town-fair/</link> + <pubDate>Tue, 02 Dec 2025 00:22:32 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-02-china-town-fair/</guid> + <description><p>Visited New York during the Thanksgiving break and had a chance to stopped by one of the most legendary landmarks North American arcade gaming history.</p>
<figure><img src="https://micro.pinapelz.com/posts/2025-12-02-china-town-fair/outside-ctf.webp"
 alt="China Town Fair Outside">
</figure>

<p>Also yep you&rsquo;re reading that right, it indeed once home to a <a href="https://davidpotorti.substack.com/p/the-dancing-chicken">dancing chicken as well as one that played tic tac toe</a>.</p>
<p>But apart from just being an old arcade, it was also home to one of the largest competitive arcade game fighting scene (Marvel vs Capcom, Street Fighter, etc.). Many of NAs top players frequented this arcade. However, as we all already know video arcades began to die down during the early 2000s and China Town Fair was no exception having closed in 2011.</p></description> + </item> + <item> + <title>Hello World - Why This</title> + <link>https://micro.pinapelz.com/posts/2025-12-01-hello-world/</link> + <pubDate>Mon, 01 Dec 2025 20:11:57 -0800</pubDate><author>yukais@pinapelz.com (Pinapelz)</author> + <guid>https://micro.pinapelz.com/posts/2025-12-01-hello-world/</guid> + <description><p>I think having control of your own data is great. The same is true for decentralized social media. I&rsquo;ve always been a primary user of microblog platforms (like Twitter/X). Having experienced both the traditional and &ldquo;decentralized&rdquo; approaches to microblogs, they both have some particular shortcoming in terms of what I want to get out of &ldquo;social media&rdquo;.</p>
<h2 id="twitterx">Twitter/X</h2>
<p>This is fairly self explanatory. The rebranding of Twitter to X and Musk&rsquo;s new ownership of the platform shifted the direction of the platform to be ever more political. X Premium boosting visibility is also something I wasn&rsquo;t a particular fan of. You can&rsquo;t view anything without signing in either, so goodbye viewing stuff anonymously. There&rsquo;s just a lot of &ldquo;features&rdquo; here I&rsquo;m not a fan of. Needless to say, there&rsquo;s a lot of reasons to not post stuff there.</p></description> + </item> + </channel> +</rss> diff --git a/micro.pinapelz.com/posts/page/1/index.html b/micro.pinapelz.com/posts/page/1/index.html new file mode 100644 index 0000000..803dfa8 --- /dev/null +++ b/micro.pinapelz.com/posts/page/1/index.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html lang="en-us"> + <head> + <title>https://micro.pinapelz.com/posts/</title> + <link rel="canonical" href="https://micro.pinapelz.com/posts/"> + <meta charset="utf-8"> + <meta http-equiv="refresh" content="0; url=https://micro.pinapelz.com/posts/"> + </head> +</html> diff --git a/micro.pinapelz.com/posts/page/2/index.html b/micro.pinapelz.com/posts/page/2/index.html new file mode 100644 index 0000000..ff3e49b --- /dev/null +++ b/micro.pinapelz.com/posts/page/2/index.html @@ -0,0 +1,238 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <style type=text/css>body{font-family:monospace;}</style> + <title>Posts | micro.pinapelz.com</title> + + <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]"> + <link rel="stylesheet" href="/css/style.css"> + <link rel="alternate" type="application/rss+xml" href="/posts/index.xml" title="micro.pinapelz.com"> + + + <link rel="me" href="https://github.com/pinapelz" /> + <link rel="me" href="mailto:yukais@pinapelz.com" /> + <link rel="me" href="https://sakurajima.social/@pinapelz" /> + <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc"> + <link + rel="authorization_endpoint" + href="https://indieauth.com/auth" + /> + <link + rel="token_endpoint" + href="https://tokens.indieauth.com/token" + /> + <link rel="webmention" href="https://webmention.io/micro.pinapelz.com/webmention" /> + + + +</head> +<body> + <header> + <div style="display:flex;flex-flow:row wrap;justify-content:space-between"> + <div style="align-self:flex-start;"> + ==============<br> + == <a href="https://micro.pinapelz.com/">Pinapelz</a> ==<br> + ============== + </div> + <div style="align-self:center;">check it out. I'm in the house like carpet</div> + </div> + <nav style="margin: 1rem auto;"> + + + <a href="/posts/"><b>Posts</b></a>. + + <a href="/categories/"><b>Categories</b></a>. + + <a href="/tags/"><b>Tags</b></a>. + + + </nav> +</header> + + +<main class="content-list"> + + + <div> + + <h1> + Posts + +<a href="/posts/index.xml"><img style="height:1.5rem; display: inline;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='RSS' role='img' viewBox='0 0 512 512'%3E%3Cpath d='M0 0h512v512H0' fill='%23f80'/%3E%3Cpath d='M109 271A132 133 0 0 1 241 403h60A192 193 0 0 0 109 211v-54A246 247 0 0 1 355 403h60A306 307 0 0 0 109 97m35 235a35 35 0 1 0 2 0' fill='%23fff'/%3E%3C/svg%3E" alt="RSS icon" /></a> + + + </h1> + + + </div> + + + <div class="h-feed"> + + + + + + + + + + + </ul> + </div> + + <div> + <h3>December 2025</h3> + <ul> + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-02T19:45:01-08:00">02</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-02-power-bank-recall/" class="u-url p-name title"> + INIU Power Bank Gets Recall + </a> + </div> + </li> + + + + + + + + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-02T00:22:32-08:00">02</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-02-china-town-fair/" class="u-url p-name title"> + China Town Fair + </a> + </div> + </li> + + + + + + + + + + <li class="h-entry"> + <div hidden> + <div class="h-card p-author bio-card" style="text-align:center;"> + + <div class="banner" style="margin-bottom: 1rem; position: relative;"> + <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;"> + <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"> + </div> + + <div class="bio"> + <p class="p-note">yo! and he's more than a cover he's a quilt<br/> + General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/> + Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/> + I Watch only slice of life (and Bandori)<br/> + Arch Linux + Hyprland user (btw)<br/> + Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p> + </div> + <p class="bio-name"><a href="https://micro.pinapelz.com/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p> +</div> +<hr/> + + </div> + <div class="post-title"> + <time class="date dt-published" datetime="2025-12-01T20:11:57-08:00">01</time>: + + <a href="https://micro.pinapelz.com/posts/2025-12-01-hello-world/" class="u-url p-name title"> + Hello World - Why This + </a> + </div> + </li> + + + + + </ul> + </div> + </div> + + <div> + + <a href="/posts/">Previous Page</a> + +2 of 2 + +</div> + +</main> + + <hr /> +<footer> + <p> + <a href="https://github.com/pinapelz"><b>Github</b></a>. + <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>. + </p> + + + + <p style="text-align: center" class="copyright"> + © <a href="https://micro.pinapelz.com/"><b>micro.pinapelz.com</b></a>. + </p> +</footer> + +</body> +</html> |
