Font Size



Jake Stine_avatar

It's the year 2009, and it's almost over at that; and as anyone reading this blog well knows, multithreaded applications are the here-and-now and future of desktop computing. It's the only way we can take advantage of multicore CPUs. But multithreaded programming offers more than just improved multicore performance. Using threaded programming is actually very important to developing software that behaves nicely. By that I mean software that refreshes its window contents quickly, responds to your mouse clicks, and lets you cancel stuff.

For that the best approach is usually threading, with the alternative being something called "Cooperative multitasking" where by a program is written such that it splits all tasks into neat little chunks. For example, the two possible ways to implement loading an image (let's say a png image):

* Load the image one scanline at a time, and then after each scanline manually check for keyboard, mouse, or other input, and refresh the screen.

* Load the image using a thread, and let the usual "global" windows message handler dispatch keyboard, mouse, and refresh messages as usual.

The second approach has several advantages. For one, it needs fewer temporary heap allocations (which are typically slow and fragment memory). It is more responsive: windows messages will be handled in parallel to the image loading, so you don't even need to "wait" until the end of a scanline for user input to have its effect. It's also more scalable: while the first system is able to load one image at a time only in co-operative fashion (extending it to support multiple is possible, but very difficult), the threaded approach can be scaled to load dozens of images at once with no additional complications.

The drawback is that thread synchronization and especially structured error handling across threads tends to be much more complicated than that of the linear cooperative model. If you don't have errors to handle, or don't really care about handling errors, then threaded tasking isn't so bad.

Enter PCSX2, where everything ends up being damn complicated. Being a perfectionist, I figured I'd design the new GUI completely on the threaded model, doing away with cooperative design almost completely. Such a design should help avoid any deadlocking scenarios and allow the emu to recover from almost any error gracefully. Problem: The emulator has a lot of inter-dependent parts and pieces that need to be interlocked and synchronized, and all of them can throw out a variety of errors -- which too I'd like to handle smartly; requesting extra user input when appropriate (and not just throwing out annoying or vague message boxes).

Interlocking dependencies can be a nightmare. For example, if you start a thread that loads an image, and then block on that thread until it completes, you're worse off than if you wrote yourself a cooperative image loader because now the whole program stalls waiting for the thread to complete anyway. And like everything else, there are two ways to handle this:

(1) Use a "friendly" blocking mechanism that periodically polls the user input and updates display. This is no better than cooperative single-thread designs though, as it has slow response times and doesn't scale well to multiple threads.

(2) Build your entire GUI around "messages" and "callbacks" (sometimes also called "signals"). This is the most flexible and user-friendly option but can add a lot of "framework" to any codebase.

I tried to use the first approach initially, because I was in a hurry to get things working. But it's been problematic since day 1, so now I'm redoing most things to use the second method instead.

The second one is in fact the recommended design by Microsoft, and one they've been using for almost everything in Windows ever since Win95. It's one of the reasons the Win32 API feels "heavy" to a lot of programmers, but as it turns out, it's not without good reason.

Jake Stine_avatar

As of Sept 30th, we've re-enabled user comments at our SVN repository (PCSX2 @ Googlecode).

Comments have been re-enabled primarily so that we can get user feedback again on plugins and the current legacy gui updates. The trunk of svn (the new wx gui) is still too volatile for user comments to be of much use, so don't be surprised if we pretty well blow off "bug reports" relating to it.

(and yes, top priorities for implementation in the new gui are framelimiter, savestates, and the advanced cpu options -- along with bug fixes and memory leak fixes. No timeframe estimates: They'll all get done when they get done!)

Jake Stine_avatar

From 0.9.5 onward PCSX2 has been a mostly open SVN revisioning process, where beta builds are SVN-marked and are widely built and distributed to users. 0.9.5 itself was never released as an official 'stable' build, and after the release of 0.9.6 we just called all subsequent SVN builds of PCSX2 "betas." (mostly because we were too lazy and/or busy to bother worrying of version numbers). This lackadaisical version pattern was a source of confusion for users and developers alike.

So starting with our next release of PCSX2 we'll be using an established versioning pattern (which likely won't be for some time -- implementing a new GUI is a complicated ordeal). The new patter will be based on some standard Open Source convention, where odd-numbered versions denote SVN/devel builds (and will have SVN numbers affixed to the version) and even numbered versions denote stable releases. By chance this is already how things have been playing out since 0.9.5, so mostly it just means we're making a conscious effort to continue to apply the pattern in the future. Thus, the past-present-future will look something like this:

0.9.4 - Official stable release
0.9.5 - Development build (SVN)

0.9.6 - Official stable release
0.9.7 - Development build (SVN) [wx-enhanced!]

0.9.8 - Official stable release
0.9.9 - Development build (SVN)
1.0.0 - Official stable release
1.1.0 - Development build (SVN)

This way when people file bug reports we can know from the main version number alone if the report is regarding a stable release or an SVN build, and furthermore users can have a clearer guide to the status of versions being released and such. Furthermore, odd versions will have the SVN revision appended to them by default, like 0.9.7.r1880.

... and yes the hope is that we're going to go to 1.0.0 after 0.9.9, and use a 1.0, 1.1, 1.2, 1.3, etc version pattern, shortening the primary version numbers from three digits to two. But that's a long way down the road yet, and anything could happen between now and then. Wink


This begins a series of blog posts intended for ps2 developers and ps2 emu authors.
Its purpose is to give some light to some of the secrets I've learned about the VUs while developing my mVU recompilers, and to describe what happens in situations that are a bit questionable.

All information has been at least somewhat tested, but of course there may be some errors.
I should also mention that everything described here mVU implements in some way (unless specifically noted otherwise).
I may even describe some tricks and clever optimizations I used in my recompilers in future articles.

Since these articles are intended to describe advance secrets, I will not bother to explain common concepts about the VUs, and reading this implies you have at least an intermediate level of how the VUs work or how to program for them.


In pcsx2's advanced options dialog (if you've dared to look), you've might have noticed there's "FPU Clamp Mode" and "VU Clamp Mode" settings. You may even have experimented with some of these modes and found out they fix or break games.
But what are they doing? And why so many options?

Well first you have to know what a floating point number is. A float is simply a representation of a rational number from a string of bits, whose decimal point can change or 'float'. (This isn't the exact definition, but good enough for this conversation).

Basically there's something called the "The IEEE Standard for Floating-Point Arithmetic" (or IEEE 754), which defines floating point representation; and most systems abide by those rules (of course not our wonderful PS2).

You are here: Home Developer Blog