SSA8.C

/******************************Module*Header*******************************\ 
* Module Name: ssa8.c
*
* Operations on .a8 files
*
* Copyright 1995 - 1998 Microsoft Corporation
*
\**************************************************************************/

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sscommon.h"

#define ESCAPE 0
#define ESC_ENDLINE 0
#define ESC_ENDBITMAP 1
#define ESC_DELTA 2
#define ESC_RANDOM 3
#define RANDOM_COUNT(c) ((c)-(ESC_RANDOM-1))

#define COUNT_SIZE 256
#define MAXRUN (COUNT_SIZE-1)
#define MAXRND (RANDOM_COUNT(COUNT_SIZE)-1)

typedef unsigned char *HwMem;
typedef unsigned long HwMemSize;
#define HW_UNALIGNED UNALIGNED

static HwMemSize HwuRld(HwMem src, HwMem dest, HwMemSize stride)
{
unsigned short code;
unsigned char run, esc;
size_t len;
HwMem s;
HwMem f;

s = src;
f = dest;
for (;;)
{
code = *((unsigned short HW_UNALIGNED *)s)++;
run = code & 0xff;
esc = code >> 8;
if (run == ESCAPE)
{
if (esc == ESC_ENDBITMAP)
{
break;
}
else if (esc == ESC_DELTA)
{
len = *((unsigned short HW_UNALIGNED *)s)++;
while (len-- > 0)
{
*f = 0;
f += stride;
}
}
else if (esc >= ESC_RANDOM)
{
len = RANDOM_COUNT(esc);
while (len-- > 0)
{
*f = *s++;
f += stride;
}
}
}
else
{
while (run-- > 0)
{
*f = esc;
f += stride;
}
}
}

return s-src;
}

static HwMemSize HwuRldTo32(HwMem src, HwMem dest, HwMemSize stride,
DWORD *translate)
{
unsigned short code;
unsigned char run, esc;
size_t len;
HwMem s;
DWORD *f, tran;

s = src;
f = (DWORD *)dest;
for (;;)
{
code = *((unsigned short HW_UNALIGNED *)s)++;
run = code & 0xff;
esc = code >> 8;
if (run == ESCAPE)
{
if (esc == ESC_ENDBITMAP)
{
break;
}
else if (esc == ESC_DELTA)
{
len = *((unsigned short HW_UNALIGNED *)s)++;
while (len-- > 0)
{
*f = translate[0];
f += stride;
}
}
else if (esc >= ESC_RANDOM)
{
len = RANDOM_COUNT(esc);
while (len-- > 0)
{
*f = translate[*s++];
f += stride;
}
}
}
else
{
tran = translate[esc];
while (run-- > 0)
{
*f = tran;
f += stride;
}
}
}

return s-src;
}

#define ALPHA_SIGNATURE 0xa0a1a2a3
#define COMPRESS_NONE 0
#define COMPRESS_RLE 1

BOOL ss_A8ImageLoad(void *pvResource, TEXTURE *ptex)
{
DWORD compress;
DWORD size;
DWORD *pal;
DWORD *pdwA8;

pdwA8 = (DWORD *)pvResource;

// Check data signature for alpha texture format
if (*pdwA8 != ALPHA_SIGNATURE)
{
return FALSE;
}
pdwA8++;

ptex->width = *pdwA8++;
ptex->height = *pdwA8++;

// Make sure depth is 8bpp
if (*pdwA8 != 8)
{
return FALSE;
}
pdwA8++;

size = ptex->width*ptex->height;

// Compression type
compress = *pdwA8++;
// Compressed data size only if compressed, not used
pdwA8++;

// Remember pointer to palette data
pal = pdwA8;
pdwA8 += 256;

if (ss_PalettedTextureEnabled())
{
// Allocate data for final image
ptex->data = malloc(size);
if (ptex->data == NULL)
{
return FALSE;
}

ptex->pal_size = 256;
ptex->pal = malloc(ptex->pal_size*sizeof(RGBQUAD));
if (ptex->pal == NULL)
{
free(ptex->data);
return FALSE;
}
memcpy(ptex->pal, pal, ptex->pal_size*sizeof(RGBQUAD));

// Unpack 8bpp data into final image
if (compress == COMPRESS_NONE)
{
memcpy(ptex->data, pdwA8, size);
}
else
{
HwuRld((HwMem)pdwA8, ptex->data, 1);
}

ptex->format = GL_COLOR_INDEX;
ptex->components = GL_COLOR_INDEX8_EXT;
}
else
{
// Allocate data for final image
ptex->data = malloc(size*sizeof(DWORD));
if (ptex->data == NULL)
{
return FALSE;
}

ptex->pal_size = 0;
ptex->pal = NULL;

// Unpack 8bpp data into final image
if (compress == COMPRESS_NONE)
{
DWORD i;
BYTE *src;
DWORD *dst;

src = (BYTE *)pdwA8;
dst = (DWORD *)ptex->data;
for (i = 0; i < size; i++)
{
*dst++ = pal[*src++];
}
}
else
{
HwuRldTo32((HwMem)pdwA8, ptex->data, 1, pal);
}

ptex->format = GL_BGRA_EXT;
ptex->components = 4;
}

return TRUE;
}