|Posted by metlslime on 2009/12/21 02:20:25|
|Baker and mh have been working on Direct3D 8 ports of popular Quake engines. The benefit of this is that people whose video cards have poor-quality OpenGL drivers can take advantage of better Direct3D drivers (many ATI and intel cards are in this boat, apparently.)
Engines ported so far:
* AguirRe's enhanced GLQuake
More info and downloads: http://quakeone.com/mh/
Not sure you received my PM, so post it here just to be sure.
I came across an issue in DirectQ where using the player lightning hack described here
causes the engine to freeze. It must have been introduced in version 1.8.8 patch 2, as it works in earlier versions (including patch 1). Possibly some stricter handling of certain things.
The freeze can be reproduced in mappi.bsp
by activating the lightning traps on the balconies in the boss/exit area on skill 2.
There's a similar issue in Quakespasm which, however, works in that particular map (but not in my current WIP map, it drops to the console with "Host_error: NAN in Traceline").
Looking at the diff between MH's 1.8.8-p1 and -p2 shows that he inherited the 64 bit compatibility code for progs strings. To compare: QuakeSpasm earlier than 0.85.1, i.e. unreleased code, svn rev.37 and older w/o that, also haven't been hitting a NaN in Traceline, but svn rev.38 ( http://quakespasm.svn.sourceforge.net/viewvc/quakespasm?view=revision&revision=38
) reveals that issue. It is _probably_ a QC issue. QS, errors only in "developer 1" mode: with developer 0, it silently sets the NaNs to 0 and carries on.
I got the message but haven't had a chance to look at this problem till now. It appears to be resolved in my current sources but I'll need to backtrack to an earlier version to determine the change that fixed it; my guess is either string handling or something in SV_TouchLinks (where I've tightened up handling of the touched edicts list a little).
This is almost definitely QC. I backtracked through 2.0.0, a (slightly patched) 1.9.0, the released 1.9.0 and the ancient 1.8.0 and am unable to reproduce it in either test case (mappi and your WIP). This is using a standard unmodified id1 progs.dat - are you using a different progs?
I just checked again (in sm133_negke, because it's the quickest testing case). And indeed, the lightning works in DirectQ 1.9.0 and QS on progs 1.0 as well as a few others. It does freeze DQ and abort QS with Travail and Quoth (v.2+) - shame on Preach? :) I was sure it also occured on Hipnotic, but I must have confused it as it works there. However, the issues remain in my WIP map, even if using unmodified ID1 progs. Try the lower and upper seals; the middle one works for some reason. I can't see an error in the .map setup, so I'm clueless as to why this still happens.
Good to know QS can deal with it if developer mode is off, though (I didn't notice since I have it set on in the autoexec.cfg).
Ok, something to make it weirder: I just grouped all lightning entities together at the top of the WIP's .map list, and now they work on "normal" progs in both engines. Before, only the first one (which happened to be the middle one) would. What the hell?
The issue is actually with FireBullets, not W_FireLightning, What makes this harder to diagnose is that the code is line-for-line identical in Quoth and the Quake source.
In particular the offending line is:
traceline (src, src + direction*2048, FALSE, self);
Since this is called by a use function, direction happens to be equal to '0 0 0', so presumably the hang is due to a zero length traceline causing an infinite loop.
The larger mystery is why this code is getting called in Quoth but not in Quake, because it's inside the
while(framecount > 0)
loop. framecount is one of the function parameters, which should default to zero because it's called as a use function (admittedly this is sort of undefined behaviour that the hack is depending on, but it's a de facto standard now). In stock Quake it's coming out as exactly 0 (according to debugging code). In Quoth it's coming out as 0.00000, so presumably it's ever so slightly larger than zero. Hence we enter the loop once and hang.
It Never Gets Boring...
Thanks for looking into it!
At least we've now identified another potential issue. If anything, it would be nice if DQ could drop to the console with an error message like QS does instead of freezing altogether.
Yeah, I could detect a zero-length traceline and drop if so, but I'd prefer a more robust solution; one that gives the result as if the trace had stopped at the start point.
I appreciate that the one approach may be better for mappers or content creators, but where I'm coming from here is that dropping to the console is a rather rude thing to do on the player if an error condition is in any way recoverable.
Of course that would be a more favorable solution. Ideally, it would just force the value to 0 like QS does in non-dev mode - if there are no serious ramifications to such an approach.
My instincts were wrong, DQ is not doing anything incorrect with paramters on a function call. In fact in Quoth, FireBullets fires one shot in fitzquake as well, so the traceline is the problem. But why different behaviour from two functions with identical code?(I even went and checked the assembly output..)
Quick lesson on calling. Quake has 8 global variables PARM0...PARM7 for function parameters (which is why QC functions can't have more than 8 parameters). To pass parameters at a function call the following sequence of events happens:
� In the calling function, at the QC level, the parameter values are stored into the global variables.
� The QC calls the function with an OPCODE which indicates how many parameters there were. The different OPCODEs only matter when calling string functions with variable arguments like dprint.
� The engine steps in here to copy the values in PARM0...PARMn into the local variables the "called function" expects them to occupy.
� Now the called function starts running.
OK, so what happens when you call a function with the wrong number of parameters? Remember it's hard to do because it's an error at compile time - but if we're setting a value in the .use field, that can't be checked statically. Well, setting the globals is the responsibility of the QC, so if you trick it like this then nobody sets the globals. This means you get stuck with whatever was put in there last time.
I suspect this is the problem with Quoth, Travail etc. In stock Quake you get very lucky: between touching the trigger and firing the use function of its target, PARM0 gets set to something that safely gets counted as 0, and no shot fires. In Quoth, some extra function, (maybe related to the extra code supporting targetname2 etc) sets PARM0 to something different, so shotcount comes out as non-zero. This causes problems, but it could be much worse: eg junk in a parameter interpreted as an entity could easily segfault the program or corrupt memory.
Before investigating I honestly believed there was some bit of code scrubbing the PARMx values, but I can't find it. So I don't believe anything does, but corrections welcomed! My suggested fix is to no longer use FireBullets in this hack, W_FireAxe is a better substitute because it takes no parameters. W_Attack should work as well. Which one is more likely to be resilient to a mod that changes the weapons? Your guess is as good as mine...
1. It seems DQ handles brush models vs visblocking differently? In MCE there's a case of disappearing func_walls in the basement that doesn't occur in other engines.
2. After changing the gamedir, one can't change it back to ID1. For instance, switching to Quoth, one can change to Hipnotic and other mods, but when trying to change to ID1, it switches back to Quoth.
Website copyright © 2002-2018 John Fitzgibbons. All posts are copyright their respective authors.