Grand Theft Auto III on the Dreamcast with Falco Girgis and Stef Kornilios Mitsis Poiitidis

8 May 2025 · 48 min

Ask about this episode

Ask anything about it. ChatGPT or Claude reads this page and answers with the times it was said.

Connect VO and ask about every podcast you hear, including the moments you saved. Add to ChatGPT · Add to Claude

In short

Podcast Summary: Grand Theft Auto III on the Dreamcast

Episode Overview Podcast Title: Software Engineering Daily Episode Title: Grand Theft Auto III on the Dreamcast Guests: Falco Girgis and Stef Kornilios Mitsis Poiitidis Description: This episode discusses the porting of the groundbreaking open-world game Grand Theft Auto III to the Sega Dreamcast, including technical challenges, development experiences, and the significance of the game in the gaming industry.

Key Themes

The Impact of Grand Theft Auto III

  • Released in 2001, GTA III revolutionized the gaming landscape:
  • Open-world design that allowed seamless exploration.
  • Combined mission-based gameplay with a living environment.
  • Cemented video games as a dominant form of storytelling and entertainment.

The Dreamcast and the Homebrew Community

  • Dreamcast was originally unable to run GTA III due to the lack of an official version.
  • The homebrew community took on the challenge to port the game to the Dreamcast.
  • The episode features developers from the GTA III Dreamcast port project, highlighting their backgrounds and motivations.

Development Challenges

Technical Hurdles

  • Memory Constraints:
  • Dreamcast has much lower memory compared to the original PS2 and PC versions (16 MB main memory, 8 MB video).
  • Developers had to compress textures, audio, and manage memory efficiently.
  • Graphics Engine:
  • Built a custom RenderWare backend for the Dreamcast.
  • Required implementing a new renderer to accommodate the Dreamcast's unique hardware capabilities.
  • Physics Engine:
  • The absence of a vector coprocessor on the Dreamcast required developers to optimize physics calculations using different mathematical techniques (e.g., using fast sine and cosine approximations).

Development Tools and Process

  • Utilized reverse engineering to adapt existing game code.
  • The team had access to:
  • Full reverse-engineered source code for the game.
  • Tools from the Calistios SDK to facilitate development.

Optimization Techniques

  • Developers shared insights on specific optimizations:
  • Transformation matrix optimizations to reduce unnecessary memory loads.
  • Custom profiling tools to identify performance bottlenecks.
  • Use of lambdas and contexts for efficient graphics rendering.

Community and Future Plans

  • Community Engagement:
  • The developers discussed their commitment to contributing back to the Dreamcast community.
  • Plans to support other games that use the same engine and middleware.
  • Future Directions:
  • Aiming to improve stability, including addressing memory fragmentation issues.
  • Potentially pursuing a port of Vice City, depending on community interest and technical feasibility.

Conclusion This episode offers a fascinating look into the intersection of gaming nostalgia and modern software engineering, showcasing the passion and ingenuity of developers who endeavor to bring iconic games to legacy hardware. The conversation highlights not only the technical challenges involved but also the community spirit that drives such ambitious projects.

Written by AI. May contain mistakes. Listen to the episode to check what was said.

Hear the part that matters, and keep it.Open this episode in VO. Double tap your headphones to save a moment as you listen.
Get VO free

Transcript

Automatic transcript. May contain errors.

0:00Grand Theft Auto 3 is a 2001 open world action adventure game developed by Rockstar Games and it had a profound impact on both gaming and popular culture. Its success cemented video games as a dominant form of entertainment and storytelling, and paved the way for future blockbuster franchises. The game was also a technological milestone that redefined what was possible in open-world game design. It was one of the first fully 3D open-world games to offer seamless exploration, blending mission-based gameplay with a living, breathing city. The game was originally released on PlayStation 2 and PC, but never had an official Sega Dreamcast version.

0:39However, the homebrew community embarked on the goal of porting the game to the Dreamcast and recently released the port to much acclaim. Falco Girgis and Steph Cornelios Mitzes-Poetidis are developers on the GTA 3 Dreamcast port. They join the podcast to talk about the Dreamcast hardware and the heroic task of porting GTA 3 to the console. Kevin Ball, or K-Ball, is the Vice President of Engineering at Mento and an independent coach for engineers and engineering leaders. He co-founded and served as CTO for two companies, founded the San Diego JavaScript Meetup, and organizes the AI in Action discussion group through Latent Space.

1:17Check out the show notes to follow KBall on Twitter or LinkedIn, or visit his website, kball.llc.

1:36hey guys welcome to the show hey thanks for having us thanks for having us yeah super excited to dig into this let's maybe start with each of you giving a little bit about your backgrounds and how you got into the sort of GTA 3 and Dreamcast world. So I'm traditionally a Dreamcast emulator developer. That means I have implemented the Dreamcast in software. That started as a childhood project. Actually, it's been ongoing for 20 years, this involvement with on and off periods. And after I kind of withdrew from that scene because I decided that other people are now So on the forefront, I don't want to do the emulation aspect so much.

2:18I was like, okay, what can I do to make something run on the Dreamcast this time? You know, play the other role. And that's how this happened for me. Awesome. What about you, Falco? All right. So I'll start off saying I actually taught myself C and C++ at age 14 because I specifically wanted to make Dreamcast games. When I was a kid, this was before there was like an iPhone market. this was before Xbox Live Arcade. There was no way for an indie developer to target a console ever, except for this Dreamcast thing, which was just recently discontinued, right? And I found this scene of developers like Steph, like so many others who are doing really cool stuff in this Dreamcast community.

2:58And I was 14 and I made a forum post, hey man, how can I make Dreamcast games? You know, do I use Pearl or whatever? And they're like, God, no, you C and C++. So I used to walk to the library to get books on it. And like fast forward way too many years. And now I helped to maintain the Calistios SDK where I used to use that SDK when I was a kid to do Dreamcast development. And for me, Steph, I knew about him and what he did and his emulator work. And every time he was in Discord, I knew, wow, this guy is really, really impressive and knows pretty much everything ever about the Dreamcast. And then he started working on a GTA 3 port, and I'm just watching from the background, and everyone's doubting this guy.

3:41And I knew that if anyone could ever pull this off, it would be him. And then I saw some other developers who were just, man, like A-tier rockstar Dreamcast people coming. And I just knew, oh my god, I have to be a part of this. Like, even if it fails, it's what a privilege to be a part of something like that. Nice. So let's maybe talk a little bit about GTA 3 and what makes it such an undertaking to port it to Dreamcast. So, yeah, there's various aspects. First of all, we are starting from the PC version. That's the reverse engineered one. So the requirements are substantially higher, especially on memory.

4:19And also the models are a little bit more complex, but it's mostly memory. Like audio memory, the sound effects don't fit. Texture memory, the textures don't fit. System memory, the game loads too many models in it. You want to tell them exactly how many megabytes we're working with? We have 16 megabytes of main memory for everything, and then 8 megabytes for video, but that's also for the transform models. So it's like at the end of it, we have like two, two and a half megabytes free for textures and a little bit less than two megabytes for audio. That's like very small specs compared to even then PC standards.

4:57Yeah, I think those of us who are in the modern world now, that's like mind bogglingly small. But I'm kind of curious, like if you look at, okay, what was this originally shipped at? How much of a downsize are we looking at here? The PS2 version that was the most compact version, it shipped for 32 megabytes of RAM and similar audio and video RAM sizes like the Dreamcast and the PS2 are not directly comparable, but they are similarities. But twice the RAM that's what we have. So we have to compress things further. Yeah, PS2 had 32 meg system RAM and four megabytes of video memory. But that gets complicated because Dreamcast, you have to store other things in video memory.

5:37I'm sure that will be something Steph talks about where it's not, oh, you have eight megs of video memory at PS2 at four. You know, why is that a problem? But yeah, I'm sure we'll get into that. Okay. So memory is a big domain. What other aspects of Dreamcast were different enough that it involved a substantial porting effort? I'll say one thing that I am working on that, oh man, I'm still working on it. because I didn't want to screw up the alpha release by pushing for it without too much testing because if you mess this up, it's really bad. And for the stability of the game, it's physics engine stuff.

6:11We can at least see in our code base where they were using a vector unit in the PlayStation 2, a coprocessor that is a little bit like a DSP and how you'd program for it. And they were accelerating a lot of like the collision check, stuff like that. We don't have that on the Dreamcast, no vector coprocessor, But we do have some pretty cool instructions that like a very fast sine, cosine, approximation, inner product of vector dot products, two 4D vectors and one instruction, things like that, to where you could start accelerating some of that math. But the only problem is, like I was saying, those are approximations.

6:50And when the approximations are too approximate in like a physics engine, that things go very poorly. But luckily, actually, this works. It seems to be a very stable physics engine. Unless I do something just really stupid, like forget to copy a sign because some inverse square root. There's a really funny approximation trick. A floating point division on the Dreamcast. Steph, how many cycles? I think it's 20-something. I have to ask him because I don't know how many. It's quicker to use. Are you familiar with the Quake 3 inverse square root approximation? Why don't we spell it out a little bit?

7:26Because not everybody will be. Okay, yeah, great. And Steph, correct me if I'm wrong. I'm not exactly 100 % sure, but the folklore is that this really crazy integer bit shifting, I don't even understand how someone could figure this out. Approximation for an inverse square root, it's very fast. And taking a real inverse square root or even a square root is extremely slow. So they figured that out. And that's very fundamental for doing things like normalizing a vector that you can multiply by the inverse square root. And the cool thing is on our FPU on the Dreamcast, that's one instruction. F-S-R-R-A.

8:04What does it stand for, Steph? I actually have no idea. Something reciprocal square root. Anyway, so it's faster for us. A division is like painfully slow. It's faster for us if the sign does not matter to multiply a number by one over the square root of itself times itself, if that makes any sense. That's kind of hilarious. Right. So I'm sitting there in the physics like, hey, maybe I can, you know, get rid of some of these divisions. And luckily, it looks like so far, it needs to be soaked a lot more. But it looks like as long as you don't actually need the sign, because you're losing it with the squaring and square root, it looks like it's pretty good.

8:43So that I think the level of optimization that we're talking here is almost it's kind of hilarious but it's endemic to building for old hardware right you're trying to take something that could not do this and squeezing every extra erg yes just wait till steph talks about what he did for the tnl the transform and lighting i think it's one of the most glorious things i have ever like if ever i wanted to see code that was like yeah this is why i'm on this team it's what he did there it was just really cool stuff well so let's maybe start at a bit of a high level, when you're doing these types of transformations, like where are you starting?

9:21Do you have original source code or do you have just a binary and you're intercepting there? Like what does this process look like to get to, oh, I have a bit of a game to run, but it's stuttering here. So I need to intervene. Like what is the flow of development? We had the full reverse engineer source code for the game by the Airy3 project. And also we had the fully reverse engineer code of the game engine that they used, the LibarW project. Without these two projects, this would have been a totally different scope. Like the Dreamcast port is a small addition to the previous work done. After finding those projects and getting everything to compile together, the rest of it was pretty straightforward to get to the menus.

10:03And then it was just we needed a new renderer for the game engine because it doesn't support. That's one of the other major chunks that we had to write, the renderer, because the game engine, of course, it only supports OpenGL, Direct3D, and it has some beats for Xbox and PS2, but only some beats. And we had to bring in support for all of the custom texture formats, the graphics card support for the Dreamcast, implement the pipeline tools to convert, to repack everything to the Dreamcast optimal formats, then actually go ahead and write the transform and lighting pipelines and submit the vertexes to the graphics card.

10:38That was the major part of the work. You know what's really cool is this driver-level graphics work he's talking about is actually separate from the GTA 3 codebase, or the reverse-engineer RE GTA 3 codebase. It's actually part of something called RenderWare that was a very famous middleware that was used in that era. So we actually made our own RenderWare backend for the Dreamcast. That's kind of cool. Yeah, actually, let's talk about that. So you're building these pieces that are specifically to adapt it to the Dreamcast. Are those reusable for other games? In theory, yes. We don't have any other projects.

11:14I mean, there is one other project using the same engine and it's the GTA 3 Reversion Engineering for, is it Vice City? What's the name? Yeah, Vice City. Like the Miami brand, Vice City. So that's another project that uses the same rendering library with some changes, but similar enough. And there are a ton of other games that use this library, especially back in the Dreamcast age. It was a very dominating library for PS2, Xbox and GameCube. so there is hope that more games will be reversing near and then use it and also ideally we would contribute back upstream so independent developers could also use LibarW to develop their own applications right their own games that was one of my motivations for wanting to be part of this team too is like okay we have this team of alpha dreamcast developers doing this like crazy lighting and we're pushing a lot of polygons and we've implemented this middleware layer and you know can we help democratize like the upper echelons of the Dreamcast hardware for the rest of the community with some of this work that we've done for GTA 3 and I think the answer is yes you know I think this could benefit the Dreamcast indie scene like as a whole.

12:26So let's maybe dive in a little bit to these different pieces and tell me if I'm wrong here but I think what I'm hearing is one, there's like big chunks that were missing for Dreamcast that you're able to sort of implement as a package. And those you can plug in your architecting in a particular way. And then there's other places where you're like, okay, this is maybe part of the game code or doing something, but it's too slow, or it's taking too much memory. We are both doing it cleanly implementing on a driver boundary. And then on the other hand, we're going in with the sledgehammer and game code too.

12:58Yes. Yes. So let's maybe like talk about for those driver pieces, like what does the architecture look like? What were some of the interesting sort of technical challenges to get this to work? And maybe for someone like you, Steph, who's deeply familiar with what the Gamecast is, it's just obvious. But for those of us who aren't, like what does that whole piece look like? And then we can come back and look at those places where you're taking in the sledgehammer or the scalpel to tweak things. Well, for the Dreamcast, for the LibarW, it actually follows a typical pattern similar to, let's say, a modern game engine would have, like Unity.

13:34It has a scene graph of transformations that have child objects. I mean, they call them atomics, they don't call them objects. So at the lower level, you have to provide basic initialization functions like query the driver for the screen size and things like that. And also it has three rendering paths. one for immediate mode 2D graphics, one for immediate mode 3D graphics, and then one for the Atomic rendering. And you slowly have to go through and implement those parts. And to get into slightly more detail, an Atomic is made up of a mesh. A mesh has an index buffer, which is the indexes of the geometry, and a vertex buffer.

14:15So you look up the index, and then you fetch the vertex, then you transform the vertex, and you send it to the graphics card. That's the basic flow. and you do this for every mesh, for every Atomic that the game engine asks you to. The game engine itself is pretty straightforward, to be honest. You register the renderer as a plugin to the game engine and it will call your callbacks. So as long as you register all of the correct plugins, then you will get all of the callbacks. And if you implement them correctly, you will get your scene rendered correctly, right? For the Dreamcast, there's some major problems.

14:46like the Dreamcast doesn't render all of the types of geometry in the order you submit them you have to sort the geometry into opaque, transparent and alpha tested and this creates some problems with the ordering of geometry because the game expects things to be rendered in the way it sends them and then we have to split them into lists. And that's universal for any port to the Dreamcast like that's fundamental to our architecture like we sort our geometry by lists that are opaque, translucent, and there's a third list punch through. Punch through. Yeah. Got it. Okay, so where does that, you said most of the game engines aren't going to expect that.

15:26That's a Dreamcast limitation. So at what layer does that transformation happen? And is it transparent to the game engine? Or do you have to go in and then start doing those interjections later? Well, this is where Steph at first was doing something cool where we were deferring everything, right? if the Dreamcast needs it in a certain order, then you have to capture the pipeline state of what you're trying to draw, the vertices that you can defer it until it needs to be drawn. And our first cast, Steph had some stateful C++11 lambdas that were just like capturing the whole pipeline state. It was like, it wasn't really what you would want for high performance code, but it was like, man, that is a really useful use of a stateful lambda right there.

16:11and then he placed them into standard vectors and then he could iterate over them later when he needed to. It's also mostly transparent to the game engine. We did have to modify the game a little bit, like in the places where it expects certain depth ordering, like, for example, the fog. It rendered it at a predefined depth and it expected this to be the minimum depth, but it did this in the wrong order of things, so we had to help it there. but for the most part it works out of the box the reordering okay cool and so to make sure i understand it you sort of implement kind of a middleware that's capturing these things as they're coming in then you sort them in the way that the dreamcast expects and send them on the way do you have like a size of buffer or is it over a per frame or like how does that it's just a vector right now it's dynamic at first but he is doing a clear but he's never doing a shrink to fit on the vector.

17:05Okay. So once it's kind of stabled out, it's basically like a static. Nice. Okay, cool. Any other of those sort of big driver layer? Well, on the driver layer, like Falco mentioned, we had this capturing lambda stuff, and it was wonderful from a language perspective. Yeah, right. It was the ultimate modern. We got a lot of stuff, man. Why do you need? When I joined the team, I was the guy who went into the make file and was like, whoops, C++23. and it caused so many problems because our host compilers couldn't support that for the tool side, you know? So I had to back it down to C++20, like, okay.

17:42And people asked, what good is that going to do you for this project? And that was right there, you know? It was pretty nice. The thing is that I unfortunately had to move away from that to avoid copies because we spend a lot of time copying the lambdas around and do it to several intricacies of the lambdas. you can't have zero copies when you can select them into a vector. So now we use this concept of contexts. So for every atomic, we create an atomic context and we attach some other contexts like a material effects context, if it has reflections, things like that. And then we capture only the context number, which is enough for us to recover the information.

18:23But from a functionality perspective, that's how the driver works. The other part is how we actually submit the geometry to the graphics card that is interesting. Because like the normal way is that you de-index the buffer, you fetch the vertex and then you transform the vertex and then you send it to the graphics card. Then there is a smarter way that you can transform all of your vertices. Like usually you have more indexes than vertices. That's why you have indexed buffers. So the smarter way is you transform all of your vertices at first and then you de-index them and then you don't have to transform them twice if they appear more than once.

19:00And then we did this approach where we sliced our buffers in 128 vertexes, which was tricky because we had to regenerate the topology of the mesh a little bit, like to cut it into chunks in a way that doesn't generate too many more vertexes, too many duplicates. It's a trade-off everywhere. And then we handled this at 128 vertexes, which actually can fit in the cache. So we freeze half of the cache with some tricks. Then we transform into the cache. And then instead of doing a memory copy for the index, we directly send the cache to the graphics card, like send the cache line. Yeah, I think that was the most mind-blowing thing.

19:41We have a mode where he split the cache in half, right? And then we can manually control what goes into the second half of cache. So he preallocates this above where the GPU expects the vertices to go. And he does all the TNL there. and then to send it to the GPU, cache flush. It blew my mind. Yeah, you just blew my mind. So if I'm understanding, you're essentially splitting the cache into two logical sections and using one of those to essentially prepare all of your data, which you can then just flush straight to the GPU. Yeah, in the order that you want. Yes. Isn't that crazy? I've been doing Dreamcast stuff for a long time and that was pretty crazy to me.

20:23Yeah, this is getting down to a level most of us never touch in terms of control over your hardware. So one of the things you said a little bit ago, Falco, made me want to kind of dig in. What does the kind of build chain tooling environment look like building for this? Okay, that's where I come from is I work on the, it's called Calistios. The Dreamcast community is kind of unique in that no one uses the commercial stuff in our community because not to brag, but our stuff is pretty good. our open source stuff, it's been around since 2001, right? It was around back when Sega was still doing Dreamcast stuff.

21:00So it's had a lot of time to mature. There's a lot of stuff in there, like supporting IPv6, supporting different mods and things for the Dreamcast, the hardware mods. Like my Dreamcast actually has 32 megs of RAM. So I don't know about this GTA 3 out of memory stuff. I'm just kidding. But yeah, we support a lot of hardware modifications that have come around for all these years. And one thing that we're pretty passionate about is keeping our tool chain up to date. Like the Super H4 is our architecture and it's still maintained in GCC, believe it or not, because it's used in Casio calculators and it used to be used in set-top boxes and routers.

21:38So it never really went away from the GCC tool chain. So we actually like, oh, GCC 14 2.0 came out the other day, I think it's 2.1 now, we had a midnight launch like, oh, hey, you can already use this some preview like C++ 26 features on the Dreamcast. You want to do that? Yeah. So we nerd out pretty hard about our tool chain stuff and our tool chain support. And the crazy thing is we're not the only ones either. The Nintendo 64 community is pretty much on the tip. The PlayStation portable community, some guys I know on the Saturn scene, I don't know what it is. When we're with retro hardware, We like to not be retro with the software in.

22:14That's awesome. Well, and I think, Steph, you mentioned you started out kind of on the emulation side. So are you able to run all of your test suite, whatever you're doing with this, on an emulated piece of hardware? Tell them about all of it. There's several layers of inception in this. But yes, I maintain a fork of my old emulator. It's no longer the best emulator for Dreamcast. But it's one I'm very confident within the code base. So I maintained that just for this project. So every feature we use, I add to the emulator, like these cast tricks. I added them to the emulator. And also, we have added a lot of validation.

22:52Like every time we have found a mistake in how we have the hardware, I try to add the check-in to the emulator. So that next time we do the same mistake again, it will warn us about it. And it was extremely useful. There were times we were stuck. And it's not so easy debugging on the Dreamcast. that, yeah, a lot of people, we have a lot of people who are like, oh, I print FDebug exclusively. We have a GDB stub, but it's not the best. It's lacking a lot of features. So Steph's inception of his virtual Dreamcast really saved our butts many times. It helps. And we can also cross-compile for PC. I mean, the code base originally worked on PC.

23:28So we did the splice thing together, like take some parts of the emulator and then splice it with the rest of GTA. so we can run into this hybrid mode where it's actually the CPU is running native but the graphics is running through the emulation and this means we can use tools like Valgrind or Address Sanitizer. A couple of bugs have been found this way. Like the memory, we had the memory leak of a matrix. There's no way we would have found where it came from without Address Sanitizer. So there's this tooling that has been developed for the project around the Dreamcast simulation that I'm familiar with and this has really helped us, yes.

24:05I think his emulation background has helped in every, you know, I have started from like indie. I haven't seen this big picture he's seen where he has had to emulate all of the AAA titles. So he knows all their tricks, you know, it's been fantastic just learning from him from that perspective. Well, and one of the things that stands out to me here is like hardware quirks, right? Things where it doesn't actually work as advertised or like, I don't think I would have ever thought about going into the abstraction layer of the cache and like splitting that out and taking separate. control of different pieces, right?

24:36So I guess that would be an interesting thread to go down is like, what unexpected hardware quirks are there within the Dreamcast? And how do you end up having to work around those? How does debugging those work in terms of the emulator, things like that? Well, hardware quirks, to be honest, most of them are handled at the Calisti OS level. Like there are some known hardware bugs, they are handled in the initialization layer and everything kind of works out of the box. The one we run into is that, so the Dreamcast has, apart from the cache, it has these two buffers called store queues, where you can collect some data and then write it all together as 32 bytes into the memory, the graphics card, whatever you want to write 32 bytes.

25:19It's like an ultra fast 32 byte mem copy or mem set, if you use it like that. They alternate and you can write into it and flush one. While one's flushing, you write into the other one and they alternate. And it's just, it's a really cool thing. But you cannot read from it. So I learned. It sounds like something you learned through pain, perhaps. And you also can only write 32 or 64 beats at them, like four or eight bytes. You cannot write two bytes or one byte, for example. And these are quirks we have in the emulator. We have them assert. Like if you use them, it goes and says, hey, you're doing something that you shouldn't be doing.

Read the full transcript

25:59Another example is null pointers. Like null pointer is usually a zero pointer. And that is a pointer to the BIOS in the Dreamcast. So you have a null pointer read, you're reading some data from the BIOS. Nobody minds you doing that. And we also have warnings for both reads and writes for that on the emulator just to catch this edge case. We could actually do this in KOS. We could install an alt-pointer page, but we don't. All right. So I think we've talked a lot about kind of the systems and the systems we had to do wholesale replacement. Let's maybe now get back into where you're having to go in and bring out the sledgehammer or the scalpel, make optimizations either in original game code or heard a lot about transforming the formats of your textures and other things.

26:48So like, what are the things that you're doing now that are no longer cleanly divided by, okay, here's the subsystem, but that you're still having to dive in to get this thing to actually run on the Dreamcast? Well, for the texture conversion tools and like the repack process, I can give some detail. I think most of the other optimization Falco has worked more on the actual game code than me, to be honest. But for the Reapack process, we copy-pasted the game loaders and made a tool that loads the textures. And then we're using some community tools. I don't remember who wrote PVR text or what's the thing you use.

27:26I think that's TapamN, but I'm not positive. Yes, TapamN is an awesome developer for the Dreamcast. They also tried this cast submission trick that we're using years before we did. I saw that in some forum posts, but ours is the first used in a real application. Also, the same thing goes for the audio files. Like we process them into a custom format. I wrote, well, for the audio files and the image formats, I actually used the ChatGPT to write the unpacking tools and the repacking tools. And what did you know? It worked on the first try. But then for the audio conversion itself, like compressing the audio, We use some tools that come with CalistOS.

28:07We just modify them to handle our peculiarities in the format and down sampling the audio if we have to. Things like that. At that level, it was mostly plumbing work to get different tools to work together and then make files where you can parallelize that work and have it in a nice experience for the developers. Got it. And is that then essentially build once ahead of time? time it's packaged you ship it and it's done or are there any dynamic aspects to it that need to be handled in the make file you can build a cd image directly from it so if you ask it to build a cd image it will pick the repacking tools it will build the game itself it will build everything it needs it will link it all together then it will run the repack tools then it will take the output and it will make a cd image for you nice falco can talk more about the game code itself i think Okay.

29:00Well, the first thing I did before I even jumped into that stuff was, I don't know if you know or if people know the Dreamcast memory card, the visual memory unit. No. So in the controller, you see how there's a screen? I can see it, but our listeners will not be able to see it. So let's describe it. So anyway, we have a very interesting memory card that looks like a Game Boy, and it even has a screen on it. So when you put this thing in the controller, a game can actually drive it as an external screen. and born partially of laziness and like, oh, I don't want to mess up the UI. And then partially out of, I think this would be cool.

29:36The first thing I did is I started displaying debug information, like performance information on this little visual memory card. So I didn't have to pollute the UI or have to figure out how it worked or anything like that. So that's one of the things that's even ongoing for me is I have a background thread that I spawn. It's like a C++ standard thread that wakes up every, I believe it's 200 milliseconds, checks in on the system. How much memory do we have left? Video memory and sound memory. Displays it, updates that little screen, goes back to sleep. I've been doing that for a bunch of other stats so that going forward, we know where to focus micro-optimizing things.

30:14I would say in terms of one of the most interesting things that I had to work on was for this physics stuff, the collision, the math for that was implemented. One of the most important things you can do is you transform a vector by a matrix, and that can be for the vertices, for the collision meshes, for the renderable meshes, for anything like that. That's one of the most fundamental operations in the engine that you can do. So this was implemented through a C++ overloaded operator that took a matrix that was on a matrix, and it took a vector. And I will say this was not inline. One of the problems we had was the way the matrices work on the Dreamcast was you have a background bank that you load, and then you can swap your active bank register so that it's undisturbed.

31:06So if this overloaded operator was having to reload the matrix to multiply it by one vertex, and then it gets called again, it reloads the matrix again, multiplies it by one vertex, usually you have a loop of like, could be like 50 verts being multiplied by one matrix. So I had to basically break out this or C-ify this C++ pattern. Wasn't to my liking. I wanted to build all the nice C++ stuff. But I had to make it basically take an array of vertices, an input, an output, and the number so that I could load the matrix one time and then swap banks, go through and multiply every vertex, and then swap back.

31:49And that, yeah, that was pretty wasteful before that was optimized more for the Dreamcast. But that was more precision thing, I would say, than a sledgehammer thing. Because, yeah, touching that code is pretty sensitive. So to make sure that I'm understanding, essentially there's like conceptually a cache. You called it a register, but like a matrix register. Yep. Kind of a little cache layer that loads the matrix. And previously what would happen is every time you would go into this code, it would spill your cache and you'd have to reload it. And so what you said is, hey, let's pull together all the operations we're going to do on this matrix so we can load the cache once, run through them, not have to keep spilling memory in and out of there.

32:28Yes, yes. Not have to keep loading and unloading that matrix into that cache area that you're talking about. Yeah. That makes a ton of sense. How did you find that? Well, to be honest with you, that's just something I've worked on this math abstraction before for our OpenGL driver. and I'm kind of used to like the load once, multiply while you're in it and then unload or load the next one pattern. And when I saw this like pretty little loop of invoking an overloaded operator, I was like, I don't, cause that's what I wish I could do, right? I'm like, man, if they're doing this efficiently, I need to know what the heck is going on here cause I can't.

33:07So yeah, that was kind of a red flag. You're like, man, I want to be able to do this. how are they doing it to make it work oh it's not working yeah exactly exactly got it okay that's cool that's an interesting example and so in that case i guess you're starting with source codes so you just go and rework the source codes you're saying instead of this we're going to just inline this into this function go yes exactly got it they wouldn't want this upstream if this were still a maintain thing we would have to make some prettier abstractions or something but you know we did what we had to do in that code well and that's actually kind of one of the places i was wondering is like to what extent can you abstract these things because like i did another interview recently with folks doing they were more in the like game emulation space and taking it and they starting from a binary rather than starting from source code so they had to use different tricks but they did a lot of like okay let's swap in you know we have this function call we're going to replace this function and go down a different path when you're working in these like we talked about a hack around for division, right?

34:08We're not going to do division. We're going to multiply by the inverse square root times itself so that we can just do a multiply and an inverse square root because those are fast. Like, are you able to do that at an abstraction layer where it just kind of applies across all the physics code? Or are you going in and finding all the examples where they're doing a divide and having to update those? You want to go first, Steph? What would you say? I was going to say there's trade-offs and especially so with that divide actually now in the code base, I have a C++ template that takes a non-template type parameter for whether it should do an actual divide or a BS divide, right?

34:46So I can kind of, if I break something, I can, oh God, change that to true, change the default on that one to true and I can go down. and that should not be extra overhead, right? Because it should be just a template that's like expanding into a couple of, I say should, I have not verified the code down both paths. So maybe there's an extra move or something. I got to look, but that's an example of when templates can do it. What would you say, Steph? I'm sure there's more runtime examples with stuff we couldn't really get away from or that we did. Well, for me, it's also very manual, this work.

35:22Like usually I go in and manually change things, put them behind the define or a template, something like that. It really depends if you care about having the code maintainable or not. If you don't really care about maintainability, like we don't really care if the code is a little bit dirtier, it's not going to be worked on further. So then we can just use the simplest approach that works. And then how are you sort of finding these opportunities? You mentioned a little bit about you've got kind of the DIY profiling tool coming onto the memory card, which I love. And in some cases, they're just like your pattern matching based on things that you've been doing before.

36:03But are you doing systematic profiling? Is it gameplay that's driving? Oh, it's getting sticky here. Like, how are you finding the places that need optimization? We have a profiler that is passed down from some other developer to me. And I modified it. And now I'm passing it down to the next developer down the line. It looks similar to GPROF. When I got it, like when SWOT gave it to me, it was compatible with GPROF. So you could use standard GPROF tools to analyze the stresses. After the modifications I did, it's no longer compatible with GPROF. But I nicely asked chat GPT for a tool that can analyze the reports.

36:42And it kindly made me one, as it does sometimes. So we have that tool and it's able to take in a full disassembly of your executable, like with OBJDump. And then it can annotate for you the lines where it gets hits on the profiler. So you can even see on hot functions, you can see individual assembly opcodes and how long they take and things like that. That helps when your operation is concentrated into function. but for the cases like Falco said when you have little cuts spread over the code then the profiler doesn't really help with that. Like it doesn't really have the, we only sample a thousand times per second.

37:27That's 60 frames per second. So that's, I don't know, 20 times per frame. That's not really enough context to understand what's happening in a frame. Like only statistically. So you try to stay still and you hope that the statistical profile will help you. So when you're running the profile are you running that in your emulated environment? Or like how much overhead does it take to run the program? Oh, I knew that question was coming. Well, for the VMU one, I will say I kept that thing really lean, except for I have a change I've been sitting on where there's a shortcoming in the C++11 threading API where you cannot set the stack size by default.

38:03You can't say I want to make a thread with this large of a stack. So we're blowing a few kilobytes that we should not be blowing every time we make standard threads and the VMU thing is sitting on a standard thread. Other than that, the thing wakes up so infrequently. It's like 0.02 % CPU overhead. I keep an eye on that one because I don't want people to say, oh, your tool's like costing me FPS or something. But what Steph was doing, what would you say for yours? I think the profiler cuts around 5 % of the performance. Oh, that's nice. And it's not terrible considering everything. I'm sorry, why stupid, yeah.

38:39It can store a trace for like 10 seconds right now in memory before it writes it to a file. And for this performance testing, it only makes sense to do it on the real hardware because on the emulator, the timing is all kinds of skewed up. So you don't really have things like CAS simulation. You don't know CAS misses. The Dreamcast has a very weak CAS and a very weak memory system. So it's not optimal if you don't model this. I need to mention there that there's also the performance counters that are part of KOS that can give you hints like how many instructions run, how much time you were waiting for memory.

39:16And you can use them on any scope or function. And then you can really micro benchmark functions and optimize them by hand. Awesome. Well, so let's maybe at this point step back a little bit and kind of give an overview of at this point. So you shipped a first working version. I think I saw somebody running through. I don't have Dreamcast hardware, though I might have to try your emulator stuff and run through it. But what would you say the status of the project is? And what are you guys excited about and working on now? Well, the status is that we thought it was fully playable, the alpha. But there were three bugs in it.

39:50It turns out all of those three are fixed. So now the game is for real fully playable. There's a lot of minor fixes that go in and minor improvements. Like also there's Falco's physics optimizations. There's things like anti-alaizing that we might be able to get in. Things like, so for example, things are correctly fogged. Things like that. The game was mostly there. The next big thing, now we are running out of memory after some time. And it doesn't seem to be some memory leak. Because if you sit still on the same region, even though the game is dynamic, it doesn't happen. It only happens where you're actively playing for an hour or so.

40:32it seems to be memory fragmentation so there is allocations all over the space the dress space and then you have a small allocation in the middle of a free region and then you can't make a big allocation because you have this small allocation in the middle so that's the next big hurdle to like for my side that would be the goal that would make this a beta because it would be fully playable including the fog fixed some new features some better performance and you can play like five hours without it crashing that would be a nice goal this is awesome so all right you've accomplished the i think some people were saying unaccomplishable court where do you want to take this next are you thinking okay we shipped gta 3 we're on to a new game are you thinking expanding within the ecosystem you also mentioned like taking stuff back to the community like where are you going post beta?

41:25I'm going wherever they're going. I had so much fun and it was such a pleasure to be around. Like as long as they'll have me around, I'll follow them. I guess there's a few different paths we can take, but it really depends on where the community also wants to go. Like Falco says, there's people that are trying to make some mods for the Dreamcast, like either to make it more Dreamcast friendly or to bring in better models, better tech suits. To make it more Dreamcast unfriendly. Yes. We have people loading like Xbox models and doing crazy stuff. It's really cool stuff though. It works. So that's one direction, like on this GTA path.

42:08The nice, I mean, for a final release, this would have to be fully localized. There's some minor things in the menu, some strings are missing, things like that. And of course it has to be fully playable, fully stable, no visual glitches. I guess then the next challenge would be Vice City. Oh, you've said that out loud. All right. So, and no committing here, but like timeline wise, are you thinking, you know, Vice City is a 2026 thing or like, what does that look like? I have no idea. Yeah, to be honest with you, I don't know. Is it, I wouldn't know if it's like starting over from another GT, surely it's not, you know, but I don't have enough experience doing GTAs to know with as much of a head start as we have on the engine and stuff, how much further there is to go, if that makes any sense.

43:00One of the original developers claimed that Vice City is essentially the same game, just kind of different story. So that is hopeful. And I guess it's one of those projects that once you are in a couple of weeks, you know how possible it is because most things should be in place. So if it doesn't have higher memory requirements, for example, which it might, things would be fine. Right. So it's one of those that once you get in, you might be shipping within a week or a few weeks or you might be looking at a year-long endeavor. Exactly. Nice. One other thing that you mentioned that I want to dive in on, you mentioned community.

43:41How would people who are interested in this, who listen to this and are like, man, that's cool. I love, Falco, your origin story here, right? You're like, I just want to hack on this cool gaming platform. Like, how do I do that? How would you recommend today people kind of start exploring and getting involved in this space? I would say start off, we have a wiki, Dreamcast.wiki. And this is like the ultimate community-driven mind dump of everything going on. And it has like the definitive, if you Google Dreamcast development, I think it should be number one on Google. And it's like the ultimate getting started.

44:16And this is how everyone starts off, like tells you, you know, what do you need software wise? What platform will we, of course, we let you do Windows, Mac, Linux. We don't, of course, we're going to support your platform. But anyway, how to set up the SDKs. And then from there, pretty much inevitably, there's a link to our Discord server and Simulant. We also have one for DCA3, GTA3, and people wind up in our Discord server. And it's a lot of fun. And that's where all the coding really happens. But we're also on GitHub, Calistios, Calistios. Yeah, you can't miss us if you look for that in Dreamcast on GitHub.

44:53Steph, you want to talk more about our site for GTA 3? Yeah, for GTA 3 specifically, we have some basic instructions, but you have to do the repack yourself. So you need to buy the game, either have a copy of it or buy a new copy. We do support the version of the game that Rockstar is selling online. So it's kind of easy. You can download that and either install it on your Windows PC or install it with Wine. I have tried both. It works. And from there on, you have to run some commands, download the Dreamcast SDK, run some commands, and it will bake everything for you. And that is on dca3.net, by the way.

45:31Yes, dca3.net. And the site is also browsable on the Dreamcast. Yeah, that's the best part. We made sure of that. The guys who made that site, yeah, made sure that it can be viewed with the Dreamcast web browser. So it's pretty cool. Yeah. And one more thing to note for Windows, there is this Dream SDK installer that installs everything for you and it gives you a ready working environment where you can tinker on Linux and macOS. People assume that, you know, you can follow a tutorial. Well, awesome. This has been super fun, guys. We're getting close to the end of the time here. Is there anything that we haven't talked about that you would like to leave folks with?

46:09Yeah, Steph, I want to put you on the spot here and ask you something I've never asked you. When this started out, this was running on an emulator only. This emulator had double the RAM of a regular Dreamcast. When you started out, did you actually think that you would be able to make it to run on a stock Dreamcast? Or were you like, you know, let's see where it takes us and maybe and you know what I mean? How did that happen? I was, let's see where it takes us because I had no idea how the code worked and if we would be able to thin it down. But to be honest, it was so effortless to get it initially to render something.

46:47It only took a couple of days. So I was very hopeful this would be too hard. Because if it takes two months to sell something, then you're like, maybe this is not so easy. Exactly. Yeah, yeah. Interesting. Yeah, I always wondered. I always wondered if you knew starting out that you would make it onto a stock Dreamcast or not. I mean, it would have been fun even if it was only for a motivated Dreamcast. Right, right. Couldn't quite make it. It would still be great, but yeah, not quite the same. Well, thank you, gentlemen. Super fun. And we will catch you another time. I will definitely be checking out getting this installed on my Mac, at least.

47:24Thanks. Thank you, Kevin.

From the publisher

Grand Theft Auto III is a 2001 an open-world action-adventure game developed by Rockstar Games and it had a profound impact on both gaming and popular culture. Its success cemented video games as a dominant form of entertainment and storytelling, and paved the way for future blockbuster franchises. The game was also a technological milestone

The post Grand Theft Auto III on the Dreamcast with Falco Girgis and Stef Kornilios Mitsis Poiitidis appeared first on Software Engineering Daily.

More from Software Engineering Daily

All 195 episodes
Grand Theft Auto III on the Dreamcast with Falco Girgis and Stef Kornilios Mitsis PoiitidisSoftware Engineering Daily · 48 min
Listen in VO