Duke3d porting team

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
BlackAura
DC Developer
DC Developer
Posts: 9951
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

Did you look at the message decryption/version/copyprotection system Ken put in? Check out the kensmessage code at the beginning of engine.c. Yeah, not like you couldn't have done that in C. I knew guys like this back in highschool who thought that thought binary searches and sorts were "so much easier to read" in x86 ASM... BLARRRGH.
Half of this stuff really does seem to be pointless. It's certainly pointless on any decent modern machine. And it's incredibly convoluted.

One bit somewhere else appears to be copying eax to edx, shifting eax left by the contents of cl, negating cl, and then shifting edx right by the contents of cl. What the heck?

Trying to get rid of some of these asm routines, I've run into some problems. First off, I'm having to use OpenWatcom 11.0c, running under Win95 OSR2 under VMWare to test it, since the DOS Build doesn't run. Secondly, the compiler is stupid. If I replace some asm with some C code that I know is functionally equivalent, it pagefaults on me. Aaargh!

Odd thing is that the code I've written works pretty much perfectly using GCC, and gives me the same answers as the original ASM. It just won't work under Watcom.
ReGex
FrNES Creator
FrNES Creator
Posts: 63
Joined: Wed Oct 17, 2001 7:44 pm
Location: Calgary, Alberta Canada
Has thanked: 0
Been thanked: 1 time
Contact:

Post by ReGex »

There's a reason why people stopped using Watcom as of about 1996.. and that probably is that VC 4.0 and GCC 2.95.x were so much more stable at that point that it wasn't worth slaggin' through piles of crappy asm code to implement something like 64-bit integers.

-ReGex
Tangent
DC Developer
DC Developer
Posts: 100
Joined: Fri Jan 17, 2003 3:01 pm
Location: Pits of Insanity
Has thanked: 0
Been thanked: 0
Contact:

Post by Tangent »

I don't know that the asm is completely pointless. . .they've got some jumps later on down the road that would be affected by the shifts. Those shifts affect the flags registers, which the jumps examine to determine whether they should move. jz jumps if the zero flag is set, and so on with the other flags.

But you're right, this is some of the ugliest assembly evah.
There are 10 kinds of people in the world: those who understand binary, and those who don't.
EverStoned
Psychotic DCEmu
Psychotic DCEmu
Posts: 602
Joined: Sat Nov 30, 2002 8:34 am
Has thanked: 0
Been thanked: 0
Contact:

Post by EverStoned »

BlackAura wrote:
Actually, my main fears center around the light + mirror engine. Rather than casting rays backwards from a mirror, you have to do some geometrical tricks to get the desired result in 3d.
Actually, the mirrors in the Build engine are faked, as far as I remember. At least in Duke 3D, you need to create a copy of the room behind the mirror, flip it around, and give it some special tags. It then renders that area normally, and clones any sprites from the real area into the mirrored area.

Basically, in real life, there appears to be another room behind the mirror. In Duke 3D, there actually is another room behind the mirror.
Even half life does this. I know there are other examples, but op_lobby in operamod does that to create the reflection of the floor of the matrix lobby.
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

There's a reason why people stopped using Watcom as of about 1996.. and that probably is that VC 4.0 and GCC 2.95.x were so much more stable at that point that it wasn't worth slaggin' through piles of crappy asm code to implement something like 64-bit integers.
So it won't do 64-bit integers properly? Useless piece of junk. No wonder it kept crashing when I replaced some asm code with a 64-bit multiply instruction.
Even half life does this. I know there are other examples, but op_lobby in operamod does that to create the reflection of the floor of the matrix lobby.
Half-life doesn't even try to do reflections, as far as I can remember. Interesting hack. I know that Unreal can do true mirrors though.
EverStoned
Psychotic DCEmu
Psychotic DCEmu
Posts: 602
Joined: Sat Nov 30, 2002 8:34 am
Has thanked: 0
Been thanked: 0
Contact:

Post by EverStoned »

BlackAura wrote:
Even half life does this. I know there are other examples, but op_lobby in operamod does that to create the reflection of the floor of the matrix lobby.
Half-life doesn't even try to do reflections, as far as I can remember. Interesting hack. I know that Unreal can do true mirrors though.
In half life, it's done by the mappers, not the engine, so I've never seen mirrors with reflective sprites.

If Dook3D had the reflective sprites/lighting, wouldn't that have to be coded..?
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

I don't really know. Either Build or the Duke3D game code implements the reflected sprites, but I can't remember which. I think it's the game code, since the engine code doesn't really do anything with the sprites apart from draw them, and move them to wherever the game tells it to.
ssj4goku128
Insane DCEmu
Insane DCEmu
Posts: 290
Joined: Wed Oct 17, 2001 7:44 pm
Has thanked: 0
Been thanked: 0

Post by ssj4goku128 »

Heck. I'll help since I got time away from my 3rd set of midterms. I can help u with sdl if you need, or if you want open gl for the port, im cool with that too.
"So I gotta be carefull, can't let tha evil of tha money trap me
so when ya see me #@#$%
ya better holla at me "

Tupac Shakur[1971-1996]
Makaveli[1996-????]
ReGex
FrNES Creator
FrNES Creator
Posts: 63
Joined: Wed Oct 17, 2001 7:44 pm
Location: Calgary, Alberta Canada
Has thanked: 0
Been thanked: 1 time
Contact:

Post by ReGex »

[quote]So it won't do 64-bit integers properly? Useless piece of junk. No wonder it kept crashing when I replaced some asm code with a 64-bit multiply instruction.[/quote]

I don't know that for sure... you could always write a simple architecture test of that. I'm curious as to why it would accept the int64 typename if it didn't actually implement it properly. I'm guessing whatever version of watcom it was originally built with didn't have any 64-bit integer support (Remember Turbo C++ was Watcom's main competition at this point and if I remember correctly it didn't have 64-bit support either).

-ReGex
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

This compiler really sucks.

First off:

Code: Select all

#define mulscale(a,b,c) (((long long)a * (long long) b) >> c)

Code: Select all

static int mulscale(long long a, long long b, unsigned char c)
{
	a *= b;
	a >>= c;
	return a;
}
The one that's implemented as a function works perfectly. The one implemented as a macro does not, and makes the game bomb after a couple of seconds.

Even weirder:

Code: Select all

#pragma aux scale =\
	"imul edx",\
	"idiv ecx",\
	parm nomemory [eax][edx][ecx]\
	modify exact [eax edx]\
Will cause massive screen corruption, followed by a pagefault, if it's replaced with C or asm code. Even the known-working stuff from icculus's Linux port. Works fine with GCC and MSVC, but does it work with Watcom? No... Lousy compiler...

The problem is that most of the other ports have just converted the inline asm to GCC format, or used it verbatim. None of them have removed all of it which, of course, we have to do to get it working on a non-x86 system. I'm still in pragmas.h, but at least I'm making some headway, even if it is slowly.

I'm starting to think that re-making the engine from the ground up, using the data structures and little bits of code from the original Build engine, would actually be easier. I'm pretty sure I could program an OpenGL level viewer at least, but I'm not certain about integrating that with the original Build code.
Phantom
DC Developer
DC Developer
Posts: 1753
Joined: Thu Jan 16, 2003 4:01 am
Location: The Netherlands
Has thanked: 0
Been thanked: 0
Contact:

Post by Phantom »

BlackAura wrote: First off:

Code: Select all

#define mulscale(a,b,c) (((long long)a * (long long) b) >> c)
This is tricky. You should enclose the dummies on the right hand side in parenthases, just to be sure. If you don't, more complex expressions for 'a', 'b' or 'c' could give a wrong result, because of the operator precedences.
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

Might be a good idea. But I'm just going to stick with using functions for the time being, and I'll macro-ify it later, if it needs it. I'd think it would need it though.

Still doesn't explain the rest of it though.
Phantom
DC Developer
DC Developer
Posts: 1753
Joined: Thu Jan 16, 2003 4:01 am
Location: The Netherlands
Has thanked: 0
Been thanked: 0
Contact:

Post by Phantom »

BlackAura wrote:Even weirder:

Code: Select all

#pragma aux scale =\
	"imul edx",\
	"idiv ecx",\
	parm nomemory [eax][edx][ecx]\
	modify exact [eax edx]\
Will cause massive screen corruption, followed by a pagefault, if it's replaced with C or asm code.
I don't understand: replacing asm with asm? :) And what C code did you try to replace it by?
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

I've got it working now. It needed a rediculous number of casts to work properly, since it's supposed to be 64-bit arithmetic. Oddly, it works under GCC without the casts.

And, I meant with a macro. :oops:

Here's the C code I ended up replacing it with:

Code: Select all

INLINE int scale (int i1, int i2, int i3)
{
  return (int)((__int64)i1 * (__int64)i2 / (__int64) i3);
}
Just built and ran a copy of KenBuild using a (mostly) C-based pragmas.h , and it works. There's just a few more functions left. Alas, they're the really weird ones.

I'm testing it under VMWare running Windows 95, and something rather weird has happened. The more code I'm replacing with C functions, the faster it seems to be running. It's now running twice as fast as it was before. Of cource, that's still not that fast, considering it's running in an emulator, but it's still faster. It's actually (nearly) playable now.
Phantom
DC Developer
DC Developer
Posts: 1753
Joined: Thu Jan 16, 2003 4:01 am
Location: The Netherlands
Has thanked: 0
Been thanked: 0
Contact:

Post by Phantom »

BlackAura wrote:There's just a few more functions left. Alas, they're the really weird ones.
Let me know if you want some help with that. I wouldn't mind helping out, I'm a Duke 3D fan. ;)

"It's time to kick ass and chew bubble-gum... and I'm all out of gum." - Duke Nukem
Bombshell
DC Developer
DC Developer
Posts: 179
Joined: Wed Nov 20, 2002 8:29 pm
Has thanked: 0
Been thanked: 0

Post by Bombshell »

Hey, If you guys need any help I might be able to offer some, as my gmae is almost ready for release.
Just a question are you guys using the original source code that was put out by 3DRealms or are you using the source code for the linux version or is there a difference?
ssj4goku128
Insane DCEmu
Insane DCEmu
Posts: 290
Joined: Wed Oct 17, 2001 7:44 pm
Has thanked: 0
Been thanked: 0

Post by ssj4goku128 »

Same here. Im picking up on some SH4-Asm too. Just disassembled a couple of ported emus and used the C source code to try to give me a direction[off topic]. But yeah, if you need help, then I will be here
"So I gotta be carefull, can't let tha evil of tha money trap me
so when ya see me #@#$%
ya better holla at me "

Tupac Shakur[1971-1996]
Makaveli[1996-????]
q_006
Mental DCEmu
Mental DCEmu
Posts: 415
Joined: Thu Oct 10, 2002 7:18 pm
Has thanked: 0
Been thanked: 0
Contact:

Re: Duke3d porting team

Post by q_006 »

ReGex wrote:Are any of you other devvers looking at porting Duke3d? I would like to do this as a team project, so I was wondering if anyone else would like to help out? I don't know if Bero has decided to do anything with this yet, but he would make the best team leader because he's done so many FPS ports before. Has anyone talked to him lately? Anyways, I'd just like to see if there's any interest out there.

-ReGex
i've read on the dcemu that Bero plans to start a port of Duke3D soon.
Has anyone been able to contact him yet?
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

Just a question are you guys using the original source code that was put out by 3DRealms or are you using the source code for the linux version or is there a difference?
The stuff I'm playing with, I'm using the original release by Ken Silverman (Build engine) an patching in stuff from icculus' port as I need it. I've not even looked at Duke 3D's source code yet. The Icculus Linux port has a lot of extra stuff that I don't think we need for a Dreamcast port, and it's easier to leave it out than remove it.

There's a load of functions in pragmas.h that I know are DOS hardware stuff, so I don't think I need to worry about those. As for the rest of them...

Code: Select all

//returns eax%ebx, dmval = eax/edx;
#pragma aux moddiv =\
	"xor edx, edx",\
	"div ebx",\
	"mov dmval, eax",\
	parm [eax][ebx]\
	modify exact [eax edx]\
	value [edx]

//eax = (unsigned min)umin(eax,ebx)
#pragma aux umin =\
	"sub eax, ebx",\
	"sbb ecx, ecx",\
	"and eax, ecx",\
	"add eax, ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax ecx]\

//eax = (unsigned max)umax(eax,ebx)
#pragma aux umax =\
	"sub eax, ebx",\
	"sbb ecx, ecx",\
	"xor ecx, 0xffffffff",\
	"and eax, ecx",\
	"add eax, ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax ecx]\

#pragma aux kmin =\
	"cmp eax, ebx",\
	"jl skipit",\
	"mov eax, ebx",\
	"skipit:",\
	parm nomemory [eax][ebx]\
	modify exact [eax]\

#pragma aux kmax =\
	"cmp eax, ebx",\
	"jg skipit",\
	"mov eax, ebx",\
	"skipit:",\
	parm nomemory [eax][ebx]\
	modify exact [eax]\
I could try to guess from the names, but I don't really know. Some of the code I've been implementing by converting each asm line into an equivalent C line, which is not a very good way to do it. But the C code is at least easier to read...

Code: Select all

INLINE void swapbuf4(int *eax, int *ebx, int ecx)
{
	int esi, edi;

begswap:
	esi = *eax;
	edi = *ebx;
	*ebx = esi;
	*eax = edi;
	eax++;
	ebx++;
	ecx--;
	if(ecx != 0)
		goto begswap;
}

INLINE void swap64bit(int *a, int *b)
{
	int c, d;
	c = a[0];
	d = b[0];
	b[0] = c;
	c = a[1];
	a[0] = d;
	d = b[1];
	b[1] = c;
	a[1] = d;
}
Unfortunately, that's only a small portion of the inline asm code in the Build engine. And I've not even touched the a.asm file, which contains a load of asm drawing functions.

I'm going to take another look at pragmas.h, and then I'm going to try writing a stand-alone OpenGL renderer.

If anyone wants to try, you're quite welcome. I reccomend that you download 3D Realms' Duke3D source, Ken's Build engine source, Icculus' port of Build, and their port of Duke 3D, at least. At the moment, I'm just playing with it, and trying to make it easier to port (before I actually consider porting it to anything).

And downloading a copy of the Watcom C compiler might be useful too, even if it's just to test that any code you've replaced works.
Phantom
DC Developer
DC Developer
Posts: 1753
Joined: Thu Jan 16, 2003 4:01 am
Location: The Netherlands
Has thanked: 0
Been thanked: 0
Contact:

Post by Phantom »

Code: Select all

//returns eax%ebx, dmval = eax/edx;
#pragma aux moddiv =\
	"xor edx, edx",\
	"div ebx",\
	"mov dmval, eax",\
	parm [eax][ebx]\
	modify exact [eax edx]\
	value [edx]
Divides two unsigned integers. The result is assigned to dmval. The remainder is returned.

Code: Select all

//eax = (unsigned min)umin(eax,ebx)
#pragma aux umin =\
	"sub eax, ebx",\
	"sbb ecx, ecx",\
	"and eax, ecx",\
	"add eax, ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax ecx]\
Returns the minimum of two unsigned integers.

Code: Select all

//eax = (unsigned max)umax(eax,ebx)
#pragma aux umax =\
	"sub eax, ebx",\
	"sbb ecx, ecx",\
	"xor ecx, 0xffffffff",\
	"and eax, ecx",\
	"add eax, ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax ecx]\
Returns the maximum of two unsigned integers.

Code: Select all

#pragma aux kmin =\
	"cmp eax, ebx",\
	"jl skipit",\
	"mov eax, ebx",\
	"skipit:",\
	parm nomemory [eax][ebx]\
	modify exact [eax]\
Returns the minimum of two signed integers.

Code: Select all

#pragma aux kmax =\
	"cmp eax, ebx",\
	"jg skipit",\
	"mov eax, ebx",\
	"skipit:",\
	parm nomemory [eax][ebx]\
	modify exact [eax]\
Returns the maximum of two signed integers.
Post Reply