
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 con...
Loading summary
Narrator
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 and console gaming. Dominic Zablowski is an engineer, game developer and hacker who has released projects such as Voidcall, QuakeVR and Q1K3, which is a 13kb 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. Dominic 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 a start in software development by creating mods and running servers for Gary's model, and game development remains his favorite way to experience and explore new technologies and concepts.
Joe Nash
Welcome Dominic, how are you doing?
Dominic Zablowski
I'm doing great, thanks. Awesome.
Joe Nash
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?
Dominic Zablowski
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 I 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. But 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.
Joe Nash
So 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 HTM5 game engine and 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?
Dominic Zablowski
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 looked so awesome but it was so expensive. So 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 or something or 10 Deutsche Mark. 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. It 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.
Joe Nash
Awesome. For folks who somehow missed waipow, can you tell us a little bit about what the game is and why it captured your attention so much?
Dominic Zablowski
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 F0 from the Super Nintendo, it was like that, but the grown up version and 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 attached to the track via magnets or something.
Joe Nash
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 how much that game was driven. Not by wanting to create any particular gameplay, but the music and how important that was for it. Yeah. Also funny you mentioned F0 again. Kind of reflecting on F0 and Wipeout leading up to this chat today, I was kind of thinking about how like the genre of like fast paced anti gravity racers is very much one that like, has kind of died off. Right. Like there's no real contemporaries to these games, but there was quite a few titles in this roster of weirdly specific racing games.
Dominic Zablowski
There's actually. I'm not sure if I got the name right. I think it's Beamng.
Joe Nash
Okay.
Dominic Zablowski
That is like a modern interpretation of Wipeout. It's on Steam Engine. I have to look up the name, but it's pretty good.
Joe Nash
Awesome. Okay, cool. Good to know.
Dominic Zablowski
But yeah, there's no like big studios embarking on this again as it seems.
Joe Nash
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? Like how does project start?
Dominic Zablowski
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. And 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 race tracks and ships and just displays it in via WebGL in the browser. So I was kind of familiar with the data format already and I have, yeah, 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 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. Yeah. And I just downloaded the zip file with all the code in it and started digging around.
Joe Nash
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. Write up everyone please check out this blog post. Make sure to put it in the show notes. Your blog post about the rewrite that other people have had to go at the source code and other people have done things with it. And part of the reason that you're going after a rewrite is part of the Fair use play. For 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?
Dominic Zablowski
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. That'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 in the blog post that I lined out is okay, 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. So it's. 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.
Joe Nash
Yeah, I've seen some unhinged things done to make sure it's like a clean room implementation of this kind of thing, like 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 been a really 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 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. Obviously you've done WebGL, you've written a framework. But predominantly from what I saw of your background, you're a web developer, a web engineer. Why did you decide to rewrite it in C instead of say in JavaScript or in Impact even?
Dominic Zablowski
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 handholding 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 and 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.
Joe Nash
Yeah, that's awesome. Yeah. I love the approach of, I don't say historical, but you know, like earlier programming languages with more the sharp edges as, you know, 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, it was playable. It seems great. How do you look at it?
Dominic Zablowski
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. And 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 60fps at should be fine. Yeah. So mostly done, I would say. But as always, like the last 10% are 90% of the work. So who knows, if Sony would really approach me to ask me to do a full port of this and polish it up, that would probably be a lot more work still.
Joe Nash
Perfect. 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?
Dominic Zablowski
Yeah, I guess I was pretty harsh in my blog post. You can look at it from two ways. The one way to look at it 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 I 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.
Joe Nash
Yeah, yeah.
Dominic Zablowski
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 race track 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 made the source code really bad in the end is that they also piled on top the PC version. And 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 ifdevs. It's like, hey, if this is ntsc, do the timestamp 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.
Joe Nash
Yeah, but I mean, it must be really interesting to get to see that kind of like layers of archeology of 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 features going missing. I think the track, was it the vertex shade, vertex lighting, renderer, or something on the track went missing between versions?
Dominic Zablowski
Yeah, the original PlayStation version, they had textured tracks that were also vertex lit, so every vortex 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 lightmap step or something. I don't think they had 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. We 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 pile. You can see it's just slapped together really quickly and not much care taken. 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 RTRH 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.
Joe Nash
Yeah, that ATI Rage one especially really fascinates me. Just the economics of that. I remember back in the day when you'd get a new computer or a new computer component, it would come with CDs of 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, 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 I hadn't thought about for many, many years, basically since. But growing up, I always had this 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.
Dominic Zablowski
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 and 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 60Hz, 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. But 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 30fps or 60fps. 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.
Joe Nash
Fascinating. Yeah, I never really thought about the cost of frame rate independence. That's a good point, actually, especially the extra molt on like. Yeah, that's got to 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 wipow, which, you know, you touched on kind of the origin of wipow 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. So 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 you're just like, no one would write this this way for any other console or any other environment. This is purely a PlayStation artifact.
Dominic Zablowski
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 Vulkan and you just switch out a module in your code. And it mostly works without you having to touch the source code all over in the game. But 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. There'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.
Joe Nash
Yeah, the renderer sounds nightmarish.
Dominic Zablowski
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 value, like the distance to the camera. And if you draw another triangle, it is compared to the stored depth value. If you have a depth 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. And 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 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. And it gets drawn in the order from back to front.
Joe Nash
The implications of that are interesting.
Dominic Zablowski
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 death 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. So it gets very complicated. And you can see a lot of these issues pop up in the PlayStation games. Like, 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.
Joe Nash
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.
Dominic Zablowski
Yes, exactly. You as a developer, you were responsible for putting it into the right position.
Joe Nash
Right.
Dominic Zablowski
So you can say, oh, it's five kilometers away from the camera, so I'll put it at position 6000 or something. The scale is up to you.
Joe Nash
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, or 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?
Dominic Zablowski
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. And 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 those gobbledygooks, 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 kind of, 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. So, yeah, it was all by accident, basically.
Joe Nash
Awesome. And yeah, you mentioned a new render module. So my next question was going to be how do you deal with these architectural oddities at the PlayStation? I guess you've changed it to a more modern rendering approach. Is that accurate?
Dominic Zablowski
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, for instance, for the ATI Rage version, all kinds of Windows headers that I didn't have or GPUs that don't exist anymore. And 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 started 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 the, on a CO processor, but 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, 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. And 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 tried to get rid of something 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 changing so much to facilitate that. So. Yeah, often quite adventurous, but a lot of fun too.
Joe Nash
A question I realized I didn't ask that I should have done is do you have an idea? Sorry, 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 how big was it ended up being in the rewrite?
Dominic Zablowski
I think I actually have the statistics in my blog post.
Joe Nash
Oh really?
Dominic Zablowski
But the way that you count it is kind of complicated by the fact that there were three versions of the game in the source code league, 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 don't know how to calculate that accurately. How to. Again, it would have been nice to get the source code for the original PlayStation version because then you would have the more accurate number on that.
Joe Nash
Okay, I found it. So 40,000 lines of code in the league versus about 8,000 is what you ended up with.
Dominic Zablowski
Yeah, again yeah, a lot of things were just you saw the same IF statements all over the place like hey, 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.
Joe Nash
Awesome. So you mentioned there that you abstracted some things away so you could use, you know, different renderers, different backends, etc. They've got the game running on both STL2 and so called, is that correct?
Dominic Zablowski
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 STL 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 wireframe software rendered version and other people have written ports to metal for macOS and trying to remember if I saw something else, maybe someone ported it to some newer console. Again, I'm not sure. So yeah, I started out with the STL 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 Lib STL 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 and I think it's like three megabytes or something. And so call 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 so called 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. I expected a lot more struggling to make it work on the web.
Joe Nash
Yeah, I hadn't heard of it before your project, but yeah, that's pretty nifty and 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?
Dominic Zablowski
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. You 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 it renders just fine on your iPhone or something.
Joe Nash
Yeah, I am surprised that works on. I can't imagine playing wiper on an iPhone 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 not even necessarily looking at the original source code because it was just too spaghetti ish and instead just looking at videos of the game being played or playing games on the emulator. Can you talk through some of those areas and why you took that approach to it?
Dominic Zablowski
Well, one of the areas was the sound code. Again, very specific to what was happening on the PlayStation and 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, you know, 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, 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. There's one thing missing though. The original PlayStation had this hall 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.
Joe Nash
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 describe that the original code followed a. You call the platform approach and you wanted a platform calls you approach. What do you mean by that?
Dominic Zablowski
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, then 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 renderer is done and you submit everything to the renderer. 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 web workers or something like that. And if you want to render a game and put something into on through the screen, you do your physics calculations, all four 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 request animation frame these days where you 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. Like even if you implement the game cleanly, you would have just one loop that handles all kinds of different scenes. So you have your infinite loop that pulls pulse for input. And then if you are in the menu scene, you do. You show the menu and handle the menu buttons and whatever. And if you're in the game, you advance the physics and you have this very outermost infinite loop. And Wipeout does is 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 that just blinks 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.
Joe Nash
Oh, I see.
Dominic Zablowski
And you had this infinite loop 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, it was quite some work to figure all this out 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. That was quite a bit of work.
Joe Nash
Yeah, that sounds a nightmarish. 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?
Dominic Zablowski
Yeah. It's actually a 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, 1,000 bytes of memory, you just advance this index to 1,000 and give back the memory address that was at zero. And 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 per 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. And at the end of the frame, it's reset to zero again. So you as the developer, you 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. So 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 allocation. And then when you start a race, the position of the bump allocator is recorded. And then I load the race track into this bump allocator. And when the race finishes, it's just reset to this position again. And the race track 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.
Joe Nash
Main question I had. 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.
Dominic Zablowski
Right.
Joe Nash
Like you're freeing up, you're just resetting the pointer back to certain things. You've got no scope to, you know, remove things within a area.
Dominic Zablowski
Right, okay, yes, 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.
Joe Nash
Which then is ideal for, as you said, something with very discreet, obvious scenes like a racetrack based game.
Dominic Zablowski
It's actually a tiny bit more complicated in Wiper 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 and 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 fun thing about that, I think the whole game allocates 16 megabytes at the start of the game for this pump allocator. And the bump allocator grows from 0 to 16 megabytes. And the temp allocator actually lives in the same 16 megabyte space, but it grows from the end, it grows downwards. So if those two allocators ever meet you out of memory, Flame of fire.
Joe Nash
But then I guess as you said, when you're building these kind of games or building for the constraint Size consoles, you often knew exactly what you needed at any point. Right? Like this.
Dominic Zablowski
Yeah. And also I can be sure that everything fits into memory because I tested it like there's no edge case where something is loaded that I didn't foresee to be loaded. 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 and I. If the game fits, it fits.
Joe Nash
It's one of those things I guess I always struggle with as like 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 like 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.
Dominic Zablowski
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. So yeah, there's no advantage to using very dynamic memory allocation and freeing objects all over the place.
Joe Nash
Perfect. So I guess moving on to future looking questions. So you mentioned a lot of the motivation has gone out now that's released. But is there anything you still want to tackle for the rewrite? Is there anything you hope to see happen with it?
Dominic Zablowski
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, I only have a 60Hz 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 eight 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, very tiny. Like just these 2 milliseconds and 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 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.
Joe Nash
I guess there will be next year. Yeah. And we are in remaster season. We've done Tomb Raider, it's time for Wipeout. Right.
Dominic Zablowski
So yeah, good timing then.
Joe Nash
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 it. 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?
Dominic Zablowski
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. And 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 in C 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.
Joe Nash
Amazing. I should go full circle and rewrite your web game engine to see to compile to wasm. That's incredible.
Dominic Zablowski
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.
Joe Nash
Nice. So it sounds like a very cool side project. It's fun to catch the seabug. I'm glad that this is an outcome of the Wipeout project. It's going back and writing more sea. That's fun. Perfect. Well, in that case, thank you so much for chatting to us about Wipeout. You are Phobos Labs everywhere on the Internet. People want to read about your work. The upcoming engine, the Wipeout rewrite, is on GitHub as well. Underneath that handle. We'll include it in the show notes. Anywhere else where people can find you that I've missed? Phobos Labs Everywhere, right?
Dominic Zablowski
Well, GitHub, the blog and Twitter mainly.
Joe Nash
Perfect. Awesome. Well, Dominic, thank you so much for joining us today.
Dominic Zablowski
Thanks for having me.
Podcast Summary: Software Engineering Daily – "WipEout with Dominic Szablewski"
Release Date: December 11, 2024
In this engaging episode of Software Engineering Daily, host Joe Nash interviews Dominic Zablowski, an accomplished engineer, game developer, and hacker known for projects like Voidcall, QuakeVR, and Q1K3—a minimalist 13KB JavaScript version of Quake. Dominic discusses his ambitious project: a nearly complete rewrite of the classic 1995 PlayStation racing game WipEout, leveraging a leaked source code to recreate the game for modern platforms including Windows, Linux, macOS, and WebAssembly (WASM).
Dominic begins by sharing his early forays into game development, starting with writing games in Quick Basic on a 486 PC. [01:26] He highlights the challenges of developing games for Windows in the early days due to complex compiler setups, which led him to explore alternative platforms. Dominic pivoted to web development, creating an HTML5 game engine in response to Steve Jobs’ announcement about the iPhone dropping Flash support. This engine facilitated his creation of casual and original games, merging his interest in retro gaming with modern technologies.
Dominic Zablowski [02:14]: "I've been always interested in retro gaming too."
Joe Nash steers the conversation toward WipEout, a seminal futuristic racing game that captivated players with its fast-paced gameplay, distinctive art direction, and licensed electronic music. Dominic recounts his first encounter with the game as a child when his family briefly owned a PlayStation, making WipEout a staple in his gaming experiences. His fascination deepened upon discovering the PC version, despite its shortcomings compared to the original PlayStation release.
Dominic Zablowski [02:45]: "Wipeout was one of the most formative games I would say."
Dominic explains that his journey to rewrite WipEout began with reverse-engineering the game's data formats during his youth. [05:56] In 2016, he developed a JavaScript renderer for WipEout assets, further solidifying his understanding of the game's structure. The catalyst for the rewrite project was the leak of WipEout's source code in 2022, which Dominic found under a legally gray area without an accompanying license. Despite uncertainties, he embarked on the project to make the game accessible on modern platforms.
Dominic Zablowski [07:27]: "It's a complete rewrite, none of the lines of code are where they were and everything is different."
The discussion delves into the complexities of source code licensing. Dominic acknowledges that while the original source code was likely protected under copyright, his approach—rewriting the game from scratch without directly copying lines of code—could be argued as Fair Use. However, he admits that the resemblance to the original code places the project in a gray legal area.
Dominic Zablowski [07:27]: "It's kind of gray area, I guess."
Joe highlights practices like clean-room implementations, where one team describes the algorithm while another, unaware of the original code, implements it, to avoid copyright infringement.
Despite Dominic’s extensive background in web development and JavaScript, he opted to rewrite WipEout in C. [09:12] This choice was driven by his desire to engage with lower-level programming, which offers greater control and clarity over system operations compared to high-level languages like JavaScript, PHP, Kotlin, and Swift that dominate his professional work. Writing in C allows Dominic to enter a “Zen state,” focusing on intricate details and solving complex programming puzzles inherent to lower-level development.
Dominic Zablowski [09:12]: "With C, you really have to be careful what you do and that's kind of the appeal to me."
As of the interview, Dominic’s WipEout rewrite is nearly complete, with the game being playable across multiple platforms. He notes that while the core functionalities are intact, minor details and physics bugs remain. Dominic expresses a lack of motivation to continue polishing the project unless approached by a major stakeholder like Sony, especially around the game’s anniversaries when remastering is popular.
Dominic Zablowski [10:24]: "It's pretty close to being done. There's still some minor details that are missing."
Potential enhancements include:
Dominic critiques the leaked WipEout source code as “abysmal” due to its spaghetti-like structure, with numerous conditional compilations (ifdevs) scattered throughout. This disorganized codebase resulted from porting the game across multiple platforms and regions, leading to redundant and tangled code segments.
Dominic Zablowski [12:16]: "It's all over the place."
He contrasts the poor code quality with the game's successful and stable performance on the PlayStation, highlighting the paradox of functional software obscured by messy code.
Dominic explains the technical differences between NTSC and PAL regions, primarily their frame rates (60Hz vs. 50Hz). This discrepancy posed significant challenges for game developers, who often resorted to hardcoding frame rates due to the hardware limitations of the time.
Dominic Zablowski [16:40]: "The main difference for Wipeout was that NTSC was 60 hertz and PAL is 50 hertz."
He elaborates on the absence of Z-buffering in PlayStation hardware, necessitating developers to render polygons in a back-to-front order manually. This limitation led to visual artifacts and meticulous rendering order management within the source code.
Dominic Zablowski [21:01]: "The PlayStation doesn't have a Z buffer."
One of the standout aspects of Dominic's rewrite is his implementation of a bump allocator for memory management. This strategy involves preallocating a fixed block of memory and managing allocations in a linear fashion, resetting the pointer upon completing tasks or changing game scenes. This approach eliminates the need for dynamic memory allocation and deallocation, reducing complexity and the potential for memory leaks—crucial considerations given the constrained memory environment of the original PlayStation.
Dominic Zablowski [38:39]: "It's actually a pretty standard approach in a lot of game development that you have a bump allocator."
He further refines this by incorporating a temporary allocator for short-lived objects during tasks like loading race tracks, efficiently managing memory within a fixed 16MB space.
Dominic details his efforts to modernize the game's architecture by abstracting platform-specific code and reworking the rendering pipeline. He moved away from the original PlayStation's ad-hoc rendering methods to implement a more flexible triangle function, allowing for the integration of various rendering backends like OpenGL, Metal, and WebGL.
Dominic Zablowski [26:12]: "I exchanged that. Like how it goes through the ordering table and gets it to the display."
Additionally, he restructured the game loop to accommodate modern environments like the web, where infinite loops are incompatible. Instead, he adapted the game to use requestAnimationFrame callbacks for rendering frames, ensuring compatibility with browsers and enabling WebAssembly compilation.
The rewrite supports multiple platforms through modular backend systems. Initially developed for STL2 on Linux with OpenGL, Dominic extended support to SoCalled, facilitating compilation to web platforms via Emscripten. This modularity allows users to swap renderers and platform backends seamlessly, enhancing the game's adaptability across diverse systems.
Dominic Zablowski [31:59]: "So-called is actually very cool... and I just have to switch out the compiler from the usual GCC to emscripten and it compiled the web version."
Looking ahead, Dominic aims to address remaining physics bugs, enhance graphical features, and possibly collaborate with Sony for an official remaster. Beyond WipEout, he is involved in projects like rewriting Impact JS into C and developing a new C-based game engine, showcased in his game Bialab Disaster. He intends to open-source these projects, fostering community contributions and further innovations.
Dominic Zablowski [46:35]: "My dream would be to be paid to make a very polished version of that would be very cool if Sony says like, hey, Wipeout is the 38th anniversary."
Dominic encourages listeners to explore his work on GitHub under the handle Phobos Labs Everywhere, his blog, and Twitter. His projects offer valuable insights into low-level programming, game development, and innovative approaches to legacy game preservation.
Dominic Zablowski [48:42]: "Well, GitHub, the blog and Twitter mainly."
Joe Nash wraps up the episode by applauding Dominic's dedication and technical prowess, noting the potential impact of his WipEout rewrite on both gaming enthusiasts and software engineers.
Notable Quotes:
Dominic Zablowski [02:14]: "I've been always interested in retro gaming too."
Dominic Zablowski [07:27]: "It's kind of gray area, I guess."
Dominic Zablowski [09:12]: "With C, you really have to be careful what you do and that's kind of the appeal to me."
Dominic Zablowski [21:01]: "The PlayStation doesn't have a Z buffer."
Dominic Zablowski [38:39]: "It's actually a pretty standard approach in a lot of game development that you have a bump allocator."
Resources Mentioned:
This detailed summary encapsulates Dominic Zablowski's expertise and passion for game development, particularly in the realm of retro game preservation and modernization. His WipEout rewrite stands as a testament to the intersection of deep technical knowledge and nostalgic reverence, offering both a playable homage and a learning platform for aspiring developers.