Jump to content

Grand Theft Auto 3 ported to the Sega Dreamcast


Recommended Posts

Back around 2001, this was THE biggest argument in video games. The PS2 came out with GTA3 and completely stomped the Dreamcast, it was an example of a kind of game the Dreamcast supposedly couldn't run, which is why it couldn't compete for the rest of the generation. For decades, conventional wisdom was that a game like GTA3 was too complex for the hardware. Recently, however, Rockstar, the people who made GTA3, said the game actually began life on the Dreamcast to begin with, and only really died on the console because Sega exited the hardware market before they could finish.

So with that in mind, a few of my friends and I have been porting Grand Theft Auto 3 to the Dreamcast in our spare time. Our goal is not only to fully port the game, but have it run better on the Dreamcast than it does on the Playstation 2. For example, the Dreamcast has much more RAM than the PS2 does, and that allows us to port over the PC version's draw distance instead of the PS2 version's shorter distance. More RAM also means more NPCs on the scene. Additionally, the Dreamcast has graphics features that the PS2 hardware does not, such as built in hardware accelerated normal maps. For this reason, the road in the Dreamcast version of GTA3 features bump mapping, completely abscent on the PS2 version. The SD Card slot on the serial port of the back of the dreamcast and network adapter also opens options not on the PS2 version, such as custom soundtrack support.

Many of the group working on this are porting masters for the Dreamcast. Myself, I ported Doom to the Dreamcast, and other members have ported things such as Mario 64, Quake, and Wipeout to the Dreamcast. We've been banging on this for a while now, and we've gotten to a point where the game runs well enough to demonstrate:

The Dreamcast is the best video game system ever made, and doing shit like this is so much fun. I love seeing how far this hardware can go. The other side of this equation is that our community tools, known as KOS, which we've all collectively been working on for about 25 years now, has finally matured to the point where it's suitable for professional, of-the-era development. Previously, it was assumed the homebrew SDK was far behind the official SDK from 1999, known as Ninja. Over the past 2 and a half decades, we've slowly added features to the SDK to bring it in line with those offered by Sega and Microsoft back in the day, like being able to generate gprof compliant profiling charts, and the creation of a SIMD-enhanced Sh4 fastmath ABI. These improvements have inched us far enough where stuff like this is finally possible.

Keep an eye out soon for a full release of this, as progress is speeding up drastically now.

  • Hook 'Em 3
Link to comment
Share on other sites

13 minutes ago, Captainant said:

That's cool as hell! What's the process to port? It seems like y'all are able to steal back some performance by pre-baking and pre-interpreting some geometry

It's sort of baking, sort of not. What we are using is known as triangle strips, it's a feature of the PVR core of the Dreamcast. Triangle strips aren't used too much anymore in games, but in the 90's they were a good performance boost. The way it works is that triangles are represented by a triplet of decimal numbers called a vertex. These numbers represent positions in space (think back to geometry class and plotting points) that form a triangle when connected. These triangles make up all the polygons in the world and characters and such. You do math on these points with what's called a matrix to do things like transform their position, rotate them around, etc. These matrix transformations are what move the polygons around the world so you can paint with them. Doing this kind of matrix math is super intensive, it's the part of computer graphics that takes the single most time, so the more triangles you have, the more vertices you have to do math on, the slower it takes.

Well, if you have a model that has two triangle that share a same edge, that means two of their points lie on exactly the same position. So, using triangle strips, you can combine them, so instead of having to do math on 4 vertices, you only have to do them on two. It works like the image below. The problem with a triangle strip is every triangle in the stip needs to share attributes about the texture being used. If you need to switch which texture is being used, you have to end the current triangle strip and start a new one.

Now, Grand Theft Auto 3 normally was not made like this, the PS2 did not use triangle strips. So the models and geometry are all with redundant vertices. So we wrote a tool that goes through the models, looks for triangles which call the same texture which reside next to one another, and figures out a funky shape to combine as many triangles as possible, to reduce the math complexity of the scene.

That's just one stage of optimization. A couple of major optimizations are being worked on right now. I'm currently working on a better caching system, the Dreamcast uses a kind of Cache known as a direct memory cache which is very different from the scratchpad cache the PS2 uses, with a lot more limitations. Currently, GTA3 basically isn't using any cache on the Dreamcast because the way the PS2 accesses cache thrashes the Dreamcast's cache. So reworking things so they're cache friendly will achieve an enormous performance boost.

At the same time, the way the Dreamcast and the PS2 do math on these vertices is completely different. The PS2 has a second processor known as a Vertex Unit that is entirely responsible for doing the math we described above. So while it's crunching the math to move these triangles, the main CPU can be doing other work. The Dreamcast has no math co-processor, all the math is done on the main SH4 CPU. This means when the Dreamcast does math, it can't work on anything else. That alone is a bottleneck, but there's a bunch of tricks to this. The Dreamcast CPU has a FPU inside known as the fast math core. This core does math extremely fast, and can also do it in parallel on multiple vertices. This is known as SIMD. The Dreamcast can do math on 3 vertices at the exact same time using this fast math core. Currently, the Dreamcast is doing all the math on the triangles without the core, through plain old C++, using none of the math hardware inside, one vertex at a time. Using this fast math core requires writing a bunch of SH4 microprocessor assembly, but once the process of translating these math calls to the SH4 fast math is done, then you'll see another enormous performance boost.

There are loads of other things that can be done to better performance on this. Most of it means really tailoring the thing to run as close to bare metal on the Dreamcast as possible, in a configuration that is specifically setup to match the way the Dreamcast is built. For example, the way the Dreamcast's ram is configured on the motherboard is in 2 separate DRAM chips that act like one giant blob of 8mb of memory. The way these DRAM chips actually work is they have 2 banks inside each. Each bank contains 512 rows of 4096 bytes of memory. When you access memory at any given location, a piece of hardware in the DRAM chip called a sense amplifier needs to move to the appropriate row to read it. If you read something that's on the same row that the sense amplifier is currently connected to, it doesn't need to move and can read the value immediately. Moving between rows takes time and incurs a performance penalty. Since each bank contains a sense amplifier, and there are 2 chips with 2 banks each, that means there are 4 sense amplifiers total. That means you can, at max, read 4 different locations in memory, spaced 2 MB apart, with no performance penalty. So using special kinds of buffers and adhering to these boundries and attacking the MMU of the Dreamcast, you can best keep locality of reference for data: data that is used frequently with others are stored together, to avoid this sort of memory performance penalty.

Bunch of stuff like that.

Triangle_Strip.svg.png

  • Hook 'Em 2
Link to comment
Share on other sites

Another example of something I'm working on: Multi-pass rendering. Normally, the homebrew SDK used for Dreamcast applications can only draw to any one target buffer per frame. So like, draw to the screen is a target buffer, draw to a texture is a target buffer. If you want to render something to a texture, then render that texture to the screen, it'd take two frames to do. That means using multi-pass rendering, every pass would halve the framerate.

There's a hidden register on the Dreamcast that KOS did not know about that I was exploring yesterday. Bit 31 of location 0x005F8160 when set to 1 enables the TA_LIST_CONT register in the PVR core, this tells the graphics chip inside the Dreamcast to continue rendering onto a second object list during the same frame. The official Sega Dreamcast SDK from Sega had an API called Ninja that had this feature, and so did Microsoft's Direct X on the Dreamcast, but KOS has never had it because we never knew about this register. I spent yesterday patching KOS so this functionality is exposed, which now gives the Dreamcast multipass rendering function. I played around yesterday with an HDR bloom demo for the Dreamcast, shown below.

What this means is we can port over the bloom effect from GTA:San Andreas if we'd like onto GTA3. This ability has lots of far reaching implications for further Dreamcast homebrew, as we can do things like use textures as image caches when using block rendering.

Screenshot_20240812_072824.png

  • Hook 'Em 2
Link to comment
Share on other sites

What a cool project.

 

did Dreamcast launch between ps1 and ps2 by like a half cycle or was it a straight contemporary of ps2? It’s so funny thinking back to that era of gaming and then for me, that era of being in intermediate and jr high - so much of gaming had to do with haggling with parents. I missed the whole n64/ps1 era and only got the ps2 when my my mom died and I guess they thought I needed a distraction. I remember picking up GTA III at Best Buy with my buddy thinking it might be cool, and then basically sitting in front of the tv for hours in a daze. No game has ever been a revelation quite like that one.

Link to comment
Share on other sites

8 minutes ago, WelfareBuysMyWeed said:

It's sort of baking, sort of not. What we are using is known as triangle strips, it's a feature of the PVR core of the Dreamcast. Triangle strips aren't used too much anymore in games, but in the 90's they were a good performance boost. The way it works is that triangles are represented by a triplet of decimal numbers called a vertex. These numbers represent positions in space (think back to geometry class and plotting points) that form a triangle when connected. These triangles make up all the polygons in the world and characters and such. You do math on these points with what's called a matrix to do things like transform their position, rotate them around, etc. These matrix transformations are what move the polygons around the world so you can paint with them. Doing this kind of matrix math is super intensive, it's the part of computer graphics that takes the single most time, so the more triangles you have, the more vertices you have to do math on, the slower it takes.

Well, if you have a model that has two triangle that share a same edge, that means two of their points lie on exactly the same position. So, using triangle strips, you can combine them, so instead of having to do math on 4 vertices, you only have to do them on two. It works like the image below. The problem with a triangle strip is every triangle in the stip needs to share attributes about the texture being used. If you need to switch which texture is being used, you have to end the current triangle strip and start a new one.

Wild, that sounds like a proto-texturing acceleration layer for texture mapping. Giving me flashbacks to linear algebra and vector cal lol

4 minutes ago, WelfareBuysMyWeed said:

Another example of something I'm working on: Multi-pass rendering. Normally, the homebrew SDK used for Dreamcast applications can only draw to any one target buffer per frame. So like, draw to the screen is a target buffer, draw to a texture is a target buffer. If you want to render something to a texture, then render that texture to the screen, it'd take two frames to do. That means using multi-pass rendering, every pass would halve the framerate.

There's a hidden register on the Dreamcast that KOS did not know about that I was exploring yesterday. Bit 31 of location 0x005F8160 when set to 1 enables the TA_LIST_CONT register in the PVR core, this tells the graphics chip inside the Dreamcast to continue rendering onto a second object list during the same frame. The official Sega Dreamcast SDK from Sega had an API called Ninja that had this feature, and so did Microsoft's Direct X on the Dreamcast, but KOS has never had it because we never knew about this register. I spent yesterday patching KOS so this functionality is exposed, which now gives the Dreamcast multipass rendering function. I played around yesterday with an HDR bloom demo for the Dreamcast, shown below.

What this means is we can port over the bloom effect from GTA:San Andreas if we'd like onto GTA3. This ability has lots of far reaching implications for further Dreamcast homebrew, as we can do things like use textures as image caches when using block rendering.

Screenshot_20240812_072824.png

Are you gamedev for your day job or just as a passion project? You're really diving into the metal if you're rediscovering new registers! 

What do you develop on? A MiSTer or actual hardware?

Link to comment
Share on other sites

2 minutes ago, Celery Man said:

What a cool project.

 

did Dreamcast launch between ps1 and ps2 by like a half cycle or was it a straight contemporary of ps2? It’s so funny thinking back to that era of gaming and then for me, that era of being in intermediate and jr high - so much of gaming had to do with haggling with parents. I missed the whole n64/ps1 era and only got the ps2 when my my mom died and I guess they thought I needed a distraction. I remember picking up GTA III at Best Buy with my buddy thinking it might be cool, and then basically sitting in front of the tv for hours in a daze. No game has ever been a revelation quite like that one.

The Dreamcast launched in 1998, only 2 years after the N64 and 2 years before the Playstation 2. For reference, the N64 and PS1 continued to see games well into 2001-2002, and the Dreamcast had already died before the Gamecube and Xbox launched. It's not really that the Dreamcast was underpowered -- it's considered the start of that entire PS2-GCN-Xbox generation and those consoles saw ports of its games -- it's that Sega ran out of money and went bankrupt midway through the Gen. Since it died just as the PS2 was releasing, there's very few games that overlap between it and the generation that it was in, outside of games ported FROM the Dreamcast TO those systems. A port FROM those systems TO the Dreamcast never really happened, and thus it's always been a question of just how much punch the Dreamcast actually had. COULD it compete and stay in step with those systems had it not died? A lot of people have said no, that GTA in particular started a trend of similar style games, none of which ever made their way to the Dreamcast. There flat out aren't any "GTA" style games on the system, and the argument was that it couldn't handle them. As GTA clones basically defined the generation, the thought is thus the DC couldn't hang.

Porting GTA3 directly to the Dreamcast is meant to refute the notion. The Dreamcast absolutely was powerful enough to hang that generation, it just never got the chance.

Link to comment
Share on other sites

Posted (edited)
9 minutes ago, Captainant said:

Are you gamedev for your day job or just as a passion project? You're really diving into the metal if you're rediscovering new registers! 

What do you develop on? A MiSTer or actual hardware?

Yep, thats my day job, I've been doing this since the mid 90's.

I develop on an actual Sega Dreamcast, which I've hacked up to connect to my computer via the serial port on the back. It lets me do step-through debugging on the real console through an actual IDE. I installed an extra 16 MB of memory on my Dreamcast so I have development overhead to hold debug symbols and such on my Dreamcast while still accessing the full 16 MB of system ram.

It's super important to do this development on real hardware because all the current Dreamcast emulators out there are broken in various ways. None of them implement the full instruction set, and there are loads of things about the PVR core inside the dreamcast that aren't understood and thus emulated. Like I'm fairly certain that bloom demo I posted above would work on at least NullDC and probably others.

The MISTER can't really support the Dreamcast, not least of which because the full SH4 and Tile Accelerator instruction sets aren't well known.

EDIT: Also, just to clarify, this is a community project. Lots of people are working on this, many of which are industry vets. But this is a passion project for us on the side from our normal jobs. We've all been doing this kind of stuff since 99. Making gamedev on the Dreamcast possible has been an ongoing thing for decades, it helps you learn new stuff that can be applied elsewhere. Doing this stuff flat out made me better at my job over the years.

Edited by WelfareBuysMyWeed
clarifying
  • Hook 'Em 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...