Episode Transcript
Transcripts are displayed as originally observed. Some content, including advertisements may have changed.
Use Ctrl + F to search
0:12
Hi, I'm Scott Hanselman. This is another
0:15
episode of Hanselminutes. Today, I'm chatting with Matthew
0:17
Shapiro. In his day job, he's a staff
0:19
video architect at Game Changer. But at night,
0:21
he's making insane things on GitHub, which is
0:23
why I'm having him here today. How are
0:25
you, sir? I am great. Thanks
0:27
for hanging out. So you had a Great
0:30
week last week, didn't you? Yeah,
0:33
the amount of
0:35
excitement I've seen from that Reddit post
0:37
that I posted of the Mario platform
0:40
has been incredible. Yeah, so
0:42
you went and you threw out something on
0:44
Reddit and you say, hey, everybody, you know,
0:46
in my copious spare time while working and
0:48
raising kids, I was messing around and I
0:50
put together a library that pulled some other
0:52
libraries together and you have a thing that
0:54
lets you use C -Sharp to
0:56
make ROMs for the Super Nintendo. And then
0:59
you also run Hacker News for a time
1:01
at the top spot. Yeah,
1:03
for a day, I was pretty on
1:06
the front page, which was incredible. I
1:08
didn't even post it there. Somebody else
1:10
did, and I found it by accident.
1:13
Yeah. So now, suddenly, this is one of
1:15
those things that happens when you kind of
1:18
go tiny viral, is that some project you
1:20
did in your spare time is now being
1:22
watched, and people want more, and then you
1:24
have to quit your job and work full
1:27
-time on Super Nintendo ROMs, right? I would
1:29
love that. But boy,
1:31
it's funny because I
1:33
do a lot of random stuff
1:35
throughout the years. And I have
1:38
a small group of engineers that
1:40
are friends. And I always get
1:42
comments of, huh, that's neat. And sometimes I'll post something
1:44
and I'll get some, huh, that's neat. And that's about
1:46
it. And this is the
1:48
first time I actually got somebody. So
1:50
I actually got one person who's so
1:52
excited that he started contributing to the
1:54
main project. And I was like, whoa, this is a
1:56
weird feeling. That's cool. So you've got
1:58
a contributor now, which is great. This is how open
2:01
source starts, right? You do things, you throw spaghetti against
2:03
the wall, and then one day it sticks, and then
2:05
you have a little community of people who are excited
2:07
about the thing you're excited about. And then you have
2:09
freak out about people looking at code that you wrote
2:11
in your hobby time. That
2:14
is the real crisis.
2:17
So let me help you understand, though,
2:19
how this started, because we know that
2:21
there's a bunch of enthusiasts, even now,
2:23
in 2025 excited about Nintendo and Super
2:25
Nintendo. We've got tons of
2:28
documentation. It has never been a better
2:30
time, I would say, to be doing
2:32
retro gaming and retro games than it
2:34
is now, right? Right. So
2:36
this actually didn't start for specifically
2:38
with the goal of Super Nintendo
2:41
in mind or any console gaming
2:43
at all. The very
2:45
short story is that one of my
2:47
good friends, Justin Johnson at Mojang, was
2:52
knew that I was going on parental leave because
2:54
my daughter was about to be born. And he's
2:56
like, hey, I have this, I have a meadow,
2:59
a wilderness labs meadow. I have a
3:01
little retro game engine on it. And
3:05
I need help optimizing it. And he's like,
3:07
you got a lot of free time coming
3:09
up because of your parental leave. How about
3:11
we, what if you do it?
3:13
And so he got me a bunch of
3:15
the equipment and I just became enthralled with
3:17
mostly embedded development. And so
3:20
I did a lot of optimizations
3:22
and I got that to a
3:24
good place. And then I started
3:26
working on, I
3:28
got it as far as I could go with it. Well,
3:31
IO constraints was what was
3:33
bought on ECV. And
3:36
so a long story short
3:38
is I wrote a small
3:40
little GPU for microprocessor that
3:43
runs on a ESP32. But
3:46
that's all C code. And
3:48
I came into a fork with a load of like,
3:50
I want to be able to write more C
3:53
-Shop. I can do most languages, but I love
3:55
C -Shop. And so
3:57
I started theory -crafting on, well,
4:00
what actually would it take to run C
4:02
-Shop on other devices? And
4:05
it's not feasible for the .NET
4:07
team to create AOT for all
4:10
the different platforms that nobody's going
4:12
to use. It's
4:14
also not feasible for me and my free time
4:16
to learn assembly for every single platform and start
4:19
doing it myself. And so I started realizing, have
4:22
you ever heard of a programming language called NIM?
4:25
NIM, yeah, sure. Yeah. Well, I thought
4:27
about it and I played with it
4:29
before and one of the things that
4:31
it does is it doesn't compile down
4:33
to LLVM IR, it compiles down to
4:36
C. And so that
4:38
allows it to run anywhere else. And so
4:40
as long as you have a C compiler,
4:43
then you can run your code, run your
4:45
NIM code anywhere else. And
4:47
then I started thinking, well, what
4:50
if you actually take
4:52
MSIL and start and
4:54
actually translate that to
4:57
C? And I started playing
4:59
around with the idea and it started working. And
5:01
so it just took off
5:04
one of the. So
5:06
I started off without an actual goal
5:08
in mind of like, let me see
5:10
if I can do this, just as
5:12
like, just an idea
5:14
in my head, just as a challenge.
5:17
And then the whole crowd
5:20
strike issue appeared. Well,
5:23
it was crashing on the machines. And
5:26
one of the reasons that doesn't necessarily
5:28
happen as badly on the Linux side
5:31
and soon to be on the Windows
5:33
side is because of EBPF. Have you
5:35
heard of that? Okay, this is keeping
5:38
the kernel separated, right? Yeah,
5:40
so it allows you to, so EBPF
5:42
works by, you
5:45
compile special programs down into a
5:47
special bytecode that the kernel can
5:49
verify that it can't crash, it
5:51
can't allocate memory, it can't stall,
5:54
it has various checks and balances
5:56
in it. Right, this is
5:58
basically, it's called the extended Berkeley packet filter
6:00
and it's a way of running sandboxed programs.
6:03
without modifying the kernel source code.
6:05
It's making little cages for your
6:07
code to run inside the kernel.
6:09
Right, exactly. It's
6:13
great because you can add a lot
6:16
of observability into Linux kernels without whisking,
6:18
nuking, or doing anything poorly, and then
6:20
you have a user space component that
6:23
talks back and forth of it and
6:25
does the user space. It's a clean
6:27
separation of concerns. Exactly. And that's why
6:29
Windows, I think, is moving towards that
6:32
model now, especially after the cloud strike.
6:35
And I was just thinking, the
6:38
EBPF applications do not
6:40
have memory allocation. So
6:42
it's a perfect use
6:44
case for where my
6:46
transpiler was at that
6:48
time. And
6:51
so I was able to, and if you
6:53
can imagine having C sharp running both the
6:55
user space and the kernel space at the
6:57
same time, that got really compelling. And
7:00
so I got proof of sample, proof
7:02
of concepts going, and that actually works.
7:06
So you can actually write Linux
7:08
EBPF programs in C sharp and
7:11
have them run inside the Linux
7:13
kernel. That's
7:16
cool. I think the .NET team will be excited about
7:18
that because there's all this talk about using Rust to
7:20
run things in the Linux kernel. Right. And
7:23
yeah, and because we're going down the
7:25
C, we can just reuse all this
7:27
rinse into normal C cheat. This normal
7:29
C tool chains that everything relies on
7:32
So I got that working and it
7:34
was actually like I did a reddit
7:36
post for that and I got some
7:38
that was some of the neat Responses
7:41
I got but wasn't nearly as much
7:43
as this and so because this is
7:45
all my hobby I was trying to
7:47
figure out what to do next to
7:50
move it forward and one of my
7:52
friends Lawrence Welpton who works at Microsoft
7:54
Mentioned that he had a He's like,
7:56
what about making SNES games? And
7:59
I was like, no, I don't know
8:01
if that's going to be possible, because I
8:03
didn't think that there was a C toolchain
8:05
for it. I thought most of those games,
8:07
most SNES games in Super Nintendo games were
8:09
in pure assembly. But
8:12
it turns out that there was
8:14
a C library, an
8:16
SDK for making Super Nintendo
8:19
games in C, and it's
8:21
actually fairly active. And
8:23
once I saw that, It fit
8:25
the bill perfectly because there's no
8:28
dynamic memory allocation. And
8:30
so I just went to town trying to
8:32
get that to work. And
8:34
it makes you really appreciate
8:36
modern debugging tools when things
8:39
don't go right. Yeah,
8:41
it makes you wonder like, There's
8:43
still people now, even in modern
8:45
times, that are very famous people
8:47
like Brendan Burns, who works on Kubernetes,
8:49
famously doesn't like debuggers. He's just
8:51
all about got here debugging and the
8:54
kinds of debugging that we would do
8:56
30 years ago with softice or whatever.
8:59
It was basically like stop and
9:01
stare at a bunch of registers and
9:03
hope for the best or a bunch
9:05
of console .write lines. Yeah, there was
9:08
some points where I was in a
9:10
emulator that's very much designed for
9:12
debugging SNES games and going through assembly
9:14
that I had that I was looking
9:17
up ad hoc demand to try and
9:19
figure out why some examples weren't
9:21
working. And it turned out
9:23
I just mistyped some things. But
9:26
like, but that takes that ends up costing you
9:28
like hours. Mm
9:30
hmm. Yeah. So help
9:33
me understand the stack. because
9:35
we know that a Super
9:37
Nintendo is, everyone
9:40
wrote those games in Assembler, correct,
9:42
at the time. And
9:44
with these, what was the processor in
9:47
a Super Nintendo? Was it a 6502
9:49
or was it a 68000? I
9:51
think it's a modified 6502. I think
9:53
it had some changes, too. Let me
9:56
think here. Oh, here
9:58
we go. It's a 65816.
10:01
which is a 16 -bit CPU, it's
10:04
not a fully -fledged 68000, but
10:06
it has a 6502 compatibility mode.
10:08
So you can do both. And
10:10
that was the magic. It was
10:12
a bridge to the future. So
10:15
you've got 65C816 for
10:18
6502 developers. Interesting.
10:21
OK. So these ROMs are well understood.
10:24
The emulators are well understood. And
10:26
you wanted to go from C
10:28
-Sharp all the way into targeting
10:31
the specific processor. And you didn't
10:33
go straight there. You bounced around.
10:35
You went MSIL to C and
10:37
then from C to assembly and
10:39
then assembly. Walk me
10:41
through the Hello World process.
10:44
Yeah, so the Hello World is
10:46
essentially creating a C -Shop program.
10:50
It's creating a C -Shop program
10:52
that's fairly standard. There's some
10:55
caveats like right now I don't support. reference
10:57
types because I haven't implemented
11:00
GC garbage collection yet and
11:02
That's kind of on my
11:04
next task although you wouldn't
11:06
use garbage collection or reference
11:08
type reference counting or really
11:10
any of that style of
11:13
programming for an SNES because
11:15
Too much overhead And there's
11:17
no dynamic memory allocation on
11:19
a SNES really So you
11:21
start with a C sharp
11:24
program And
11:26
you run it through a program
11:28
that I call dntc, which is my
11:30
.net2c transpiler. And that
11:32
actually goes through and you give it
11:34
a root function of what function you
11:37
want to start the transpilation process at.
11:39
And it sort of creates a dependency
11:41
graph of your whole, all
11:43
the types involved, all the functions
11:45
that get called, everything that it
11:47
needs. And it makes sure everything
11:49
that gets called, it has a
11:52
solution for. And then
11:54
one by one, it starts
11:56
taking the IL and converting
11:59
it into a syntax tree
12:01
that it then converts into
12:03
C statements as it reads
12:06
the IL one bit at
12:08
a time. It's
12:12
a fairly interesting process because
12:14
the .NET bytecode is very
12:16
much made specifically for as
12:19
a stack machine. And it's
12:21
designed, it's a stock machine
12:24
and it's evaluating at one
12:26
time. And I
12:28
got, I have a huge
12:30
appreciation for the .NET JIT
12:32
team now because trying to
12:34
take that stock machine and
12:36
figuring out optimizations of how
12:38
to do that ahead of
12:41
time is really fascinating. It's
12:44
hard there's a lot going on and i
12:46
think that people who are even in the
12:48
regular dotnet community who aren't building things for
12:50
a super nintendo don't really understand how deep.
12:53
The possibilities are the combinatorics because the
12:55
jitter right now says oh you're on
12:57
x86 oh you're on x64 oh you're
13:00
on arm and then looks at. Specific
13:03
processor instructions is oh you're on
13:05
x64 but you're on an older
13:07
intel or you're on a newer
13:09
intel makes all kinds of decisions
13:11
jitter level so then you have
13:13
this. this Cartesian product of all
13:15
the different operating systems, all the
13:17
different processors, all the
13:19
different flavors within sub flavors and subversions
13:21
of processors, it gets complicated. And then
13:23
if you wanted to apply AOT to
13:25
that, things get really,
13:27
really hairy. Well, especially
13:29
if you think about some optimizations that the
13:32
C sharp compiler itself does. So if you're
13:34
just doing a simple swap of two variables,
13:36
you have A, you have B, and you
13:38
want to swap the values. even
13:41
if you use temporary variables, the
13:44
C sharp compiler will optimize it into just
13:46
put A's value on the stack, put B's
13:48
value on the stack, and then just pop
13:50
them in the opposite order into the alternate
13:52
variables. But you can't do
13:54
that ahead of time. You can't do
13:57
that. That doesn't work ahead of time.
13:59
And especially with the transpiler, I have
14:01
to know exactly what it's targeting. And
14:04
so you actually have to jump through some hoops
14:06
to be able to resolve that, recognize that that
14:08
situation is going to occur. and
14:10
then resolve it into assembly language
14:12
or C that actually does the
14:14
correct behavior that you're expecting. My
14:17
goodness. So you're
14:20
taking any language that can
14:22
compile to MSIL, to
14:24
intermediate language, presumably C
14:26
sharp primarily, and you
14:29
compile it into C source
14:31
code, specifically C99, that flavor
14:33
of C. Is that correct?
14:35
Yeah. So the intention was
14:37
C99, but there's a lot
14:39
of... So when
14:42
when you when you the idea
14:44
was the idea right now is
14:46
that you take a You build
14:48
a transpiler you can build transpiler
14:51
plug -in to to change things
14:53
up a bit and That's needed
14:55
because the C library that targets
14:57
SNES doesn't actually isn't C99 compliant.
14:59
And so there are some features
15:02
like zeroing out globals that are
15:04
not actually supported that you didn't
15:06
have to like customize the transpilation
15:08
operations to handle So
15:13
it tries to be C99
15:15
compliant, but there's the customization
15:18
and flexibility to be able
15:20
to target anything, any C
15:22
compiler really. And
15:25
one of the things that I think you do really
15:27
cool, and I want to understand if it's part of
15:29
your... this dntc
15:31
.net to see transpiler is you have
15:33
these attributes like native function call or
15:35
native global or custom function name because
15:38
you're basically kind of taking extern C
15:40
to the next level and basically letting
15:42
C sharp in this transpiler almost work
15:44
in both directions. You're really giving hints
15:46
on how the C code should end
15:48
up and what the results are and
15:51
it feels like this is an oversimplification
15:53
but P invoke right platform invoke is
15:55
the ability of C sharp to go
15:57
and call into extra and C's into
15:59
C's that are sitting around in random
16:02
libraries whether it be a shared object
16:04
in Linux or a DLL. In
16:06
in windows but if you're on the
16:08
way downstairs anyway right you apply these
16:10
attributes and then they find them with
16:13
their way all the way down and
16:15
you basically set up your calling conventions
16:17
for success right with these with these
16:19
attributes. Yeah,
16:22
so one of the core
16:24
principles that I built this
16:26
transpiler on is that it
16:28
should be easy not only
16:30
to create a C sharp
16:32
application that references C code,
16:35
like the SNES example is you can
16:37
kind of think of it as a
16:40
C sharp program that's calling into native
16:42
C functions for the SDK. But
16:45
there's also the reverse that I wanted
16:47
to make sure was a first -class
16:49
citizen of you can take C sharp
16:51
code and integrate it into your existing
16:53
C application or as long as you
16:55
have C headers. So there's
16:57
a lot of these customizations and attributes
16:59
that you can add to really customize
17:01
how things are done. For
17:03
the SNES ROM, it's specifically looking for
17:06
a function called main with a lowercase
17:08
m and all those things. So you
17:10
need to be able to tell the
17:12
transpiler, hey, tweak this name a bit
17:14
so that it fits. And
17:17
with the SNES ROMs,
17:19
you actually have labels
17:21
in the assembly. You
17:25
have labels in the
17:28
assembly files that actually
17:30
target memory locations. And
17:33
so you need to be able to call
17:35
those with the exact names. And
17:38
so there's a lot of examples of that.
17:41
Well, I can look at an example
17:43
here. I'm looking at your game public
17:45
static class game. Yeah. And you've got
17:48
a main public static in main and
17:50
then you made sure that it's main
17:52
you said custom function name lowercase main.
17:54
Yeah. And then you've got some things
17:57
like tile font or pal font. And
17:59
these are little static bytes where things
18:01
need to show up. Right. And then
18:03
if you go over into like data
18:05
dot ASM which is the assembly language
18:08
kind of like resource that's along for
18:10
the ride. There it is. Tile font,
18:12
pal font. So it's this you're creating
18:14
this chain of responsibility to make sure
18:17
that everything lines up when it all
18:19
happens at the last minute Yeah, and
18:21
and it makes sure everything it makes
18:23
sure there's no disconnections when you are
18:26
actually calling a native function Like you
18:28
said the like a native P invoke
18:30
and it makes it like it makes
18:32
it zero cost to actually convert all
18:34
your to actually call
18:37
native functions because it's all linked
18:39
together in the final binary. It's
18:41
not actually doing a shared library.
18:44
Now, this is not idiomatic. I'm
18:46
looking at this and I see
18:48
using .NET SNES core and namespace and
18:51
that all feels good. I see
18:53
some attributes and that's cool. Then
18:55
it looks like it's mostly static.
18:58
Functions hanging off of helpers like
19:00
SNES console you know set the
19:02
text or background dot set graphics
19:04
pointer. Yeah, but it still also
19:06
feels high level. So it's funny
19:08
you feel high level but you
19:11
really aren't. So the Mario platform
19:13
or example was very much a
19:15
almost line by line conversion that
19:17
I did from the C example
19:19
to it. there are
19:21
ways that I want to, that I have, there are ideas
19:23
that I have to make it a bit more idiomatic C
19:26
sharp. Like so, for
19:28
example, one part of that, one part
19:30
of that code passes around function pointers,
19:33
or it passes on delegates, which gets
19:35
transpiled down to function pointers. But
19:38
I want to be able to say, use
19:41
static interface members to replace
19:43
that, for example. There's
19:47
a lot of opportunities. The breakout example
19:49
is a better example of where there's
19:51
a bit more idiomatic, where I've taken
19:53
a bit more time to make the
19:55
example a bit more idiomatic. The
19:58
Mario one was mostly just let me make
20:00
sure that everything works end to end before
20:02
I start messing. There's
20:05
something new from our sponsor, Text
20:07
Control. For decades, TX Text Control's
20:09
rendering was tied to Windows functionality.
20:12
But now, it's a new era. TX
20:14
Text Control is platform independent. You
20:17
can run your .NET applications on Windows or
20:19
Linux. Deploy with Docker containers,
20:22
Kubernetes, or host directly in Azure App
20:24
Services. Seamlessly integrate document
20:26
editing, signing, collaboration, and PDF
20:29
processing into your ASP .NET
20:31
Core and Angular applications. Are
20:34
you ready to see it in action? Check
20:36
out the live demo
20:38
at demos .textcontrol.com. That's
20:42
demos .textcontrol.com. Now,
20:45
this is all sitting
20:48
on top of a
20:50
thing called PVSNESLive, made
20:52
by a gentleman named Alec out of France.
20:55
It's a library that's been around for
20:57
three or four years that I think
20:59
that they started from an SDK called
21:02
the SNES SDK over on Google
21:04
code by a gentleman named Ulrich
21:06
Hect. So this is 10 or
21:08
15 years of people trying to
21:10
get C programming available for Super
21:12
Nintendo. So this gentleman
21:14
Alec is sitting on top of the shoulders of
21:17
this other gentleman named Ulrich and on as well
21:19
as a community and lots of different things. How
21:21
did you know this would all line up though?
21:23
How do you pick a library and you say,
21:25
yeah, I'm going to stand on that. And
21:28
I think it'll be supported me. It'll
21:30
support me. It's that's the whole
21:32
thing of like everything I do. Um,
21:36
I'm just standing on the shoulder of what
21:38
people have done before. So even
21:40
just like the IL functionality, um,
21:44
like I wouldn't be able to do any, this would be hard.
21:47
This would be hard. And if I, if
21:49
I targeted C sharp for the transpilation, that
21:51
would be hard. I could use a Roslin,
21:53
but that would be hard because C shops
21:55
kind of a moving target. And I'd have
21:57
to keep that updated. But the MSIL is
21:59
a good base. But
22:01
I wouldn't want to write the
22:03
whole library to actually interpret all
22:06
the MSIL code itself. But the
22:08
Mono project, I think Mono
22:10
.Ciso is a, I don't know if Mono .Ciso
22:12
is an official project or not. I think it
22:14
is. I mean, certainly the world is sitting on
22:16
top of Cecil. So yeah, I think it's pretty
22:18
important. Yeah. So like without
22:20
Cecil, without PVS, NES. I
22:24
wouldn't have been able to do it.
22:26
And really, the only reason I was
22:28
even able to do the EPPF stuff
22:30
functional is because all of the work
22:32
that went into the C libraries to
22:34
unlock all of that capabilities. So
22:37
it's really, it's always fascinating when I take a
22:39
step back and look at like everything that I'm
22:41
like, what made everything I'm doing possible. Yeah.
22:44
Yeah. It's overwhelming. The stack is so deep
22:46
now. I think it's funny when people call
22:48
themselves full stack developers. But
22:50
they don't realize how many shoulders they're standing
22:53
on top of over so much time because
22:55
this is about the most documented piece of
22:57
hardware on the planet at this point. And
22:59
watching the emulators, I think, is super fun
23:01
because it's not just emulating a ROM. You
23:03
can actually have emulators that will show what's
23:06
happening in real time in the memory of
23:08
the Super Nintendo. So it's a really great
23:10
way to learn computer science. Yeah,
23:12
there were several bugs that I
23:14
was going to during the SNES.
23:16
process where I was trying to
23:18
Like I was I was I
23:21
was a value. I was looking
23:23
at all the stack registers on
23:25
the SNES. I was looking at
23:27
memory locations I was looking at
23:29
tilesets trying to figure out why
23:31
something wasn't appearing on the screen
23:33
when I figured it should And
23:35
it's it's fascinating to go down
23:37
like this whole trip has made
23:39
me really want to I actually
23:41
bought an assembly an x86 assembly
23:44
book just to start like understanding that part
23:46
of the stack a bit more. Just
23:49
how everything works. And this has
23:51
also made me want to go to
23:54
start work playing with FPGAs. Playing
23:59
around with a lot of the digital logic
24:01
that that entails. Yeah, I bought recently. Where
24:03
is it here? I think it was called
24:05
an ice stick Yeah, FPGA and it just
24:07
plugs directly into your USB and it's you
24:09
know, I don't know if it would be
24:11
big enough to do something like that But
24:13
if you think about some of the really
24:15
cool work that's happening on these Programmable gated
24:17
arrays these FPGA systems like the analog pocket,
24:19
which I think is truly one of the
24:22
most extraordinary pieces of hardware that's just happened
24:24
along with the mr. What
24:26
MIS TR to
24:28
allow someone to effectively transform
24:30
dynamically a piece of hardware
24:32
into another piece of hardware
24:34
and then run the original
24:36
code on it with these
24:39
cores is amazing. Yeah,
24:41
and once you start learning, once you start doing, once
24:43
you start playing with those and you
24:46
start realizing what those are doing and
24:48
you start learning, because I started going
24:50
through a website called Nan Game, which
24:54
takes you all the way from
24:56
a NAND gate all the way
24:58
to a very basic port CPU
25:01
and memory unit. A very basic
25:03
computer, essentially. Well, there's
25:05
also NAND 2 Tetris. Yeah,
25:07
there's NAND 2 Tetris. There's also a game.
25:11
I'm blanking on the name on Steam. There's also a
25:13
couple of things on Steam that do that. And
25:16
it's when you start realizing how... I
25:18
really want to put a presentation together
25:20
at one point for work, but like...
25:22
abstractions that make up a CPU is
25:24
just fascinating. It's not even just like
25:27
the implementation details of how each step,
25:29
it's how all the abstractions work together
25:31
to get to that point. I
25:33
feel like at some point I need to quit my
25:35
job just to do these projects in my spare time.
25:38
Oh, yeah. Especially
25:40
now that I have kids, it's extremely
25:42
difficult with my one hour free time
25:44
at night. There's
25:47
a buddy of mine who's got a
25:49
website called Pikuma. PI, KUMA. You love
25:51
that guy? So, I love that guy.
25:53
And so, the next step for my
25:56
project is I actually bought his PlayStation
25:58
1 course. And I actually
26:00
want to get reference types working
26:03
and start working on a very
26:05
basic PS1 C -Shop engine. Yeah.
26:09
That's Gustavo Petsi. And he is
26:11
fantastic. He was on the show
26:13
a while back, and he, for
26:15
folks that are listening, has a
26:18
Nintendo programming with assembly course, Atari
26:20
programming with assembly. He's even got a really
26:23
great course, which I think is really the
26:25
best one he's got, which is his ray
26:27
casting engine with C. So
26:29
he basically, like you basically write
26:32
Castle Wolfenstein from C from scratch.
26:34
I found his course from the
26:37
3D graphics from 3D rendering from
26:39
scratch course. That's how
26:41
I started with it, yeah. Yeah,
26:43
so I was able to get this working
26:45
really easily. I just went to your GitHub,
26:48
which is K -A -L -L -D -R -E -X
26:50
-X. We'll have a link in the show notes. And
26:53
I just did a Git clone.
26:55
Although you do need two things,
26:57
you have to do a Git
27:00
submodule update in it recursive because
27:02
you pull in two specific, you've
27:04
actually pinned down to a commit,
27:06
two specific submodules. One is
27:08
the PS. pvs -snes and
27:10
then one is your own dntc.
27:13
And then you have to use SSH keys.
27:15
You can't do this with the standard way
27:17
of logging in. So if folks are listening
27:19
and they're not super familiar with how to
27:21
do this, the easiest way is to get
27:23
the GitHub CLI. And then
27:25
you say gh -auth -login. And
27:27
it'll actually create the SSH keys
27:29
for you. And I was able
27:32
to get this running inside of
27:34
WSL, the Windows Subsystem for Linux,
27:36
in just about 10 minutes. And
27:38
then I picked up a free
27:40
Super Nintendo emulator and then just
27:42
ran make. It was amazing. It
27:44
just worked. It was 10 minutes
27:46
in to end. Yeah,
27:48
it took a it was I've never done
27:50
a lot of make file stuff before this
27:52
project. And that was you're
27:54
kidding. I was going to compliment you
27:57
on your use of make files. And
27:59
I thought I said this person's a
28:01
make file expert because you had make
28:03
file defaults make file base. And I
28:05
was actually running around relearning. how make
28:07
files do their dependency tree. No,
28:10
I said I had a very basic one set
28:12
up and I'm like this is gonna be a
28:14
pain for anyone who wants to make a start
28:16
a new project or based off of and so
28:18
I just tried to figure out how to actually.
28:22
I just forced my way into I came up
28:24
with something somewhat sane. Well,
28:27
I thought it worked out really great because you
28:29
didn't try to make it. fight with .NET build.
28:32
You cleaned it up nice and simple because you
28:34
have a lot of other things that people don't
28:36
realize when you're putting together a Super Nintendo and
28:38
that's assets, tiles, bitmaps,
28:41
fonts or bitmaps, sprites. It kind of
28:43
goes on and on and on. As
28:45
we get towards the end here, I
28:48
know that people will go and check out all of these
28:50
samples, Hello World, the Mario one, and
28:52
then the more advanced one, which you want to check
28:54
out, which is the breakout one. But just understanding the
28:56
Mario one for a second, there's
28:58
the Mario. like long PNG that
29:01
represents his first level. How
29:03
does he know what to jump on versus
29:05
like what's a pixel versus what's he allowed
29:07
to touch? Well, what's interesting,
29:10
the PVSNESlib SDK is kind
29:12
of interesting in that regard
29:15
in that it uses tiled
29:17
to create the tile map.
29:20
So it allows you to
29:22
use a modern tool to
29:25
make your maps. And
29:27
so It
29:30
has you you can actually set
29:32
collisions based on the tile types
29:34
that you're mapping out in the
29:37
tile program and the SDK is
29:39
automatically set up to convert those
29:41
and So it's not the PV
29:44
SNES lib isn't necessarily a SNES
29:46
generic SDK, it
29:48
has some opinions about how objects
29:51
should react, how sprites should react,
29:54
how maps react. And so
29:56
it has built -in collision detection
29:58
and built -in entities for that
30:00
functionality. So it
30:02
makes it really easy to actually do that
30:04
with somewhat modern tools. If
30:06
you ever watch those interviews... That's a really
30:09
nice way to think about it. If you
30:11
ever watch those interviews, those old things with
30:13
Miyamoto where he... They'll show how they how
30:15
they actually made Super Mario Brothers. They actually
30:17
had like good people and they're actually mocking
30:19
out different blocks and how to do it.
30:21
And then the programmer would have to go
30:23
in and mainly enter all those bytes. That's
30:26
funny that you mentioned that because if you poke
30:28
around inside of your Mario example, you
30:30
know, you've got a couple of, you know, ASMX
30:32
files. And then I just dropped into one of
30:34
the map files, which was a TMJ. And
30:37
it's just a big old JSON
30:39
filled with bytes. that go
30:42
on forever and ever and ever and
30:44
ever. But it's also cool that
30:46
we've got PNGs in there, which is
30:48
a modern graphics format, and we've
30:50
got Mario's jump sound as a modern
30:53
wave file. So it is this
30:55
wonderful amalgamation of things that didn't exist
30:57
at the time that the NES
30:59
was created and things that exist now.
31:01
Why not take advantage of those modern
31:04
bits of comfort? Yeah, and
31:06
some of the things that the... The
31:09
modern community there is actually doing
31:11
the games that they're actually making
31:13
at the pv snes lib discord
31:15
is pretty incredible. Yeah
31:18
this is a great way to jump into
31:20
the community the the you're standing on top
31:22
of them and they're sitting on top of
31:24
others and everyone is just having fun. Put
31:27
these things together you can get all this
31:30
running really really easily i think it's worth
31:32
taking. You know twenty minutes it's also a
31:34
testament to windows in the wsl on how
31:36
easy it was. I dropped
31:38
into WSL, I did the make
31:40
once I had done a couple
31:43
of apt updates and installed some
31:45
basic make file things and then
31:47
I typed explorer .exe which then
31:49
opened Explorer inside of WSL and
31:51
I dragged the newly created Mario
31:53
game directly into the surface of
31:55
my Windows emulator and now I'm
31:57
going to go and out the
31:59
breakout game as well that you've
32:01
got working. And we actually
32:04
have actually the video I have a
32:06
video on my LinkedIn somebody actually took
32:08
the Mm -hmm the breakout game and
32:10
actually it was running on real SNES
32:12
hardware. Oh wow, so they dumped it
32:14
somehow into the Yeah, they put on
32:16
a flat they were able to put
32:18
on a flash car and run it
32:20
on a real super real super Nintendo.
32:23
Oh man That's so cool.
32:25
I'll include a link to that in
32:27
the show notes. So able
32:30
to see that on your LinkedIn right now.
32:32
Fantastic. What fun you're having in
32:34
your hour of free time each night, Matt.
32:38
I can't actually have small projects.
32:40
My brain doesn't let me do
32:42
small projects. It's always big projects
32:44
that nag me for months on
32:46
end. There's nothing wrong
32:49
with that not if those if those small
32:51
projects allow me to write C sharp on
32:53
in modern day C sharp on a on
32:55
a super nintendo i think that's that's worth
32:57
it so i appreciate your service and certainly
33:00
those that whose shoulders we stand on top
33:02
of thank you so much matthew Shapiro for
33:04
hanging out with me today thank you for
33:06
having me it's been a pleasure this has
33:08
been another episode of handsome minutes and we'll
33:10
see you again next week.
Podchaser is the ultimate destination for podcast data, search, and discovery. Learn More