Jump to content
cncfan

Suggestions for Nyerguds C&C TDawn 1.06c

Recommended Posts

Eh? Do it myself? That was just about manually expanding the videos list in RA1 to add some new vids to it... The images stretching code and WSA playing code is really complex, I haven't figured out anything in it. Even my attempts to make the full video surface stretch to full screen to make videos center have all failed to produce any result.

 

If you could help to stretch these videos and WSA animations in the Y dimension automatically ingame I'd be very grateful.

 

The ddraw override replaces the graphics handling system, so right now there's not really a choice. At the moment the dll code gets it it's already the fully composed image the game produced.

Share this post


Link to post

The following function is called when drawing movies and map selection and so on. The int at 0x542AC8 equals 1 if a movie is playing, 0 if not. Helps to decide what is drawn. The source image has already been decompressed, so I'll skip info about decompressing images here.

 

The problem is there is a difference between rendering (which is easy and centralized) and interacting with that. I can apply deinterlacing quite easily, but the click zones won't change and thus would not correspond to the images on-screen any more. If you want to see how the internal renderer does its work, change the instruction at 0x459CD7 to "mov eax, 1" (duplication) or "mov eax, 2" (full deinterlace). Default is 0 (interlace).

 

Full deinterlace produces a faulty line on the bottom. This can be corrected by NOPing the decrease at 0x4E5F14 and skipping the three 'mov's and the 'rep movsd' at 0x4E5F8D.

 

Around 0x459CD7 EDI and ESI contain pointers to structures (of length 0xA4 in Red Alert) that hold the buffers, the source and target respectively. Important first members are:

byte* Pixels;
int Width;
int Height;
int LeftMargin??;
int field_10;
int field_14;
int RightMargin??;
...
int cPixels; // 0x2C -> Width*Height

 

The first member, Pixels is a pointer to an array of "byte Pixels[cPixels]". The source image is copied into that. Source is most likely 320x200, target depends on what you've set. These are indices into the palette.

 

EBX is set to "2 * (pTarget->Width + pTarget->LeftMargin + pTarget->RightMargin);" -- effectively advancing two lines on the target buffer for every line in the source. Thus copying/interpolating is line based. The gaps are filled in by the functions called by the modus explained above; the functions are ugly because they don't work on bytes but on shorts and ints instead, so they aren't clearly readable.

 

0x54430C holds the VQP files contents, 65536 bytes, essentially an array of 256x256 palette indices; to interpolate between two values, use arr[pixel1*256+pixel2].

 

I haven't tried this, but it might be as easy as increasing the target buffer pointer by (pTarget->Width*top)+right number of pixels to move the final image.

 

The game has no functions to stretch the contents to user defined sizes -- they are always stretched to twice the source size. To do this, the drawing function would have to be rewritten completely. I did that for any size in C++, and it was slow, though unoptimized. And then the clickzone problems occur and I haven't looked into that yet. Also, the fonts are rendered on their original positions way after the image is resized, thus they appear in the wrong place. Without resizing it looks perfectly alright.

 

---

 

For a quick test you can use Syringe and the magic.dll and change its inj-files contents to this:

;Enables duplication for all interlaced content.
459CD7 = DisplayClass95_DisplayContent1, 5

 

;Enables full deinterlace for interlaced content and fixes the last line.
459CD7 = DisplayClass95_DisplayContent2, 5
4E5F11 = DisplayClass95_DrawContentAntialiased_A, 6
4E5F8D = DisplayClass95_DrawContentAntialiased_B, 6

 

Then run

Syringe.exe "C&C95.exe"

 

---

 

These images were taken using ddraw.dll, but with resizevideo=false.

 

command_conquer-2011-02-18-04_52_00.png

Duplication mode.

 

command_conquer-2011-02-18-05_10_58.png

Full deinterlace mode. Note the vertical offset of the background image.

 

Early Red Alert test using mode 2. Note the image errors on the lower border. They are fixed already.

 

EDIT: An address was three bytes too low.

Edited by AlexB

Share this post


Link to post

That is amazing. Wow.

 

I can have the best of both worlds... change scan line removal to make it internal, and make the ddraw override stretch the 640x400 corner to full screen as it does now (by checking on true palette colour #0 black; only, we'll have to change to checking just right of the 640x400 area). That also prevents the click zone problem :)

 

By the way, I've had similar stretch problems (the lowest line getting errors) on the function that is used to stretch the CPS image (the "coming attraction" screen) to full screen. Do you have any idea how that could be fixed? If I remember correctly they're mostly noticeable on the German version since that one has a full image.

 

The original game solved this simply by not stretching all the way to the bottom, but rather taking 320x199 and stretching it to 640x398... a typical Westwood workaround X_x

Share this post


Link to post

Indeed the best thing to do. And otherwise fonts would be out of proportion, even if click zones are corrected.

 

And yeah, that sounds like Westwood. :lol: And indeed, they hardcoded a source height of 199 and a target height of 398 all over the place. Looks like the easiest way to solve it is to change the function at 0x4D525E to change [ebp+2Ch] to 400 if it is 398 and [ebp+24h] to 200 if it is 199. The first line is there three times and the last line occurs only once that way. The cleanest solution would be to fix two immediate values for the trailers for the Intro/Sneak Peek button and the GDI and Nod endings each. (For instance at 0x439BAB, 0x439BE8, 0x439E1F and 0x439E2E.)

Share this post


Link to post

Eh, I did change all those values to 320 and 200, but that's what caused the bug to appear. I don't really understand what you mean here... I just want it to stretch it to fullscreen correctly, since I can't really use the 320x199 workaround to stretch to 1024x768, or any other resolution dynamically.

 

What exactly is that function at 4D5254, by the way?

 

If you want to see how the internal renderer does its work, change the instruction at 0x459CD7 to "mov eax, 1" (duplication) or "mov eax, 2" (full deinterlace). Default is 0 (interlace).

 

Full deinterlace produces a faulty line on the bottom. This can be corrected by NOPing the decrease at 0x4E5F14 and skipping the three 'mov's and the 'rep movsd' at 0x4E5F8D.

Wow, nice. I think I'm going to make this fully user-controlled, meaning I just set the 00554310 value to whatever I want :)

 

[edit]

 

I did the edits, making the mode a conquer.ini option. It works great.

 

But interpolation mode still produces errors at the last line, even after I followed your instructions to fix it...

 

score_screen_faulty_line_interpolate.png

 

Around 0x459CD7 EDI and ESI contain pointers to structures (of length 0xA4 in Red Alert) that hold the buffers, the source and target respectively. Important first members are:

byte* Pixels;
int Width;
int Height;
int LeftMargin??;
int field_10;
int field_14;
int RightMargin??;
...
int cPixels; // 0x2C -> Width*Height

 

The first member, Pixels is a pointer to an array of "byte Pixels[cPixels]". The source image is copied into that. Source is most likely 320x200, target depends on what you've set. These are indices into the palette.

Ah yeah, the game surfaces... I've done some research on them, and there are a whole bunch of them. I had already found 4 before you pointed me to this 5th one, and I immediately realized the Pixels array to be an array of palette indexes. I didn't know it used a 320x200 object of the same type as source to stretch from though... thanks for that :)

 

EBX is set to "2 * (pTarget->Width + pTarget->LeftMargin + pTarget->RightMargin);" -- effectively advancing two lines on the target buffer for every line in the source. Thus copying/interpolating is line based. The gaps are filled in by the functions called by the modus explained above; the functions are ugly because they don't work on bytes but on shorts and ints instead, so they aren't clearly readable.

I see...

 

0x54430C holds the VQP files contents, 65536 bytes, essentially an array of 256x256 palette indices; to interpolate between two values, use arr[pixel1*256+pixel2].

Yeah, I know that one. I even made a tool to generate them (for the .pal files used by WSA files).

See http://www.moddb.com/mods/command-conquer-...ca-mission-info ;)

The actual VQP files are stored differently though... looking at the file size, I think they simply don't contain the duplicate Y,X entries for the X,Y colour pairs, which makes them a lot smaller. They can also contain multiple stretch tables, for scenes with different palettes in the video.

 

 

I haven't tried this, but it might be as easy as increasing the target buffer pointer by (pTarget->Width*top)+right number of pixels to move the final image.

You mean to center an image? Hmm...

 

The game has no functions to stretch the contents to user defined sizes -- they are always stretched to twice the source size. To do this, the drawing function would have to be rewritten completely. I did that for any size in C++, and it was slow, though unoptimized. And then the clickzone problems occur and I haven't looked into that yet. Also, the fonts are rendered on their original positions way after the image is resized, thus they appear in the wrong place. Without resizing it looks perfectly alright.

Actually, the function used to stretch CPS images could perfectly stretch them to 1024x768. In my database you'll find the function I made to dynamically set the target resolution value at 005C8290; trace its xrefs and you could find the function that does the stretch to fullscreen. You can enable the stretching to full screen by putting StretchAttract=true in conquer.ini's [Options] section.

 

For a quick test you can use Syringe and the magic.dll and change its inj-files contents to this:

;Enables duplication for all interlaced content.
459CD7 = DisplayClass95_DisplayContent1, 5

 

;Enables full deinterlace for interlaced content and fixes the last line.
459CD7 = DisplayClass95_DisplayContent2, 5
4E5F11 = DisplayClass95_DrawContentAntialiased_A, 6
4E5F8D = DisplayClass95_DrawContentAntialiased_B, 6

Then run

Syringe.exe "C&C95.exe"

What magic.dll? The only one you ever gave was the one for the video adding in RA1 v3.03.

 

[edit]

 

Wow, there's quite some stuff in that dll. Odd how this does produce the correct results, while following your edits described above don't. Are you sure you just skipped all these commands, and didn't do anything else there?

Share this post


Link to post

00459BD4 -> Interpolate_2X_Scale(GraphicBufferClass *, GraphicViewPortClass *, char *)

 

My two cents, as i know nothing other than the names of the functions hehe

Share this post


Link to post
Eh, I did change all those values to 320 and 200, but that's what caused the bug to appear. I don't really understand what you mean here... I just want it to stretch it to fullscreen correctly, since I can't really use the 320x199 workaround to stretch to 1024x768, or any other resolution dynamically.

Edit: forgot to answer this :mellow:

I just added a hook to change 199->200 and 398->400. The result is this a correctly strected Coming Attraction screen, no faulty line at the bottom. I didn't try to stretch it to full screen. I'll have to look into the function stretching the CPS to see what it does/can be made to do. Stretched to 400.

 

I did the edits, making the mode a conquer.ini option. It works great.

 

But interpolation mode still produces errors at the last line, even after I followed your instructions to fix it...

Cool! The specific hooks are implemented like this:

DEFINE_HOOK(4E5F11, DisplayClass95_DrawContentAntialiased_A, 6) {
    // hooks must be longer than 4 bytes, thus hook in earlier
    // and recreate the original instruction while omitting the 'dec'.
    int value = R->Stack<int>(-0x8);
    int x = value;
    value += R->ESI<int>();
    R->Stack<int>(-0x8, value);
    return 0x4E5F17;
}

DEFINE_HOOK(4E5F8D, DisplayClass95_DrawContentAntialiased_B, 6) {
    // because of the first change, we'll have to skip this
    return 0x4E5F98;
}

In Red Alert I had to skip the call to the sub before that. In C&C95 this would be the bytes from 4E5F7C to 4E5F8D instead. But via dll this approach didn't work in C&C95, which left me puzzled, too. :huh:

 

Yeah, I know that one. I even made a tool to generate them (for the .pal files used by WSA files).

See http://www.moddb.com/mods/command-conquer-...ca-mission-info ;)

The actual VQP files are stored differently though... looking at the file size, I think they simply don't contain the duplicate Y,X entries for the X,Y colour pairs, which makes them a lot smaller. They can also contain multiple stretch tables, for scenes with different palettes in the video.

Makes sense. It could be represented by a triangular matrix, saving about half the space.

 

Actually, the function used to stretch CPS images could perfectly stretch them to 1024x768. In my database you'll find the function I made to dynamically set the target resolution value at 005C8290; trace its xrefs and you could find the function that does the stretch to fullscreen. You can enable the stretching to full screen by putting StretchAttract=true in conquer.ini's [Options] section.

I have to look into those. It'll take some time because I have to make myself a little more familliar with TD.

 

Wow, there's quite some stuff in that dll. Odd how this does produce the correct results, while following your edits described above don't. Are you sure you just skipped all these commands, and didn't do anything else there?

Yeah, there's a little more stuff in there, I just didn't include the hooks for that. Helitransports won't take off with GNRLs on board in multiplayer modes, theater manipulations (always use temperate for testing purposes), putting TTNK where originally was an MRJ, deinterlacing for the RA movies and adding a buildable 23rd unit type (for testing, JEEPS are replaced by this type dynamically). But, though almost working, this is rather a proof of concept and I did it just for fun. It's not polished, no [unitTypes] section or something ^_^

Edited by AlexB

Share this post


Link to post
Cool! The specific hooks are implemented like this:

DEFINE_HOOK(4E5F11, DisplayClass95_DrawContentAntialiased_A, 6) {
    // hooks must be longer than 4 bytes, thus hook in earlier
    // and recreate the original instruction while omitting the 'dec'.
    int value = R->Stack<int>(-0x8);
    int x = value;
    value += R->ESI<int>();
    R->Stack<int>(-0x8, value);
    return 0x4E5F17;
}

DEFINE_HOOK(4E5F8D, DisplayClass95_DrawContentAntialiased_B, 6) {
    // because of the first change, we'll have to skip this
    return 0x4E5F98;
}

In Red Alert I had to skip the call to the sub before that. In C&C95 this would be the bytes from 4E5F7C to 4E5F8D instead. But via dll this approach didn't work in C&C95, which left me puzzled, too. :huh:

I just tried removing that too, it still didn't fix the bug.

 

I don't really see what you do in this though... I'm not familiar with Ares code or C++. That section B's return, does that end the function or just the hook? To me, that seems like it just bites 6 bytes out of the function and then continues, which means it'd only remove 2 of the mov commands, and not the third one or the 'rep movsd'.

 

[edit]

Ah, nevermind, the return value is the address to jump back to. I see now.

 

Makes sense. It could be represented by a triangular matrix, saving about half the space.

Obviously, in my generator I immediately saved the values I calculated for X,Y on Y,X too, and let the next loop skip the ones I already saved by putting my starting number one higher. :)

 

I have to look into those. It'll take some time because I have to make myself a little more familliar with TD.

I'd be incredibly grateful if you could somehow make it stretch the title screen to full screen... that's one of the things that's keeping me from implementing free resolution switching at the moment. Though the PCX handling classes seem to be separate from what I can see -_-

 

Yeah, there's a little more stuff in there, I just didn't include the hooks for that. Helitransports won't take off with GNRLs on board in multiplayer modes, theater manipulations (always use temperate for testing purposes), putting TTNK where originally was an MRJ, deinterlacing for the RA movies and adding a buildable 23rd unit type (for testing, JEEPS are replaced by this type dynamically). But, though almost working, this is rather a proof of concept and I did it just for fun. It's not polished, no [unitTypes] section or something ^_^

heh, actually I'm very close to that in C&C1. I already did it for the music, AND I already fixed the TD equivalent of the "100 units bug". That's probably something you'll be confronted with too... if C&C1 has it and TS has it, no doubt RA1 has it too.

Share this post


Link to post
heh, actually I'm very close to that in C&C1. I already did it for the music, AND I already fixed the TD equivalent of the "100 units bug". That's probably something you'll be confronted with too... if C&C1 has it and TS has it, no doubt RA1 has it too.

Yes, in RA there's the 22-unit-bug, the 7-vessel-bug, the 78-buidling-bug, .... That one I haven't fixed yet.

Share this post


Link to post

hehe yep, that one :P I took the easy way out that WW took for TS though, and just put the new limit on 100 (for both infantry and vehicles; they're the only things the C&C1 AI produces). If I'd known back then the game had vectors I could use, I might've done it quite differently though... right now, all I did was mess with the stack to make it reserve more stack space for the arrays.

Share this post


Link to post

I uploaded them all here:

http://nyerguds.arsaneus-design.com/cnc95u...ncddraw-cncfan/

By the way, cncfan, could you separate the "stretch 640x400 scenes to fullscreen" and "Y-stretch to fill in black lines" options? Seeing as I can do Y-stretching natively now, you can check on 640x400 scenes by checking if the pixels right next to the 640x400 scene are colour #0 to see if it needs stretching.

Share this post


Link to post
Full deinterlace produces a faulty line on the bottom. This can be corrected by NOPing the decrease at 0x4E5F14 and skipping the three 'mov's and the 'rep movsd' at 0x4E5F8D.

NOPing that decrease at 0x4E5F14 turned out to be a bad move... the decrease was there so it'd only calculate 199 lines instead of 200, which is exactly right since it takes averages between lines; there ARE only 199 in-between lines. The fact this decrease was gone made it also try to calculate the average between the last line and whatever data happened to be stored right after it, resulting in the faulty line at the bottom.

 

I restored the decrease at the start, and it is now fixed completely. The line stays black even for full 320x200 videos, but since the stretching method of adding in-between pixels really just stretches to 639x399 anyway this doesn't really matter.

 

I wonder if there's a way to control X-stretching too...

 

[edit]

 

lol, nope, same functions. Basically all 3 functions seem to do X stretching the same way, but differ in how they do Y stretching. Pity, it means full doubling isn't possible (not without making an extra function myself anyway)

Share this post


Link to post
I uploaded a small pack for using the scanline removal of cncfan's ddraw on RA1 without any hassle. The entire thing is explained here:

http://www.commandandconquer.com/forums/sh...p?328#post11084

 

Hi Nyegrguds

 

Tried the dll, following all the steps in readme's and forum threads. Ended up with a white screen in both widow and fullscreen modes... The same problem with CnC and the version of the dll built by cncfan. :(

 

The weird thing is that HIFI's builds work just fine, but I'd really like to have "deinterlaced" movies.

 

Any idea what I can be doing wrong, or what to try?

Share this post


Link to post

meh, I'll see if I can find the code in the RA exe -_-

 

[edit]

 

Change the bytes at address 1B24D0 in RA95.dat to B8 02 00 00 00

 

Do note this will make all scenes (including map selection) interpolate vertically. If you get the errors at the bottom of the screen, you could change the second byte in the sequence to 01 instead, to use the duplication method.

Share this post


Link to post
Hi Nyegrguds

 

Tried the dll, following all the steps in readme's and forum threads. Ended up with a white screen in both widow and fullscreen modes... The same problem with CnC and the version of the dll built by cncfan. :(

 

The weird thing is that HIFI's builds work just fine, but I'd really like to have "deinterlaced" movies.

 

Any idea what I can be doing wrong, or what to try?

 

meh, The CnCFan version ONLY works with v1.06c_r2, where still on Beta...

you SHOULD use the hifi version until the new version is avaliable.

Share this post


Link to post

What the heck? No it doesn't. I managed to make the dll stretch RA videos perfectly.

Share this post


Link to post
meh, I'll see if I can find the code in the RA exe -_-

 

[edit]

 

Change the bytes at address 1B24D0 in RA95.dat to B8 02 00 00 00

 

Do note this will make all scenes (including map selection) interpolate vertically. If you get the errors at the bottom of the screen, you could change the second byte in the sequence to 01 instead, to use the duplication method.

 

Tried the suggested edit but still can only see a blank white window. Maybe I'm looking at a wrong version of ra95.dat? Mine is from TFD + your 3.0.3 patch installer.

Share this post


Link to post

um, obviously this was a solution INSTEAD of the dll. This actually enables stretching in RA itself, it doesn't affect how or why cncfan's experimental dll fails on your PC, so just don't use that dll.

Share this post


Link to post
um, obviously this was a solution INSTEAD of the dll. This actually enables stretching in RA itself, it doesn't affect how or why cncfan's experimental dll fails on your PC, so just don't use that dll.

 

Thanks a lot for the clarification! TLF videos just rock with horizontal lines removed!

post-7849-1300453913_thumb.png

Share this post


Link to post

meh, I'll see if I can find the code in the RA exe -_-

 

[edit]

 

Change the bytes at address 1B24D0 in RA95.dat to B8 02 00 00 00

 

Do note this will make all scenes (including map selection) interpolate vertically. If you get the errors at the bottom of the screen, you could change the second byte in the sequence to 01 instead, to use the duplication method.

 

Awesome, that worked perfectly, thanks a lot Nyerguds.

Share this post


Link to post

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.

×