Making SNES ROMS with C# and Matthew Shapiro's DotnetSnes

Making SNES ROMS with C# and Matthew Shapiro's DotnetSnes

Released Thursday, 1st May 2025
Good episode? Give it some love!
Making SNES ROMS with C# and Matthew Shapiro's DotnetSnes

Making SNES ROMS with C# and Matthew Shapiro's DotnetSnes

Making SNES ROMS with C# and Matthew Shapiro's DotnetSnes

Making SNES ROMS with C# and Matthew Shapiro's DotnetSnes

Thursday, 1st May 2025
Good episode? Give it some love!
Rate Episode

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.

Unlock more with Podchaser Pro

  • Audience Insights
  • Contact Information
  • Demographics
  • Charts
  • Sponsor History
  • and More!
Pro Features