Forum

ProQuake 4.70 PSP Build

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Postby Ranger366 » Tue Nov 30, 2010 3:17 pm

The new half-byte loader (rev 109) runs now all Quake engines without any problems. And your engine speeds up Sisah bugged Kurok Mod... amazing (i mean the FPS Rate with that).

This is true win baker.
User avatar
Ranger366
 
Posts: 203
Joined: Thu Mar 18, 2010 5:51 pm

Postby Mexicouger » Tue Nov 30, 2010 11:51 pm

Ranger366 wrote:The new half-byte loader (rev 109) runs now all Quake engines without any problems. And your engine speeds up Sisah bugged Kurok Mod... amazing (i mean the FPS Rate with that).

This is true win baker.


So what do you mean? Kurok runs faster on HBL? Or someone made a faster Kurok?
User avatar
Mexicouger
 
Posts: 514
Joined: Sat May 01, 2010 10:12 pm

Postby Biodude » Wed Dec 01, 2010 2:58 am

I really like your engine, baker, but external wad support would be great to have, besides the fact of the memory usage
User avatar
Biodude
 
Posts: 186
Joined: Wed Aug 27, 2008 7:17 pm

Postby Ranger366 » Wed Dec 01, 2010 3:23 pm

@Mexicouger
I played unchanged Half-Life PSP (by Sisah) on my uncracked PHAT PSP and it ran with ca 12 fps, on ProQuake Half-Life PSP has ca 50fps. Thats a big difference. Just change out the E-boot and look how it works.

Half-Life PSP is not really fun, but it shows us that we should stock up Quake with Half-Life Formats. I think im going to make a thread about this.
User avatar
Ranger366
 
Posts: 203
Joined: Thu Mar 18, 2010 5:51 pm

Postby revelator » Wed Dec 01, 2010 6:26 pm

Code: Select all
// the palette immediately follows the texture.  load it and convert the texture to 32 bit,
// then upload it.
int LoadHLTexture (char *texname, int width, int height, byte *texpix)
{
#ifdef HALFLIFEBSP
    // each halflife texture has it's own palette
    byte      HL_Red[256];
    byte      HL_Green[256];
    byte      HL_Blue[256];

    int         palette_offset;
    int         i, j;
    byte      *hl_rgba;
    int         hltexnum;
    qboolean   alpha;
    qboolean   mipmap;

    // add 2 cos the first 2 bytes after the pixels are a short giving the number of palette
    // entries.  while this can, in theory, change, in reality it's always 256.  i have yet
    // to see a halflife bsp or wad where it wasn't 256, anyway.
    palette_offset = (int) (((float) height * (float) width * 1.328125) + 2.0);

    for (i = 0; i < 256; i++)
    {
        HL_Red[i] = texpix[palette_offset++];
        HL_Green[i] = texpix[palette_offset++];
        HL_Blue[i] = texpix[palette_offset++];

        // load the underwater fog stuff if we have a fog texture
        if (texname[0] == '!')
        {
            if (i == 4) fog_density = HL_Red[i];

            if (i == 3)
            {
                fog_colour[0] = HL_Red[i];
                fog_colour[1] = HL_Green[i];
                fog_colour[2] = HL_Blue[i];
            }
        }
    }

    hl_rgba = (byte *) malloc (height * width * 4);
    alpha = false;

    // convert to rgba
    for (i = 0, j = 0; i < height * width; i++)
    {
        if (texpix[i] == 255 && texname[0] == '{')
        {
            // yeah, i know it looks amateurish, just go fuck off.
            hl_rgba[j++] = 0;
            hl_rgba[j++] = 0;
            hl_rgba[j++] = 0;
            hl_rgba[j++] = 0;
            alpha = true;
        }
        else
        {
            hl_rgba[j++] = HL_Red[texpix[i]];
            hl_rgba[j++] = HL_Green[texpix[i]];
            hl_rgba[j++] = HL_Blue[texpix[i]];
            hl_rgba[j++] = 255;
        }
    }

    // don't mipmap grates cos it's ugly
    if (texname[0] == '{')
   {
        mipmap = false;
   }
    else
   {
      mipmap = true;
   }
    hltexnum = MHGL_LoadTexture (texname, width, height, &hl_rgba[0], mipmap, alpha, 32);

    free (hl_rgba);

    return hltexnum;
#else
    return -1;
#endif
}


// most of the code in here comes from a wad3 to tga utility i wrote a year ago - so please don't
// expect me to be able to explain what's going on in it.
int HL_SearchWAD3File (char *wad3name, miptex_t *mt, gltexture_t *tx)
{
#ifdef HALFLIFEBSP
    FILE         *wadfile;
    char         wad3path[1024];
    int            i, j, pixels;
   byte         *loadtexture;

    hlwadinfo_t      wadheader;
    hllumpinfo_t   waddirectory;
    hlmiptex_t      wadtexture;

    sprintf (wad3path, "textures/%s.wad", wad3name);

    i = COM_FOpenFile (wad3path, &wadfile);

    if (!wadfile)
    {
        return -1;
    }
   
    // search for the texture
    // read and verify the header
    fread (&wadheader, sizeof (wadheader), 1, wadfile);

    if (strncmp (wadheader.identification, "WAD3", 4))
    {
        // try for WAD2 - this is dangerous.  Half-Life supports WAD2 as a valid ID which means
        // that this program WILL TRY TO DO SOMETHING with a standard Quake WAD2.  So watch your
        // step here. this returns -1 rather than crashing out.
        if (strncmp (wadheader.identification, "WAD2", 4))
      {
            return -1;
      }
    }

    for (i = 0; i < wadheader.numlumps; i++)
    {
        // read the current entry in  the wad directory
        fseek (wadfile, (wadheader.infotableofs + (sizeof (waddirectory) * i)), SEEK_SET);
        fread (&waddirectory, sizeof (waddirectory), 1, wadfile);

        // fucking uppercase texture names
        if (!strcmp (strlwr (waddirectory.name), strlwr (tx->name)))
        {
            // gotcha, ya little bastard!
            // seek to the texture data
            fseek (wadfile, waddirectory.filepos, SEEK_SET);
            fread (&wadtexture, sizeof (wadtexture), 1, wadfile);

            // don't really need this in glquake, but what the hell...
            for (j = 0; j < MIPLEVELS; j++)
         {
                tx->offsets[j] = wadtexture.offsets[j] + sizeof(gltexture_t) - sizeof(hlmiptex_t);
         }

            // at this stage, wadtexture contains the same data as mt in the main texture loading
            // function, so we can do similar stuff with it - firstly, make the contents of mt
            // the same as those of wadtexture (just call me paranoid)
            mt->height = wadtexture.height;
            strcpy (mt->name, wadtexture.name);
            mt->width = wadtexture.width;

            for (j = 0; j < MIPLEVELS; j++)
         {
                mt->offsets[j] = wadtexture.offsets[j];
         }

            // i had hoped that i wouldn't have had to do this...
            pixels = (mt->width * mt->height / 64 * 85) + 770;

            // our file pointer is in the right position for this, so just read away
            loadtexture = (byte *) malloc (pixels);
            fread (loadtexture, pixels, 1, wadfile);

            // then load the texture
            tx->gl_texturenum = LoadHLTexture (tx->name, tx->width, tx->height, loadtexture);

            free (loadtexture);

            fclose (wadfile);

            return tx->gl_texturenum;
        }
    }

    // didn't find it
    fclose (wadfile);
#endif
    return -1;
}

int LoadHLWAD3Texture (miptex_t *mt, gltexture_t *tx)
{
#ifdef HALFLIFEBSP
    int      i, j, k;
    char   wadname[64];
    int      texnum;

    // no WAD3 specified and Quake is expecting one!  Oh shit!!
    if (wadstring[0] == '\0')
   {
        return notexture_num;
   }
   i = 0;

    // parse the wadstring
    if (i < strlen (wadstring))
    {
        // hunt for a '.'
        do
      {
            if (i >= strlen (wadstring))
         {
                return notexture_num;
         }
         i++;

      } while (wadstring[i] != '.');

        // save the current i (+ 1)
        j = i + 1;

        // read backwards for a '/' or a '\' or a ' ' or until i is 0
        do
        {
            if (i <= 0)
            {
                i = 0;    // just in case it ever does go < 0...
                break;
            }
         i--;

        } while (wadstring[i] != ' ' && wadstring[i] != '/' && wadstring[i] != '\\');

        // read forwards to the '.' again, this time loading the wadname - we increment i here
        // cos we want to start at the first character after the '/' or whatever (only if i != 0)
        if (i)
      {
         i++;
      }
      k = 0;

        do
      {
            wadname[k++] = wadstring[i++];
      } while (wadstring[i] != '.');

        wadname[k] = '\0';

        // find the texture
        texnum = HL_SearchWAD3File (wadname, mt, tx);

        // got it!
        if (texnum != -1)
      {
         return texnum;
      }

        // restore the saved i
        i = j;
    }
#endif

    // if we've got this far, the engine was unable to find a texture, so return the
    // notexture texture.
    return notexture_num;
}


void Mod_LoadHLTextures (miptex_t *mt, gltexture_t *tx, int pixels)
{
#ifdef HALFLIFEBSP
    int j;

    fog_colour[0] = fog_colour[1] = fog_colour[2] = fog_density = 255;

    // the pixels immediately follow the structures - halflife doesn't do sky the same
    // as quake, so we're cool...
    texture_mode = GL_LINEAR_MIPMAP_LINEAR;

    if (mt->offsets[0])
    {
        for (j=0 ; j<MIPLEVELS ; j++)
      {
            tx->offsets[j] = mt->offsets[j] + sizeof(gltexture_t) - sizeof(miptex_t);
      }

        // texture is stored in the BSP
        memcpy (tx+1, mt+1, pixels);

        // external texture loading
        tx->gl_texturenum = GL_LoadTexture (mt->name, &tx->width, &tx->height, NULL, true, true);

        if (tx->gl_texturenum == -1)
      {
            tx->gl_texturenum = LoadHLTexture (mt->name, tx->width, tx->height, (byte *)(tx+1));
      }
    }
    else
    {
        // external texture loading (TGA/JPG/PCX, not WAD3)
        tx->gl_texturenum = GL_LoadTexture (mt->name, &tx->width, &tx->height, NULL, true, true);

        // grab the texture from an external WAD3
        if (tx->gl_texturenum == -1)
      {
            tx->gl_texturenum = LoadHLWAD3Texture (mt, tx);
      }
    }

    // halflife has no fullbrights
    tx->fullbright = -1;   // because 0 is a potentially valid texture number

    texture_mode = GL_LINEAR;

    // set underwater fog colour and density
    tx->water_fog_density = (float) fog_density / 255.0;
    tx->water_fog_colour[0] = (float) fog_colour[0] / 255.0;
    tx->water_fog_colour[1] = (float) fog_colour[1] / 255.0;
    tx->water_fog_colour[2] = (float) fog_colour[2] / 255.0;
#endif
}

// doesn't support LIT files
void Mod_LoadHLLighting (lump_t *l)
{
#ifdef HALFLIFEBSP
    int     i, j;
    byte    *explit;
    int     r, g, b;

    loadmodel->lightdata = NULL;

    if (!l->filelen) return;

    // halflife uses 3 component lightmaps in the bsp, so we expand them to 4
    Con_DPrintf ("Using Light Data from %s - HalfLife BSP format\n", loadmodel->name);

    if (gl_useclight)
    {
        // load from the bsp and expand to rgba
        loadmodel->lightdata = Hunk_AllocName ((l->filelen / 3) * 4, loadname);
        explit = (byte *) malloc (l->filelen);
        memcpy (explit, mod_base + l->fileofs, l->filelen);

        for (i = 0, j = 0; i < l->filelen; i += 3, j += 4)
        {
            r = loadmodel->lightdata[j] = explit[i];
            g = loadmodel->lightdata[j + 1] = explit[i + 1];
            b = loadmodel->lightdata[j + 2] = explit[i + 2];
            loadmodel->lightdata[j + 3] = (r + g + b) / 3;
        }
        free (explit);
    }
    else
    {
        // load from the bsp and condense - this means we can explicitly force white light
        // in halflife bsps if the performance hit caused by coloured light is too much to
        // cope with!
        loadmodel->lightdata = Hunk_AllocName (l->filelen / 3, loadname);
        explit = (byte *) malloc (l->filelen);
        memcpy (explit, mod_base + l->fileofs, l->filelen);

        for (i = 0, j = 0; i < l->filelen; i += 3, j++)
        {
            r = explit[i];
            g = explit[i+1];
            b = explit[i+2];
            loadmodel->lightdata[j] = (r + g + b) / 3;
        }
        free (explit);
    }
#endif
}


old code from mh might be handy ;) enjoy.
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby Ranger366 » Wed Dec 01, 2010 6:28 pm

reckless wrote:*Posts most useful code snippet on the thread*


Thanks :D

Quake already rules the PSP Homebrew Scene, and the cool thing is that we have the hottest Engines for it.. awesome.
User avatar
Ranger366
 
Posts: 203
Joined: Thu Mar 18, 2010 5:51 pm

Postby revelator » Wed Dec 01, 2010 6:34 pm

might need a little work :) not just copy pasta.

mh's old mhglqr6 while still somewhat quake alike codewise did have
quite a few changes.

i left the source code for mhglqr6 in the thread about me looking for an old fix i made to the codebase if you get stuck on some varable its the best place to hunt for the solution.

viewtopic.php?t=2780
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby frag.machine » Wed Dec 01, 2010 6:46 pm

Ranger366 wrote:Half-Life PSP is not really fun, but it shows us that we should stock up Quake with Half-Life Formats.


You should instead bug Valve guys to release the old Half Life 1 engine source under the GPL. :roll:
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Postby Ranger366 » Wed Dec 01, 2010 6:58 pm

frag.machine wrote:You should instead bug Valve guys to release the old Half Life 1 engine source under the GPL. :roll:


bug valve guys? wtf?

i could ask Uncle Mike to give out the engine.dll source of xash3D

http://translate.google.com/translate?h ... .google.de
Last edited by Ranger366 on Thu Dec 02, 2010 1:47 pm, edited 1 time in total.
User avatar
Ranger366
 
Posts: 203
Joined: Thu Mar 18, 2010 5:51 pm

Postby frag.machine » Wed Dec 01, 2010 8:41 pm

Ranger366 wrote:
frag.machine wrote:
Ranger366 wrote:You should instead bug Valve guys to release the old Half Life 1 engine source under the GPL. :roll:


bug valve guys? wtf?


Sorry if what I wrote makes no sense. English is not my primary language, hence sometimes I wrote things thinking in Portuguese and later when I read back I just "wtf I was thinking when wrote this ?" :D.

But what I mean is: when you say "Half-Life PSP is not really fun, but it shows us that we should stock up Quake with Half-Life Formats." this means to me you're not actually looking for a Quake engine - you want a port of the HL1/Source engine. It's okay, nothing wrong about this - unless when you guys insist on turning one thing into another. Quake isn't (and will never be) Half Life. For a start, the HL1 engine started as a Quake engine, then it was ported to C++, then later some of the Quake 2 tech was added to it, Valve replaced a really big bunch of things (like the model format) or heavily modified other bunch (like the bsp format), to a point where the final result barely resembles the original id code. It's unlikely that anyone here will follow this tortuous roadmap only because you guys do prefer to use HL tools for mapping or modeling (even though I agree they are far better options than Quake counterparts). So, the solution to me is quite obvious: go ask Valve guys if they would like to contribute to the PSP mod community and release the HL1 engine source under GPL or any other OSS license they prefer. After all, Christmas is approaching and, who knows ? Maybe Gabe Newell is feeling generous...
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Postby Mexicouger » Wed Dec 01, 2010 11:59 pm

:D

Half life map format would definitely be nice. Solely so we can make more exotic areas. I think another model format would be good too. I am starting to see that mdl has alot of pits to it. Let's see that Bakers ProQuake prevails.
User avatar
Mexicouger
 
Posts: 514
Joined: Sat May 01, 2010 10:12 pm

Postby Rich » Thu Dec 02, 2010 1:15 am

Adding HL MDL to a PSP engine would be a bit of a mistake. You're then getting into the realm of doing a lot of software vertex calculations, and that's going to be very wasteful and limit your geometry counts severely. Maybe you can live with it, but it's going to be a huge burden on performance in the long run, once you've backed yourself into a corner with people now having the expectation that they can natively display HL MDL with your engine.

The right thing to do for skeletal formats on the PSP is to break the model into triangle strips, also limiting each surface to no more than 8 bone references so that you can utilize hardware skinning. There are also a number of geometry preprocessing/sorting operations you will probably want to do - Sony's official GMO model format is the best example for best-practices in data pre-processing. With the kinds of bone counts we see in PSP games, this may sound like a terrible idea to programmers who are used to the idea of batching to minimize draw calls. However, it's actually the optimal approach on the PSP - though you will definitely want to avoid needless splits and/or redundant matrix uploads resulting from poor/non-existent geometry-bone sorting.

Doing the necessary processing on a HL MDL on a PSP at load time would impose a hideous amount of overhead, so the better thing to do is to implement a PSP-optimized model format (just bake your surfaces out with optimized data and the corresponding int32 format specifier), and force people to convert the data for their mods if they want the mods to run on your PSP port. Otherwise, you're just going to end up with terrible load times or extremely sub-par performance that can't even compare to what we see in commercial titles.
Rich
 
Posts: 35
Joined: Tue Nov 02, 2010 3:46 am

Postby Downsider » Thu Dec 02, 2010 2:41 am

Rich wrote:Adding HL MDL to a PSP engine would be a bit of a mistake. You're then getting into the realm of doing a lot of software vertex calculations, and that's going to be very wasteful and limit your geometry counts severely. Maybe you can live with it, but it's going to be a huge burden on performance in the long run, once you've backed yourself into a corner with people now having the expectation that they can natively display HL MDL with your engine.

The right thing to do for skeletal formats on the PSP is to break the model into triangle strips, also limiting each surface to no more than 8 bone references so that you can utilize hardware skinning. There are also a number of geometry preprocessing/sorting operations you will probably want to do - Sony's official GMO model format is the best example for best-practices in data pre-processing. With the kinds of bone counts we see in PSP games, this may sound like a terrible idea to programmers who are used to the idea of batching to minimize draw calls. However, it's actually the optimal approach on the PSP - though you will definitely want to avoid needless splits and/or redundant matrix uploads resulting from poor/non-existent geometry-bone sorting.

Doing the necessary processing on a HL MDL on a PSP at load time would impose a hideous amount of overhead, so the better thing to do is to implement a PSP-optimized model format (just bake your surfaces out with optimized data and the corresponding int32 format specifier), and force people to convert the data for their mods if they want the mods to run on your PSP port. Otherwise, you're just going to end up with terrible load times or extremely sub-par performance that can't even compare to what we see in commercial titles.


I've got HL MDL in my engine and it works perfectly fine; and I save a crapload of RAM so I'd hardly call it a mistake.
User avatar
Downsider
 
Posts: 621
Joined: Tue Sep 16, 2008 1:35 am

Postby Rich » Thu Dec 02, 2010 2:49 am

Downsider wrote:I've got HL MDL in my engine and it works perfectly fine; and I save a crapload of RAM so I'd hardly call it a mistake.

It may use less memory that storing lots of vertex frames in memory, but it's still a terrible format to use natively on PSP hardware. As mentioned, maybe you can live with it, but in doing so you've just committed yourself to living with a lower performance ceiling. Better to just do it right to begin with and avoid the whole mess of supporting even more model formats later on just to get a better framerate. (with the added hassle of trying to get people to actually use your more optimal format)

In the end, an engine on an embedded system really ought to just support the minimal number of formats, and let tools handle getting everything else into those formats. The PC world is for supporting everything in the world natively and jamming horses and midgets into your codebase until it's got a 10MB footprint.
Rich
 
Posts: 35
Joined: Tue Nov 02, 2010 3:46 am

Postby Baker » Thu Dec 02, 2010 3:00 am

Out of curiosity, which Rich are you? I'd offer some guesses but I'd probably be wrong. Not knowing bugs me :D
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

PreviousNext

Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 1 guest