Pod Insights Syntax - Tasty Web Development Treats 935: CJ Made A Sega Game In 2025 About this episode CJ takes us behind the scenes of Hackweek to share how he built a custom Sega Genesis game from scratch, complete with assembly code, level loading, and retro hardware tricks. From SGDK to parallax faking, this episode is a deep dive into old-school game dev with a modern twist.
Show Notes
00:00 Welcome to Syntax!
00:44 Why a Sega game?
Sega Genesis.
Sega Master System.
MKBHD Retro Tech: Sega.
06:55 What is it running on?
07:49 Working with assembly code.
10:11 Sega Genesis Development Kit.
Stephane-D GitHub.
10:54 Awesome Megadrive.
12:02 Booting on an emulator.
13:07 Gens and KMod.
15:54 Compiling stage.
17:44 Genesis Code VS Code Extension.
18:22 Images and Assets.
19:46 Loading images with bitmap.
23:50 Megacat Studios.
25:21 Z index?
Faking Parallax.
27:34 Specific code examples.
27:51 Platformer Engine.
30:01 Platformer Sample Game.
30:44 LDTK (Level Designer Toolkit).
33:13 Tiled Collision mapping.
37:42 What about debugging?
39:37 Loading in levels.
RetroGameMechanicsExplained.
Sega Mega-CD Development Unit.
43:56 Challenges with graphics.
49:56 Adding music.
Super Cartridge.
Flahskit Programmer MD.
Flashkit Cart MD.
Hit us up on Socials!
Syntax: X Instagram Tiktok LinkedIn Threads
Wes: X Instagram Tiktok LinkedIn Threads
Scott: X Instagram Tiktok LinkedIn Threads
Randy: X Instagram YouTube Threads
Transcript Speaker names marked ? are inferred from speaking time and the show’s known hosts — they are not voice-verified.
0:05 Speaker 00 Welcome to Syntax. I think that was my first, my first one.
0:10 Scott Tolinski? Yeah, yeah.
0:11 Wes Bos? Oh, man, that was good.
0:12 Speaker 00 CJ here, and today I'm talking all about this custom Sega Genesis video game that I made for Sentry Hack Week. So Hack Week is put on every year by Sentry. Essentially, everyone at the company gets an entire week to work on whatever they want. And this year, I decided I wanted to try to create a Sega Genesis game. So with me today is Scott and Wes. What's up, guys?
0:37 Wes Bos? Yo. Hi.
0:38 Scott Tolinski? Hey.
0:39 Wes Bos? Yeah, no, don't care about us. You made a frickin' Sega game? Yes, yes.
0:44 Scott Tolinski? Holy smokes. I gotta say, why Sega? We all know that Nintendo does what Sega don't. Or no, wait.
0:50 Speaker 00 No, Sega does what Nintendo don't.
0:52 Scott Tolinski? Does what Nintendo don't. Oh. Uh-oh.
0:55 Speaker 00 But that's, that's my first question for you guys. And first, like some back, some backstory here for all the Gen Z people watching that don't know what a Sega Genesis is. This is a 16-bit game console that was released in the US in 1989. So my first question for you two is, were you an SNES guy or a Sega guy? What did you have?
1:15 Scott Tolinski? I don't feel like this is a real question. I had the NES and then I had the SNES. I was SNES head all day. I never, ever owned a system made by Sega. I kinda went the Nintendo route up until the GameCube and then moved to PlayStation. And then, obviously, Nintendo Switch. And Wii, I had a Wii. I'm a video game person. Wes is not necessarily, but I, I've played a lot of video games in my, in my life, that's for sure. Still do.
1:43 Wes Bos? So when I was a kid, we had, I just looked it up, Master System?
1:48 Speaker 00 That's the Sega Master System, yeah.
1:50 Scott Tolinski? Yeah. You had the Master System.
1:52 Wes Bos? So we got it at a garage sale, and it came with 20 games. And my parents went through them and took away 19 of them because they had fighting, fighting in them, like guns and stuff. So we had one game for that, and maybe that's why I don't like games, because my parents would take it away. And then we had the NES, and it was, we didn't have Super Nintendo, a neighbor did. And then I'd like, I pretty much like lived on like, like N64, though. That was like my big game in days.
2:25 Scott Tolinski? Well, I guess I had gaming days with all systems, but N64 for me was high school, which means we're doing sleepovers, we're playing GoldenEye, we're playing Mario Party, pretty much GoldenEye. You know, it is like, yeah, that was for me a lot of 64.
2:39 Speaker 00 Yeah, I would agree. Like, most of my childhood was N64 and then PlayStation 1, but the early days was Sega. And I think probably one of the first memories I have of games is Mortal Kombat. Did you guys ever play Mortal Kombat?
2:54 Scott Tolinski? I had Mortal Kombat for
2:55 Speaker 00 Too much fighting.
2:57 Scott Tolinski? the Super Nintendo, and it was like
2:59 Speaker 00 Okay.
2:59 Scott Tolinski? completely, like, my parents wouldn't let me get it, and they only let me get it for that one because they found out all the blood was removed, and it was like, yeah, very neutered, for sure.
3:09 Speaker 00 So, yeah, I won't get into it. There's like, go on YouTube and just look for Sega documentaries. There's one by NKPHD that, like, puts all of this in perspective, because back then, that was the deal. It was Sega came out and to really position themselves, they wanted to be like the edgy console. So they had Mortal Kombat, they had fighting games. They were like the game console for cool kids, I guess. Degenerates. Yeah, exactly.
3:32 Scott Tolinski? Yeah, degenerates.
3:34 Speaker 00 Hold on. CJ, were you allowed to watch The Simpsons as a kid?
3:37 Scott Tolinski? Oh, I was.
3:38 Speaker 00 I wouldn't say allowed to. I probably wasn't allowed to play the Sega either. I was very sheltered, but I found ways and I had friends, so.
3:46 Scott Tolinski? I could watch The Simpsons, yeah.
3:48 Speaker 00 Yeah, we could tell, Scott.
3:49 Scott Tolinski? I am. I'm pretty much Bart Simpson embodied, right, guys?
3:52 Speaker 00 Yeah.
3:53 Scott Tolinski? You know, E my shorts and all that. Yeah.
3:56 Speaker 00 Okay, so that was a fun nostalgia and such, but I'm just gonna go ahead and show you. Here is my game running on Sega Genesis.
4:05 Scott Tolinski? Oh, that's so dope.
4:06 Speaker 00 I guess I'll also say that the modern world of retro gaming is kind of amazing. So I actually use this wireless 8-bit do controller, and it works with my Sega, so I can literally be wireless and on my Sega. So this is the game I made. Right now, it's just a single level, and you are the AI debugger called Sentry. So you're this little pyramid guy. And my idea with the first level is you go through collecting these little balls, and these are traces. So if you use Sentry, you know that you get traces in terms of like what's happening in your app. Like, was there a request on the front end or the back end? Was there a database request? All of that is traced. So the idea is you collect these traces as an AI agent, and then
4:52 Speaker 00 There would be another level where you can then use these traces to throw at a bug that you're trying to kill. Unfortunately, I only got this one level working, which is good.
5:04 Scott Tolinski? It's still dang impressive. Yeah. I gotta say, for people who are not watching this, if you're listening to this on the radio, CJ's not only just playing on a normal Sega Genesis, he's playing on a CRT monitor that has like, refresh scrolling going on on the camera. It is like, it's such an experience. So if you feel like you'll get more out of this in video, this is on YouTube, youtube.com forward slash at syntax FM, we will be showing things as well.
5:31 Speaker 00 Definitely. And this will be the last time I show you on the CRT, because it's really hard to see. The nice thing is you can actually develop inside of an emulator. I'll show you that. But basically, I was scrambling, this was like, 20 minutes before we needed to turn in our Hack Week videos. And so I was like, okay, I have one level, now I'm just gonna add some text. And so this says, this is where you'd go through all the other levels and then battle a boss, but I ran out of time. And so that shows up on the screen. That's the game that I built, and I had a fun time doing it. So I'll kind of like walk you through what's involved here, and also how I even decided that I wanted to do this.
6:08 Wes Bos? Yeah. I have so many questions about how, you know, like, I remember being a kid and being like, how do websites work? But I don't know that I ever asked, like, how do video games work? And it's so interesting to me that you can just make one.
6:23 Speaker 00 Yeah. And that's kind of where the idea came from as well. Because I, same thing, I never, I think, last week was the first time I was like, I want to make a custom Sega game. It had never crossed my mind, but I'm a developer. I've made games in the browser, I've made Unity games. Why not make a Sega game? And as I'll show you, like, the modern ecosystem for retro games is actually, it's pretty big and pretty approachable, I think. At least if you have a basic understanding of programming, you can do this kind of stuff. But I'll also show you the first demo that I got working was the syntax logo scrolling onto the screen. Yeah.
7:03 Scott Tolinski? That's so cool.
7:04 Wes Bos? Man. Because that was-
7:06 Scott Tolinski? And this is running off a cart right now?
7:08 Speaker 00 Yes, exactly. It's running off the cart. So I'll talk about how it's done, but basically, there's an SD card. I'll show you on the menu itself. So if I reset-
7:19 Speaker 00 I'm using a cartridge called the Everdrive and so it basically has a custom ROM on it. Where when you go to select game, this is reading off of the SD card. And so you can see I have two .bin files. This syntax .bin is just a game that loads the syntax logo and then seer bin is the full seer game. But whenever you load it, you choose it and that actually writes it to the ROM or the read only memory on the cartridge itself. And then reboots into that ROM.
7:49 Wes Bos? Man, and those, I don't know if you're gonna get into this, but those bin files are assembly code?
7:56 Speaker 00 I will say there are areas of this where because it was easy enough, I don't have the full understanding of it. But my thought is the bin files actually are binary, but.
8:06 Wes Bos? Compiled binary, yeah.
8:07 Speaker 00 Yes, compiled assembly code for the Motorola 68000. So the Motorola 68000 is the processor that's on the Sega Genesis. And to write assembly code for it, the Motorola 68000, there's literally a language that corresponds to that processor. That says like move memory here, store data here, all of that is specific to the 68000. And so your resulting Sega game are instructions for that processor. And then that needs to be compiled into binary so that it can, it can run on the processor itself.
8:40 Wes Bos? Okay. And, and those images, like I'm, like you're not just putting PNGs on that, right? They had to be converted into like byte arrays?
8:48 Speaker 00 Yeah, well, we'll get into it. So.
8:50 Wes Bos? Okay.
8:51 Speaker 00 Yeah.
8:51 Wes Bos? That's my question. You showed us earlier and I was like, I want to know how that happened. Go ahead. Sorry.
8:56 Speaker 00 Okay. So first of all, the way I even thought this was possible is when I, so I bought this Sega. And I guess if you've ever seen my backdrop, you know that I have retro computer stuff back there, right? I've got the Apple computer and then there's an IBM.
9:10 Speaker 00 First, like it's the 330, it was the very first personal PC. So retro stuff. And I had a Sega Genesis back there because like, you know, trying to relive my childhood or whatever. Uh, but I bought this. So this is the, uh, it's a, it's a cartridge that has, I can't, oh, I forgot. This isn't autofocus, but it's a cartridge that, um, has every single Sega game ever made on this one cartridge.
9:33 Scott Tolinski? Wow.
9:34 Speaker 00 Modern retro gaming has this, so you can get a Game Boy cartridge with every single Game Boy game ever made, or an N64 cartridge with every Game Boy game, or every N64 game ever made. So I already had that, so the gears were already turning of like, okay, if it's possible to store that much stuff on a cartridge, what are they doing? I opened this up early on because I was like, oh, is it just an SD card that I can plug in? But they have a soldered memory chip on the board itself. It's like a 4GB memory chip that has all the ROMs on it. But you can get cartridges like this for retro consoles. And that got me thinking, okay, if they can do that, then can I make my own game? And yeah, a lot of different ways to go about it. But I came across the SGDK.
10:16 Speaker 00 So this is the Sega Development Kit, created by Stefan de Longville. And he's a wizard. So he created GENS, which is an emulator for the Sega Genesis, Mega Drive, Sega CD, and the Sega 32X. And then he also created the Sega Genesis Dev Kit. And essentially, this is a C code dev kit that allows you to write C code that, at the end of the day, will be compiled into the Motorola 68000 assembly, which then gets turned into a binary. So the SGDK is what allows me to write higher level code to make the games. I'll say a little bit of nomenclature. I learned this as well.
10:59 Speaker 00 The name Genesis is what it was, what the console was called in the US. But in Europe and Asia, it was called the Mega Drive. And I learned that last week because a lot of these resources for creating assets and developing referenced the word Mega Drive. They don't necessarily reference Genesis. So anything you come across that's Mega Drive or Genesis is the same thing. It's just, that's how it was released, not in the US. And I came across this Git repo called Awesome Mega Drive that has everything. So there are people that have created tutorials for using the SGDK. There's like the original Sega Genesis manual. If you really want to get low level and like write assembly, like there's just so many resources for this.
11:40 Speaker 00 There's also like a YouTube video of a guy that wanted to develop games for the Sega the same way that they used to do it back in the day. So he found a Sega Genesis dev console. He has this whole chipboard that he like plugs in and he's able to like write it in real time. I didn't have to do any of that. Everything I was doing is just running on my computer in an emulator. And then eventually I put it onto an SD card.
12:03 Wes Bos? Okay, I was gonna ask that because like when I've done custom stuff for like a ESP32 microcontroller, there's no emulator for that. So you have to like compile the whole thing, load it onto the thing and then, and then boot it up. But like, what, what, what does the, the feedback loop look like when you're building a, a game? You can run it on an emulator?
12:26 Speaker 00 Yes, you can. So there are a lot of different emulators out there. And I would say probably the one hurdle I had all of last week is everybody doing this is doing it for Windows. Like there's barely any resources for doing it on a Mac.
12:39 Wes Bos? Yeah.
12:40 Speaker 00 And then like a few for like doing it on Linux. And a lot of times the Linux stuff can technically run on a Mac if you like recompile it. But that was my biggest issue. And so I actually am running an emulator using Wine. So Wine was originally developed for Linux. It's the Windows something layer. But basically you can run Windows applications on Linux and you can use Brew to install Wine on a Mac.
13:05 Wes Bos? Windows subsystem.
13:07 Speaker 00 So this is running an emulator called Gens. This is the one that Stefan made. But the nice thing about this one, it's called Kmod. And this actually gives you debug messages. And that's the main thing is like a lot of the other emulators, you just load the RAM in, your game crashes, what happens? This literally has the debug messages window. And so when you load a RAM in, you can actually see any messages that get printed out. They also have a debug window for looking at like, what are the sprites that get loaded in?
13:37 Wes Bos? Yeah.
13:38 Speaker 00 This emulator is one of the best ones for like making your own custom games.
13:42 Wes Bos? I watch a guy on YouTube who does like changing RAM values in NES games via an emulator as they're running. And it's like, he's showing how things like Game Genie worked or stuff like that. And it's so fascinating inside these emulators to see like what exactly is going on.
14:00 Speaker 00 Yeah. And so this is me running that same ROM right here in the emulator. And then one of the nice things about the SGDK is they have just a bunch of samples. So in the source code folder, there's a folder called sample and they have all kinds of stuff. So like basics, advanced, games. And so if you go into basics, there is a hello world example that you can just load into the emulator. Just prints hello world to the screen. And then we can actually look at the source code for this.
14:27 Scott Tolinski? Yes, please do.
14:28 Speaker 00 Yeah, so we have a main.c file. There is an int main. It accepts a boolean that's hard reset and then it uses vdp draw text. So vdp draw text is provided by the SGDK. You can pass in what text do you want to draw? Where do you want to draw it on the screen? So this says draw text hello world at x12 y12. From there, there is another built in method in SGDK called sys do v blank process. And this just runs in a loop so that it keeps the draw text, the text that was drawn on the screen itself.
15:01 Scott Tolinski? Oh, that's like canvas, except you, a very small canvas, right? Like, what's the resolution?
15:07 Speaker 00 You're 320 by 240?
15:11 Scott Tolinski? Holy smokes.
15:12 Speaker 00 Yeah, so let me pull up the, because I have a globals file where I store all of that. 320 by 224 is the screen width and screen height. So you're working with a very small area. Honestly, that's one of the nice things about a fixed area is you don't have to worry about flex box or like different device sizes. So like, when I write the text hello world to x12 y12, it's going to be in the same spot on everyone whoever loads this game because it's always loaded within that same.
15:40 Scott Tolinski? Right, yeah, you're dealing with a hard pixel resolution, yeah. Is that, is that why you like to position things fixed in our CSS paddles?
15:47 Wes Bos? Yeah. He's stuck on Netscape Navigator.
15:51 Speaker 00 Yeah, exactly.
15:53 Scott Tolinski? I wish, that's, yeah, it'd be nice.
15:55 Speaker 00 Yeah, so SGDK makes it this simple to write your programs. And then to compile them, you use a custom make file. So if you've ever worked in C, typically there's a file called make or makefile, and that describes how to compile this program. Yeah, so for example, if we want to compile this hello world example, when you set up the SGDK on your computer, it's going to put a makefile in a custom spot. And so you can say make-f and then specify that makefile. So, once I got the whole SDK set up on my home drive, there's a folder called build and there's this makefile gin. So this specifically will allow me to compile it on my machine. It knows where all the headers are.
16:37 Speaker 00 It knows where the SGDK source code is. And I can use that make command. So clean will delete the out directory and then debug will compile it in debug mode. And so I run this command. I have now compiled it into a ROM. And from there, I can go and reload it in the emulator. So let's actually just change the text to say hello syntax. So change the text, recompile, and then inside of the emulator reopen the ROM. And this was my life last week is just navigating all these directories.
17:12 Wes Bos? Does that drive you nuts when it's so slow to go through it? That always drives me nuts when like an app doesn't use the built in like macOS Finder.
17:20 Speaker 00 Yeah.
17:20 Wes Bos? And you have to like go through some tree structure.
17:23 Speaker 00 And that's one of the issues of running this emulator inside of Wine is like it's emulating the file windows to be able to like
17:29 Wes Bos? Right.
17:29 Speaker 00 to look at macOS directory structure and stuff. But I found it and now it's now the program says hello syntax.
17:36 Wes Bos? Woo!
17:37 Speaker 00 Yeah.
17:39 Speaker 00 So that's, that's, that's kind of the flow. Basically, write your code, compile, load it in the ROM. I will say there is a VS Code extension that I didn't end up using that tries to make this a little bit better. But all, like I said, all of this is designed for Windows. And so I think there is a flow, at least within this extension here, where you can point it to the emulator. And for certain emulators, it can like reload the ROM without you having to like go through file menus. So if you're on Windows, you're probably going to have an easier time. I didn't work on it long enough to figure that out. It might be possible, but right now it's like a three step process. Compile, choose the ROM, run.
18:20 Wes Bos? Dang.
18:21 Speaker 00 That's amazing. So that's the basics. Now let's talk about images and assets because that's what really, really makes a game. And the SGD makes this so easy. So built into the SGD is a subprogram called ResComp or Resource Composer.
18:39 Scott Tolinski? It's always funny how something like Resource Composer can get a cool ass name like ResComp.
18:44 Speaker 00 Yeah. Also, these docs are where I spent a lot of my time last week because they have all of the descriptions of like the functions you can call and everything else. But ResComp is just a separate program that gets run whenever you build the program. So part of this generated make file, inside of there, it has instructions that say, hey, let's look at the res file in this directory. For any resources like images or maps or sounds, we're then going to run those through the ResComp tool. And you can see that ResComp supports bitmaps, tilesets, images, sprites, and then various types of audio like WAV,
19:27 Speaker 00 which is like sampled audio, but they also support XGM, which is kind of like MIDI in that it's music that describes the notes and the instruments. And then that gets played through the actual synthesizer on the Sega itself, if you were to create your own custom XGM files. If we want to load an image, we could use bitmap. And inside of the res file, you would say bitmap, the name of the file you want to load in, and then the path to that image file. So let me show you my syntax example. So I'll show you the basics because the syntax one gets more convoluted because the image was too big to load into a single one. So I had to like split it up.
20:11 Speaker 00 But if you look at like this image example here, in the res folder, they have this file, a .res file. So in your Sega projects, you'll specify all of your resources. You say the type. In this case, they're using the image type. So if we look in rescomp, there also is an image type here. This next value is the name of the variable as it'll be inside of your C program. And then this is the path to that file. And then there's some other options like compression and how to load it in. So in this example, they're loading this SGD logo into a file called logoAPlib and logoUCOMP. When you run the build, that actually generates a header file. So let me run the build for this project.
20:55 Speaker 00 So we run the build, that looked at this res file and then generated this C header file. And so this is what actually gives us those variables that we can use in our program. So this gives us the logoAPlib variable and the logoUCOMP variable, which are of image type, which comes from the SGD. So with that, then you can write code that actually draws it to the screen. So in our main.c, in this case, it's using loadTileSet. So the way that it's loading in this slightly larger image is by turning it into tiles. And then under the hood, SGD is able to get all of that tile data and write the tiles to the correct location accordingly.
21:34 Scott Tolinski? Okay.
21:35 Speaker 00 The Sega itself works on 8x8 pixel tiles. So any image you have, if it's 8x8 pixels, there is a assembly code that says like load that 8x8 pixel data into a specific tile on the screen. And so SGD has basically abstracted all of that away. It's basically like, okay, take this PNG, turn it into multiple tiles. That's all going to be available in the compiled program. And then in our C code, we now have access to the tile set, which points to an array that has all of those tiles inside of it. And then we can, we can load it onto the screen.
22:13 Scott Tolinski? That's dope that it abstracts that because that seems like a pain in the ass.
22:16 Speaker 00 Yeah, so this loads it into memory. And then you need to actually draw it, you do, you need to do setTileMapEx. And this describes where you should draw it. So this is the other tricky part of writing a program is like you're constantly loading things either into like video memory or regular memory. And then you're writing code that can access that memory to then draw it onto the screen. So that's what this line of code is doing. It's saying, draw the tile map for that one image asset onto the BGA plane using a specific color palette. We haven't talked about color constraints yet. And then at this specific location. And then where do you want to offload it to? In this case, the CPU.
22:59 Speaker 00 So these two lines of code draw those images onto the screen.
23:03 Wes Bos? How many tiles are there?
23:05 Speaker 00 So it would be 320 divided by eight.
23:09 Wes Bos? Okay.
23:10 Speaker 00 Uh, so there are 40 tiles across and then 224 divided by eight would be 28 tiles down.
23:17 Wes Bos? Man, this is so dope. Yeah, what a like a resource constrained environment. Like I, I did a bunch of like Arduino programming in the past and it's, it's similar to this where you write C and you, I had to convert some of my like JavaScript files over to just like byte arrays. But like, that's, that's all modern stuff. That's crazy. This stuff is what 20? How old is this 25 years old, probably?
23:43 Speaker 00 Uh, the Sega itself was released in 89, so it's 34 years old or 36 years old.
23:50 Wes Bos? Wow.
23:51 Speaker 00 Okay, so that's how to draw images. I'll point you to some of the resources I found that were like super helpful to kind of break all of this down. Uh, this one's from Megacat Studios. I believe Megacat Studios actually released a modern Sega Genesis game. Yeah, so they had a Kickstarter, I, I think. I don't want to get this too confused, but basically
24:09 Wes Bos? Sure.
24:09 Speaker 00 They, they released a Sega game in the modern era and you could, you could buy it online and like play it on your old Sega. So with that, they have a lot of resources on like how to make your own games. And so this tutorial was great, uh, cause it talks about like, what is VDP? So VDP stands for Video Display Processor. We saw that in the method names like VDP set text. There's also vram, which is video RAM. So how you like load stuff into video memory. Um, and like I mentioned, you have eight by eight pixel images that are all of your tiles. Earlier I mentioned that you don't have to worry about resolution. That's really only if you're. Writing for a specific region because in NTSC, that's 320 by 224.
24:50 Speaker 00 But in PAL, PAL is 320 by 240. So usually Genesis's, Genes- Genesai are locked to a specific region. So you're building games specifically for NTSC or PAL.
25:02 Scott Tolinski? Right. And they have different frameworks as well, right?
25:05 Speaker 00 I believe so. So yeah, so 60 hertz on NTSC and then 50 hertz on PAL. So you potentially, if you're trying to do something according to the clock, it might be accidentally running a little bit slower on PAL versus NTSC.
25:18 Scott Tolinski? Unless you prepare for that. Oh, man.
25:21 Speaker 00 Yeah. But the one thing I want to show you that was really helpful from this guide is how to work inside of graphics on the Sega. So Sega actually has four different planes that you can draw graphics onto. And that's what gives you the, like the scrolling and parallax effect that you often see in games. So like if you know Sonic the Hedgehog, it always has that like light scrolling backdrop. That back area there with like the mountains and the water, that's being drawn onto BGA. Or sorry, BGB. That's your, your scroll background.
25:53 Scott Tolinski? You got Z-index.
25:55 Speaker 00 Yeah, exactly. So that's your like-
25:56 Scott Tolinski? You got Z-index for sure.
25:57 Speaker 00 And it was funny, interesting to learn about this because I was thinking, okay, is this an abstraction that the S G D K has made? But no, this, this is available to you on the Sega console itself. So it has that back BGB and then on top of that is BGA. So here where they're drawing the ground and the trees, that would probably be on BGA. And then there's also another layer called the window layer. And that likely is drawing like the text and like the heads up display. And then there's the sprite layer, which is your like moving parts and pieces. So the, the character itself would be drawn onto the sprite layer. And so you basically-
26:34 Scott Tolinski? You want to get into some crazy technical hacks? Look up, and I'll, I'll try to find a video on this. Look up how NES developers faked parallax on the NES because they didn't have access to these layers. Where the SNES did have layers like the, the Genesis did and, and yeah, that's a, that's a whole world. It's pretty dope.
26:56 Speaker 00 Yeah. So it was cool to learn this because now you can play around with that. And so the game that I wrote, there's a scrolling grid background. Like, I wanted it to look like you're kind of in the matrix, you're inside of a computer fixing bugs. So the scroll B layer is just a grid that's moving. Scroll A is the level itself. So I have a giant level image that I'm just like moving the location on. And then I'm using the sprite layer to actually draw the player that kind of like moves around. Any questions so far? If not, I'll kind of dive into a lot of the tools I wrote and show you some of the specific code for my game.
27:30 Scott Tolinski? No, let's see.
27:31 Speaker 00 Yeah, let's do it.
27:32 Scott Tolinski? Yeah, let's do it.
27:33 Speaker 00 Okay, so the first day was literally just me getting the thing to compile. So like, that was great. Day two was getting images loaded. And so that's when I did the syntax logo image. I got that working on day two. And then on day three, I was like, okay, I can run custom stuff now. How do I actually build a game? And that's what led me to some work that was done to create the platform engine, platformer engine by Jared Gascon. So they wrote this for the SGDK about three years ago. If you look in their GitHub repo, they have this folder called platformer engine. And this is basically just the source code for a Sega ROM. And inside of there is where they have all the hard stuff.
28:16 Speaker 00 So working with a camera, physics, having a player, being able to load a level tile set onto the scroll pane. So all of the hard work was done already. I didn't have to figure out how to do any of that because you could do all of this manually, right? You know, basically what scroll planes you have access to and you can put stuff into them. But it's a lot of work to figure out, okay, now we need a camera system and different stuff like that. So this was like, probably 80% of my code is using this engine that has the camera and the player and levels and everything else.
28:54 Scott Tolinski? Yeah, as somebody who's been building a platformer just for fun on Godot and like not using a starter kit, yeah, you gotta worry about so much stuff. Yeah, you really take it for granted. Like, ultimately, what I want is Mario Maker. Like, something that I can just click a couple buttons and have a video game and not do any of the work, but. Yeah, man, that there's so many little things that you don't think about until you get into it, especially with camera position and physics and yeah.
29:24 Speaker 00 Definitely. And so this example is actually the one that is included with the SGD. So when you download the SGD, there's a folder called samples and that's what had like this hello world and this image example. But if you go into the game folder, there's one called platformer. And this had all of that basic code for camera and levels and physics and everything. So my thought was, okay, I'm gonna start here as a base, but I just want to get my own level loaded in because I'll show you the game that you get with this platformer. And then you can judge me on whether or not I actually wrote much of my own code.
30:01 Scott Tolinski? Yeah.
30:02 Speaker 00 This is the the platformer example code. And let me plug in my controllers.
30:09 Scott Tolinski? Did CJ just plan this episode so he could play video game on?
30:12 Wes Bos? Yeah. Are you? Hold on, are you getting paid to play video games?
30:16 Speaker 00 I think I am.
30:18 Wes Bos? Have you? Have you had that realization yet?
30:21 Speaker 00 I haven't. I've been so knee deep in just like getting this done. We're gonna be at your right. I mean, I'm playing games at work. Absolutely. So this is the example that you get. My next thought was, okay, I want to I want to customize this. I basically, we have a working way to jump on the platforms and everything else. But like, I want to get my own tiles loaded in here. I want to be able to customize this map. That is the the next rabbit hole that I went down. Inside of this repo, the platformer engine is a folder called level. And I found out that this is for a tool called LDTK. And so this is a level designer toolkit file that you can actually load in. I think I uninstalled LDTK. Yeah, because I didn't like it. And it was very frustrating to work with.
31:05 Scott Tolinski? I currently have LDK, LDTK installed and also had a very similar experience where it's like, it's cool as hell. And it's like, I wanted to work so badly because of the promise of it. For me, it was connecting to Godot. I was having a hard time with that.
31:19 Speaker 00 It's cool. It's modern. I'll say that. Like, the one that a lot of people use is called tiled, and it works in a very similar way, but it's supported in a lot of other places. And spoiler, that's what I ended up using instead. But I started here because I saw that their example was using this LDDK file, and it had this tiles export file. So this one file here basically describes what all the tiles are. So if I want to turn this into my own custom game, it's just a matter of loading this into an image editor and changing what each of these tiles are, and then reloading the game and see, do those assets get applied? And part of LDDK is it takes that tile map, combines it with this LDDK file, and now we have an entire level that was designed.
32:03 Speaker 00 So I spent an entire day just trying to get this working with my own custom tiles, and I kind of got there. But the next thing that you'll run into is, okay, well, now I need collisions as well. So the fact that the player, when he goes to these specific platforms, is not falling through them, that means there's some collision data somewhere as well. And this example did not have that. If you look in the source code, it's literally just a hardcoded
32:32 Speaker 00 in-by-in array. Why? That's, I don't know. That's what I, like, that's why my first day was like, okay, now I'm gonna build a tool that can turn LDDK into a collision.
32:44 Speaker 00 This map.c file is just a giant 48 by 48 matrix that describes where all of the collisions are. So everywhere you see a 1 in here is where this, this player is colliding with a specific platform. Oh my god.
33:00 Wes Bos? What's crazy is I have CJ's video zoomed out right now, and I can, if you just look at that array, you can see the collision areas just by glancing at the array because the ones and zeros are like an ASCII one.
33:14 Speaker 00 So honestly, if I was a better planner, I would have just gotten this working first. I would have just been like, okay, let me just put a bunch of ones and zeros to design my own level and then like that, get that loaded in. But I wanted something better. I wanted to be able to just directly modify the tile map and then recompile my game and everything's good to go. And so that's, that's what I started working on next. And that's what led me to use tiled. So this is, this is my map loaded inside of tiled. It has multiple layers. So I have a background layer where I can define where all of these tiles go. And then you can, on the right-hand side here, you can see my tile map. So this is my cyberpunk inside the computer version of that tile map that we saw for the example game.
33:57 Speaker 00 And in here, inside of tiled, I can basically just like choose some tiles and then draw them on to a specific layer. And LDGK works in a very similar way, not as intuitive to use, and they have a lot of extra features, but that's my background layer. And then I could have another layer, which is my base layer. And so this actually draws where the, the platforms are, where the player can go. And then I have another layer called collectibles. So this defines where all of those traces should spawn. On top of that, I have a collisions layer. So this collisions layer basically says that for any one of those platforms, it should be a ground tile where the player does not fall through it. So I spent a whole day writing an importer that could take this TMX file defined with
34:42 Speaker 00 tiled and turn it into resources for the SGDK and load in each of these layers in a way where I could just use it directly.
34:49 Scott Tolinski? Wow.
34:50 Speaker 00 So, and so I guess I can show you, like literally, we could redefine the layer, compile it, and we're good to go. So like, let's just add some, some more stuff. Now I just save this file, recompile my game, load it into the emulator, and the, the level is, is ready to go. So I've kind of have more of a modern workflow in terms of being able to like change my level, change my assets, and then load that into the game.
35:15 Scott Tolinski? Man, I, I think you'd be interested in how Godot does some of this stuff too, because they have a built-in tiling thing, which my understanding is it's better than the way it used to be. But you are, yeah, you're on individual tile types, you're defining what those collision areas look like on a given tile, and then... You don't have to have a separate layer. I think some people still do it with a separate layer, but I believe you you're defining that collision on the tile set itself.
35:47 Speaker 00 Yeah, and I think I technically could do that as well. Like, basically, if tile ID is 35 or whatever, treat it as a collision versus trying to load the collision layer separate. But yeah, I think you could go about it both ways. But once I got that working, it's just a matter of like designing your level now because you can see I reloaded the game in the emulator and all of those spots now have those tiles appearing. And so it's really just a matter of go over to tiled, change what you want, recompile your ROM, and now you can you can play around with it.
36:18 Wes Bos? That is so cool. How appreciative are you of JavaScript and CSS now that you've done this?
36:25 Speaker 00 Much, but at the same time, I actually, I also appreciate how low, how low level this stuff is. And like with C programming, I mean, anybody that knows C that's watching this, I might make you cringe at this point, but basically, a C program is just everything's in the global state. So like every variable you define everywhere is available everywhere, even if it's in another file. So that's a little bit freeing as well.
36:49 Scott Tolinski? I like globals.
36:52 Scott Tolinski? The guy that likes globals, yeah.
36:54 Wes Bos? Yeah, like every, every image is in the global, you know, and like, everything gets overwritten. But like, I guess, how much C can you write before you fill this thing up, you know? You can't get in too much trouble.
37:07 Speaker 00 No, I mean, and the thing is, before I added the background music, my ROM was still only 128K, which the Sega ROMs can support up to four megabytes.
37:17 Wes Bos? Oh, wow. Oh, so you could, you could have gone, what, like, like 20 times bigger?
37:23 Speaker 00 Yeah, so like my example map, like I, I had big plans. You can see that my, my, my canvas was this big. So my idea was like each, each vertical layer could have been a different level that you're inside of with different collectibles, different enemies that you're fighting against.
37:42 Speaker 00 That's so dumb.
37:43 Wes Bos? I got a question about debugging.
37:45 Speaker 00 Yeah.
37:45 Wes Bos? The entire state of where you're at, that's just stored in memory. And I know that a lot of these emulators will allow you to just save a game anywhere. And is it just taking an entire snapshot of memory and putting it in? And is that how you were to debug like a certain level?
38:05 Speaker 00 Yes, but also we have logging. We basically have console logs, which I'll show you.
38:09 Scott Tolinski? But you're right about that, Wes. It is just RAM. And here's something really cool. Any video game that saved your progress on the Nintendo or any system that didn't have a memory card system. If the system doesn't have a memory card system, the way that video games saved your progress when you shut them off was by having a literal battery inside of the cartridge.
38:30 Speaker 00 Yep.
38:31 Scott Tolinski? So that the game wouldn't shut off. That crazy? Before that, they did pass codes, which the pass codes then reset the RAM values.
38:38 Wes Bos? And that's how like motherboards work still. You know, there's a coin cell that keeps time.
38:43 Speaker 00 Yeah. First of all, I'll show you what I ran into also and why this game isn't finished. If we open up the debug logs on here, I am running into DMA temporary buffer full errors because I'm trying to load too many tiles onto the screen. I know there's like a smart way to do it, but basically I have overloaded the video RAM with too many tiles because I have background tiles, foreground tiles, sprites. But this is the debug message log area. So you can see I actually have some debug logs when the game loads up. So the size of the map that has the collectibles and then those circles, I'm calling them traces. This is what your character is collecting. You can see the specific positions that it got registered from. These were my debug logs when I was figuring out how to load in
39:25 Speaker 00 that layer with the collisions and then positioning them in the right spot. And then inside of SGDK, there's a method called Klog. And this lets you just write things to that console that'll show up here as debug messages. So game is loading. I can define custom levels. I have this tile editor thing in the loader. But first, let me show you how I'm actually loading this level in. So we talked about rescomp earlier. It supports TMX files directly. So the SGDK rescomp has already been written to take in that TMX file. And this is one of the reasons I switched to tiled instead of LDTK is they already have a loader that can look at that file and then load it in to be used. The one issue that I ran into is if you have separate layers like this,
40:10 Speaker 00 they weren't accessible as exact arrays so that I could see like the X, Y coordinates of the collisions. Basically, it would load that data in, but then it would just be like in memory. I need like an in by in matrix so I can say, does this specific tile have a collision inside of it? So, part of ResComp is you can create custom loaders. And in their docs, they mention extensions. So you can write an extension in Java that defines a new resource type and then loads it in yourself. So, part of the code that I have written here, I have my own custom extension that defined the collision tile map resource type.
40:55 Speaker 00 And then also the map auto palette processor, which I'll talk about in a second. So when you, when you look at my, my resource file, to load that world map in, this is my custom type here, the map auto palette and the collision tile map. And then, this is just custom Java code, and I use the existing SGD Java code as a, as an example, that can load this file in and then create the correct C header files and C files that can then be used by my program automatically. So, that made it so that I didn't have to have a big in by in matrix manually updating in my code. I just set up the resource as a collision tile map, and then that becomes available
41:36 Speaker 00 as a variable called the collectibles map, or the collision map. And then, in my header file, these are all of the variables that get created to then be able to use them. So, this collision map is a tile map, then that then is used in my codes to determine when a player is moving, are they colliding with the ground? It basically takes in that collision map, and then makes it available so that in my other pieces of code, on any given tile, I can determine, is this a ground tile or a blank tile?
42:08 Scott Tolinski? Yeah, so this is, this is all just so... Dang different in a good way. I mean, I I've done game programming a bit, but like this is so like, I love taking little detours from our our our web dev world to see stuff like this.
42:26 Wes Bos? Yeah, unreal being able to like dip into all of this and to think that that's how these games were were were made.
42:35 Speaker 00 And it was even harder back then, too.
42:37 Wes Bos? Yeah.
42:37 Speaker 00 Yeah.
42:38 Wes Bos? Yeah.
42:38 Speaker 00 So, oh, yeah. This is hard, but it was even harder.
42:40 Wes Bos? Like, did they? They didn't have emulators. I guess they they probably have like a like a development units, right?
42:48 Scott Tolinski? Yeah, they're running on the computer. Yeah. If you're interested in this, folks, Retro Game Mechanics Explained. Um, there's a few YouTube channels that do some really cool stuff where they talk in depth about like, let's debug this, like one of them. Here's here's like a Contra game from the NES. It was like, uh, Contra 3, or it may have been whatever, and it has this lag. Let's figure out why it has this lag. And they go through the the ROM and they go through the code and they find out, oh, they're painting this in this way, and that's why it's creating this ROM. They could have done this to fix it. It's like the coolest stuff in the entire world because of just how intense the solutions have to be in the memory management and the tile drawing. It's so creative.
43:33 Speaker 00 Yeah. And this, I think, is the YouTube video that, yeah, so the the Sega Mega CD Development Unit. So this is one of the development kits where, uh, this is what developers would have on their desk when they were writing custom, uh, games for the Genesis, um, which also supported Mega CD. But as you can see, it has the the cartridge slot on the top, too.
43:54 Wes Bos? Yeah, that's crazy.
43:57 Speaker 00 Yeah. So, yeah, I think I've covered everything. The main thing is that it was also super hard and probably what took me the most time is is just graphics. So
44:04 Scott Tolinski? Yeah.
44:04 Speaker 00 I talked about like the different scroll panes and everything else, but the other thing to think to know about is your VDP color RAM. So the Sega Genesis supports 256 colors in total, so 256 unique colors. You can put any one of those colors on the screen. But for any given tile, you can only use up to 16 colors in that one tile. And you can only have up to four palettes loaded at a time. So on one single screen, you can only have up to 64 different colors being drawn on the screen. What that kind of boils down to is, to make it super simple, I just made it so that all of my assets use the same 16 colors.
44:48 Speaker 00 Because beyond that, you'd have to be swapping palettes and coming up with it. Well, actually, I have, no, I have two palettes. I have a palette for the tile set, I have a palette for the player, and then, three palettes, and then a palette for the traces themselves. And so that's basically three different color swatches, you could say, that I have access to, to actually draw things on the screen. And so because of that, in the early days of trying to get my custom graphics on here, it just looked horrible. It was like these weird inverted colors, and like, I couldn't figure out exactly how to get it into the right format. So I built a web app to help me with that. So this basically allows you to load a file in and then generate a palette.
45:31 Speaker 00 So you can see here, here is my tile set. This is the original tile set as it was inside of Figma. And then my tool extracts out the 15 best colors plus transparency. So, left-hand side is the original image, and basically what I did inside of Figma is I overlaid my own things on top of that original player tile set that was in the example game. So I'm putting my tiles on top of that to make sure they're aligned where they should be. And then I have various images that I used Mid Journey to generate, and I'm kind of like placing them there. So, work inside of Figma, but then once I have it inside of Figma, load it into my
46:13 Speaker 00 tool, generate the color palette, and then I can go in and decide, okay, that color there, I actually want that to be like a pink color. On the right-hand side is an image that is only using 16 colors in total. And how did you build this? Purely vibcoted. I did not look at the code. So this was made using Claude code. I was like, I had a whole prompt of like, I've got images, they need to be 16 colors, we need to extract the most commonly used colors, and then I just vibed my way into a UI that, at this point, would let me export it. And then that file is ready to go for ResComp. ResComp will read this file that only has 16 colors in exactly, it won't even error out, because it's just 16 colors, and then I can use it inside of my game.
46:57 Wes Bos? Man.
46:58 Scott Tolinski? See? Yeah. Yeah, this is what vibe coding is good for.
47:02 Wes Bos? Yeah.
47:03 Scott Tolinski? Dang.
47:03 Wes Bos? Building tools that you need quick and dirty, because you could have spent all week just building this tool alone. Right.
47:08 Speaker 00 Exactly. Exactly. Or the ResComp extension. Or I haven't showed you this, but I basically have these bash scripts that also use Image Magic to convert images. So like, like technically, the exported image here is fine, but it's not the exact format.
47:23 Scott Tolinski? Yeah.
47:23 Speaker 00 I can run it through Image Magic and make sure that the color bit depth is only four and it only uses 16 colors. And but yeah, all these, all these little one-off scripts, AI was perfect for that.
47:33 Scott Tolinski? Damn.
47:34 Speaker 00 Okay.
47:34 Scott Tolinski? CJ.
47:35 Speaker 00 Yeah, that's all I got. I think what I'll, what I'll leave you with is I, I got a game working. I'm proud of that. Uh, but there's like so much more I wanted to do. Um, what I learned is that Sega controllers are actually just nine-pin serial communication. And people have actually created projects where you can send and receive data over the controller port. Uh, and so I bought this custom cable. Like this is actually a breakout board. Um, that I was gonna like hook up to an Arduino and then like, uh, can't even, can't even get it open, but it breaks out wires from here to an Arduino and then I could like read and write data into the Sega. I wanted to do that.
48:13 Speaker 00 Um, also you could create a fully custom ROM. So there are these flash carts that have empty memory. And instead of like inserting an SD card, you could buy one of these by a flashing tool and then just put the ROM directly onto the cart itself. And then it'll just, it'll boot directly into the game. So yeah, I want to do that in the future. Um, and then get it connected to the internet. Initially, I thought it would have been so cool to like see your Sentry issues listed out on a Sega Genesis. But I didn't get there.
48:43 Wes Bos? Wait, how would you connect to the internet?
48:46 Speaker 00 Well, uh, either the Arduino or on the other side, you have like a Raspberry Pi. It's connected to the internet and then it could communicate over serial to like push data to the ROM.
48:56 Wes Bos? It would send the data over serial.
48:59 Speaker 00 Yeah. The thing is, uh, there is Mega Drive Wi-Fi. People have created a custom cart. So basically, uh, this is the thing that gets inserted into the Sega. They've created a custom one that has like a Bluetooth and Wi-Fi module on it.
49:14 Scott Tolinski? Wow.
49:14 Speaker 00 Yeah. People have done some crazy stuff with this thing.
49:16 Wes Bos? That's cool. Man, I, I saw.
49:20 Wes Bos? I forget what it was, but some, some conference, people had like the, the crappiest keyboards ever. Or, or like the crappiest way to transmit data. And it was just like, like, like one output and one input and you had to build something in between. So there was like some, like some physical stuff, some, some was like sending sound and, and receiving it. And like, like, I guess you could send any data over, uh, over just like ones and zeros, right? So that would be, you could just, you could send it over ups and downs as well.
49:53 Speaker 00 Yeah.
49:54 Wes Bos? Yeah.
49:55 Scott Tolinski? Ups and downs. Yeah.
49:57 Speaker 00 Last thing, I didn't tell you about the music. Because of ResComp, I could just load WAV files in. So I used Suno, which is like a music generator to come up with some, uh, eight bit sounding music. Turn that into a WAV file and then ResComp was able to load it into the game. I do want to play it for you because this was the other cool thing is like, just like modern, cool electronic music actually playing on the Sega. Cause back then we didn't, we didn't know about dubstep or like drops or anything.
50:24 Wes Bos? Oh, yeah.
50:25 Scott Tolinski? Modern cool music. We didn't know about dubstep.
50:28 Speaker 00 So, uh, being able to hear that kind of music on the Sega itself is also a trip.
50:36 Speaker 00 So the jump is like a hover sound. There's like a scan sound when you collect the traces.
50:52 Speaker 00 So yeah, that's the game. I had a ton of fun. There's so much more I want to do. Yeah. Oh, and I guess I didn't show this, but I made a physical box. I kind of showed that at the beginning, but like, at the last second, I was like, there's gotta be some way I can like, show what I built and like having a physical box where like printed some art on was part of it as well.
51:10 Scott Tolinski? Hell yeah, dude. Uh, wow. What a hack week, guys. We have a video game that uses hardware and software. We have a hardware and software LED crappy monitor, uh, LED panel that is so dope. And then, uh, coding game. And then we're going to actually bring on Randy to talk about his project in another video here. Because well, Randy did something very interesting. He built a whole thing. Vibe. He vibed it. He's not a developer and he built a whole usable thing. So it's going to give us a chance to talk to somebody who's coming at this from a complete non-developer perspective. So keep your eyes peeled for that one. It's going to be a lot of fun. Any closing thoughts or anything you want to hit us with CJ?
51:54 Speaker 00 No, I think what one thing I will do is get this game working on the web because there are emulators that can run in the browser.
52:01 Wes Bos? Ah, that'd be cool.
52:02 Speaker 00 Yeah, I didn't think to do that. I should literally have a site where you can play my dumb one level game. So yeah, I'll do that. Look out for that.
52:08 Scott Tolinski? I love it. Hell yeah.
52:09 Wes Bos? All right. Thank you so much CJ. That was super cool. Kind of tempted now to go try it myself. I appreciate that and we'll catch you later.
52:18 Speaker 00 Peace.
Previous 934: We Built a Real-Time, Local-Data, Competitive Coding Game Next 936: Realtime LED Wall With React + Websockets (I Let Strangers Control It) Page updated November 1, 2026 · transcript and summary are machine-generated