Jump to content

320x200 image interpolation comparison


Blade

Recommended Posts

The WSA and most of the VQA animation in game are only 320x200 and require scaling up for the Win95 version of the game. Although most RA players will only have noticed the scaling on the VQAs which uses an interleaved scaling by default (blank scan lines), its actually also used on the mission select screen. The difference being the algorithm used. There are actually 3 algorithms implemented in the game, ranging from the fast interlaced version where it does a bilinear interpolation of even lines, but leaves the odd ones blank to the full interpolation version where it bilinear scales the whole thing. The one in the middle scales the even lines, but just copies them to the odd lines.

 

Anyhow we have reimplemented them, so check out the difference in scaling quality.

 

Ignore the fact it says ORA in the window title, that is because I haven't changed the text for the test app title bar yet to reflect the project rename.

xinterpol.png.8b95d5c4235645dc14e5b01c3a10dfaa.png

xinterpolydouble.png.1960f9bf501b9e3ec926d6c80fd2b80d.png

xyinterpol.png.6228639d2b25047ce3db8f3e55f827ff.png

Link to comment
Share on other sites

The function that acts as the interface for the different interpolators also takes an optional filename. If the file exists it is loaded as the table, otherwise one is generated and the file written out to disk to load next time. Of course you can just pass it NULL and it will just generate one. The generation is also controlled by a bool that gets set when a new palette is loaded and cleared once the table is generated for that palette to prevent unnecessary loading/generating.

In RA most of the time a filename isn't provided so it just generates it, I am guessing that in C&C95 a filename is always provided so it attempts a load, but if it was missing, would generate the requested file (might be interesting to test that theory by removing the interpolation files in C&C95 and seeing what it does).

Link to comment
Share on other sites

  • 2 weeks later...

In C&C95, I know that for VQA playing the filename is automatically derived from the video base name, and the game hangs if that file doesn't exist.  :huh:

 

In the WSA logics I actually found code to not only generate the missing stretch table, but in fact write it to disk. Though the physical disk format for the WSA tables is uncompressed, whereas the vqp format has all (x,y) <-> (y,x) type duplicates stripped from the saved files.

Link to comment
Share on other sites

  • 2 weeks later...

It seems I was a bit confused in my response to LavenderMoon, my reply related to the WSA loading logic not the VQA stuff, oops :) The VQA stretch table format is the same between RA95 and C&C95 though and is pre-computed for both.

 

As Nyerguds says there is logic to write out the WSA table to file, it should be called if the function to load (or generate) a table is called with a filename to load, but that file doesn't actually exist in the search path. Since RA never calls the function with a filename, they never get written out, but C&C95 should write them out if they weren't found in the mix files.

Link to comment
Share on other sites

Actually, I think that code to write the table to disk was only present in a few select cases; it wasn't a general part of the table generating code.

 

It's a bit of a tricky issue, see, since the names of the tables and the names of the wsas typically don't match... and, in fact, my patch adds a bunch of these tables that were missing and erroneously used tables from different wsa files, giving bugs in the stretching.

 

http://media.moddb.com/images/mods/1/17/16823/South-Africa-620.png

Link to comment
Share on other sites

In RA, the WSA style interpolation palette load and save is decided on by Interpolate_2X_Scale function, which is the front end function for the 3 possible scaling types. It is passed GraphicBuffer classes for source and destination buffers, a char * to use as a filename and an enum that decides which interpolation technique will be used. If the filename char * isn't NULL and the palette to use during interpolation has changed, it will load the filename if it is available on disk. If it isn't available it will generate it and then attempt to write it out.

 

The filename can be anything, it doesn't have to relate to the actual WSA filename being interpolated. If the C&C95 code is the same as the RA95 code, I guess the problem was that Interpolate_2X_Scale was being called with the wrong file name, so during development it never generated the file it was supposed to to bundle in the mix files, it just kept using the wrong one. If you had just fixed the changed the interpolation pal filename for the problem WSA files, the game might have generated them for you. Alternatively, just changing the code to pass NULL as the filename for those WSA files would have made the game generate them everytime which would also probably work.

Link to comment
Share on other sites

If you had just fixed the changed the interpolation pal filename for the problem WSA files, the game might have generated them for you.

Myeah, if I remember correctly I had to jump through quite some hoops to make that writing-to-disk code work, and as I said, it was one very specific WSA playing instance where the code was present, so I suspect it's not the same. In fact, a ton of WSA-related stuff seems to be macro-based in C&C95, rather than a called function. There's literally a loop with a "fetch next WSA frame" function call on every place that plays a WSA.

Link to comment
Share on other sites

Well, I'm just saying how the RA95 code works, I haven't seen any for the interpolate function from C&C95, so I can't be certain they are the same.

I'd be very surprised if the WSA draw code was significantly different though, the code in RA is virtually identical to that seen in OpenDUNE (and by extension Dune2) as far as I can tell apart from a few adjustments made to the format between the games. Are the loops you refer to something similar to those see in https://github.com/OpenDUNE/OpenDUNE/blob/master/src/wsa.c at line 463 and below?

Link to comment
Share on other sites

this function to scale .wsa to fullscreen high res works in both ra and cnc95

 

CALL(0x005B30F0, _scale_vqa); // ra

CALL(0x459CF7, _scale_vqa); // cnc95

 

void scale_vqa(char *src, char *dst, int src_h, int src_w, int bufsiz)

{

    float scale = (ScreenWidth / src_w > ScreenHeight / src_h) ? (float)ScreenHeight / src_h: (float)ScreenWidth / src_w;

 

    int dst_w = (int)(src_w * scale);

    int dst_h = (int)(src_h * scale);

    int dst_x = (ScreenWidth - dst_w) / 2;

    int dst_y = (ScreenHeight - dst_h) / 2;

 

    for (int x = 0; x < dst_w; x++) {

        for (int y = 0; y < dst_h; y++) {

            dst[(x + dst_x) + (ScreenWidth * (y + dst_y))] = src[(unsigned int)(x / scale) + (src_w * (unsigned int)(y / scale))];

        }

    }

}

 

Link to comment
Share on other sites

Just a note, your most inner loop iterates trought Y and you're doing a multiplication with a constant there, where X is fixed. You are accessing the memory in somehow a "random" way and loosing the speed-up from L1 cache. Reimplementing it fixing Y and iterating trough X *might* improve performance.

 

(This trick is used a lot in Gaussian Elimination/Cholesky implementations)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...