Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Wide Screen Client

Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Guide to Displaying the Client in Widescreen

Contents
Contents





Introduction
Welcome back. Nice to see you all. I hope you all have a good "code head" on and are eager to make your PT client even more funky and cool. :D:

In this guide I'm going to go into some detail about how my Butchered client supports Wide Screen monitors and windows without the classic black bars either side or "stretched pixels", restricting the actual play view to 4:3 no matter what the screen or windows' dimensions are.

So basically, we are going from this:-
cU24a - Wide Screen Client - RaGEZONE Forums

to this:-
PdGWP - Wide Screen Client - RaGEZONE Forums


Most of you probably know that my client has done this for years. But a friend recently pointed out that I never clearly documented (as a guide, or tutorial) how this is achieved.

There are a number of flaws in my implementation which I will highlight. However, from the point of view of a user, these are mostly invisible and no bugs are created. So when I say "flaws" what I really mean is that there are effects produced which could be improved upon, if you have the time and the inclination.

I think this is a good patch for any PT client to have, because I'm guessing that by now most of us don't have a perfect 4:3 display, and any such resolutions will either produce black borders or stretch all our PT characters into Munchkins. (short squat people) This guide will ignore offsets in my Butchered client, and should apply to any client you want to modify. There is a connected issue regarding using non-standard resolutions and window sizes which you should probably resolve first, but I'm not going to cover that in this guide. (It has been documented via a couple of techniques before... but I'm not sure it's listed as a guide... I'll re-check) I shall assume, for the sake of argument, that you have already resolved that.

It would also be nice to resolve the outstanding flaws. So I'd love to get feedback from someone who has the time to look into them and report back their findings. For my self, this method has proved "sufficient" despite not being perfect, and I can't seem to warrant the extra time to clean up those little mistakes. (in truth, I only really have time to look, see, and offer advise to other devs most of the time these days)
Applies to: ANY official client
AFAIK. So far, any official client I tried, this works as illustrated.​
Level: Intermediate
requires intermediate maths, some basic machine code and Olly Debug understanding and the ability to adapt where your target (the client you want to modify) may differ from the example one. I've done this to several clients, so I know the basics are the same.​
Required:
Official PT client without XTrap, and perhapse some means of achieving non-standard (for PT) resolutions
preferably kPT, jPT or cPT. ePT and bPT will work, but we know there are other issues with them. lPT is still an unknown quantity for me. Old tPT and PTvn clients (now discontinued) are also known to work.​
(preferably a 2.x version)
A working Private server to attach your NoXTrap client to? (You can't use this patch on official servers ... please don't ask)​
 

Attachments

You must be registered for see attachments list
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Getting Started
First of all, we need to orient our selves around the particular client we are trying to fix.

When you first attach your client to Olly, it will normally display disassembly somewhere around here:-
Ublja - Wide Screen Client - RaGEZONE Forums

I'm using kPT2453 with optional XTrap patch, just because I've never done much with it, so it won't contain all my usual documented addresses and offsets to confuse anyone.
The idea is that you can use whatever you like. However, it's better if you don't try on an already heavily modified pServer client (unless the modifications are your own) stick with kPT or jPT. (possibly cPT)​

That's the executables' original entry point. This code is setting up the standard C environment for the main code. (Windows isn't POSIX, and doesn't provide a C style int main(int argc, char *argv[]) entry point for programs which run on it, despite the fact that most Windows programs are still developed as C / C++... slightly surprising is that the kernel doesn't even start code with the Visual C++ WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); :/:)

So we should run down this initialisation code to find the actual entry point of the C[++] source code.
wq0kZ - Wide Screen Client - RaGEZONE Forums
This illustrates the point where the CRT init code goes into WinMain(). It's usually pretty similar in all clients, but I changed it a fair bit to make the x86 lighter and more readable in Butchered. (and ignored some code which should never become true... something like, "is this binary for a non-x86 CPU" which would have been discounted by the kernel if it was :/:)

The red boxes highlight areas my eye picks up straight away when scrolling down. The GetStartupInfoA() is key, because it's that structure that this code needs to convert to C[++] style entry point, and the broken Arguments to the WinMain() call is common in most Visual C++ built programs. (though Butchered fixed it so Olly can read it ... I think I in-lined the CALL code into the main routine after removing the nonsense code:ehh:)

That CALL (which Olly can't determine all the arguments passed to it) is the redirect to the source level entry point, a.k.a. WinMain(). Select that CALL, tap "Return" (that's the back to front L arrow key on the far right of the Keyboard just before the Numeric pad, if you have one) and Olly will take you to the CALL target address.

You can now "label" that address "WinMain" (I usually tap ":" but there's probably some menu option for GUI people) and the code starts to get a little more readable.
aG6yM - Wide Screen Client - RaGEZONE Forums

Ooh... Momma lookit! Movies!​

You told Olly some useful information it didn't figure out which allows it to present cleaner disassembly. :D: (I used to call this "TrueStart" or something if you look at older posts... what it is called doesn't really matter, but in VC it was "WinMain" and since Olly knows the form of a "WinMain" in VC, it can tell you more if you follow that convention)

That's almost a universal starting point with Olly, and I'm sure I've described it before.

The place we really want to find is a routine that the PT source typically exports (I don't know why they would choose to share that info with us, but it's very nice of them) as InitD3D(), which initialises Direct3D. (what a surprise)
f5DlI - Wide Screen Client - RaGEZONE Forums
As you can see, this happens right after the window is created, updated and assigned a mouse pointer. (an empty, or invisible one, by default ... but not in Butchered)​
 

Attachments

You must be registered for see attachments list
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Nitty Gritty
Let's look at this routine, as it stands.
lmp0V - Wide Screen Client - RaGEZONE Forums
frsSY - Wide Screen Client - RaGEZONE Forums
Now the disassembly on the left is Olly reading my unknown kPT2453 client where I feel very much like a fish out of water. The listing on the right is from Olly reading Butchered4pre which has my usual labels exported. You should be able to see why developers get used to a certain client and feel at home modifying it. We'll need some of those offsets, and so I'll probably need to explain that they are usually found in the routine which reads Hotuk.ini. (and the other client configuration areas)

My labelling convention is almost certainly not what these variables are called in the official PT source. It's just for my convenience, but if you are going to read it, it would be beneficial for you to know what information I store in a label and how.

The first thing I usually include is a couple of letters describing the type of data. I don't use the C style Hungarian n = int, lp is a "long pointer" and such... but do use something very much like it for x86 purposes. TBH, I often do still use sz for a C style string, and lpsz for a pointer to a string. (I don't see any reason not to) I declare f as a long floating point number (4 byte float) and dw as a normal 32-bit integer. I don't specify int / uint because there are no types and so no type casting or union rubbish in x86.

Next I provide what I think is the most meaningful short-name in Camel-case. (initial letter of each word is upper-case) I may drop vowels like sms text messages to save overly long labels, and where I apply Cpy to the end, it's because the configuration reading routines often keep 2 global variables for each setting read. The first, where the routine has read it from a file or the system registry, and the second, after it has decided which of two conflicting configurations takes presidents. (I think that's the wrong spelling... :/: You know what I mean)

Next, I'm going to break out to a new routine, so we need to find a "code cave" and concern ourselves with the size of instruction encodings. Fortunately, the first instruction in InitD3D() is a nice big 6 byte instruction, and a CALL is only 5 bytes, so I'm going to make that my replacement, and must remember to include that instruction in my new routine.

My routine is called CalcZoom(), but you can call it what-ever you like, or just leave it as a number. (names aren't necessary, just nice :wink:) This is what it looks like in Butchered:-
I7ZvY - Wide Screen Client - RaGEZONE Forums
Remember, the last instruction is the one we are going to destroy with our CALL CalcZoom.
Code:
mov ecx,[dwDisplayWidthCpy]
We need to find 31 bytes for this code in the .text section, or add a new one, or import the code from a DLL. It doesn't matter what method you chose to use... but I need to pick one to illustrate.

So I had a look at my executable... I'm not sure who made the XTrap patch, but I don't think it was me. I make lots of empty space by clearing out areas with XTrap code. Doesn't matter, but I found that the export fcEXP is just filled with NOPs followed by a RET.
GsoxP - Wide Screen Client - RaGEZONE Forums
Looking at other clients, that's pretty common. It does nothing, but it looks like a good cave to me.

I'll make it just return right away, and use those NOP bytes to place my code. :D:

Now we need to know about those offsets that I've labelled in CalcZoom. So, we need to know the following labels locations in this client. :-
dwDisplayHeightCpy
dwDisplayWidthCpy
fZoomFactor
fTrueZoom​
Some we can see from the snippet above. So we know:-
dwDisplayHeightCpy = 5FEDC4
dwDisplayWidthCpy = 5FEDC0​
We need to find out fZoomFactor, and fTrueZoom? Well, actually, I "invented" one of those from a data "cave". ^_^ There are lots of those if you aren't using XTrap, because of the Hex signatures which are stored as ASCII.

The value I label "fTrueZoom" is the address the code usually stores as a constant 0.2272727 "long" or 32-bit float, as I prefer to think of it. ;) (this is how OllyDbg will describe it in the dump view) While uninitialised, I set this value to 0, to make my job easier seeing it change, knowing when it has not been set, and 0 usually compresses well. XD

In most clients, including both Butchered (formerly kPT 1977) and 2453, this value is stored between the ASCII strings "Image\Logo.bmp" and "%s x %d". That value is stored at the offset 5C9F7C in the .rdata section of 2453. So it that value is now known.
fXg08 - Wide Screen Client - RaGEZONE Forums
Havining said that, it was a constant, which was stored in .rdata, and that's fine because .rdata is write protected. But I want fZoomFactor to be constant and fTrueZoom to be variable depending on the aspect ratio of the users chosen display!

You can just set the .rdata section to be writeable, but that destroys a lot of your clients run-time protection. So what I usually do is reverse the positions of these two variables once I've chosen the spot for the other. (more correctly, 1 constant and a variable)

I've decided that 712EEC is almost certainly free, and probably part of old XTrap routines in this client, so that will be my new fTrueZoom, and all the old fZoomFactor pointers will have to be updated to it.

So, our named offsets are now:-
dwDisplayHeightCpy = 5FEDC4
dwDisplayWidthCpy = 5FEDC0
fZoomFactor = 5C9F7C
fTrueZoom = 712EEC​
We need to set fTrueZoom to 0.0, and fZoomFactor to 0.3030303. (see end of *this post* to understand why I choose this value) You can do this in the Dump, and if you set the view to 32-Bit float. Double clicking the value at the appropriate address will allow you to enter such a value. (in case you are used to entering hex numbers as bytes :wink:)

Don't forget to copy this stuff to your new executable.

When done, this is my CalcZoom function:-
lf761 - Wide Screen Client - RaGEZONE Forums
And this is the InitD3D after it's been labelled with the required offsets for this project only.
phhOt - Wide Screen Client - RaGEZONE Forums
[highlight]Don't forget to update any other pointers to the old, constant fTrueZoom![/highlight] (which should now be labelled fZoomFactor) The only thing which should reference that now should be your CalcZoom function.

[highlight]Don't forget to copy every edit to your executable![/highlight] It's a good idea to save it out, with your Olly labels as a .udd file, quit Olly, and reload your client in Olly again, re-check all the code, all the offsets, and all the references to them before even trying to play.

Why is my "fZoomFactor" 0.3030303? Well, the original "zoom" (the original fTrueZoom constant) was 0.2272727. I work out the ultimate fTrueZoom from Height ÷ Width × fZoomFactor. This is great, because it gives a ratio for width to height and bases the zoom on that.
480 ÷ 640 = 0.75
600 ÷ 800 = 0.75
768 ÷ 1024 = 0.75
1024 ÷ 1280 = 0.8​
Yea, 1280 × 1024 isn't exactly a 4:3 aspect ratio either... but it's close enough for what we want. (and original PT didn't allow for that discrepancy either :wink:) 0.2272727 ÷ 0.75 = 0.30303026r, so to set the fZoomFactor to 0.3030303 is sufficient (considering analogue to digital loss) to get the zoom to fit the edges of the screen, no matter what the aspect ratio.(* see , below re. displays higher than they are wide)​
 

Attachments

You must be registered for see attachments list
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
The Flaws?
I said, in the that there are a number of flaws with this method. So what are they? Doesn't this seem to solve everything? Nothing has gone wrong and the game all runs fine... right? (I hope so, if you followed my instructions very carefully)

Well, the first thing you will notice, is that the portrait of your target PC / NPC (or monster, if the target NPC is hostile) will be enlarged more than the frame within which it is supposed to fit. There is probably a couple of ways you could resolve that. You could create a new fOldZoom constant set to 0.2272727, and find the pointer you updated which affects just that, and point it to your new 0.2272727 fOldZoom constant. That should / may work. Or you could find where the frame is displayed and update that some how. I'd love to hear how you get on by the way. :D:

The other thing my friend confirmed for me when I explained my method to him (or her :wink: screen-names are not indicative, and we're not that close) is that a 4:3 ratio 3D window is still being rendered, but the top and bottom are cropped off your 16:9 or 16:10 or WHY display. That's wasteful on the GPU, and probably graphics RAM. But until you resolve the GDI font rendering issue, I really don't think it will affect your frame-rate in any noticeable way. If anyone can think of a better way of doing this, of course, I'd love to hear from you, and be happy to assign credit, or not, as you would prefer.

Finally, what if you have one of those monitors which swivels so you could have a 3:4 or even 9:16 display? Yea, I don't allow for that. You can expand the CalcZoom function to work in reverse if dwDisplayWidthCpy is greater than dwDisplayHeightCpy if it really bothers you. However, I suspect that "gamers" are not likely to have a display setup like that. It's more common for publishers who want a display which represents a written page. (say, a magazine or such) However, if they normally play top-down scrolling shooters, this used to be a popular setup in some arcade games. :lol:

---EDIT---
I seem to have forgotten one I was quite aware of when I first made this. The bottom border of your HUD? It's okay in exactly 720p, because it recognises the width 1280 from 1280 x 1024, but it doesn't work for 1440 x 900, 1920 x 1080 type resolutions, because it doesn't recognise those widths. Seems to be hardcoded to switch - case on specific display widths. I'm sure it's not *very* hard to find that switch - case code and add some, or just make it smarter and more flexible. ^_^​

Credits
No credits?

Well, it's not actually like anyone helped me work all this out. :/: I was working pretty much alone. But that doesn't mean I wasn't consciously aware of things I'd been told elsewhere.

I'd like to thank my friend for pointing out how little I documented this technique and prompting me to write it up in this thread, but I gather they'd rather I didn't. Maybe they will change their mind, in time.

I'd like to thank this community in general; Sandurr, for making me realise the value of telling Olly that WinMain is WinMain and not just TrueStart or such, Gregoo for his earlier guides which got me into doing this stuff... but those are rather tertiary acknowledgements. (ie. they got me doing this sort of thing, but didn't specifically contribute to this particular development)

Where it came from was that I was playing with the configuration reading routines, and the window and Direct3D routines. Trying to figure out what these magic floating point numbers meant, and found I could change the size of the screen to anything I liked. I was playing most games in 720p, and thought PT would be cool in that too. I hit the black bars, and remembered I'd already zoomed in the 3D display messing with those floats. The combination of accidents lead to some head scratching and a simple routine to combine the two into a happy coincidence. :D: Now it' is available to all. Enjoy.​
 
Last edited:
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Reserved... but probably not needed. (unless some really cool info or discussions lead on from this)
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
[...]Well, the first thing you will notice, is that the portrait of your target PC / NPC (or monster, if the target NPC is hostile) will be enlarged more than the frame within which it is supposed to fit.[...]

Was the issue ever resolved?
I was digging in PT and I don't get it few things.
Your fix producing black bars. I did something like that:

my monitor is 16:9 full hd so I:

changed PT resolution to full hd 1920x1080
changed -> 0.22727272 to -> 0.166 (strange 0.166 is 16:10 right? 1.77:1 or 1.78:1 (16:9) giving me black bars on right and left side)
It look like its working with any PT resolution and custom resolutions o_O

at this point black bars evaporate even from opening sequence but camera zoomed too close for this resolution so I:

changed 32768.0 to -> 34816.0 (too big values can give funny effects) and I have nice big FOV
there is only one value like that so you can find it easily, if you can't than it's near text "SMD Stage data Ver 0.72"

bugs:
HP bar on mobs need to be fixed for resolution... some simple formula would do the trick:

0.00125 is default but its shorter than mob 'frame' when everything is untouched, this need fix by itself.
I change it to 0.00095999998 and it look nice on full hd resolution. But as I said it need formula for resolution change. Not that important.

Same bug as you had NPC/MOB icon going out of frame and it look like its glued to main camera (0.22727272).

What you think about 0.166 and npc/mob going out of frame?


SS:
OPENING:

jFjlgh5 - Wide Screen Client - RaGEZONE Forums


B4 HP BAR FIX:

nlfFQbT - Wide Screen Client - RaGEZONE Forums


AFTER HP BAR FIX:

JpNpN8R - Wide Screen Client - RaGEZONE Forums
 

Attachments

You must be registered for see attachments list
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
Models are in 3D its not .tga related. There are values that can scale NPC/MOB frame but it's not way it should be fixed.
It need to be adaptable to any resolution.
 
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
I only got black borders (left and right?) when the display was portrait. (ie. higher than it is wide) Except for the intro, which adds letterboxing on 4:3 displays anyway. I also use 1080p display these days.

Yes, I'm confident there should be a render-scale for the projected / overlayed 3D rendering of the portraits, which should be reduced in size compared to the AR of the display.

I didn't find where that code is.
 
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
I found float values to scale almost everything including NPC/MOB 'frame' except 3D portrait itself. It always scaled with whole screen :/
meh...anyway for pixel perfect screen I prefer full screen or I change desktop resolution to PT resolution and go borderless windowed pseudo fullscreen.
 
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
Find what? I did not found it <.<

Other values are not that important. They zoom in/out camera, scale some .tga etc. NPC/MOB 3D portrait glued itself to the screen. Even bob did not found it.
 
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
I never looked that hard. It didn't "bother" me enough to try. XD I'd be happy to not render the frame behind it too small. If there was no frame at all, that'd be fine... If there was no target portrait, that would be fine too.

I quite like games where the target portrait is a static artistic render of the person / animal.

If there is no place for the scale, then just finding where that render happens and faking the details of the screen size it reads would be sufficient. Maybe it's reading the width of the display directly? Get it to read somewhere else.
 
Joined
Jan 19, 2007
Messages
400
Reaction score
38
yeah, but, even the HUD need to be Fixed for a full Box =D. the tutorial of Bob is SOOOOO GREAT, i make, with bobs help, a client how change by a ptreg word, to Wide, and Normal, scream. and works very nice, in fact once you use wide mode u never want back to normal again =D, the chars get higher a bit, MAYBE, ** if you are HIGH ** u see the NPC, and MOBS, in that window in right side, in a 3D View =D, they look like are jumpping that window =D, when you creat a character the name is in the center and looks very nice.
i Like so much this client, in this way, i did not change a thing in it =D, well... maybe the only change will be for do this Wide with Vov Font =D, that will be a very good patch =D.
 
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
Yes. If you can find something which controls only the target portrait, and manually fiddle that thing till it "looks right" at 16:9, or a compromise "okay" for 16:9 / 16:10, then limit resolution to switch Widescreen / Full Mode, which also toggles the input to the portrait render... that would be a good solution which covers most situations. ^_^

--- EDIT ---
People may like to note, and comment on the recent update in . While I knew this effect occurred, and it was discussed when I was posting Butchered betas, I forgot to mention it here. >.<
 
Last edited:
Custom Title Activated
Loyal Member
Joined
Jan 28, 2009
Messages
1,320
Reaction score
616
Also:
- map mode "M' need resizing
- in between sod screens need to be resized

But those are minor problems. IMO biggest one is portrait bug :/
 
Joined
Jan 19, 2007
Messages
400
Reaction score
38
Also:
- map mode "M' need resizing
- in between sod screens need to be resized

But those are minor problems. IMO biggest one is portrait bug :/
its like i told, its a crasy view =D
you can do a easy fix by this :
\image\cw.tga
serach by it, cw.tga, and you will find where the place who the "EAX" where.
find all references to it, and will be easy to fix the pixel of it =D
 
Custom Title Activated
Loyal Member
Joined
May 26, 2007
Messages
5,545
Reaction score
1,315
The idea of the guide was to enable you to make the changes to any client versions, but I know you're struggling.

View attachment kPT2453.7z
 

Attachments

You must be registered for see attachments list
Newbie Spellweaver
Joined
Jun 9, 2010
Messages
14
Reaction score
1
Thank bobsobol but still like that, I could not understand some parts because of my bad english :/

If any Brazilian could give me this help, at least correctly translating the topic, or the parts are most important, I would be eternally grateful, or if someone could help me in any way, I thank you, all help is welcome.

Intender keep trying the tutorial, if someone is willing to help, please contact me. thanks.

EDIT:
I got! Thank bobsobol the game helped intender the tutorial, thanks
 
Last edited:
Back
Top