VOGONS


Quake2 + Acebot for DOSBox (128mb)

Topic actions

Reply 204 of 862, by Maraakate

User metadata
Rank Oldbie
Rank
Oldbie

I can tell you on real hardware if youre doing VGA modes it mostly makes no difference. Maybe on very old computers there was a difference. But once you get into that P1 and P2 range the framerates all seem to be about the same. I have a slew of different PCI and AGP cards and experimented with that for a while.

This also reminds me, I tested the banked code on a P3 550 and there was no performance penalty between using banked 640x480 and LFB 640x480.

On net_udp.c: Only for a *nix port, which we haven't made a makefile for, but you should be able to generate a *nix binary if you really want to. The game already compiles windows binaries just fine.

Reply 205 of 862, by ggorts

User metadata
Rank Member
Rank
Member

That's very good news. With all your work on q2dos, I think I'd run it on Windows, too, over any other port. Even if just for stability, given all the debugging work.

That's interesting on the video versus cpu bottleneck in performance. The banked modes was also useful in the path to modex, I think.

Reply 206 of 862, by Maraakate

User metadata
Rank Oldbie
Rank
Oldbie

Yup, it helped me learn a few things about how to set video registers and such. Compiling the static linked build (haven't maintained separate dynamic builds in a long time) is easy. Just install VS6 and compile from the .dsw files in msvc directory.

Reply 209 of 862, by Stiletto

User metadata
Rank l33t++
Rank
l33t++
ggorts wrote:

I guess I shouldn't be surprised that there isn't a subforum here for NTVDM. 😀

Yeah, because originally NTVDM WAS one of the main focuses, so it didn't need a subforum, it WAS the forum. 😁

The NTVDM support of VOGONS forums basically turned into the following:
The Guide -> DOS: "Getting old DOS games working.": DOS
VDMSound General: "General information and assistance with VDMSound.": VDMSound General
VDMSound Development: "Developer's Forum, for discussion of bugs, code, and other developmental aspects of VDMSound.": VDMSound Development
Speedset: "Problems related to Speedset.": Speedset

That's right, "The Guide -> DOS" was originally intended for all sorts of discussion of NTVDM compatibility hacks and game patches and whatnot, back in 2002. It was "PC Emulation" that was intended for actual emulator discussion. But after several years of having absorbed the DOSBox support forums, it all started blending together (lazy moderators... heh.) These days if you posted something NTVDM-related in "The Guide->DOS", the first questions you'd be asked would be a. why aren't you running it in DOSBox and b. you should try building a retro PC to run it properly, haha! 🤣

"I see a little silhouette-o of a man, Scaramouche, Scaramouche, will you
do the Fandango!" - Queen

Stiletto

Reply 210 of 862, by Maraakate

User metadata
Rank Oldbie
Rank
Oldbie
leileilol wrote:
Maraakate wrote:

I may just change the default to be 320x240.

Seconding this. You should as that's quake2's canonical resolution

Done, compiling now and will upload shortly.

Reply 211 of 862, by Maraakate

User metadata
Rank Oldbie
Rank
Oldbie
ggorts wrote:

The modex should be faster, aspect friendly, and as compatible with other video cards as 0x13?

Also, it won't be any faster because it does have an extra 12800 pixels to draw. You can see this by setting 320x200 and 320x240 LFB if the card supports it. And with the planar modes Abrash came up with some custom ASM code because there's apparently a performance hit with having to switch between the planes. With his code, on my P2 400 it appears to be about the same level of performance between a 320x240 Mode-X and 320x240 LFB which is good.

Reply 212 of 862, by ggorts

User metadata
Rank Member
Rank
Member
Stiletto wrote:

That's right, "The Guide -> DOS" was originally intended for all sorts of discussion of NTVDM compatibility hacks and game patches and whatnot, back in 2002. It was "PC Emulation" that was intended for actual emulator discussion. But after several years of having absorbed the DOSBox support forums, it all started blending together (lazy moderators... heh.) These days if you posted something NTVDM-related in "The Guide->DOS", the first questions you'd be asked would be a. why aren't you running it in DOSBox and b. you should try building a retro PC to run it properly, haha! :lol:

The solutions to running older games seems to have changed over time in a way unforeseen. :) With MS removing features intentionally and unintentionally, it seems that there is another schism developing by which operating system version is running.

Also, I still have nt4compatible.com bookmarked, but I think someone has taken it down and left us in the lurch!

Reply 213 of 862, by ggorts

User metadata
Rank Member
Rank
Member
Maraakate wrote:
ggorts wrote:

The modex should be faster, aspect friendly, and as compatible with other video cards as 0x13?

Also, it won't be any faster because it does have an extra 12800 pixels to draw. You can see this by setting 320x200 and 320x240 LFB if the card supports it. And with the planar modes Abrash came up with some custom ASM code because there's apparently a performance hit with having to switch between the planes. With his code, on my P2 400 it appears to be about the same level of performance between a 320x240 Mode-X and 320x240 LFB which is good.

That's a good result. I incorrectly thought that mode-x is universally faster, but that must only apply to cases wheres special objects are drawn which utilize the advantages of the planar mode (I think something about using 1 byte in a way to draw 4 pixels instead of 1). In this case the mode is used as a general framebuffer, so as you said, it must be similar in speed to the LFB mode of same dimension, or even slower with the plane switching counteracted by any ASM speed-up. :)

I spend quite a while just testing all your improvements to q2dos, I noted a lot of fixes to all the components. It's running great!

Reply 214 of 862, by leileilol

User metadata
Rank l33t++
Rank
l33t++

Attempting to fix the aspect thing. The relevant function is R_ViewChanged in ref_soft/r_misc.c

So far 320x200 aspect is proper, but every other mode is screwed. Still hacking at it locally.

Colored lighting definitely not included since i'm prototyping this in a win32 ref_soft I have lying around

EDIT: Much better now. 320x400 works, no other modes are screwed.

EDIT2: Here's the new R_ViewChanged. Plop this in your DOS version source whereever it may be, can't be arsed to setup djgpp and try it out myself
It could be faster (i.e. doing what Quake does, assigning a precalculated aspect value to every initialized video mode)

/*
===============
R_ViewChanged

Called every time the vid structure or r_refdef changes.
Guaranteed to be called before the first refresh
===============
*/
void R_ViewChanged (vrect_t *vr)
{
int i;
float pixelAspect, screenAspect;

r_refdef.vrect = *vr;

r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);;
verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);

r_refdef.fvrectx = (float)r_refdef.vrect.x;
r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
r_refdef.fvrecty = (float)r_refdef.vrect.y;
r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
r_refdef.fvrectright = (float)r_refdef.vrectright;
r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;

r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
r_refdef.aliasvrect.width;
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
r_refdef.aliasvrect.height;

xOrigin = r_refdef.xOrigin;
yOrigin = r_refdef.yOrigin;

// leilei - Aspect stuff nicked from Q1
pixelAspect = 1.000 + (1.3333 - ((float)vid.width / (float)vid.height));

screenAspect = r_refdef.vrect.width*pixelAspect /
r_refdef.vrect.height;
verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect;


// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
r_refdef.vrect.x - 0.5;
Show last 49 lines
	aliasxcenter = xcenter * r_aliasuvscale;
ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
r_refdef.vrect.y - 0.5;
aliasycenter = ycenter * r_aliasuvscale;

xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
aliasxscale = xscale * r_aliasuvscale;
xscaleinv = 1.0 / xscale;
yscale = xscale * pixelAspect; // leilei - aspect stuff
//yscale = xscale;
aliasyscale = yscale * r_aliasuvscale;
yscaleinv = 1.0 / yscale;
xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
//yscaleshrink = xscaleshrink;
yscaleshrink = xscaleshrink*pixelAspect; // leilei - aspect stuff

// left side clip
screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
screenedge[0].normal[1] = 0;
screenedge[0].normal[2] = 1;
screenedge[0].type = PLANE_ANYZ;

// right side clip
screenedge[1].normal[0] =
1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
screenedge[1].normal[1] = 0;
screenedge[1].normal[2] = 1;
screenedge[1].type = PLANE_ANYZ;

// top side clip
screenedge[2].normal[0] = 0;
screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
screenedge[2].normal[2] = 1;
screenedge[2].type = PLANE_ANYZ;

// bottom side clip
screenedge[3].normal[0] = 0;
screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
screenedge[3].normal[2] = 1;
screenedge[3].type = PLANE_ANYZ;

for (i=0 ; i<4 ; i++)
VectorNormalize (screenedge[i].normal);

D_ViewChanged ();
}


Attachments

  • quake03.gif
    Filename
    quake03.gif
    File size
    82.61 KiB
    Views
    749 views
    File license
    Fair use/fair dealing exception
  • quake02.gif
    Filename
    quake02.gif
    File size
    34.9 KiB
    Views
    753 views
    File license
    Fair use/fair dealing exception
Last edited by leileilol on 2015-07-06, 21:21. Edited 1 time in total.

apsosig.png
long live PCem

Reply 216 of 862, by leileilol

User metadata
Rank l33t++
Rank
l33t++

by every other mode I meant EVERY other normal mode. 320x240, 640x480 etc. but that's moot now as it's fixed. 😀
This was prototyped on msvc6+q23.21, I changed 400x300/512x384 to 320x200/320x400 to help test that and tried to keep the changes self-contained and as simple as possible.

Last edited by leileilol on 2015-07-06, 21:24. Edited 2 times in total.

apsosig.png
long live PCem

Reply 217 of 862, by Maraakate

User metadata
Rank Oldbie
Rank
Oldbie
leileilol wrote:

by every other mode I meant EVERY other mode. 320x240, 640x480 etc. but that's moot now as it's fixed.

Have you seen the latest source I already made a hacky solution to the issue. I took Q1s code but the aspect shifting is only applied to 320x200. It looks like you tried what I originally tried to do... take Q1s aspect code and just apply it but I noticed all the modes got fucked this way. I guess xscale and yscale, etc. have new math that are depending on straight up 4:3.

Reply 218 of 862, by Maraakate

User metadata
Rank Oldbie
Rank
Oldbie

Here is what is currently in the code and works OK, but not perfect.

void R_ViewChanged (vrect_t *vr)
{
int i;
float screenAspect, pixelAspect; // FS: From Q1

r_refdef.vrect = *vr;

r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);
// Knightmare- catch 5:4 modes pushing top and bottom clips beyond screen buffer
if ( (r_refdef.vrect.width != r_newrefdef.width || r_refdef.vrect.height != r_newrefdef.height)
&& (((float)r_newrefdef.width / (float)r_newrefdef.height) < (640.0f/480.0f)) )
{
float x;
x = r_refdef.vrect.width/tan(r_newrefdef.fov_x/360*M_PI);
verticalFieldOfView = 2*(r_refdef.vrect.height/x);
}
else
verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);
// end Knightmare

r_refdef.fvrectx = (float)r_refdef.vrect.x;
r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
r_refdef.fvrecty = (float)r_refdef.vrect.y;
r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
r_refdef.fvrectright = (float)r_refdef.vrectright;
r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;

r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
r_refdef.aliasvrect.width;
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
r_refdef.aliasvrect.height;

xOrigin = r_refdef.xOrigin;
yOrigin = r_refdef.yOrigin;

if(r_newrefdef.width == 320.0f && r_newrefdef.height == 200.0f) // FS: Special hack for 320x200
{
pixelAspect = 0.9; //(float)r_newrefdef.width / (float)r_newrefdef.height;
screenAspect = r_refdef.vrect.width*pixelAspect /
r_refdef.vrect.height;

verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect;
}
else
{
pixelAspect = 1.0f;
screenAspect = 1.0f;
}

Show last 56 lines
// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
r_refdef.vrect.x - 0.5;
aliasxcenter = xcenter * r_aliasuvscale;
ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
r_refdef.vrect.y - 0.5;
aliasycenter = ycenter * r_aliasuvscale;

xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
aliasxscale = xscale * r_aliasuvscale;
xscaleinv = 1.0 / xscale;

// yscale = xscale;
yscale = xscale * pixelAspect; // FS: From Q1
aliasyscale = yscale * r_aliasuvscale;
yscaleinv = 1.0 / yscale;
xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
// yscaleshrink = xscaleshrink;
yscaleshrink = xscaleshrink*pixelAspect; // FS: From Q1

// left side clip
screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
screenedge[0].normal[1] = 0;
screenedge[0].normal[2] = 1;
screenedge[0].type = PLANE_ANYZ;

// right side clip
screenedge[1].normal[0] =
1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
screenedge[1].normal[1] = 0;
screenedge[1].normal[2] = 1;
screenedge[1].type = PLANE_ANYZ;

// top side clip
screenedge[2].normal[0] = 0;
screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
screenedge[2].normal[2] = 1;
screenedge[2].type = PLANE_ANYZ;

// bottom side clip
screenedge[3].normal[0] = 0;
screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
screenedge[3].normal[2] = 1;
screenedge[3].type = PLANE_ANYZ;

for (i=0 ; i<4 ; i++)
VectorNormalize (screenedge[i].normal);

D_ViewChanged ();
}

Reply 219 of 862, by ggorts

User metadata
Rank Member
Rank
Member

The aspect looks very good on all intended modes.

I ran tests to determine the source of those fpu under/overflow errors in dosbox while "stress testing" q2dos and a custom test build (repeated game mod loading/unloading with maps). It's very likely that the fpu emulation of dosbox (given my settings) is not matching perfectly to real hardware and likewise this is an active issue on the github for dosbox-x (worked on by TheGreatCodeholio). This is obviously not occurring on real hardware nor is it expected to.

One possible reason is arithmetic stack overflow, but I have a solution that has worked so far. The cflags "-ffloat-store" and "-fexcess-precision=standard" are avoiding the error and the latter flag is recommended anyways to compile quake2 under GCC4 versions (given another set of test conditions). Some background is here:
http://blog.jwhitham.org/2015/04/gcc-bug-323- … o-heart-of.html
http://stackoverflow.com/questions/20869904/c … xcess-precision

The downside is a few percent performance cost of the flags, but perhaps these flags could be considered for builds intended for emulators where the fpu emulation is not tested against quake2. I don't suggest these flags as default ones, but perhaps commented out in a makefile as a reminder?

My other issue is not yet resolved. Dday mod causes a page fault when it is loaded and then the single player option is chosen. The mod doesn't support single player anyways, but some of the other tested mods do not have this issue. The symify technique with debugging symbols available in the binary does not show the error in q2, but the debugging information points to an "uninitialized pointer or missing call to malloc". I think one good solution is to prevent single player option where the dday mod is loaded. I can look into this further, but I hope I can share my results on these two issues. :)