avp/3dc/win95/d3load.c
Rebellion Developments 218ca90543 Import Aliens vs Predator - Gold (Build 116)
Source code release, imported from:
https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code

All text files were converted to Unix format.
2019-08-19 05:45:17 +02:00

316 lines
11 KiB
C

/***************************************************************************/
/* Loading a PPM file into a surface */
/***************************************************************************/
/*
* LoadSurface
* Loads a ppm file into a texture map DD surface of the given format. The
* memory flag specifies DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY.
*/
LPDIRECTDRAWSURFACE
D3DAppILoadSurface(LPDIRECTDRAW lpDD, LPCSTR lpName,
LPDDSURFACEDESC lpFormat, DWORD memoryflag)
{
LPDIRECTDRAWSURFACE lpDDS;
DDSURFACEDESC ddsd, format;
D3DCOLOR colors[256];
D3DCOLOR c;
DWORD dwWidth, dwHeight;
int i, j;
FILE *fp;
char *lpC;
CHAR buf[100];
LPDIRECTDRAWPALETTE lpDDPal;
PALETTEENTRY ppe[256];
int psize;
DWORD pcaps;
int color_count;
BOOL bQuant = FALSE;
HRESULT ddrval;
/*
* Find the image file and open it
*/
fp = D3DAppIFindFile(lpName, "rb");
if (fp == NULL) {
D3DAppISetErrorString("Cannot find %s.\n", lpName);
return NULL;
}
/*
* Is it a PPM file?
*/
fgets(buf, sizeof buf, fp);
if (lstrcmp(buf, "P6\n")) {
fclose(fp);
D3DAppISetErrorString("%s is not a PPM file.\n", lpName);
return NULL;
}
/*
* Skip any comments
*/
do {
fgets(buf, sizeof buf, fp);
} while (buf[0] == '#');
/*
* Read the width and height
*/
sscanf(buf, "%d %d\n", &dwWidth, &dwHeight);
fgets(buf, sizeof buf, fp); /* skip next line */
/*
* Create a surface of the given format using the dimensions of the PPM
* file.
*/
memcpy(&format, lpFormat, sizeof(DDSURFACEDESC));
if (format.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
bQuant = TRUE;
psize = 256;
pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
} else if (format.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
bQuant = TRUE;
psize = 16;
pcaps = DDPCAPS_4BIT;
}
memcpy(&ddsd, &format, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | memoryflag;
ddsd.dwHeight = dwHeight;
ddsd.dwWidth = dwWidth;
ddrval = lpDD->lpVtbl->CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
if (ddrval != DD_OK) {
D3DAppISetErrorString("CreateSurface for texture failed (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return NULL;
}
/*
* Lock the surface so it can be filled with the PPM file
*/
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddrval = lpDDS->lpVtbl->Lock(lpDDS, NULL, &ddsd, 0, NULL);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Lock failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return NULL;
}
/*
* The method of loading depends on the pixel format of the dest surface
*/
if (!bQuant) {
/*
* The texture surface is not palettized
*/
unsigned long* lpLP;
unsigned short* lpSP;
unsigned char* lpCP;
unsigned long m;
int s;
int red_shift, red_scale;
int green_shift, green_scale;
int blue_shift, blue_scale;
/*
* Determine the red, green and blue masks' shift and scale.
*/
for (s = 0, m = format.ddpfPixelFormat.dwRBitMask; !(m & 1);
s++, m >>= 1);
red_shift = s;
red_scale = 255 / (format.ddpfPixelFormat.dwRBitMask >> s);
for (s = 0, m = format.ddpfPixelFormat.dwGBitMask; !(m & 1);
s++, m >>= 1);
green_shift = s;
green_scale = 255 / (format.ddpfPixelFormat.dwGBitMask >> s);
for (s = 0, m = format.ddpfPixelFormat.dwBBitMask; !(m & 1);
s++, m >>= 1);
blue_shift = s;
blue_scale = 255 / (format.ddpfPixelFormat.dwBBitMask >> s);
/*
* Each RGB bit count requires different pointers
*/
switch (format.ddpfPixelFormat.dwRGBBitCount) {
case 32 :
for (j = 0; j < (int)dwHeight; j++) {
/*
* Point to next row in texture surface
*/
lpLP = (unsigned long*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
/*
* Read each value, scale it and shift it into position
*/
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpLP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpLP++;
}
}
break;
case 16 :
for (j = 0; j < (int)dwHeight; j++) {
lpSP = (unsigned short*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpSP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpSP++;
}
}
break;
case 8:
for (j = 0; j < (int)dwHeight; j++) {
lpCP = (unsigned char*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpCP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpCP++;
}
}
break;
default:
/*
* This wasn't a format I recognize
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
fclose(fp);
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Unknown pixel format (loadtex).");
return NULL;
}
/*
* Unlock the texture and return the surface pointer
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
fclose(fp);
return (lpDDS);
}
/*
* We assume the 8-bit palettized case
*/
color_count = 0; /* number of colors in the texture */
for (j = 0; j < (int)dwHeight; j++) {
/*
* Point to next row in surface
*/
lpC = ((char*)ddsd.lpSurface) + ddsd.lPitch * j;
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b, k;
/*
* Get the next red, green and blue values and turn them into a
* D3DCOLOR
*/
r = getc(fp);
g = getc(fp);
b = getc(fp);
c = RGB_MAKE(r, g, b);
/*
* Search for this color in a table of colors in this texture
*/
for (k = 0; k < color_count; k++)
if (c == colors[k]) break;
if (k == color_count) {
/*
* This is a new color, so add it to the list
*/
color_count++;
/*
* More than 256 and we fail (8-bit)
*/
if (color_count > psize) {
color_count--;
k = color_count - 1;
//goto burst_colors;
}
colors[k] = c;
}
/*
* Set the "pixel" value on the surface to be the index into the
* color table
*/
if (psize == 16) {
if ((i & 1) == 0)
*lpC = k & 0xf;
else {
*lpC |= (k & 0xf) << 4;
lpC++;
}
} else {
*lpC = (char)k;
lpC++;
}
}
}
/*
* Close the file and unlock the surface
*/
fclose(fp);
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
//burst_colors:
if (color_count > psize) {
/*
* If there are more than 256 colors, we overran our palette
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Palette burst. (loadtex).\n");
return (NULL);
}
/*
* Create a palette with the colors in our color table
*/
memset(ppe, 0, sizeof(PALETTEENTRY) * 256);
for (i = 0; i < color_count; i++) {
ppe[i].peRed = (unsigned char)RGB_GETRED(colors[i]);
ppe[i].peGreen = (unsigned char)RGB_GETGREEN(colors[i]);
ppe[i].peBlue = (unsigned char)RGB_GETBLUE(colors[i]);
}
/*
* Set all remaining entry flags to D3DPAL_RESERVED, which are ignored by
* the renderer.
*/
for (; i < 256; i++)
ppe[i].peFlags = D3DPAL_RESERVED;
/*
* Create the palette with the DDPCAPS_ALLOW256 flag because we want to
* have access to all entries.
*/
ddrval = lpDD->lpVtbl->CreatePalette(lpDD,
DDPCAPS_INITIALIZE | pcaps,
ppe, &lpDDPal, NULL);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Create palette failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return (NULL);
}
/*
* Finally, bind the palette to the surface
*/
ddrval = lpDDS->lpVtbl->SetPalette(lpDDS, lpDDPal);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
lpDDPal->lpVtbl->Release(lpDDPal);
D3DAppISetErrorString("SetPalette failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return (NULL);
}
lpDDPal->lpVtbl->Release(lpDDPal);
return lpDDS;
}