In short
Podcast Notes: Software Engineering Daily - WipEout with Dominic Szablewski
Episode Overview
- Title: WipEout with Dominic Szablewski
- Description: Discussion surrounding WipEout, a groundbreaking futuristic racing game released in 1995 for the PlayStation, and the near-complete rewrite of the game by Dominic Szablewski based on a leaked source code.
Guest Introduction
- Dominic Szablewski: Engineer, game developer, and hacker. Known for projects like:
- Voidcall
- QuakeVR
- Q1K3: A 13-kilobyte version of Quake written in JavaScript.
- Joe Nash: Host of the episode, developer and educator with experience at various tech companies.
Key Topics Discussed
WipEout Game Background
- Release Year: 1995
- Significance: Cultural phenomenon and an early showcase for 3D graphics in console gaming.
- Gameplay: Fast-paced racing with hover ships and licensed electronic music.
Dominic's Game Development Journey
- Early Development:
- Started programming games on a family 486 with QuickBasic.
- Transitioned to developing HTML5 games after realizing Flash wouldn't be supported on iPhone.
- Interest in WipEout:
- Played WipEout during childhood; it was a formative experience.
- Attempted to modify the game as a child.
The Rewrite Project
- Source Code Leak:
- In 2022, a version of the WipEout source code was leaked, leading to Dominic's rewrite.
- Project Motivation:
- Initial goal was to make it compile and run.
- Progressed into a complete rewrite due to code quality improvements.
- Legal Considerations:
- Work done in a legal gray area, emphasizing fair use through complete code rewrite.
Technical Aspects of the Rewrite
- Programming Language Choice:
- Chose to rewrite in C for its low-level control, contrasting with higher-level languages used in professional work.
- Memory Management:
- Utilized bump allocators to manage memory efficiently.
- Graphics and Rendering:
- Transitioned from PlayStation-specific rendering approaches to a more modern graphics architecture.
- Implemented motion blur by rendering multiple frames.
- Aiming for frame-rate independence and improved collision mechanics.
- Multiplatform Support:
- Utilized SDL2 and Sokol for cross-platform compatibility, including WebAssembly support.
Challenges and Reflections
- Source Code Quality:
- Original code described as "abysmal," leading to the decision to rewrite many sections from scratch.
- Game Mechanics:
- Explored historical inaccuracies and inconsistencies in the original code, such as how collision mechanics functioned on PlayStation.
Future Aspirations
- Potential Improvements:
- Aiming to incorporate features like dynamic lighting and more forgiving collision responses.
- Dream Project:
- Hopes for collaboration with Sony to create a polished version of WipEout.
Closing Remarks
- Dominic's Current and Future Projects:
- Work on a C implementation of the Impact game engine.
- Focus on open-sourcing projects and further exploring game development in C.
- Contact Information: Available on GitHub and various social platforms under Phobos Labs.
Key Takeaways
- WipEout's impact on gaming culture and technology is significant, highlighting the evolution of game design and development.
- The importance of understanding both historical context and technical limitations in game development.
- Embrace of lower-level programming can enhance understanding and control over game mechanics, offering unique challenges and rewards.
Written by AI. May contain mistakes. Listen to the episode to check what was said.
Transcript
Automatic transcript. May contain errors.0:00Wipeout is a futuristic racing game that was originally released in 1995 for the PlayStation. The game fused fast gameplay, striking art direction, and licensed electronic music. It was a cultural phenomenon and an early showcase for 3D graphics and console gaming. Dominic Zabluski is an engineer, game developer, and hacker who has released projects such as Voidcall, QuakeVR, and Q1K3, which is a 13-kilobyte version of Quake written in JavaScript. A version of Wipeout Source Code was leaked in 2022, and Dominic created a nearly complete rewrite of the game that compiles to Windows, Linux, macOS, and Wasm.
0:37Dominic joins the podcast to talk about the project. Joe Nash is a developer, educator, and award-winning community builder who has worked at companies including GitHub, Twilio, Unity, and PayPal. Joe got his start in software development by creating mods and running servers for Garry's Mod. And game development remains his favorite way to experience and explore new technologies and concepts.
1:13Welcome, Dominic. How are you doing? I'm doing great. Thanks. Awesome. Thank you so much for joining us today. So to kick off, you know, we're here to talk about a rewire of a classic PlayStation game. But I wanted to know, what was your game development journey? How did you get to this point? Oh, it's a pretty long journey. I think the first game I ever wrote was on my parents' 486 in Quick Basic. But then it got really hard to develop games because developing games for Windows was complicated, setting up compilers and whatever. And I didn't do that for a while. But then later, I completely ignored Flash.
1:46But I remember when Steve Jobs announced that the iPhone won't have Flash on it. I thought that maybe there's an opportunity to do it with like the things that the browser comes with, like HTML5. And I developed this HTML5 game engine and was pretty successful with that. And then I did some casual games with the game engine and some original ones. And yeah, I've been always interested in retro gaming too. That's awesome. Yeah, your game engine impact, I believe. That is correct. I'm familiar with it. It's good to hear where that came from and the timing about that, because I've always perceived it as a very early HTML5 game engine.
2:25And it's great to hear that was like literally the stated purpose, which is very cool. So leading into, I guess, what we're here to talk about, where did you get involved in Wipeout? Like was Wipeout a game you played earlier in your life? I've seen you've done a variety of Wipeout related projects leading up to this complete rewrite. Has it always been something you've been interested in? Yeah, kind of. It was one of the most formative games, I would say, when I was growing up. We had a Super Nintendo at home and the PlayStation came out and we saw the advertisements for it and it looked so awesome, but it was so expensive.
2:58So we sent our father to the local video rental store to pick up a PlayStation for a few days. And he came back with the PlayStation and Wipeout and maybe another game, I can't remember. But Wipeout was definitely in there and we played it the whole weekend and it was really good we've never seen anything like that before then a few years later i saw in a local shop they had wipeout for the pc and for like 10 euros or something or 10 deutschmark so i picked that up and played that a bunch on my pc but i noticed that it's not that good as the playstation original but nevertheless i poked around on the cd and i saw that there's PCX graphics and I tried to put my name on a billboard in the game.
3:41It never really worked out. I don't know. It was all gobbled in the end. But yeah, I've been always kind of interested in hacking Wipeout. Awesome. For folks who somehow missed Wipeout, can you tell us a bit about what the game is and why it captured your attention so much? I think it was a launch title for the original PlayStation in 1995. And it was developed by a British developer. And they had a very distinct graphical style. There was a professional graphics designer who did all the logos in the game and all the menu artwork and whatever. But it was really an important game because it was like, if you know F-Zero from the Super Nintendo, it was like that, but the grown-up version.
4:21And it was like fully 3D. It had polygons and it had like this dance music and like a more serious maybe not serious but grown-up vibe to the game so yeah i guess i left out the most important thing it's it's a racing game a futuristic racing game where you fly around in like these hover ships that attach to the track via magnets or something yeah i mean you say you missed out the most important bit you did mention the music i actually didn't i was very young when wipeout came out and i didn't realize until the noclip documentary just like how much that game was driven not by wanting to create any particular gameplay but like the music and how important that was for it yeah also funny you mentioned f-zero again kind of reflecting on f-zero and wipeout leading up to this chat today i was just kind of thinking about how like the genre of like fast-paced anti-gravity races is very much one that like has kind of died off right like there's no real contemporaries to these games but there was like quite a few titles in this roster of weirdly specific racing games there's actually i'm not sure if i got the name right i I think it's BeamNG.
5:28Okay. That is like a modern interpretation of Wipeout. It's on Steam. Interesting. I have to look up the name, but it's pretty good. Awesome. Okay, cool. Good to know. But yeah, there's no like big studios embarking on this again, as it seems. Yeah, absolutely. Cool. So yeah, onto the project. So you have rewritten Wipeout based on, my understanding, some leaked source code that came out a couple of years ago. Can you fill us in? How does the project start? Well, it started a bit earlier than that, actually. I did a reverse engineering of the data format for Wipeout. When I was young, I tried to put in my name into the graphics and it didn't work out.
6:06And later, with a bit more experience, and I think in 2016, I tried to figure out all the data formats for Wipeout. And I built a JavaScript renderer that just loads all the racetracks and ships and just displays it via WebGL in the browser. So I was kind of familiar with the data format already. And I was interested in this YBOT thing. And then the source code leak happened. I don't think there's any information where exactly it came from, but it just showed up on its website and it doesn't come with any license. So it's kind of a legal gray area, I guess. And while I couldn't really get into it directly, I think it took a year until I found the time and the motivation to really dig into it.
6:50And yeah, and I just downloaded the zip file with all the code in it and started digging around. Awesome. Yeah. So the legally gray area, I think, is a really interesting one. Just touch on it briefly. You mentioned in your blog post, which, by the way, excellent blog post right up. Everyone, please check out this blog post. Make sure we put it in the show notes. Your blog post about the rewrite that, you know, other people have had to go at this source code and other people have done things with it. And part of the reason that you're going after a rewrite is, you know, part of the fair use play.
7:17For folks who are not familiar with the fun world of source code licensing, can you briefly go into that and why a rewrite in this case is an interesting way to explore the source code? Well, that's kind of tongue in cheek. I guess I'm still in the dark gray area, even with this rewrite. So yeah, source code is usually, if you write a program, it's usually copyrighted. And if somebody steals your source code, you can sue them for copyright infringement. And then there's licenses you can attach to your source code and say, hey, if you use the source code and modify it, you also have to release the modified source code.
7:52That's a GPL license. And then there's more permissive licenses like the MIT license where it's like, oh, you can do whatever you want. And while my argument of the blog post that I lined out is, OK, it's based on the original source code, but it's a complete rewrite. None of the lines of code are where they were and everything is different. And so I think you can still see the resemblance to the original source code in a lot of places. But yeah, you can make an argument that it's an original work. Yeah. Again, I guess it's kind of gray area. Yeah, I've seen some unhinged things done to make sure it's like a clean room implementation of this kind of thing.
8:33Like someone reading the code, describing the algorithm, and then giving it to someone who's never seen the code and this kind of thing. So it's a really interesting one, but it seems like it must have been a really, you know, fun project trying to rebuild this thing in a way that's, as you say, original and different. So with that in mind, one of the first questions I guess I wanted to ask you is, you know, you as we've kind of covered in your introduction, you've done a lot of, I guess I would say like lower level JavaScript programming. You've done WebGL, you've written a framework, but, you know, predominantly from what I saw of your background, you're a web developer, a web engineer.
9:06Why did you decide to rewrite it in C instead of, say, in JavaScript or in Impact even? Well, in my day job, I have to write in a lot of languages that are very high level. So JavaScript, I do a lot of PHP, Kotlin, and Swift for the iPhone, and all these very hand-holding languages that are often nice to work with, but they obscure what is really going on. And, well, in the recent years, I've just found it interesting to write C in my free time, because it's like you get into this Zen state, I guess. So it's very, you have to think about all the details and it's fun to piece it all together. And it's like solving a big puzzle.
9:50And it gives you all the challenges that you don't have with higher level languages, where you just throw together some objects and see what happens. And with C, you really have to be careful what you do. and that's kind of the appeal to me. So I really like writing C even if it's not the economically sensible thing to do. Yeah, that's awesome. Yeah, I love the approach of, I don't say historical, but you know, like earlier programming languages with more of the sharp edges as a fun alternative to the modern languages you have to use in workplace. So what is the state of the rewrite? I've played it.
10:22It was playable. It seems great. How do you look at it? Well, it's difficult to find more motivation for it now that it's out. You know, once you release something and you get all the praise for it, you kind of stop working on it a lot. It's pretty close to being done. There's still some minor details that are missing. And of course, there's a whole bunch of improvements that could be done that are like improvements on the original game. Like the original game had a very steep learning curve because the collision response is just so unforgiving. You bump into a wall and you stop dead in the track.
10:54And newer games fixed that, the newer games in the Wipeout series, this could be backported to this version two. And then just like graphical effects, like the ships are, for instance, not lit. Like if you go into a dark tunnel, it's not reflected on the ship. And sparks flying when you hit the walls or stuff like that. But yeah, it's playable and it's complete. There might be a few more physics bugs because I rewrote all the physics code. And it's probably not completely frame rate independent in some places. But if you play with 60 FPS, it should be fine. yeah so mostly done I would say but as always like the last 10 % or 90 % of the work so who knows if if Sony would really approach me to ask me to do a full part of this and polish it up that would probably be a lot more work still.
11:43Perfect yeah I really love that you mentioned the backporting mechanics we'll come back to that later because I have a whole heap of questions about how you feel about I guess like the historical archival purposes of a project like this. But first, I want to get into the rewrite itself and how it came about. And I guess the best place to start is the state of the leaked source code as you found it. I think it's fair to say from your blog post that you weren't super impressed. I believe you used the word abysmal, which I imagine was slightly tongue in cheek. But can you tell us a little bit about the state of the source code as and when this particular version of the game that was released?
12:16Yeah, I guess I was pretty harsh in my blog post. You can look at it from two ways. The one way to look at is it is just to see the source code and see that's a whole mess and that I don't know the global variables declared in one file are used in another file and it all doesn't make sense it's all over the place and then you can look at it from the other way and say that hey it was a really cool game and a lot of people enjoyed it and it works and it never crashed on the psx it's perfectly playable so it's you know it justifies the means maybe to have a working game in the end so maybe the source code is all bad but the game is playable yeah yeah and i guess how it all came together is if you really dig into the source code and try to figure out what was coming first you can see that maybe the track rendering the racetrack rendering and the physics for the ships was being implemented first and then everything else is kind of piled on top of that and what What made the source code really bad in the end is that they also piled on top the PC version.
13:20And there's a lot of if devs that, like, if this is on PC, do this. If it's on PlayStation, do that. And even for the PlayStation version, they had a lot of if devs for different type of controllers. And it's all very ad hoc and all piled on top of the previous version. And then, as I mentioned, this game was developed in the UK. So they built the PAL version first, and then they had to do the NTSC version. And because the game wasn't frame rate independent, it had a fixed tick rate. So it advances the same time step every frame. They had to change it in a bunch of places. And again, they did this with a bunch of if devs.
13:57It's like, hey, if this is NTSC, do the time step like this and this much. And again, the PC version on top. And then there came a GPU accelerated version for the ATI rage. And it's all cobbled together in the same source code that was leaked. I guess the whole rewrite would have been a lot easier if I just got the clean PAL version PlayStation source. Yeah but I mean it must be really interesting to get to see that kind of like layers of archaeology of like the game's history as it's ported and moved from platform and region and that kind of thing. It was really interesting as well how you described like features going missing.
14:31I think the track was it the vertex lighting render or something on the track like went missing between versions? Yeah the original PlayStation version they had textured tracks that were also vertex lit. So every vertex of the scene could have a distinct color and they all baked this into the models themselves. So I don't know how they did it. I guess they painted it by hand. I don't think they had like a light calculation. Like, you know, for modern games, you have this light map step or something. I don't think they have that. And all these vertex colors are missing in the PC-DOS version. And actually one of the programmers that was working on this approached me on Twitter and said that, hey, yeah, we tried our best, but it was just too slow.
15:14We couldn't do the vertex lighting on top of the textured tracks to make it run fast enough. And then I guess the ATI Rage version that was just like a promo thing, that was really the pinnacle of the garbage part. You can see it's just slapped together really quickly and not much care taken. And it's interestingly also by different set of programmers each time. So PC-DOS version was handled by other people than the PlayStation version. And the ATI Rage version was handled by different people still. And they all had to make sense of what came before. So I guess they had a really tough job too.
15:49Yeah, that ATI Rage one especially really fascinates me. Just the economics of that. Like I remember back in the day when you'd get like a new computer or a new computer component. It would come with like CDs of like free games or whatever. And I imagine that's what this setup was. and so the idea of porting a game to give out under those conditions like whatever porting house was given that was probably given a miserable budget so it's kind of understandable but okay so going back to some of these layers one of the things you mentioned just now and also in the blog post was the difference between ntsc and pal and this was a thing that i guess like i haven't thought about for many many years basically like since but like growing up i always had this like vague understanding that these regions existed because sometimes you'd end up with a PlayStation game from the wrong region and whatever but I've never really looked into the fact there's a technical difference what actually is the difference between NTSC and PAL and how does that come through in you know porting a game well the main difference for whiteboard was that NTSC was 60 hertz and PAL is 50 hertz and yeah that was complicated for all platforms that came before like Super Nintendo games also had the same problems and often the developers were kind of lazy and the Super Nintendo version just runs a little bit slower.
17:01And none of us in Europe knew, so nobody cared. But yeah, the main difference comes down to the frame rate. And well, nowadays everyone has a 60Hz monitor at least, or even a variable refresh rate. And the way that games deal with this today is that you have a variable time step. At least that's my understanding. I'm not in the AAA game development sphere, but you just measure how much time has elapsed since the last frame was rendered. So for 60 hertz, that's 16 milliseconds, usually if you hit your frame rate. And then you just multiply all physics that you do with this time step. So if you have your speed multiplied with the tick rate, you get a smooth physics integration that is mostly the same on all kinds of different frame rates.
17:46But again, back in the day, nobody did that because you were sure, like if you order a game for the Super Nintendo or PlayStation, you knew you were going to hit 30 FPS or 60 FPS. You knew what your time step was going to be. And it made development a lot easier because you never had to deal with variable time steps. And I guess you were also quite limited on these old consoles. So multiplying with a time step for every object that you want to move is kind of prohibitive. I guess it was okay on the PlayStation, but not so much on the consoles that came before. Fascinating. yeah i never really thought about the cost of frame rate independence that's a good point actually especially the extra mole on like yeah that's gotta add up awesome so speaking of old consoles and you know the cost and the hardware so you know any game even modern ones are very much you know a product of the architecture they were built for and that's increasingly true well more true for console games and especially for wipeout which you know you touched on kind of the origin of Wipeout a little bit, but like, as far as I understood it, you know, the, not only was it a launch title, but the developer or the publisher was very much involved with like making the PlayStation a usable dev platform.
18:56So it was all tangled together in a big mess. Are there any interesting places like in the source code where you really see the PlayStation architecture come through? Like, are there any things that are just like, no one would write this, this way for any other console, any other environment. This is purely a PlayStation artifact oh yeah for sure there's especially in the rendering code it is very specific to the playstation console usually these days when you write a game you have your game objects and you have your renderer kind of like an abstract thing on the side so you can maybe switch out your rendering code like you want to switch from opengl to vulcan and you just you know switch out a module in your code and it mostly works without you having to touch the source code all over in the game.
19:40But again, back then you didn't have this freedom. All this abstraction obviously costs a little bit of compute time and you were writing stuff very close to the metal. You were trying to deal with the things as immediate as you could. So all the rendering code that is in the wipeout source is very specific to the PlayStation and it's very ad hoc. There's no renderer module that just accepts all the triangles and then tries to figure out how to best submit it to the hardware or something like that. So yeah, that's probably the part that is closest to the PlayStation. But then there's all kinds of different things too, like the controllers, for instance.
20:17There's also no abstraction of like controller input, like whether you have a PC keyboard attached or a game controller or, I don't know, a racing wheel. All these controllers were also in the source code, like with if statements, like, hey, if this is the PC version and a mouse is attached, then check the mouse coordinates now. It's not like abstracted the way that you have an input module that says, hey, when the mouse moves left, give the input to the game move left. So yeah, very ad hoc. But also I guess it's kind of because the game was so successful and they didn't anticipate they had to port it to so many different platforms that it was just all piled in in the end.
20:57Yeah, the renderer sounds nightmarish. that is an especially interesting topic I found. Actually, when I was doing the rewrite, I looked into how the PlayStation produced polygons on the screen. And the most interesting thing to me is that the PlayStation doesn't have a Z-buffer. So if you do 3D rendering and you submit two triangles to the GPU to render and it gets rasterized, the CPU figures out which triangle is in front of the other one with the help of the Z-buffer. So if you draw a triangle, it gets drawn to the color buffer and you have the Z-buffer that just stores the depth's value, like the distance to the camera.
21:37And if you draw another triangle, it is compared to the stored depth's value. If you have a depth's value that is closer to the camera than the one you want to write, then your object is obscured, at least on this pixel by the previously drawn object. So the GPU doesn't draw it. And you as a programmer, you don't have to care that much about it. You just set up your depth buffer and the GPU does it. But again, the PlayStation didn't have that. And you had to draw all the polygons in the order that they should appear on the screen. So the furthest back triangles need to be drawn first. And then the closer you get through the camera, it's piled on top.
22:18And the development library that came with the PlayStation, they had some kind of cool functions to make that a bit more ergonomic. they had this ordering table where you could set it up and say i want to have 8 000 different depth values and for each polygon that you want to draw you figure out how far it is from the camera and then you put it into the ordering table at that distance and if you do that for all polygons you have the ordering just right in the end because see it is drawn well back to front again So you put everything into the ordering table, just like a big ass array. The implementation details are a bit more interesting than that, though.
22:59And it gets drawn in the order from back to front. The implications of that are interesting. Yeah, you have some visual artifacts, for instance. So there's a few cases where you have three triangles on the screen, for instance, and one triangle overlaps the other one, like layered on top, and no triangle is in front of all the other triangles. So each triangle is overlapped by some other triangle. You can't draw that accurately on the PlayStation because you can only draw triangles at one depth value and you get around on this problem with modern GPUs with the Z-buffer. So what you would have to do on the PlayStation if you wanted to have this accurately, you would need to subdivide your polygons, basically.
23:40So it gets very complicated and you can see a lot of these issues pop up in the PlayStation games. If you look closely, play a PlayStation game, you can see that there's some polygons peeking through where they shouldn't be but most developers did a very good job of hiding that or the resolution was so bad that you didn't notice or didn't care yeah i was also immediately just thinking about like is 8 000 depth values enough but i guess for most games of the era it definitely would be and i guess it's not opinionated on how you define a depth right like that depends on the scale of your game yes exactly yeah you as a developer you were responsible for putting it into the right position right so you can say oh it's five kilometers away from the camera so i'll put it at position six thousand or something the scale is up to you interesting okay so i guess to start with a question we kind of teased out earlier when you were talking about backporting mechanics to what extent were you aiming for a you know a recreation of this code that's like accurate to how the game worked like all how the code was versus like the mechanics of the game were you just trying to make the game as good as possible or was there some effort to preserve the spirit of the source code if that makes sense well i started out by just looking at the source code and all i wanted to do is to make it run again to make it compile and run again on a modern computer but the more i read into it and the more things i changed the more i noticed that there's a lot of room for code quality improvements.
25:11And for some reason, I really like refactoring code, I guess most programmers do. And one thing led to the other, like, I changed this, now I need to change that. So I didn't set out to make a full rewrite, but in the end, it just happened because I felt it was the best way to approach this, to make the game live on for many more years. because if you have this gobbled original source code, making it run on every platform, on every new platform that comes along is very time-consuming, very difficult. But if you have a clean slate and a clean source code that in this case even abstracts the renderer away so you can plug in another rendering module, make it run on different platforms, that makes it so much easier to keep the game alive too.
25:59So yeah, it was all by accident basically. Awesome. And yeah, you mentioned a new rendering module. So my next question was going to be, how do you deal with these architectural oddities of the PlayStation? I guess you've changed it to a more modern rendering approach. Is that accurate? Yeah. So the first thing I did was trying to get the thing to compile and run, which was pretty difficult to begin with. And well, the first step trying to make it compile was already very challenging because it relies on so many different things that weren't there anymore. For instance, for the ATI Rage version, all kinds of windows headers that I didn't have or GPUs that don't exist anymore.
26:35And for the PlayStation version, same thing. I don't have a PlayStation to compile this for and the PlayStation libraries are missing. So I just ripped out everything that wasn't really essential to start the game. So commenting out all the places where polygons are rendered, commenting out all the places where controller input is checked, commenting out places where something PlayStation specific happened. And then finally I got it to compile. And then I started to slowly adding things back in again. Again, the PlayStation version was using this ordering table and transforming polygons on a coprocessor.
27:11But the DOS version was doing the transformation on the CPU and they had all the routines to do that there. But they were still using this ordering table because it was so ingrained into the source code. And I started using this ordering table too. I just, in all the transformation of the polygons that runs on every CPU, you can run it on a modern computer. And just then the last step, like when it is, when these polygons are handed over to the GPU, I exchanged that, like how it goes through the ordering table and gets it to the display. Yeah, the first thing I had was this flat shaded version of Wipeout where it just had something on the screen that runs.
27:51and from there on I started to clean things up more like getting rid of this ordering table and having a proper triangle function and using that instead of sticking stuff into the ordering table all over the place yeah so step by step very very slow progress at times very tedious because also you you tried to get rid of something that was that was in there and rewrite it and then you were working for five six hours on it and you could not compile in between to see if it works because you were like changing so much to facilitate that. So yeah, often quite adventurous, but a lot of fun too. A question I realized I didn't ask that I should have done is, do you have a idea?
Read the full transcript
28:32Sorry, this is like a hard numbers question on top of your head. Like how big was the original source leak in terms of lines of code? And like how big was it ended up being in the rewrite? I think I actually have the statistics in my blog post. Oh, really? but the you know the way you that you count it is kind of complicated by the fact that there were three versions of the game in the source code leak but none of these were working independently like if you wanted to compile the pc dos version it pulled in some source code from the playstation version too so i i don't know how to calculate that actually how to again it would have been nice to get the source code for the original playstation version because and then you would have the more accurate number on that okay i found it so 40 000 lines of code in the league versus about 8 000 is what you ended up with yeah again yeah a lot of things were just you saw the same if statements all over the place like hey if it is if it is this controller do that if it is this other controller do that and if you just abstract that away into like an input module you get rid of a lot of repetition and a lot of source code, a lot of source lines.
29:41Awesome. So you mentioned there that, you know, you abstracted some things away so you could use, you know, different renderers, different backends, etc. You've got the game running on both STL2 and SoCal, is that correct? That is correct, yes. I started out with STL2. I'm doing this on Linux and I just had OpenGL here and so I tried to get that running first. And well, there's two things you can swap out the rewritten source code is built in a way that you can swap out the what i call platform and that is sdl or the so-called app and then you can swap out the renderer so currently there's the official opengl version and i have a viaframe software rendered version and other people have written ports to metal for mac os and trying to remember if i saw something else.
30:33Maybe someone ported it to some newer console again. I'm not sure. So yeah, I started out with the SDL platform and because I knew that I wanted to have the possibility to have different platforms, adding then the so-called backend was quite straightforward. There's only very few functions that the platform needs to implement, like setting up the window, sound output and stuff like that. And so-called is actually very cool. Like libSTL is a big library And you get the header files so that you can compile your code. But then you also have this library that you either need to also link to your binary or just dynamically link.
31:14And I think it's like three megabytes or something. And Sokol, on the other hand, is you are expected to include the whole source code. And it comes all in one file. And you just include it in your C source. And it just works. And I was actually very surprised when I got this working on my desktop and I could open a window with Sokol and play the game and input works and whatever. I just had to switch out the compiler from the usual GCC to EMScripten and it compiled the web version and it just works. I could play the game and sound output worked. Graphics via WebGL worked. It was kind of amazing.
31:55I expected a lot more struggling to make it work on the web. Yeah, I hadn't heard of it before your project. But yeah, that's pretty nifty. And it does lead me to my next question was, you know, you're targeting Wasm, you're targeting web platform. I guess you've kind of just answered it, which is you didn't really have to do anything special because Circle handed it for you. But was there anything during the rewrite where you had to keep it in mind that you were targeting Wasm? Well, other than that, I wanted to target different platforms. Not really, because, you know, I was using OpenGL anyway, and I knew WebGL is pretty close to that.
32:27You have this GL ES2. And I didn't need any fancy shader code. Like I don't have any shadow calculations or whatever. It's just textured triangles with a color as basic as it gets. And WebGL can do that just fine. So in that regard, I didn't need to think about any changes. In the end, I had to do a little bit of work for the Wasm version to make it work on mobile, especially you know i needed to have some buttons on the screen that are then forwarded to the c code and that was a little bit of work and it's not really not really fun to play because these on-screen buttons are not very responsive and positioned wrong and it's more like a proof of concept it works on mobile and the trend is just fine and on your iphone or something yeah i am surprised that works on i can't imagine playing white power on an iphone with the screen with buttons in the way I always already feel like it's just like too fast paced for that small screen so I guess to rewind a little bit and go back to rewriting stuff there was a couple of interesting parts in your blog post where you mentioned like not even necessarily looking at the original source code because it was just like too spaghetti-ish and instead just looking at like videos of the game being played or playing games on the emulator can you talk through some of those areas and like why you took that approach to it well one of the areas was the sound code again and very specific to what was happening on the PlayStation.
33:55And this was actually fairly abstracted away. So in the game, there were calls to just play a sound at a certain position. And I knew what the game wanted to do. And I just thought that, okay, instead of digging through all this sound code that is there, I just re-implemented because I know what they want to achieve. There's music playing, there's sounds playing at different positions. and I know where they get called. And it was a pretty good decision, I would say, because again, the original code was so specific to the PlayStation that it would have taken a lot of time to figure everything out and just rewriting it was the faster way.
34:36There's one thing missing, though. The original PlayStation had this haul effect. Like if you go into a tunnel, you could hear like a reverb of your engine sound and also a reverb of the music that is playing. And that is still missing from the rewrite. Right. Interesting. Reverb of the music that's playing is also an interesting one because that implies it's coming from the ship and isn't just background music, which I'd never noticed before. One thing you said in the podcast really interested me because I hadn't heard the term before. So at one point you described that the original code followed a you call the platform approach and you wanted a platform calls you approach.
35:09What do you mean by that? So typically the way you wrote games is like you start your program, you load your graphics and your sound files and everything that you need to run the game. And then you go into an infinite loop that just runs forever. And in this infinite loop, you check if any buttons are pressed, you advance your physics calculations. So advance the world state, and then you put everything onto the screen and it goes into the next iteration. So you call the platform, you call everything that you need to do by yourself. So you wait in your own code for the next, until the render is done.
35:47and you submit everything to the render. And you can't do that on the web and in WebAssembly because you would basically crash the whole page or stall the page. You cannot go into an infinite loop. You have to give control back to the browser. So like if you have a, in JavaScript, just, if you just write a loop in JavaScript that runs forever, the browser after 15 seconds will say, hey, this page is not responding anymore. And you can't interact with this page in the meantime. So all this, because JavaScript is single threaded, there's nothing running in the background if you don't use WebWorker or something like that.
36:26And if you want to render a game and put something on through the screen, you do your physics calculations, pull for input and put it on the screen. And then you give control back to the browser and wait until your code is getting called again. So what you do is you just set up an interval or a request animation frame these days. We just say, I want to get this callback called every 16 milliseconds. And in these callbacks, you do all the things that you need to do and then you return. And that's the only way you can do it on the web. And interestingly, the original wipeout code didn't have just one infinite loop.
37:08Like even if you implement the game cleanly, cleanly, you would have just one loop that handles all kinds of different scenes. So you have your infinite loop that pulls for input. And then if you are in the menu scene, you show the menu and handle the menu buttons and whatever. And if you're in the game, you advance to physics. And you have this very outermost infinite loop. And Wipeout does, it has this infinite loop on the title screen. so it just shows an image and says press start and there's an infinite loop it just links the press start button and as soon as you press start it jumps to another part of the code where there is another infinite loop and you have this infinite loop for the for the menu and then if you go into the game you had another infinite loop in the race functions so lots of different infinite loops that you have to untangle and yeah that was quite some work to figure all this out and and where you switch between those loops and how you maintain all the state and all the all the things that were loaded like which kind of graphics do you still need which kind of graphics can you throw away because they are from a different racetrack or something there was quite a bit of work yeah that sounds a nightmarish but yes you've just reminded me speaking of which graphics you retain you had an interesting approach to the memory management in the rewrite right which is you did away with allocating memory and just said i will have this much memory and that's all i need forever can you talk a little bit about that yeah it's actually pretty standard approach in a lot of game development that you have a bump allocator so that's a big area of memory that you allocate first and then you say i start at the index zero and if i want to have i don't know 1000 bytes of memory, you just advance this index to 1000 and give back the memory address that was at zero.
39:03And then next time you want like 20 bytes, you advance the index by 20 and just give back what was at the previous position. And so it's just like a linear memory that just grows and grows and grows and everything grows on top of the previously allocated thing. And then if you don't need your memory anymore you just reset your index to zero and you don't have to free anything you just know that all the memory that i allocated here is free now and a lot of games these days do this for like they have this bump allocator for a frame so at the start of the frame they start at zero and some things in the game need to allocate some memory to do some calculations or whatever, and the allocator grows and grows and grows.
39:52And at the end of the frame, it's reset to zero again. So you as the developer, as the game developer, you never have to care about memory allocations. As long as your buffer in total is big enough to handle one frame, you don't have to free anything ever again because it's automatically freed at the end of the frame. And you can use that concept. You can further that by just saying, hey, I don't only have one of these bump allocators. But I have multiple ones. So one that is like per frame and another one that I do, I don't know, per level. So each time a level gets loaded, it's reset. And yeah, the way I did this in Wipeout is there's actually just one bump allocator, but it remembers different levels.
40:36So first, when the game starts up, it's at zero. And then I load some graphics that the whole game needs. Like for instance, the graphics for the font and the ships are needed in all races and the textures for the ships. And these are put into the bump allocator. And then when you start a race, the position of the bump allocator is recorded. And then I load the racetrack into this bump allocator. And when the race finishes, it's just reset to this position again. And the racetrack is basically thrown away and makes room for the next racetrack to load. so that's a very very simple approach to memory management and it works i have to say it worked really well for this game because you have these very distinct scenes that all have their own graphics and own models and yeah you have some models that you just load before you load the first scene like the ships and whatever and they just persist all the time so yeah you never have to free anything and you know that you cannot leak memory because it's reset to the previous level again i think you answered the main question i had to do so i wasn't familiar with that concept that's really interesting thank you for diving into it but i guess the main thing you have to do here is like logically group what you're loading because you couldn't for example like free something in the middle of a block right like you're freeing up you're just resetting the point about certain things you've got no scope to you know remove things within a area right Right, okay.
42:06Yes, exactly. So yeah, you cannot free something from the middle and make room again. Everything that is in there is in there until you reset the pointer, yes. Which then is ideal for, as you said, something with very discreet, obvious scenes, like a racetrack-based game. Gets actually a tiny bit more complicated in Wipeout because I needed some of this memory that I can free out of order again. So for instance, when you load a racetrack from the disk, from a file, the whole file is loaded first and then I go through this file and look for all the data that I need for all the vertices and whatever.
42:41And I put them into another structure that is more efficient for rendering. And this is the final data that I use in the game is put into the bump allocator. But the file that I load, I can free again later. So I needed to have what I call the temporary allocator for these very short-lived objects that you have to explicitly free again. And yeah, this is mostly used for loading files and transforming them in some way. And one thing about that, I think the whole game allocates 16 megabytes at the start of the game for this bump allocator. And the bump allocator grows from zero to 16 megabytes. And the temp allocator actually lives in the same 16 megabyte space, but it grows from the end.
43:28It grows downwards. So if those two allocators ever meet you out of memory. Play them with fire. But then I guess, as you said, when you're building these kind of games or building for the constraints of those consoles, you often knew exactly what you needed at any point, right? Like this. Yeah. And also, I can be sure that everything fits into memory because I tested it. There's no edge case where something is loaded that I didn't foresee to be loaded. But like, these are very distinct scenes. And as long as all the scenes, all the racetracks load just fine, I know the memory level will be reset to a known value.
44:01And if the game fits, it fits. It's one of those things I guess I always struggle with as high-level programming is like, you've always got that temptation to make the thing work for every case, right? And to make it as maximally abstract and maximally generic and maximally fault tolerant. But sometimes you actually do just know exactly how much memory you're putting in the data structure. And you can just rely on that. And it's so, it makes me itchy, like accepting that, but it is, it works and it makes the game work and that's fine. Yeah. Realistically. Yeah. If you develop for the PlayStation, you know, you only have, I think it was four megabytes or maybe even two megabytes of RAM, you know, the room that you have to work with.
44:36So yeah, there's no advantage to using very dynamic memory allocation and, and freeing objects all over the place. Perfect. So I guess moving on to future looking questions. So you mentioned, you know, a lot of the motivation has gone out now that it's released, but is there anything you still want to tackle for the rewrite? Is there anything you hope to see happen with it? Well, I still want to investigate this. There's probably a physics bug you can crash into the racetrack when your frame rate is too high. And I figured that out by, I implemented this very crude version of motion blur because the game runs with 5 ,000 frames per second on my computer anyway.
45:14I only have a 60 Hertz monitor. I thought, okay, let's just, you know, I have 16 milliseconds between each frame. Why not divide 16 by 8 and just advance the game 2 milliseconds at a time and render a frame? And I take 8 of these frames together and blend between them. And that is the final output frame that is sent to the display. So this is how the motion blur is implemented. It's like the real version of motion blur. It's very computationally expensive. but with this game it's trivial to do because it runs so fast. And I basically had eight times the number of frames that are being processed and the physics step was getting very tiny, like just these two milliseconds.
45:59And there is some bug in there somewhere that makes you crash into the ground and I want to fix that so that it's truly frame rate independent. And yeah, if I find the motivation, I want to do some of the graphical things like lighting on the ship when you go into a tunnel that it gets a bit darker and stuff like that and maybe also the more forgiving collision but yeah i lined this out in the blog post too my dream would be to be paid to make a very polished version of that would be very cool if sony says like hey now it's the 38th anniversary of wipeout it will be actually next year i guess it will be next year yeah we are in remaster season we've done tomb raider it's time for wipeout right so yeah good timing then sony if you're listening to this you know where dominic is yeah that makes total sense i hope that happens and yeah i hope the big corporation is nice about that that would be lovely as well so outside of wipeout do you have any upcoming game projects you're excited about any other rewrites of random source code i saw your work making a c version of impact as well is that just dabbling that is true yeah i got it into this rewriting i guess So Impact.js was one of the very first JavaScript game engines, maybe the first one, I'm not exactly sure.
47:15And that's from 2010. And yeah, I got a lot of experience writing C by doing this wipeout stuff and a few projects before. And I thought that, hey, it might be fun to revisit the game engine and see if I could reimplement this elegantly and see code again. and I've gotten pretty far now. So the first game that I developed with my own game engine, Biolab Disaster, it's still playable on the web. You can now play, it's now rewritten in C and you can compile it for your desktop and also again, compile it with WebAssembly and play it on the web again. Amazing. I'll have to go full circle and rewrite your web game engine to see you take a part of WASM.
48:01That's incredible. Yeah, so the plan for that is to just release it as open source, maybe write a bit of documentation for it and see what people are doing with it. Yeah, just a side project. Nice. So it sounds like a very cool side project. It's fun to catch the C bug. I'm glad that this is an outcome of the Wipeout project is going back and writing more C. That's fun. Perfect. Well, in that case, thank you so much for chatting to us about Wipeout. You are Phobos Labs. Everyone on the internet, people want to read about your work, the upcoming engine, the Wipeout rewrite is on GitHub as well.
48:33Underneath that handle, we'll include it in the show notes. Anywhere else where people can find you that I've missed? Phobos Labs everywhere. Well, GitHub, the blog, and Twitter mainly. Perfect. Awesome. Well, Dominic, thank you so much for joining us today. Thanks for having me.
From the publisher
WipEout is a futuristic racing game that was originally released in 1995 for the PlayStation. The game fused fast gameplay, striking art direction, and licensed electronic music. It was a cultural phenomenon and an early showcase for 3D graphics in console gaming. Dominic Szablewski is an engineer, game developer and hacker who has released projects
The post WipEout with Dominic Szablewski appeared first on Software Engineering Daily.
