Code for https://gm112.neocities.org/ gm112.neocities.org/

content: add more content for 2026-02-27 post feat: add navigation between pages fix: address theme issues #5 chore: cleanup styles chore: remove unnecessary prose components #1

merged opened by gm112.bsky.social targeting main from content/2026-02-27
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:lemtcfd5mbsbbvw3zl5eq2e6/sh.tangled.repo.pull/3mfqc655osf22
+317 -185
Diff #0
+49 -1
app/app.config.ts
··· 16 16 link: { 17 17 variants: { 18 18 active: { 19 - false: 'text-zelda-alttp-triforce-gold-500 hover:text-zelda-alttp-triforce-gold-500', 19 + false: 'text-zelda-alttp-triforce-gold hover:text-alttp-white', 20 20 }, 21 21 }, 22 22 compoundVariants: [ ··· 68 68 }, 69 69 }, 70 70 }, 71 + prose: { 72 + a: { 73 + base: 'text-zelda-alttp-triforce-gold hover:text-zelda-alttp-triforce-gold-50', 74 + }, 75 + h1: { 76 + slots: { 77 + base: 'text-[64px] font-normal', 78 + }, 79 + }, 80 + h2: { 81 + slots: { 82 + base: 'text-[48px] font-normal', 83 + leading: 'top-5.5', 84 + }, 85 + }, 86 + h3: { 87 + slots: { 88 + base: 'text-[32px] font-normal', 89 + leading: 'top-2 ', 90 + }, 91 + }, 92 + 93 + pre: { 94 + slots: { 95 + filename: 'text-base', 96 + }, 97 + }, 98 + 99 + code: { 100 + base: 'alttp-text text-base font-normal', 101 + variants: { 102 + color: { 103 + primary: 'text-alttp-white', 104 + }, 105 + }, 106 + }, 107 + 108 + codeGroup: { 109 + slots: { 110 + trigger: 'text-base alttp-text', 111 + }, 112 + }, 113 + codeCollapse: { 114 + slots: { 115 + trigger: 'text-base', 116 + }, 117 + }, 118 + }, 71 119 }, 72 120 })
+10
app/assets/components/border-alttp.css
··· 1 + .border-alttp { 2 + border-image-source: url('/images/sprites/alttp-textbox-css-sprite.png'); 3 + border-image-slice: 7 6; 4 + border-image-width: 21px 18px; 5 + border-image-repeat: stretch; 6 + border-style: solid; 7 + border-width: 21px 18px; 8 + image-rendering: crisp-edges; 9 + image-rendering: pixelated; 10 + }
+43
app/assets/components/text-alttp.css
··· 1 + .alttp-text { 2 + font-family: 'alttp', serif; 3 + color: var(--color-alttp-white); 4 + 5 + image-rendering: crisp-edges; 6 + image-rendering: pixelated; 7 + -webkit-font-smoothing: none; 8 + font-smooth: never; 9 + 10 + text-shadow: 11 + var(--ui-alttp-text-drop-shadow-size-neg) 0 var(--ui-alttp-text-shadow-color), 12 + var(--ui-alttp-text-drop-shadow-size) 0 var(--ui-alttp-text-shadow-color), 13 + 0 var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-shadow-color), 14 + 0 var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-shadow-color), 15 + var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size-neg) 16 + var(--ui-alttp-text-shadow-color), 17 + var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size-neg) 18 + var(--ui-alttp-text-shadow-color), 19 + var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size) 20 + var(--ui-alttp-text-shadow-color), 21 + var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size) 22 + var(--ui-alttp-text-shadow-color); 23 + 24 + & > ::selection { 25 + text-shadow: 26 + var(--ui-alttp-text-drop-shadow-size-neg) 0 var(--ui-alttp-text-shadow-color), 27 + var(--ui-alttp-text-drop-shadow-size) 0 var(--ui-alttp-text-shadow-color), 28 + 0 var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-shadow-color), 29 + 0 var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-shadow-color), 30 + var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size-neg) 31 + var(--ui-alttp-text-shadow-color), 32 + var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size-neg) 33 + var(--ui-alttp-text-shadow-color), 34 + var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size) 35 + var(--ui-alttp-text-shadow-color), 36 + var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size) 37 + var(--ui-alttp-text-shadow-color); 38 + } 39 + 40 + & :where(code) { 41 + @apply text-shadow-none selection:text-shadow-none; 42 + } 43 + }
+12
app/assets/components/triforce-cursor.css
··· 1 + .cursor::after { 2 + content: 'โ–ผ'; 3 + animation: blink 0.8s step-start infinite; 4 + margin-left: 0.25rem; 5 + color: var(--color-zelda-alttp-triforce-gold-500); 6 + } 7 + 8 + .cursor:hover { 9 + &::after { 10 + color: var(--ui-text-muted); 11 + } 12 + }
+49 -117
app/assets/main.css
··· 1 1 @import 'tailwindcss' theme(static); 2 2 @import '@nuxt/ui'; 3 - @import './animations/rotate.css'; 4 - @import './animations/blink.css'; 5 3 6 4 @theme static { 5 + --color-zelda-alttp-triforce-gold: oklch(88.805% 0.18375 98.426); 6 + --color-zelda-alttp-triforce-gold-50: oklch(96.262% 0.08423 100.53); 7 + --color-zelda-alttp-triforce-gold-100: oklch(95.496% 0.10611 101.23); 8 + --color-zelda-alttp-triforce-gold-200: oklch(93.726% 0.14167 100.89); 9 + --color-zelda-alttp-triforce-gold-300: oklch(92.35% 0.16808 100.65); 10 + --color-zelda-alttp-triforce-gold-400: oklch(91.137% 0.18324 99.835); 11 + --color-zelda-alttp-triforce-gold-500: oklch(88.805% 0.18375 98.426); 12 + --color-zelda-alttp-triforce-gold-600: oklch(73.431% 0.15199 98.538); 13 + --color-zelda-alttp-triforce-gold-700: oklch(57.198% 0.11845 98.731); 14 + --color-zelda-alttp-triforce-gold-800: oklch(39.696% 0.08231 99.146); 15 + --color-zelda-alttp-triforce-gold-900: oklch(19.883% 0.04143 100.69); 16 + --color-zelda-alttp-triforce-gold-950: oklch(0% 0 none); 17 + 18 + --color-alttp-white: oklch(97.913% 0 none); 19 + --color-alttp-white-50: oklch(100% 0 none); 20 + --color-alttp-white-100: oklch(100% 0 none); 21 + --color-alttp-white-200: oklch(100% 0 none); 22 + --color-alttp-white-300: oklch(100% 0 none); 23 + --color-alttp-white-400: oklch(100% 0 none); 24 + --color-alttp-white-500: oklch(97.913% 0 none); 25 + --color-alttp-white-600: oklch(89.449% 0 none); 26 + --color-alttp-white-700: oklch(80.78% 0 none); 27 + --color-alttp-white-800: oklch(71.871% 0 none); 28 + --color-alttp-white-900: oklch(62.675% 0 none); 29 + --color-alttp-white-950: oklch(57.951% 0 none); 30 + 7 31 --font-sans: 'alttp', 'Comic Sans MS', sans-serif; 8 32 --font-serif: 'alttp', 'Comic Sans MS', serif; 9 33 --ui-radius: 0rem; 10 - --ui-primary: var(--ui-color-blue-400); 11 - --ui-alttp-text-drop-shadow-size: 0.0625rem; 12 - --ui-alttp-text-drop-shadow-size-neg: -0.0625rem; 13 - --ui-alttp-text-shadow-color: #000071; 14 34 15 - --color-zelda-alttp-triforce-gold-50: #feffe7; 16 - --color-zelda-alttp-triforce-gold-100: #fcffc1; 17 - --color-zelda-alttp-triforce-gold-200: #fdff86; 18 - --color-zelda-alttp-triforce-gold-300: #fffa41; 19 - --color-zelda-alttp-triforce-gold-400: #ffed0d; 20 - --color-zelda-alttp-triforce-gold-500: #fada00; 21 - --color-zelda-alttp-triforce-gold-600: #d1a400; 22 - --color-zelda-alttp-triforce-gold-700: #a67602; 23 - --color-zelda-alttp-triforce-gold-800: #895c0a; 24 - --color-zelda-alttp-triforce-gold-900: #744b0f; 25 - --color-zelda-alttp-triforce-gold-950: #442704; 35 + --ui-alttp-text-drop-shadow-size: 1px; 36 + --ui-alttp-text-drop-shadow-size-neg: -1px; 37 + --ui-alttp-text-shadow-color: #000071; 26 38 } 27 39 28 40 @layer theme { 29 41 .light { 30 - --ui-primary: var(--ui-color-primary-400); 31 42 --ui-bg: var(--ui-color-primary-800); 32 43 --ui-bg-muted: oklch(from var(--ui-primary) calc(l - 0.5) c h / 0.5); 33 44 --ui-bg-elevated: var(--color-primary-900); 34 45 --ui-bg-accented: var(--color-primary-950); 35 46 --ui-bg-inverted: var(--color-primary-100); 36 47 37 - --ui-text: var(--color-neutral-100); 38 - --ui-text-muted: var(--color-neutral-300); 39 - --ui-text-highlighted: var(--color-neutral-100); 48 + --ui-text: var(--color-alttp-white); 49 + --ui-text-muted: var(--color-alttp-white-700); 50 + --ui-text-highlighted: var(--color-alttp-white-50); 40 51 } 41 52 42 53 .dark { ··· 57 68 ::selection { 58 69 background-color: var(--ui-primary); 59 70 } 71 + 72 + pre > code ::selection { 73 + background-color: var(--ui-bg-elevated); 74 + } 60 75 } 61 76 62 77 @layer base { 63 - :root { 78 + :root, 79 + :host, 80 + body { 64 81 scrollbar-width: thin; 65 82 scrollbar-gutter: stable; 66 - } 67 - 68 - body { 69 - @apply subpixel-antialiased; 70 - } 71 - 72 - pre > code { 73 - @apply text-shadow-none selection:text-shadow-none; 74 - } 75 - } 76 - 77 - @layer utilities { 78 - .alttp-text { 79 - font-family: 'alttp', serif; 80 - color: #f8f8f8; 81 - 82 - image-rendering: crisp-edges; 83 + text-rendering: optimizeSpeed; 83 84 image-rendering: pixelated; 84 85 -webkit-font-smoothing: none; 86 + -moz-osx-font-smoothing: none; 85 87 font-smooth: never; 86 - 87 - text-shadow: 88 - var(--ui-alttp-text-drop-shadow-size-neg) 0 var(--ui-alttp-text-shadow-color), 89 - var(--ui-alttp-text-drop-shadow-size) 0 var(--ui-alttp-text-shadow-color), 90 - 0 var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-shadow-color), 91 - 0 var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-shadow-color), 92 - var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size-neg) 93 - var(--ui-alttp-text-shadow-color), 94 - var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size-neg) 95 - var(--ui-alttp-text-shadow-color), 96 - var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size) 97 - var(--ui-alttp-text-shadow-color), 98 - var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size) 99 - var(--ui-alttp-text-shadow-color); 100 - 101 - & > ::selection { 102 - text-shadow: 103 - var(--ui-alttp-text-drop-shadow-size-neg) 0 var(--ui-alttp-text-shadow-color), 104 - var(--ui-alttp-text-drop-shadow-size) 0 var(--ui-alttp-text-shadow-color), 105 - 0 var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-shadow-color), 106 - 0 var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-shadow-color), 107 - var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size-neg) 108 - var(--ui-alttp-text-shadow-color), 109 - var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size-neg) 110 - var(--ui-alttp-text-shadow-color), 111 - var(--ui-alttp-text-drop-shadow-size-neg) var(--ui-alttp-text-drop-shadow-size) 112 - var(--ui-alttp-text-shadow-color), 113 - var(--ui-alttp-text-drop-shadow-size) var(--ui-alttp-text-drop-shadow-size) 114 - var(--ui-alttp-text-shadow-color); 115 - } 116 - } 117 - 118 - .cursor::after { 119 - content: 'โ–ผ'; 120 - animation: blink 0.8s step-start infinite; 121 - margin-left: 0.25rem; 122 - color: var(--color-zelda-alttp-triforce-gold-500); 123 - } 124 - 125 - .cursor:hover { 126 - &::after { 127 - color: var(--ui-text-muted); 128 - } 129 88 } 89 + } 130 90 131 - .border-alttp { 132 - border-image-source: url('/images/sprites/alttp-textbox-css-sprite.png'); 133 - border-image-slice: 7 6; 134 - border-image-width: 21px 18px; 135 - border-image-repeat: stretch; 136 - border-style: solid; 137 - border-width: 21px 18px; 138 - image-rendering: crisp-edges; 139 - image-rendering: pixelated; 140 - } 141 - 142 - .font-no-smoothing { 143 - text-rendering: optimizeSpeed; 144 - image-rendering: pixelated; 145 - } 146 - 147 - /* 148 - This is a little hacky, but it works. 149 - 150 - ContentSurround expects you use an icon, but we're not and we're using 151 - an image instead. 152 - */ 153 - .link-da-flute-boi-img { 154 - background: url('/images/link-da-flute-boi.png') no-repeat; 155 - background-color: initial; 156 - background-size: contain; 157 - width: 100px; 158 - height: 156px; 159 - mask-image: none; 160 - -webkit-mask-image: none; 161 - 162 - &:where(.i-lucide\:arrow-left) { 163 - transform: scaleX(-1); 164 - } 165 - } 91 + @layer utilities { 92 + @import './animations/rotate.css'; 93 + @import './animations/blink.css'; 94 + @import './components/triforce-cursor.css'; 95 + @import './components/border-alttp.css'; 96 + @import './components/img-link-da-flute-boi.css'; 97 + @import './components/text-alttp.css'; 166 98 }
-23
app/components/content/ProseA.vue
··· 1 - <template> 2 - <u-link :href="props.href" :target="props.target" :attrs="$attrs"> 3 - <slot /> 4 - </u-link> 5 - </template> 6 - 7 - <script setup lang="ts"> 8 - import type { PropType } from 'vue' 9 - 10 - const props = defineProps({ 11 - href: { 12 - type: String, 13 - default: '', 14 - }, 15 - target: { 16 - type: String as PropType< 17 - '_blank' | '_parent' | '_self' | '_top' | (string & object) | null | undefined 18 - >, 19 - default: undefined, 20 - required: false, 21 - }, 22 - }) 23 - </script>
-3
app/components/content/ProseImg.vue
··· 1 - <template> 2 - <nuxt-img v-bind="$attrs" /> 3 - </template>
+1 -1
app/pages/[...slug].vue
··· 13 13 <content-renderer :value="page" class="grow-0 w-full sm:px-6" /> 14 14 </div> --> 15 15 <post-toc :page="page" /> 16 - <content-renderer :value="page" class="grow-0 w-full sm:px-6" /> 16 + <content-renderer :value="page" class="sm:px-6 overflow-wrap" /> 17 17 <u-content-surround :surround="surroundings" class="border-alttp bg-black" /> 18 18 </post-detail> 19 19 <u-skeleton v-else class="flex-1" />
+2 -2
app/pages/list.vue
··· 28 28 <span class="py-2">{{ format_date(post.date) }} - {{ post.title }}</span> 29 29 </div> 30 30 </u-link> 31 - <div class="border-alttp bg-black" v-if="post.meta.excerpt"> 32 - <content-renderer :value="post.meta.excerpt" :excerpt="true" /> 31 + <div class="border-alttp bg-black" v-if="post.excerpt"> 32 + <content-renderer :value="post.excerpt" :excerpt="true" /> 33 33 <u-link :to="post.path" prefetch-on="interaction"> 34 34 <div class="alttp-text cursor hover:text-muted text-base"> 35 35 <span>{{ t('posts.go_to_post') }}</span>
+8 -1
content.config.ts
··· 3 3 4 4 const schema = v.object({ 5 5 title: v.string(), 6 + excerpt: v.optional( 7 + v.object({ 8 + type: v.string(), 9 + children: v.optional(v.unknown()), 10 + value: v.optional(v.array(v.unknown())), 11 + }), 12 + ), 6 13 description: v.string(), 7 14 date: v.string(), 8 15 time: v.string(), 9 16 time_zone: v.string(), 10 - encrypted: v.boolean(), 17 + encrypted: v.optional(v.boolean()), 11 18 }) 12 19 13 20 export default defineContentConfig({
+113 -37
content/blog/en/2026-02-27.md
··· 18 18 ### MG-Zero and gm112 combine their half-braincells together to form one braincell 19 19 20 20 During a conversation with Steve, we had talked about Ocarina of Time 2D and how 21 - nice it would have been to do a panel on it. That discussion evolved into a 22 - project that went down a rabbit hole of learning how to make a game on the 23 - Game Boy. The idea was to make an Ocarina of Time 2D demo that would 24 - play into the hopelessness of Demo 4 (I will write an article about this later). 21 + nice it would have been to do a panel on it. To give a spotlight to the community 22 + of where OoT2D was born. That discussion evolved into a project that went down 23 + a rabbit hole of learning how to make a game on the Game Boy. The idea was to 24 + make an Ocarina of Time 2D demo that would play into the hopelessness 25 + of Demo 4 (I will write an article about this later). 26 + 27 + Thankfully, I had already had been helping another friend of mine, Aaron, 28 + with theirown Game Boy project, Dearborn, which has a similar playstyle to 29 + 2D Zeldas. 25 30 26 - Thankfully, I had already had been helping another friend of mine with their 27 - own Game Boy project, Dearborn, which has a similar playstyle to 2D Zeldas. 28 31 Aaron had been working on Dearborn, and then reached out to me to help with 29 32 developing the game. Since we were in pre-production, we experimented with 30 33 a couple of different ideas. One was a turned based combat system demo, which ··· 59 62 60 63 ### Figuring out the audio situation 61 64 62 - For streaming the audio, originally I had written a simple bash script that 63 - converted the WAV files into a C array. And then, I wrote a function that 64 - DMA'd the array into the APU's Channel 3 effectively. The first atttempts 65 - at this did not work, due to timing issues, logic that was too dumb, and 66 - honestly I had no idea what I was doing. Ultimately, I decided to try 67 - using GBVM's sound fx functions, seeing that it had a 3 second limitation. 68 - It seemed if you timed it right, you could queue up multiple samples of 69 - sounds and chain together a complete song! At this point, there was 70 - no optimization, so the CPU was spent entirely on sending these commands. 71 - Luckily, most of that time was spent idling, so it was simple enough to 72 - move the commands into a GBVM script that ran on a separate "thread" that 73 - instead no-ops. At this point, it was possible for the player to interact 74 - with the game while they were being rick rolled. \:D 75 - 76 - TOOD: Rework this section, and talk about setting up the audio. 77 - 78 - <details class="bg-info p-4"> 79 - <summary>Click to see code! \:D</summary> 80 - 81 - ```asm 65 + [GB Studio](https://www.gbstudio.dev/docs/assets/sound-effects/) noted 66 + that audio had to be formatted a certain way. Using [yt-dlp](https://github.com/yt-dlp/yt-dlp){target="\_blank"} 67 + and [ffmpeg](https://www.ffmpeg.org/){target="\_blank"} from the 68 + AUR and started with a script to generate the WAV files. 69 + 70 + ::code-collapse 71 + 72 + ::code-group{name="Click to see code! :D"} 73 + 74 + ```bash [convert.sh] 75 + #!/usr/bin/env bash 76 + set -e 77 + 78 + INPUT="$1" 79 + OUTDIR="$2" 80 + 81 + if [[ -z "$INPUT" || -z "$OUTDIR" ]]; then 82 + echo "Usage: $0 input.webm output_dir" 83 + exit 1 84 + fi 85 + 86 + mkdir -p "$OUTDIR" 87 + 88 + ffmpeg -i "$INPUT" \ 89 + -filter_complex "\ 90 + [0:a]\ 91 + dcshift=0,\ 92 + pan=mono|c0=0.5*c0+0.5*c1,\ 93 + highpass=60,\ 94 + lowpass=3300,\ 95 + equalizer=f=400:t=q:w=1:g=-1.5,\ 96 + equalizer=f=1200:t=q:w=1:g=1.2,\ 97 + equalizer=f=1800:t=q:w=1:g=1.8,\ 98 + equalizer=f=2500:t=q:w=1:g=-3.2,\ 99 + volume=3.0\ 100 + [aud]; \ 101 + anoisesrc=color=white:amplitude=0.0007 \ 102 + [noise]; \ 103 + [aud][noise]amix=inputs=2:weights=1 0.15:duration=shortest,\ 104 + alimiter=limit=0.86\ 105 + [out]" \ 106 + -map "[out]" \ 107 + -ac 1 \ 108 + -ar 8000 \ 109 + -c:a pcm_u8 \ 110 + -f segment \ 111 + -segment_time 3 \ 112 + -reset_timestamps 1 \ 113 + "$OUTDIR/never-gonna-give-you-up-%03d.wav" 114 + ``` 115 + 116 + ```bash [output.log] 117 + ls -1 | wc -l 118 + 119 + # 72 120 + ``` 121 + 122 + :: 123 + 124 + :: 125 + 126 + With around 72 output files, I removed 3 of them and replaced the last 127 + one with a silence file. The next step was to see if we could playback the wave 128 + files. My first attempt involved queuing up two GBVM `VM_SFX_PLAY` commands, 129 + which didn't work on its own. Then I tried using a C-style array, and manually 130 + using a DMA transfer to the APU's Channel 3. This worked, but my implementation 131 + stole the CPU. 132 + 133 + Going back to the drawing board, I felt the `VM_SFX_PLAY` approach could work. 134 + Being the simpleton I am, I remembered that for the demo, I implemented a 135 + function that played back a sound effect on the noise channel on a separate 136 + script thread for a sword swing sound. 137 + 138 + If that worked, then surely I could do the same thing, except with many WAV files! 139 + 140 + ::code-collapse 141 + 142 + ```asm [rick-roll.asm] 82 143 .macro PLAY_WAIT bank, snd, mask 83 144 VM_SFX_PLAY bank, snd, mask, .SFX_PRIORITY_NORMAL 84 145 VM_SET_CONST 0, 174 ··· 95 156 VM_RET_FAR 96 157 ``` 97 158 98 - </details> 159 + :: 99 160 100 161 This bone headed bit of code was stuffed into a GBVM Script in the project file, 101 162 and thankfully it was good enough to handle playback. Shoutouts to the GBVM and 102 163 GB Studio developers for making this possible! Psst. See if you can find the 103 164 hidden easter egg in the ROM or code! 104 165 166 + At this point I began testing in other emulators. 167 + 168 + ### Emulator Accuracy 169 + 170 + This has to be called out, but upon realizing that I might have a problem with 171 + audio playback on hardware, I resorted to testing the ROM on multiple emulators. 172 + Up until this point, I had used [SkyEmu](https://skyemu.app/){target="\_blank"} 173 + for testing. But, it seems every other emulator I tried, had issues with audio 174 + playback. Audio pops, no playback, etc, it felt like maybe I was walking into a 175 + brick wall once I tried this on a real Game Boy. Many hours and nights were 176 + spent trying to figure out what was going on. 177 + 178 + At this point my shipment of flashcarts had arrived, and I was able to test the 179 + ROM on real hardware, and all seemed well! At this point, I wrote off the audio 180 + issues in other emulators as something that's just out of scope to deal with, 181 + especially given the simple approach to playing back Rick Astley's "Never Gonna 182 + Give You Up". ;p 183 + 105 184 ### Departing 106 185 107 186 A few months pass... ··· 158 237 things, and also the people who were rooming with us at the hotel! Everyone was 159 238 chill. 160 239 161 - TODO: Finish this section. 240 + We made it to the hotel room, and I plopped on the bed and busted 241 + out the goods. >: ) 162 242 163 243 ### Flashing Game Boy Carts 164 244 245 + Because of missing some of the object data, I decided 246 + to scrap Kikori Forest, the Great Deku Tree, and just make a simple 247 + single room for the rick roll. After fiddling with the scene script, 248 + a ROM flashing extravaganza happened! haha 249 + 165 250 ![Flashing Game Boy Carts with my best bud MG-Zero](/images/content/2026-02-27/IMG_4228.webp){ 166 251 fit="cover" 167 252 quality="90" ··· 172 257 loading="lazy" 173 258 } 174 259 175 - We made it to the hotel room, and I plopped on the bed and busted 176 - out the goods. >: ) Because of missing some of the object data, I decided 177 - to scrap Kikori Forest, the Great Deku Tree, and just make a simple 178 - single room for the rick roll. 179 - 180 - TODO: Finish this section 181 - 182 260 ## Unleashing Rick Astley onto MAGFest 183 261 184 - ## The Rick Roll 185 - 186 262 To describe the rick roll, essentially just imagine a legitimate 187 263 startup sequence that hits you with an 8-bit rendering of the raw 188 264 waveforms of Rick Astley's "Never Gonna Give You Up". Haha, with
+1
package.json
··· 22 22 "devDependencies": { 23 23 "@iconify-json/lucide": "^1.2.93", 24 24 "@iconify-json/pixel": "^1.2.1", 25 + "@iconify-json/vscode-icons": "^1.2.44", 25 26 "@js-temporal/polyfill": "^0.5.1", 26 27 "@nuxt/test-utils": "4.0.0", 27 28 "@nuxtjs/i18n": "^10.2.3",
+10
pnpm-lock.yaml
··· 39 39 '@iconify-json/pixel': 40 40 specifier: ^1.2.1 41 41 version: 1.2.1 42 + '@iconify-json/vscode-icons': 43 + specifier: ^1.2.44 44 + version: 1.2.44 42 45 '@js-temporal/polyfill': 43 46 specifier: ^0.5.1 44 47 version: 0.5.1 ··· 1036 1039 '@iconify-json/pixel@1.2.1': 1037 1040 resolution: {integrity: sha512-XwzURAMyZ/BJKeygh4PloKo9cUvS8GfcePueApzwrePvmwCwYT8SC581AQLxJHJl2FZjGWmUMVQ2FN3b9/cYyw==} 1038 1041 1042 + '@iconify-json/vscode-icons@1.2.44': 1043 + resolution: {integrity: sha512-3fLOIRRtsm6HD6UPJ3Y6/UztqxNTYgKA8VxrWeg1C+042MD3A/06CkWSsii1pz/f1zl0+YxvCHIVM3tXUlho+A==} 1044 + 1039 1045 '@iconify/collections@1.0.653': 1040 1046 resolution: {integrity: sha512-XT+u9JpO+o8dB2qrcI2FrNAZlDH0+flUqcOye4HkYnB+nPLjBXjFbJJTfODOCJzonSw/5axd5w/8fyY1g52d/w==} 1041 1047 ··· 8596 8602 dependencies: 8597 8603 '@iconify/types': 2.0.0 8598 8604 8605 + '@iconify-json/vscode-icons@1.2.44': 8606 + dependencies: 8607 + '@iconify/types': 2.0.0 8608 + 8599 8609 '@iconify/collections@1.0.653': 8600 8610 dependencies: 8601 8611 '@iconify/types': 2.0.0

History

1 round 0 comments
sign up or login to add to the discussion
1 commit
expand
content: add more content for 2026-02-27 post feat: add navigation between pages fix: address theme issues #5 chore: cleanup styles chore: remove unnecessary prose components
expand 0 comments
pull request successfully merged