About Social Code
summaryrefslogtreecommitdiff
path: root/html/notes/n64brew-gamejam-2021.html
blob: b7764c252f3e5485285b43717cd785c84167f63c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!doctype html>

<html class="html-note-page" lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>N64Brew GameJam 2021</title>
    <meta name="dcterms.date" content="2021-12-10" />

    <link rel="stylesheet" href="/assets/style.css">
    <link rel="icon" type="image/x-icon" href="/assets/favicon.svg">
    <link rel="icon" type="image/png" href="/assets/favicon.png">
    <link rel="alternate" type="application/atom+xml" title="Fryzek Concepts" href="/feed.xml">
</head>

<body>
    <div class="header-bar">
        <a href="/index.html">
            <img src="/assets/favicon.svg" alt="frycon logo">
        </a>
        <div class="header-links">
                        <a href="/now.html" class="header-link">Now</a>
            <a href="/about.html" class="header-link">About</a>
            <a rel="me" href="https://mastodon.social/@hazematman" class="header-link">Social</a>
            <a href="https://git.fryzekconcepts.com" class="header-link">Code</a>
        </div>
    </div>
    <main>
<div class="page-title-header-container">
    <h1 class="page-title-header">N64Brew GameJam 2021</h1>
        <div class="page-info-container">
                    <div class="plant-status">
                    <img src="/assets/evergreen.svg">
                    <div class="plant-status-text">
                    <p>evergreen</p>
                    </div>
                    </div>
                <div class="page-info-date-container">
            <p class="page-info-date">Published: 2021-12-10</p>
            <p class="page-info-date">Last Edited: 2023-01-20</p>
        </div>
    </div>
    </div>
<div class="note-divider"></div>
<div class="main-container">
    <div class="note-body">
<p>So this year, myself and two others decided to participate together
in the N64Brew homebrew GameJam, where we were supposed to build a
homebrew game that would run on a real Nintendo 64. The game jam took
place from October 8th until December 8th and was the second GameJam in
N64Brew history. Unfortunately, we never ended up finishing the game,
but we did build a really cool tech demo. Our project was called
“Bug Game”, and if you want to check it out you can find it <a
href="https://hazematman.itch.io/bug-game">here</a>. To play the game
you’ll need a flash cart to load it on a real Nintendo 64, or you can
use an accurate emulator such as <a
href="https://ares.dev/">ares</a> or <a
href="https://github.com/n64dev/cen64">cen64</a>. The reason an accurate
emulator is required is that we made use of this new open source 3D
microcode for N64 called “<a
href="https://github.com/snacchus/libdragon/tree/ugfx">ugfx</a>”,
created by the user Snacchus. This microcode is part of the Libdragon
project, which is trying to build a completely open source library and
toolchain to build N64 games, instead of relying on the official SDK
that has been leaked to the public through liquidation auctions of game
companies that have shut down over the years.</p>
<div class="gallery">
<p><img src="/assets/2021-12-10-n64brew-gamejam-2021/bug_1.png" /> <img
src="/assets/2021-12-10-n64brew-gamejam-2021/bug_2.png" /> <img
src="/assets/2021-12-10-n64brew-gamejam-2021/bug_4.png" /> <img
src="/assets/2021-12-10-n64brew-gamejam-2021/bug_5.png" /> <img
src="/assets/2021-12-10-n64brew-gamejam-2021/bug_3.png" /></p>
<p>Screenshots of Bug Game</p>
</div>
<h2 id="libdragon-and-ugfx">Libdragon and UGFX</h2>
<p>Ugfx was a brand new development in the N64 homebrew scene. By
complete coincidence, Snacchus happened to release it on September 21st,
just weeks before the GameJam was announced. There have been many
attempts to create an open source 3D microcode for the N64 (my <a
href="https://github.com/Hazematman/libhfx">libhfx</a> project
included), but ugfx was the first project to complete with easily usable
documentation and examples. This was an exciting development for the
open source N64 brew community, as for the first time we could build 3D
games that ran on the N64 without using the legally questionable
official SDK. I jumped at the opportunity to use this and be one of the
first fully 3D games running on Libdragon.</p>
<p>One of the “drawbacks” of ufgx was that it tried to follow a lot of
the design decisions the official 3D microcode for Nintendo used. This
made it easier for people familiar with the official SDK to jump ship
over to libdragon, but also went against the philosophy of the libdragon
project to provide simple easy to use APIs. The Nintendo 64 was
notoriously difficult to develop for, and one of the reasons for that
was because of the extremely low level interface that the official 3D
microcodes provided. Honestly writing 3D graphics code on the N64
reminds me more of writing a 3D OpenGL graphics driver (like I do in my
day job), than building a graphics application. Unnecessarily increasing
the burden of entry to developing 3D games on the Nintendo 64. Now that
ugfx has been released, there is an ongoing effort in the community to
revamp it and build a more user friendly API to access the 3D
functionality of the N64.</p>
<h2 id="ease-of-development">Ease of development</h2>
<p>One of the major selling points of libdragon is that it tries to
provide a standard toolchain with access to things like the c standard
library as well as the c++ standard library. To save time on the
development of bug game, I decided to put that claim to test. When
building a 3D game from scratch two things that can be extremely time
consuming are implementing linear algebra operations, and implementing
physics that work in 3D. Luckily for modern developers, there are many
open source libraries you can use instead of building these from
scratch, like <a href="https://glm.g-truc.net/0.9.9/">GLM</a> for math
operations and <a
href="https://github.com/bulletphysics/bullet3">Bullet</a> for physics.
I don’t believe anyone has tried to do this before, but knowing that
libdragon provides a pretty standard c++ development environment I tried
to build GLM and Bullet to run on the Nintendo 64 and I was successful!
Both GLM and Bullet were able to run on real N64 hardware. This saved
time during development as we were no longer concerned with having to
build our own physics or math libraries. There were some tricks I needed
to do to get bullet running on the hardware.</p>
<p>First bullet will allocate more memory for its internal pools than is
available on the N64. This is an easy fix as you can adjust the heap
sizes when you go to initialize Bullet using the below code:</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>btDefaultCollisionConstructionInfo constructionInfo <span class="op">=</span> btDefaultCollisionConstructionInfo<span class="op">();</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>constructionInfo<span class="op">.</span><span class="va">m_defaultMaxCollisionAlgorithmPoolSize</span> <span class="op">=</span> <span class="dv">512</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>constructionInfo<span class="op">.</span><span class="va">m_defaultMaxPersistentManifoldPoolSize</span> <span class="op">=</span> <span class="dv">512</span><span class="op">;</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>btDefaultCollisionConfiguration<span class="op">*</span> collisionConfiguration <span class="op">=</span> <span class="kw">new</span> btDefaultCollisionConfiguration<span class="op">(</span>constructionInfo<span class="op">);</span></span></code></pre></div>
<p>This lets you modify the memory pools and specify a size in KB for
the pools to use. The above code will limit the internal pools to 1MB,
allowing us to easily run within the 4MB of RAM that is available on the
N64 without the expansion pak (an accessory to the N64 that increases
the available RAM to 8MB).</p>
<p>The second issue I ran into with bullet was that the N64 floating
point unit does not implement de-normalized floating point numbers. Now
I’m not an expert in floating point numbers, but from my understanding,
de-normalized numbers are a way to represent values between the smallest
normal floating point number and zero. This allows floating point
calculations to slowly fall towards zero in a more accurate way instead
of rounding directly to zero. Since the N64 CPU does not implement
de-normalized floats, if any calculations would have generated
de-normalized float on the N64 they would instead cause a floating point
exception. Because of the way the physics engine works, when two objects
got very close together this would cause de-normalized floats to be
generated and crash the FPU. This was a problem that had me stumped for
a bit, I was concerned I would have to go into bullet’s source code and
modify and calculations to round to zero if the result would be small
enough. This would have been a monumental effort! Thankfully after
digging through the NEC VR4300 programmer’s manual I was able to
discover that there is a mode you can set the FPU to, which forces
rounding towards zero if a de-normalized float would be generated. I
enabled this mode and tested it out, and all my floating point troubles
were resolved! I submitted a <a
href="https://github.com/DragonMinded/libdragon/pull/195">pull
request</a> (that was accepted) to the libdragon project to have this
implemented by default, so no one else will run into the same annoying
problems I ran into.</p>
<h2 id="whats-next">What’s next?</h2>
<p>If you decided to play our game you probably would have noticed that
it’s not very much of a game. Even though this is the case I’m very
happy with how the project turned out, as it’s one of the first 3D
libdragon projects to be released. It also easily makes use of amazing
open technologies like bullet physics, showcasing just how easy
libdragon is to integrate with modern tools and libraries. As I
mentioned before in this post there is an effort to take Snacchus’s work
and build an easier to use graphics API that feels more like building
graphics applications and less like building a graphics driver. The
effort for that has already started and I plan to contribute to it. Some
of the cool features this effort is bringing are:</p>
<ul>
<li>A standard interface for display lists and microcode overlays.
Easily allowing multiple different microcodes to seamless run on the RSP
and swap out with display list commands. This will be valuable for using
the RSP for audio and graphics at the same time.</li>
<li>A new 3D microcode that takes some lessons learned from ugfx to
build a more powerful and easier to use interface.</li>
</ul>
<p>Overall this is an exciting time for Nintendo 64 homebrew
development! It’s easier than ever to build homebrew on the N64 without
knowing about the arcane innards of the console. I hope that this
continued development of libdragon will bring more people to the scene
and allow us to see new and novel games running on the N64. One project
I would be excited to start working on is using the serial port on
modern N64 Flashcarts for networking, allowing the N64 to have online
multiplayer through a computer connected over USB. I feel that projects
like this could really elevate the kind of content that is available on
the N64 and bring it into the modern era.</p>
    </div>
</div>    </main>
</body>
</html>