Files
Hellfire/ENGINE.CPP
T
2026-05-30 02:50:21 -07:00

4048 lines
94 KiB
C++

/*-----------------------------------------------------------------------**
** Diablo
**
** Engine file
**
** (C)1995 Condor, Inc. All rights reserved.
**
**-----------------------------------------------------------------------**
** $Header: /Diablo/ENGINE.CPP 2 1/22/97 2:32p Dgartner $
**-----------------------------------------------------------------------*/
#include "diablo.h"
#pragma hdrstop
#include "resource.h"
#include "storm/h/storm.h"
#include "engine.h"
#include "lighting.h"
#include "scrollrt.h"
#include "debug.h"
#include "gendung.h"
#include "palette.h"
//******************************************************************
// extern
//******************************************************************
void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine);
extern "C" {
extern BYTE gbLevelTileEnhanceActive;
extern BYTE gbLevelUnitContrastTable[];
extern BYTE gbLevelUnitLumaTable[];
extern BYTE gbLevelUnitSharpenLightTable[];
extern BYTE gbLevelUnitAoTable[];
}
//******************************************************************
// Registration info
//******************************************************************
#include "regconst.h"
char sgszRegSig1[REG_LEN] = "REGISTRATION_BLOCK";
//******************************************************************
// random numbers
//******************************************************************
static long sglGameSeed;
/*-----------------------------------------------------------------------**
** Decode RLE data without lighting
**-----------------------------------------------------------------------*/
void DecodeFullCel (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth)
{
long nBufferW;
app_assert(pDecodeTo != NULL);
app_assert(pRLEBytes != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pDecodeTo == NULL || pRLEBytes == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov esi,dword ptr [pRLEBytes] // Source
mov edi,dword ptr [pDecodeTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nWidth]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [lRLECount]
add ebx,esi
_T1Lp1: mov edx,dword ptr [nWidth]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
sub edx,eax
mov ecx,eax
shr ecx,1
jnc _T1w
movsb
jecxz _T1x
_T1w: shr ecx,1
jnc _T1Lp3
movsw
jecxz _T1x
_T1Lp3: rep movsd
_T1x: or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
**-----------------------------------------------------------------------*/
void DrawCel (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
pTo = gpBuffer + nBuffWTbl[yp] + xp;
DecodeFullCel (pTo, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
**-----------------------------------------------------------------------*/
void DrawCelP (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW)
{
BYTE *pFrom;
long RLELen;
app_assert(pCelBuff != NULL);
app_assert(pBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL || pBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
DecodeFullCel (pBuff, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
**-----------------------------------------------------------------------*/
void DrawSlabCel (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
DecodeFullCel(pTo, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
**-----------------------------------------------------------------------*/
void DrawSlabCelP (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
app_assert(pBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL || pBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
DecodeFullCel(pBuff, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Decode RLE data with light translation
**-----------------------------------------------------------------------*/
void DecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth)
{
long nBufferW, nL;
app_assert(pDecodeTo != NULL);
app_assert(pRLEBytes != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pDecodeTo == NULL || pRLEBytes == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov eax,dword ptr [nLVal];
shl eax,8
add eax,dword ptr [pLightTbl];
mov dword ptr [nL],eax
mov esi,dword ptr [pRLEBytes] // Source
mov edi,dword ptr [pDecodeTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nWidth]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [lRLECount]
add ebx,esi
_T1Lp1: mov edx,dword ptr [nWidth]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
push ebx
mov ebx,dword ptr [nL]
sub edx,eax
mov ecx,eax
push edx
call xbytes
pop edx
pop ebx
or edx,edx
jnz _T1Lp2
jmp _T1Nxt
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
cmp ebx,esi
jnz _T1Lp1
jmp _done
xbytes:
shr cl,1
jnc xwords
mov dl, [esi]
mov dl, [ebx+edx]
mov [edi],dl
add esi,1
add edi,1
xwords:
shr cl,1
jnc xquads
mov dl, [esi]
mov ch, [ebx+edx]
mov [edi],ch
mov dl, [esi+1]
mov ch, [ebx+edx]
mov [edi+1],ch
add esi,2
add edi,2
xquads:
test cl,cl
jz _xend
xnext:
mov eax, [esi]
add esi,4
mov dl,al
mov ch,[ebx+edx]
mov dl,ah
ror eax,16
mov [edi],ch
mov ch,[ebx+edx]
mov dl,al
mov [edi+1],ch
mov ch,[ebx+edx]
mov dl,ah
mov [edi+2],ch
mov ch,[ebx+edx]
mov [edi+3],ch
add edi,4
dec cl
jnz xnext
_xend:
ret
_done:
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Decode RLE data with light translation and transparency
**-----------------------------------------------------------------------*/
void TDecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth)
{
long nBufferW, nL, LineVal;
app_assert(pDecodeTo != NULL);
app_assert(pRLEBytes != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pDecodeTo == NULL || pRLEBytes == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov eax,dword ptr [nLVal];
shl eax,8
add eax,dword ptr [pLightTbl];
mov dword ptr [nL],eax
mov esi,dword ptr [pRLEBytes] // Source
mov edi,dword ptr [pDecodeTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nWidth]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [lRLECount]
add ebx,esi
mov eax,edi
and eax,1
mov dword ptr [LineVal],eax
_T1Lp1: mov edx,dword ptr [nWidth]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
push ebx
mov ebx,dword ptr [nL]
sub edx,eax
mov ecx,eax
mov eax,edi
and eax,1
cmp eax,dword ptr [LineVal]
jnz _T1Od
shr ecx,1
jnc _T1w
inc esi
inc edi
jecxz _T1x
jmp _T1w2
_T1w: shr ecx,1
jnc _T1Lp3
inc esi
inc edi
lodsb
xlatb
stosb
jecxz _T1x
_T1Lp3: lodsd
inc edi
ror eax,8
xlatb
stosb
ror eax,16
inc edi
xlatb
stosb
loop _T1Lp3
jmp _T1x
_T1Od: shr ecx,1
jnc _T1w2
lodsb
xlatb
stosb
jecxz _T1x
jmp _T1w
_T1w2: shr ecx,1
jnc _T1Lp4
lodsb
xlatb
stosb
inc esi
inc edi
jecxz _T1x
_T1Lp4: lodsd
xlatb
stosb
inc edi
ror eax,16
xlatb
stosb
inc edi
loop _T1Lp4
_T1x: pop ebx
or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
mov eax,dword ptr [LineVal]
inc eax
and eax,1
mov dword ptr [LineVal],eax
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void DrawCelL (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
pTo = gpBuffer + nBuffWTbl[yp] + xp;
if (nLVal)
DecodeFullCelL (pTo, pFrom, RLELen, nCelW);
else
DecodeFullCel (pTo, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
/*
void DrawCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW)
{
BYTE *pFrom;
long RLELen;
app_assert(pCelBuff != NULL);
app_assert(pBuff != NULL);
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
if (nLVal)
DecodeFullCelL (pBuff, pFrom, RLELen, nCelW);
else
DecodeFullCel (pBuff, pFrom, RLELen, nCelW);
}
*/
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void DrawSlabCelL (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
if (nLVal)
DecodeFullCelL (pTo, pFrom, RLELen, nCelW);
else
DecodeFullCel (pTo, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
/*
void DrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
app_assert(pBuff != NULL);
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
if (nLVal)
DecodeFullCelL (pBuff, pFrom, RLELen, nCelW);
else
DecodeFullCel (pBuff, pFrom, RLELen, nCelW);
}
*/
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer. with transparency
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void TDrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
app_assert(pBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL || pBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
if (nTrans)
TDecodeFullCelL (pBuff, pFrom, RLELen, nCelW);
else if (nLVal)
DecodeFullCelL (pBuff, pFrom, RLELen, nCelW);
else
DecodeFullCel (pBuff, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer. With infared vision
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void DrawSlabCelI (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
long nBufferW, nL, ltaboff;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
__asm {
mov eax,dword ptr [pLightTbl]
add eax,dword ptr [ltaboff]
mov dword ptr [nL],eax
mov esi,dword ptr [pFrom] // Source
mov edi,dword ptr [pTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nCelW]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [RLELen]
add ebx,esi
_T1Lp1:
mov edx,dword ptr [nCelW]
_T1Lp2:
xor eax,eax // Load control byte
mov al,[esi]
inc esi
test al,al
js _T1J
push ebx
mov ebx,dword ptr [nL]
sub edx,eax
mov ecx,eax
Bytes:
mov al,[esi]
inc esi
mov al,[ebx+eax]
mov [edi],al
dec ecx
lea edi,[edi+1]
jnz Bytes
pop ebx
test edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J:
neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt:
sub edi,dword ptr [nBufferW]
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Decode RLE data without lighting, with clipping
**-----------------------------------------------------------------------*/
void CDecodeFullCel (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth)
{
long nBufferW;
app_assert(pDecodeTo != NULL);
app_assert(pRLEBytes != NULL);
app_assert(gpBuffer);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pDecodeTo == NULL || pRLEBytes == NULL || gpBuffer == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov esi,dword ptr [pRLEBytes] // Source
mov edi,dword ptr [pDecodeTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nWidth]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [lRLECount]
add ebx,esi
_T1Lp1: mov edx,dword ptr [nWidth]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
sub edx,eax
cmp edi,dword ptr [glClipY]
jb _T1C1
add esi,eax
add edi,eax
jmp _T1x
_T1C1: mov ecx,eax
shr ecx,1
jnc _T1w
movsb
jecxz _T1x
_T1w: shr ecx,1
jnc _T1Lp3
movsw
jecxz _T1x
_T1Lp3: rep movsd
_T1x: or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
**-----------------------------------------------------------------------*/
void CDrawSlabCel (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
CDecodeFullCel(pTo, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
**-----------------------------------------------------------------------*/
void CDrawSlabCelP (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
app_assert(pBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL || pBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = *(WORD*)(pFrom + oend);
if (oend == 8)
offval2 = 0;
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
CDecodeFullCel (pBuff, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Decode RLE data with light translation and with clipping
**-----------------------------------------------------------------------*/
void CDecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth)
{
long nBufferW, nL;
app_assert(pDecodeTo != NULL);
app_assert(pRLEBytes != NULL);
app_assert(gpBuffer);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pDecodeTo == NULL || pRLEBytes == NULL || gpBuffer == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov eax,dword ptr [nLVal];
shl eax,8
add eax,dword ptr [pLightTbl];
mov dword ptr [nL],eax
mov esi,dword ptr [pRLEBytes] // Source
mov edi,dword ptr [pDecodeTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nWidth]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [lRLECount]
add ebx,esi
_T1Lp1: mov edx,dword ptr [nWidth]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
push ebx
mov ebx,dword ptr [nL]
sub edx,eax
cmp edi,dword ptr [glClipY]
jb _T1C1
add esi,eax
add edi,eax
jmp _T1x
_T1C1: mov ecx,eax
push edx
call xbytes
pop edx
_T1x: pop ebx
or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
cmp ebx,esi
jnz _T1Lp1
jmp _done
xbytes:
shr cl,1
jnc xwords
mov dl, [esi]
mov dl, [ebx+edx]
mov [edi],dl
add esi,1
add edi,1
xwords:
shr cl,1
jnc xquads
mov dl, [esi]
mov ch, [ebx+edx]
mov [edi],ch
mov dl, [esi+1]
mov ch, [ebx+edx]
mov [edi+1],ch
add esi,2
add edi,2
xquads:
test cl,cl
jz _xend
xnext:
mov eax, [esi]
add esi,4
mov dl,al
mov ch,[ebx+edx]
mov dl,ah
ror eax,16
mov [edi],ch
mov ch,[ebx+edx]
mov dl,al
mov [edi+1],ch
mov ch,[ebx+edx]
mov dl,ah
mov [edi+2],ch
mov ch,[ebx+edx]
mov [edi+3],ch
add edi,4
dec cl
jnz xnext
_xend:
ret
_done:
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Decode RLE data with light translation and with clipping and transparency
**-----------------------------------------------------------------------*/
void TCDecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth)
{
long nBufferW, nL, LineVal;
app_assert(pDecodeTo != NULL);
app_assert(pRLEBytes != NULL);
app_assert(gpBuffer);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pDecodeTo == NULL || pRLEBytes == NULL || gpBuffer == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov eax,dword ptr [nLVal];
shl eax,8
add eax,dword ptr [pLightTbl];
mov dword ptr [nL],eax
mov esi,dword ptr [pRLEBytes] // Source
mov edi,dword ptr [pDecodeTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nWidth]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [lRLECount]
add ebx,esi
mov eax,edi
and eax,1
mov dword ptr [LineVal],eax
_T1Lp1: mov edx,dword ptr [nWidth]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
push ebx
mov ebx,dword ptr [nL]
sub edx,eax
cmp edi,dword ptr [glClipY]
jb _T1C1
add esi,eax
add edi,eax
jmp _T1x
_T1C1: mov ecx,eax
mov eax,edi
and eax,1
cmp eax,dword ptr [LineVal]
jnz _T1Od
shr ecx,1
jnc _T1w
inc esi
inc edi
jecxz _T1x
jmp _T1w2
_T1w: shr ecx,1
jnc _T1Lp3
inc esi
inc edi
lodsb
xlatb
stosb
jecxz _T1x
_T1Lp3: lodsd
inc edi
ror eax,8
xlatb
stosb
ror eax,16
inc edi
xlatb
stosb
loop _T1Lp3
jmp _T1x
_T1Od: shr ecx,1
jnc _T1w2
lodsb
xlatb
stosb
jecxz _T1x
jmp _T1w
_T1w2: shr ecx,1
jnc _T1Lp4
lodsb
xlatb
stosb
inc esi
inc edi
jecxz _T1x
_T1Lp4: lodsd
xlatb
stosb
inc edi
ror eax,16
xlatb
stosb
inc edi
loop _T1Lp4
_T1x: pop ebx
or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
mov eax,dword ptr [LineVal]
inc eax
and eax,1
mov dword ptr [LineVal],eax
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void CDrawSlabCelL (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = *(WORD*)(pFrom + oend);
if (oend == 8)
offval2 = 0;
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
if (nLVal)
CDecodeFullCelL(pTo, pFrom, RLELen, nCelW);
else
CDecodeFullCel(pTo, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
/*
void CDrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = *(WORD*)(pFrom + oend);
if (oend == 8)
offval2 = 0;
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
if (nLVal)
CDecodeFullCelL (pBuff, pFrom, RLELen, nCelW);
else
CDecodeFullCel (pBuff, pFrom, RLELen, nCelW);
}
*/
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer.
**
** *pBuff = pointer to destination x,y in offscreen buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void TCDrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pFrom;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = *(WORD*)(pFrom + oend);
if (oend == 8)
offval2 = 0;
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
if (nTrans)
TCDecodeFullCelL (pBuff, pFrom, RLELen, nCelW);
else if (nLVal)
CDecodeFullCelL (pBuff, pFrom, RLELen, nCelW);
else
CDecodeFullCel (pBuff, pFrom, RLELen, nCelW);
}
/*-----------------------------------------------------------------------**
** Draws a 5 offset slab cel in a cel file RAM buffer. With infared vision and clipping
**
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void CDrawSlabCelI (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
long nBufferW, nL, ltaboff;
app_assert(gpBuffer);
app_assert(pCelBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel);
offval = *(WORD*)(pFrom + ostart);
if (!offval)
return;
RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel);
offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend);
RLELen = offval2 ? offval2 - offval : RLELen - offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
nL = (long)(pLightTbl + ltaboff);
nBufferW = 768 + nCelW; // Increase width
__asm {
mov esi,[pFrom] // Source
mov edi,[pTo] // Dest
mov ecx,[RLELen]
add ecx,esi
_T1Lp1:
push ecx
mov edx,[nCelW]
xor ecx,ecx
_T1Lp2:
xor eax,eax // Load control byte
mov al,[esi]
inc esi
test al,al
js _T1J
mov ebx,[nL]
sub edx,eax
cmp edi,[glClipY]
jb _T1C1
add esi,eax
add edi,eax
jmp _T1x
_T1C1:
mov cl,[esi]
inc esi
mov cl,[ebx+ecx]
mov [edi],cl
dec eax
lea edi,[edi+1]
jnz _T1C1
_T1x:
test edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J:
neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt:
pop ecx
sub edi,dword ptr [nBufferW]
cmp ecx,esi
jnz _T1Lp1
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel
**
** pBuff = Buffer to draw in
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** nBuffW = Width of the buffer
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
**-----------------------------------------------------------------------*/
void DrawBuffCel(BYTE *pBuff, long xp, long yp, long nBuffW, BYTE *pCelBuff, long nCel, long nCelW)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen;
app_assert(pCelBuff != NULL);
app_assert(pBuff != NULL);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL || pBuff == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov ebx,dword ptr [pCelBuff]
mov eax,dword ptr [nCel]
shl eax,2
add ebx,eax
mov eax,dword ptr [ebx+4]
sub eax,dword ptr [ebx]
mov dword ptr [RLELen],eax
mov eax,dword ptr [pCelBuff]
add eax,dword ptr [ebx]
mov dword ptr [pFrom],eax
}
pTo = pBuff + (nBuffW * yp) + xp;
__asm {
mov esi,dword ptr [pFrom] // Source
mov edi,dword ptr [pTo] // Dest
mov eax,dword ptr [nBuffW] // Increase width
add eax,dword ptr [nCelW]
mov dword ptr [nBuffW],eax
mov ebx,dword ptr [RLELen]
add ebx,esi
_T1Lp1: mov edx,dword ptr [nCelW]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
sub edx,eax
mov ecx,eax
shr ecx,1
jnc _T1w
movsb
jecxz _T1x
_T1w: shr ecx,1
jnc _T1Lp3
movsw
jecxz _T1x
_T1Lp3: rep movsd
_T1x: or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBuffW]
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
/*-----------------------------------------------------------------------**
** Makes a mask outline of a 5 offset slab cel in a cel file RAM buffer
**
** ocolor = Color to outline object with
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void OutlineSlabCel(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
long nBufferW;
app_assert(pCelBuff != NULL);
app_assert(gpBuffer);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL || gpBuffer == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov ebx,dword ptr [pCelBuff]
mov eax,dword ptr [nCel]
shl eax,2
add ebx,eax
mov eax,dword ptr [ebx+4]
sub eax,dword ptr [ebx]
mov dword ptr [RLELen],eax
mov edx,dword ptr [pCelBuff]
add edx,dword ptr [ebx]
mov dword ptr [pFrom],edx
add edx,dword ptr [ostart]
xor eax,eax
mov ax,word ptr [edx]
mov dword ptr [offval],eax
mov edx,dword ptr [pFrom]
add edx,dword ptr [oend]
mov ax,word ptr [edx]
mov dword ptr [offval2],eax
}
if (offval != 0) {
if (oend == 8) offval2 = 0;
if (offval2 != 0) RLELen = offval2 - offval;
else RLELen -= offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
__asm {
mov esi,dword ptr [pFrom] // Source
mov edi,dword ptr [pTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nCelW]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [RLELen]
add ebx,esi
_T1Lp1: mov edx,dword ptr [nCelW]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
sub edx,eax
mov ecx,eax
mov ah,byte ptr [ocolor]
_T1Lp3: lodsb
or al,al
jz _T1Skip
mov byte ptr [edi-768],ah
mov byte ptr [edi-1],ah
mov byte ptr [edi+1],ah
mov byte ptr [edi+768],ah
_T1Skip: inc edi
loop _T1Lp3
or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
}
/*-----------------------------------------------------------------------**
** Makes a mask outline of a 5 offset slab cel in a cel file RAM buffer. With clipping
**
** ocolor = Color to outline object with
** xp = Left X pixel position in offscreen buffer to draw to
** yp = Bottom Y pixel position in offscreen buffer to draw to
** *pCelBuff = pointer to cel file RAM buffer
** nCel = Cel number to draw in cel file (start with 1!!!!)
** nCelW = width of cel to draw
** nLVal = light value
**-----------------------------------------------------------------------*/
void COutlineSlabCel(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE *pTo;
BYTE *pFrom;
long RLELen, offval, offval2;
long nBufferW;
app_assert(pCelBuff != NULL);
app_assert(gpBuffer);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (pCelBuff == NULL || gpBuffer == NULL)
return;
#endif
// jcm.patch1.end.1/14/97
__asm {
mov ebx,dword ptr [pCelBuff]
mov eax,dword ptr [nCel]
shl eax,2
add ebx,eax
mov eax,dword ptr [ebx+4]
sub eax,dword ptr [ebx]
mov dword ptr [RLELen],eax
mov edx,dword ptr [pCelBuff]
add edx,dword ptr [ebx]
mov dword ptr [pFrom],edx
add edx,dword ptr [ostart]
xor eax,eax
mov ax,word ptr [edx]
mov dword ptr [offval],eax
mov edx,dword ptr [pFrom]
add edx,dword ptr [oend]
mov ax,word ptr [edx]
mov dword ptr [offval2],eax
}
if (offval != 0) {
if (oend == 8) offval2 = 0;
if (offval2 != 0) RLELen = offval2 - offval;
else RLELen -= offval;
pFrom += offval;
pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
__asm {
mov esi,dword ptr [pFrom] // Source
mov edi,dword ptr [pTo] // Dest
mov eax,768 // Increase width
add eax,dword ptr [nCelW]
mov dword ptr [nBufferW],eax
mov ebx,dword ptr [RLELen]
add ebx,esi
_T1Lp1: mov edx,dword ptr [nCelW]
_T1Lp2: xor eax,eax // Load control byte
lodsb
or al,al
js _T1J
sub edx,eax
mov ecx,dword ptr [glClipY]
cmp edi,ecx
jb _T1C1
add esi,eax
add edi,eax
jmp _T1x
_T1C1: sub ecx,768
cmp edi,ecx
jae _T1C2
mov ecx,eax
mov ah,byte ptr [ocolor]
_T1Lp3: lodsb
or al,al
jz _T1Skip
mov byte ptr [edi-768],ah
mov byte ptr [edi-1],ah
mov byte ptr [edi+1],ah
mov byte ptr [edi+768],ah
_T1Skip: inc edi
loop _T1Lp3
jmp _T1x
_T1C2: mov ecx,eax
mov ah,byte ptr [ocolor]
_T1Lp4: lodsb
or al,al
jz _T1Skip2
mov byte ptr [edi-768],ah
mov byte ptr [edi-1],ah
mov byte ptr [edi+1],ah
_T1Skip2: inc edi
loop _T1Lp4
_T1x: or edx,edx
jz _T1Nxt
jmp _T1Lp2
_T1J: neg al // Do jump
add edi,eax
sub edx,eax
jnz _T1Lp2
_T1Nxt: sub edi,dword ptr [nBufferW]
cmp ebx,esi
jnz _T1Lp1
} // end of asm block
}
}
/*-----------------------------------------------------------------------*
**-----------------------------------------------------------------------*/
#if !RLE_DRAW
void TranslateCels(byte *p, byte *ttbl, int nf)
{
int j;
app_assert(p != NULL);
app_assert(ttbl != NULL);
for (j = 1; j <= nf; j++) {
__asm {
mov ebx,dword ptr [p]
mov eax,dword ptr [j]
shl eax,2
add ebx,eax
mov esi,dword ptr [p]
add esi,dword ptr [ebx]
add esi,10 // Source
mov edx,dword ptr [ebx+4] // Size
sub edx,dword ptr [ebx]
sub edx,10
mov edi,esi // Dest
mov ebx,dword ptr [ttbl] // Color conversion table
_TLp1: xor eax,eax // Load control byte
lodsb
stosb
dec edx
jz _TNxt
or al,al
js _TLp1
sub edx,eax
mov ecx,eax
_TLp2: lodsb
xlatb
stosb
loop _TLp2
or edx,edx
jnz _TLp1
_TNxt: nop
}
}
}
#endif
/*-----------------------------------------------------------------------**
** Plot a point
**-----------------------------------------------------------------------*/
void DrawPoint(int x, int y, byte c)
{
BYTE *pTo;
app_assert(gpBuffer);
if ((y < 0) || (y >= 640)) return;
if ((x < 64) || (x >= 704)) return;
pTo = gpBuffer + nBuffWTbl[y] + x;
__asm {
mov edi, dword ptr [pTo];
cmp edi, dword ptr [glClipY]
jae _NoD
mov al, byte ptr [c]
mov byte ptr [edi], al
_NoD:
}
}
/*-----------------------------------------------------------------------**
** For line drawing
**-----------------------------------------------------------------------*/
#define dlswap(a,b) { a^=b; b^=a; a^=b; }
#define absolute(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1)))
int dlreverse;
byte dlcolor;
BOOL dlclipflag;
/*-----------------------------------------------------------------------**
** plot for line drawing (temp probably, will write in asm)
**-----------------------------------------------------------------------*/
void plot(int x, int y)
{
BYTE *pTo;
app_assert(gpBuffer);
if (dlreverse) {
if (dlclipflag) {
if ((x < 0) || (x >= 640)) return;
if ((y < 64) || (y >= 704)) return;
}
pTo = gpBuffer + nBuffWTbl[x] + y;
} else {
if (dlclipflag) {
if ((y < 0) || (y >= 640)) return;
if ((x < 64) || (x >= 704)) return;
}
pTo = gpBuffer + nBuffWTbl[y] + x;
}
__asm {
mov edi, dword ptr [pTo];
cmp edi,dword ptr [glClipY]
jae _NoD
mov al,byte ptr [dlcolor]
mov byte ptr [edi],al
_NoD:
}
}
/*-----------------------------------------------------------------------**
** line drawing ctrl (temp probably, will write in asm)
**-----------------------------------------------------------------------*/
void DrawLine(int a1, int b1, int a2, int b2, byte clr)
{
int dx, dy, incr1, incr2, D, x, y, _xend, c, pixels_left;
int x1, y1;
int sign_x, sign_y, step, i;
dlcolor = clr;
// Test clipping bounds to see if we even need to test on the pixel level
dlclipflag = FALSE;
if ((a1 < 64) || (a1 >= 704)) dlclipflag = TRUE;
if ((a2 < 64) || (a2 >= 704)) dlclipflag = TRUE;
if ((b1 < 160) || (b1 >= 512)) dlclipflag = TRUE;
if ((b2 < 160) || (b2 >= 512)) dlclipflag = TRUE;
dx = absolute(a2, a1, sign_x);
dy = absolute(b2, b1, sign_y);
if (sign_x == sign_y)
step = 1;
else
step = -1;
if (dy > dx) {
dlswap(a1, b1);
dlswap(a2, b2);
dlswap(dx, dy);
dlreverse = 1;
} else
dlreverse = 0;
if (a1 > a2) {
x = a2;
y = b2;
x1 = a1;
y1 = b1;
} else {
x = a1;
y = b1;
x1 = a2;
y1 = b2;
}
_xend = (dx - 1) / 4;
pixels_left = (dx - 1) % 4;
plot(x, y);
plot(x1, y1);
incr2 = 4 * dy - 2 * dx;
if (incr2 < 0) {
c = 2 * dy;
incr1 = 2 * c;
D = incr1 - dx;
for (i = 0; i < _xend; i++) {
++x;
--x1;
if (D < 0) {
plot(x, y);
plot(++x, y);
plot(x1, y1);
plot(--x1, y1);
D += incr1;
} else {
if (D < c) {
plot(x, y);
plot(++x, y += step);
plot(x1, y1);
plot(--x1, y1 -= step);
} else {
plot(x, y += step);
plot(++x, y);
plot(x1, y1 -= step);
plot(--x1, y1);
}
D += incr2;
}
}
if (pixels_left) {
if (D < 0) {
plot(++x, y);
if (pixels_left > 1)
plot(++x, y);
if (pixels_left > 2)
plot(--x1, y1);
} else {
if (D < c) {
plot(++x, y);
if (pixels_left > 1)
plot(++x, y += step);
if (pixels_left > 2)
plot(--x1, y1);
} else {
plot(++x, y += step);
if (pixels_left > 1)
plot(++x, y);
if (pixels_left > 2)
plot(--x1, y1 -= step);
}
}
}
} else {
c = 2 * (dy - dx);
incr1 = 2 * c;
D = incr1 + dx;
for (i = 0; i < _xend; i++) {
++x;
--x1;
if (D > 0) {
plot(x, y += step);
plot(++x, y += step);
plot(x1, y1 -= step);
plot(--x1, y1 -= step);
D += incr1;
} else {
if (D < c) {
plot(x, y);
plot(++x, y += step);
plot(x1, y1);
plot(--x1, y1 -= step);
} else {
plot(x, y += step);
plot(++x, y);
plot(x1, y1 -= step);
plot(--x1, y1);
}
D += incr2;
}
}
if (pixels_left) {
if (D > 0) {
plot(++x, y += step);
if (pixels_left > 1)
plot(++x, y += step);
if (pixels_left > 2)
plot(--x1, y1 -= step);
} else {
if (D < c) {
plot(++x, y);
if (pixels_left > 1)
plot(++x, y += step);
if (pixels_left > 2)
plot(--x1, y1);
} else {
plot(++x, y += step);
if (pixels_left > 1)
plot(++x, y);
if (pixels_left > 2) {
if (D > c)
plot(--x1, y1 -= step);
else
plot(--x1, y1);
}
}
}
}
}
}
/*-----------------------------------------------------------------------**
**-----------------------------------------------------------------------*/
int GetDirection(int x1, int y1, int x2, int y2)
{
int mx, my, md;
mx = x2-x1;
my = y2-y1;
if (mx >= 0) {
if (my >= 0) {
md = 0;
if ((mx << 1) < my) md = 1;
if ((my << 1) < mx) md = 7;
} else {
md = 6;
my = -my;
if ((mx << 1) < my) md = 5;
if ((my << 1) < mx) md = 7;
}
} else {
if (my >= 0) {
md = 2;
mx = -mx;
if ((mx << 1) < my) md = 1;
if ((my << 1) < mx) md = 3;
} else {
md = 4;
mx = -mx;
my = -my;
if ((mx << 1) < my) md = 5;
if ((my << 1) < mx) md = 3;
}
}
return (md);
}
int SeedCount;
long orgseed;
//***************************************************************************
//***************************************************************************
void SetRndSeed(long s) {
sglGameSeed = s;
orgseed = s; //debug
SeedCount = 0;
}
//***************************************************************************
//***************************************************************************
long GetRndSeed() {
SeedCount++;
static const DWORD INCREMENT = 1;
static const DWORD MULTIPLIER = 0x015a4e35L;
sglGameSeed = MULTIPLIER * sglGameSeed + INCREMENT;
return abs(sglGameSeed);
}
//***************************************************************************
//***************************************************************************
long random(byte idx,long v) {
if (v <= 0) return 0;
// high order bits are more "random" than low order bits
if (v < 0x0ffff) return (GetRndSeed() >> 16) % v;
return GetRndSeed() % v;
}
//******************************************************************
// memory manager vars
//******************************************************************
#define TRACK_MEM_BLOCKS 1 // 0 in final
#if DEBUG_MEM
#define DUMP_MEM_BLOCKS 1 // 0 in final
#else
#define DUMP_MEM_BLOCKS 0 // 0 in final
#endif
#ifdef NDEBUG
#undef TRACK_MEM_BLOCKS
#undef DUMP_MEM_BLOCKS
#define TRACK_MEM_BLOCKS 0
#define DUMP_MEM_BLOCKS 0
#endif
#if DEBUG_MEM && TRACK_MEM_BLOCKS
typedef struct TMemType {
struct TMemType * pNext;
DWORD dwSig;
// current amount of memory allocated with this signature
DWORD dwCurrAmount;
// maximum amount ever allocated for this signature
DWORD dwMostEver;
// amount of memory allocated to this signature when the
// program had its maximum memory allocated
DWORD dwAmountAtMax;
} TMemType;
typedef union TPrintSig {
DWORD dwSig;
char szSig[sizeof(DWORD) + 1];
} TPrintSig;
static DWORD sgdwCurrAllocated = 0;
static DWORD sgdwHighestAllocated = 0;
static TMemType * sgpMemTypeHead = NULL;
typedef struct TMemBlockHdr {
DWORD dwBytes;
DWORD dwSig;
DWORD dwCheck1;
DWORD dwCheck2;
} TMemBlockHdr;
typedef struct TMemBlockFtr {
DWORD dwCheck3;
DWORD dwCheck4;
} TMemBlockFtr;
#define MEM_CHECK1 0x497208ab
#define MEM_CHECK2 0x127834dc
#define MEM_CHECK3 0x023481a9
#define MEM_CHECK4 0xfcb87147
#endif
// serialize access to memory manager -- according to Mike O'Brien,
// malloc does not serialize access in all cases in NT 4.0 even
// when using LIBCMT.LIB. Therefore, don't trust *any* memory munger
static CCritSect sgMemCrit;
//******************************************************************
//******************************************************************
#if DEBUG_MEM && TRACK_MEM_BLOCKS
static const char * sig_to_string(DWORD dwSig,TPrintSig * pSig) {
__asm mov eax, dwSig
__asm bswap eax
__asm mov dwSig, eax
pSig->dwSig = dwSig;
pSig->szSig[sizeof(DWORD)] = 0;
return pSig->szSig;
}
#endif
//******************************************************************
//******************************************************************
void mem_cleanup(BOOL bNormalExit) {
#if DEBUG_MEM && TRACK_MEM_BLOCKS
// serialize access to memory manager -- according to Mike O'Brien,
// malloc does not serialize access in all cases in NT 4.0 even
// when using LIBCMT.LIB. Therefore, don't trust *any* memory munger
sgMemCrit.Enter();
FILE * f = NULL;
#if DUMP_MEM_BLOCKS
if (bNormalExit) f = fopen("c:\\memdump.txt","wb");
#endif
if (f) {
fprintf(
f,
"sig most ever amount at max at end of game\r\n"
"------------------------------------------------------\r\n"
);
}
TMemType * pNext = NULL;
for (TMemType * pType = sgpMemTypeHead; pType; pType = pNext) {
if (f) {
TPrintSig sig;
fprintf(
f,
"%4s 0x%08x 0x%08x %8dk %8d\r\n",
sig_to_string(pType->dwSig,&sig),
pType->dwMostEver,
pType->dwAmountAtMax,
pType->dwAmountAtMax / 1024,
pType->dwCurrAmount
);
}
pNext = pType->pNext;
SMemFree(pType,__FILE__,__LINE__);
}
if (f) {
fprintf(
f,
"------------------------------------------------\r\n"
"max allocated 0x%08x %8dk\r\n",
sgdwHighestAllocated,
sgdwHighestAllocated / 1024
);
fclose(f);
}
sgMemCrit.Leave();
#endif
}
//******************************************************************
//******************************************************************
#if DEBUG_MEM && TRACK_MEM_BLOCKS
static TMemType * find_mem_type_by_sig(DWORD dwSig) {
// find existing block with signature
for (TMemType * pType = sgpMemTypeHead; pType; pType = pType->pNext)
if (pType->dwSig == dwSig) return pType;
// create a new signature block
pType = (TMemType *) SMemAlloc(sizeof(TMemType),__FILE__,__LINE__);
ZeroMemory(pType,sizeof TMemType);
pType->dwSig = dwSig;
// link to list
pType->pNext = sgpMemTypeHead;
sgpMemTypeHead = pType;
// return new signature block
return pType;
}
#endif
//******************************************************************
//******************************************************************
#if DEBUG_MEM && TRACK_MEM_BLOCKS
static void mem_addto_type(TMemType * pType,DWORD dwBytes) {
// fixup memory for this type
pType->dwCurrAmount += dwBytes;
if (pType->dwMostEver < pType->dwCurrAmount)
pType->dwMostEver = pType->dwCurrAmount;
// fixup memory for all types
sgdwCurrAllocated += dwBytes;
if (sgdwHighestAllocated < sgdwCurrAllocated) {
sgdwHighestAllocated = sgdwCurrAllocated;
for (TMemType * pHigh = sgpMemTypeHead; pHigh; pHigh = pHigh->pNext)
pHigh->dwAmountAtMax = pHigh->dwCurrAmount;
}
}
#endif
//******************************************************************
//******************************************************************
#if DEBUG_MEM && TRACK_MEM_BLOCKS
static const char * mem_freefrom_type(TMemType * pType,DWORD dwBytes) {
// fixup memory for this type
DWORD dwTemp = pType->dwCurrAmount;
pType->dwCurrAmount -= dwBytes;
if (pType->dwCurrAmount > dwTemp)
return "memory block signature underflow: %s";
// fixup global memory indicator
dwTemp = sgdwCurrAllocated;
sgdwCurrAllocated -= dwBytes;
if (sgdwCurrAllocated > dwTemp)
return "memory free underflow";
return NULL;
}
#endif
//******************************************************************
//******************************************************************
#if DEBUG_MEM
void mem_use_sig(DWORD dwSig,DWORD dwBytes) {
#if TRACK_MEM_BLOCKS
TMemType * pType = find_mem_type_by_sig(dwSig);
if (! pType) ErrorDlg(IDD_MEM_ERR,GetLastError(),__FILE__,__LINE__);
mem_addto_type(pType,dwBytes);
#endif
}
//******************************************************************
//******************************************************************
void mem_unuse_sig(DWORD dwSig,DWORD dwBytes) {
#if TRACK_MEM_BLOCKS
const char * pszErr_s;
TMemType * pType = find_mem_type_by_sig(dwSig);
if (pType)
pszErr_s = mem_freefrom_type(pType,dwBytes);
else
pszErr_s = "Bad signature unused: %s";
TPrintSig sig;
if (pszErr_s) app_fatal(pszErr_s,sig_to_string(dwSig,&sig));
#endif
}
#endif
//******************************************************************
//******************************************************************
#if DEBUG_MEM
BYTE * mem_malloc_dbg(DWORD dwBytes,DWORD dwSig,DWORD dwLine,const TCHAR * pszFile)
#else
BYTE * DiabloAllocPtr(DWORD dwBytes)
#endif
{
// serialize access to memory manager -- according to Mike O'Brien,
// malloc does not serialize access in all cases in NT 4.0 even
// when using LIBCMT.LIB. Therefore, don't trust *any* memory munger
sgMemCrit.Enter();
// allocate memory block
#if DEBUG_MEM && TRACK_MEM_BLOCKS
DWORD dwAlloc = dwBytes + sizeof(TMemBlockHdr) + sizeof(TMemBlockFtr);
BYTE * rv = (BYTE *) SMemAlloc(dwAlloc,pszFile,dwLine);
#elif DEBUG_MEM
BYTE * rv = (BYTE *) SMemAlloc(dwBytes,pszFile,dwLine);
#else
BYTE * rv = (BYTE *) SMemAlloc(dwBytes,__FILE__,__LINE__);
#endif
#if DEBUG_MEM && TRACK_MEM_BLOCKS
if (rv) {
TMemType * pType = find_mem_type_by_sig(dwSig);
if (pType) {
mem_addto_type(pType,dwBytes);
TMemBlockHdr * pHdr = (TMemBlockHdr *) rv;
rv += sizeof(TMemBlockHdr);
TMemBlockFtr * pFtr = (TMemBlockFtr *) (rv + dwBytes);
pHdr->dwSig = dwSig;
pHdr->dwBytes = dwBytes;
pHdr->dwCheck1 = MEM_CHECK1;
pHdr->dwCheck2 = MEM_CHECK2;
pFtr->dwCheck3 = MEM_CHECK3;
pFtr->dwCheck4 = MEM_CHECK4;
}
else {
SMemFree(rv,__FILE__,__LINE__);
rv = NULL;
}
}
#endif
sgMemCrit.Leave();
#if DEBUG_MEM
if (! rv) ErrorDlg(IDD_MEM_ERR,GetLastError(),pszFile,dwLine);
#else
if (! rv) ErrorDlg(IDD_MEM_ERR,GetLastError(),__FILE__,__LINE__);
#endif
return rv;
}
//******************************************************************
//******************************************************************
#if DEBUG_MEM
void mem_free_dbg(void * p,DWORD dwLine,const TCHAR * pszFile)
#else
void mem_free_dbg(void * p)
#endif
{
if (! p) return;
// serialize access to memory manager -- according to Mike O'Brien,
// malloc does not serialize access in all cases in NT 4.0 even
// when using LIBCMT.LIB. Therefore, don't trust *any* memory munger
sgMemCrit.Enter();
// free memory block
#if DEBUG_MEM && TRACK_MEM_BLOCKS
const char * pszErr_s = NULL;
TMemBlockHdr * pHdr = (TMemBlockHdr *) ((BYTE *) p - sizeof(TMemBlockHdr));
DWORD dwSig = pHdr->dwSig; // assume signature is valid
if (pHdr->dwCheck1 != MEM_CHECK1 || pHdr->dwCheck2 != MEM_CHECK2)
pszErr_s = "Memory block header corruption: %s";
else {
// Now change it so if there is duplicate free we'll catch it.
pHdr->dwCheck1 = 0xDEADC0DE;
pHdr->dwCheck2 = 0xDEADC0DE;
}
if (! pszErr_s) {
TMemBlockFtr * pFtr = (TMemBlockFtr *) ((BYTE *) p + pHdr->dwBytes);
if (pFtr->dwCheck3 != MEM_CHECK3 || pFtr->dwCheck4 != MEM_CHECK4)
pszErr_s = "Memory block footer corruption: %s";
else {
// Now change it so if there is duplicate free we'll catch it.
pFtr->dwCheck3 = 0xDEADC0DE;
pFtr->dwCheck4 = 0xDEADC0DE;
}
}
if (! pszErr_s) {
TMemType * pType = find_mem_type_by_sig(dwSig);
if (pType)
pszErr_s = mem_freefrom_type(pType,pHdr->dwBytes);
else
pszErr_s = "Attempt to free memory with unknown signature %s";
}
p = (void *) pHdr;
SMemFree(p,pszFile,dwLine);
#elif DEBUG_MEM
SMemFree(p,pszFile,dwLine);
#else
SMemFree(p,__FILE__,__LINE__);
#endif
sgMemCrit.Leave();
// display any error which occurred -- outside critical section
#if DEBUG_MEM && TRACK_MEM_BLOCKS
if (pszErr_s) {
TPrintSig sig;
app_fatal(pszErr_s,sig_to_string(dwSig,&sig));
}
#endif
}
//******************************************************************
//******************************************************************
#if DEBUG_MEM
BYTE * load_file_dbg(const char * pszName,DWORD * pdwFileLen,DWORD dwSig,DWORD dwLine,const TCHAR * pszFile)
#else
BYTE * LoadFileInMem(const char * pszName,DWORD * pdwFileLen)
#endif
{
HSFILE hFile;
#if DEBUG_MEM
if (! pszName) app_fatal("LoadFileInMem: %s:%d",pszFile,dwLine);
#else
app_assert(pszName);
#endif
patSFileOpenFile(pszName,&hFile);
DWORD dwFileLen = patSFileGetFileSize(hFile,NULL);
if (pdwFileLen) *pdwFileLen = dwFileLen;
if (! dwFileLen) app_fatal("Zero length SFILE:\n%s",pszName);
#if DEBUG_MEM
BYTE * pbMem = mem_malloc_dbg(dwFileLen,dwSig,dwLine,pszFile);
#else
BYTE * pbMem = DiabloAllocPtr(dwFileLen);
#endif
patSFileReadFile(hFile,pbMem,dwFileLen);
patSFileCloseFile(hFile);
return pbMem;
}
//******************************************************************
//******************************************************************
DWORD LoadFileWithMem(const char * pszName,BYTE * pbMem) {
HSFILE hFile;
app_assert(pszName);
if (! pbMem) app_fatal("LoadFileWithMem(NULL):\n%s",pszName);
patSFileOpenFile(pszName,&hFile);
DWORD dwFileLen = patSFileGetFileSize(hFile,NULL);
if (! dwFileLen) app_fatal("Zero length SFILE:\n%s",pszName);
patSFileReadFile(hFile,pbMem,dwFileLen);
patSFileCloseFile(hFile);
return dwFileLen;
}
//*************************************************************
// RLE Unitdraw Code
//*************************************************************
#if RLE_DRAW
#define MAX_RLE_COPY 65
static int sgnWidth; //used in both RLEDrawLitUnit f'cns
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void TranslateCels(BYTE *p, BYTE *ttbl, int nFrames)
{
app_assert(p != NULL);
app_assert(ttbl != NULL);
int nDataSize;
BYTE * pImage;
char bBlock;
for (int j = 1; j <= nFrames; j++) {
pImage = p + ((DWORD*)p)[j] + sizeof(WORD)*5;
nDataSize = ((DWORD*)p)[j+1] - ((DWORD*)p)[j] - sizeof(WORD)*5;
while (nDataSize) {
bBlock = *pImage++;
nDataSize--;
app_assert(nDataSize >= 0);
//check for skip
if (bBlock >= 0)
continue;
bBlock = -bBlock;
//check for run
if (bBlock > MAX_RLE_COPY) {
bBlock -= MAX_RLE_COPY;
nDataSize--;
app_assert(nDataSize >= 0);
*pImage = ttbl[*pImage++];
continue;
}
//do copy
nDataSize -= bBlock;
app_assert(nDataSize >= 0);
while (bBlock--)
*pImage = ttbl[*pImage++];
}
}
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
static void RLEDrawUnit(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth) {
_asm {
//**** Assumes _fastcall convention!! ****
push ebx
push esi
push edi
//eax - copy/run/skip block size
//ebx - pixels left to draw this line
//ecx - bytes of RLE data left
//edx - scratch
//esi - source RLE data
//edi - destination buffer
mov esi, edx
mov edi, ecx
xor eax, eax
mov ebx, [nWidth]
mov ecx, [nDataSize]
Loop1:
mov al,[esi]
inc esi
dec ecx
//negative packets are copy/runs, nonnegative are skips
test al,al
jns SkipLoop
neg al
//packets larger than MAX_RLE_COPY are runs, rest are copies
cmp al,MAX_RLE_COPY
jle Copy
//get size of run
sub al,MAX_RLE_COPY
dec ecx
//write out run packet
mov dl,[esi]
inc esi
sub ebx,eax
RunMemset:
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz RunMemset
jmp EOLTest
Copy:
//write out copy packet
sub ecx,eax
sub ebx,eax
CopyMemcpy:
mov dl,[esi]
inc esi
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz CopyMemcpy
EOLTest:
//if at end of line, move dst and reset linecounter
test ebx,ebx
jnz NextBlock
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
jmp NextBlock
SkipLoop:
//does skip extend past end of this line?
cmp eax,ebx
jle SingleLineSkip
mov edx,ebx
add edi,ebx
sub eax,ebx
jmp SkipMem
SingleLineSkip:
mov edx,eax
add edi,eax
xor eax,eax
SkipMem:
//if at end of line, move dst and reset linecounter
sub ebx,edx
jnz SkipNotEOL
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
SkipNotEOL:
//have we finished off this block? (skips may span multiple lines)
test eax,eax
jnz SkipLoop
NextBlock:
test ecx,ecx
jnz Loop1
pop edi
pop esi
pop ebx
}
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
static void RLEDrawOutline(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE bOutLineColor) {
_asm {
//**** Assumes _fastcall convention!! ****
push ebx
push esi
push edi
//eax - copy/run/skip block size
//ebx - pixels left to draw this line
//ecx - bytes of RLE data left
//dl - outline color
//dh - scratch
//esi - source RLE data
//edi - destination buffer
mov esi,edx
mov edi,ecx
xor eax,eax
mov ebx,[nWidth]
xor edx,edx
mov ecx,[nDataSize]
mov dl, [bOutLineColor]
Loop1:
mov al,[esi]
inc esi
dec ecx
//negative packets are copy/runs, nonnegative are skips
test al,al
jns SkipLoop
neg al
//packets larger than MAX_RLE_COPY are runs, rest are copies
cmp al,MAX_RLE_COPY
jle Copy
//get size of run
sub al,MAX_RLE_COPY
dec ecx
//no outline for color zero (shadows)
mov dh,[esi]
inc esi
test dh,dh
jz SkipLoop
//write outline for run packet
mov [edi-1],dl //outline pixel left
sub ebx,eax
mov [edi+eax],dl //and right of run
RunMemset:
mov [edi-BUFFERX],dl //outline above
mov [edi+BUFFERX],dl //and below run
dec eax
lea edi,[edi+1]
jnz RunMemset
jmp EOLCheck
Copy:
sub ecx,eax
sub ebx,eax
CopyMemcpy:
mov dh,[esi]
inc esi
//don't draw outline for shadow pixels
test dh,dh
jz SkipPixel
mov [edi-1],dl //outline pixel left
mov [edi+1],dl //and right of copy
mov [edi-BUFFERX],dl //outline above
mov [edi+BUFFERX],dl //and below copy
SkipPixel:
dec eax
lea edi,[edi+1]
jnz CopyMemcpy
EOLCheck:
//if at end of line, move dst and reset linecounter
test ebx,ebx
jnz NextBlock
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
jmp NextBlock
SkipLoop:
cmp eax,ebx
jle SingleLineSkip
mov edx,ebx
add edi,ebx
sub eax,ebx
jmp SkipMem
SingleLineSkip:
mov edx,eax
add edi,eax
xor eax,eax
SkipMem:
//if at end of line, move dst and reset linecounter
sub ebx,edx
jnz SkipNotEOL
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
SkipNotEOL:
//have we finished off this block?
test eax,eax
jnz SkipLoop
mov dl, [bOutLineColor]
NextBlock:
test ecx,ecx
jnz Loop1
pop edi
pop esi
pop ebx
}
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
static void RLEDrawLitUnit(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE * pLightTable) {
_asm {
//**** Assumes _fastcall convention!! ****
push ebx
push esi
push edi
//eax - copy/run/skip block size
//ebx - pixels left to draw this line
//ecx - bytes of RLE data left
//edx - scratch
//ebp - light table pointer
//esi - source RLE data
//edi - destination buffer
mov esi, edx
mov edi, ecx
mov ebx, [nWidth]
mov ecx, [nDataSize]
mov edx, [pLightTable]
push ebp
mov [sgnWidth],ebx //cheesy way to avoid using ebp
mov ebp,edx
xor eax,eax
xor edx,edx
Loop1:
mov al,[esi]
inc esi
dec ecx
//negative packets are copy/runs, nonnegative are skips
test al,al
jns SkipLoop
neg al
//packets larger than MAX_RLE_COPY are runs, rest are copies
cmp al,MAX_RLE_COPY
jle Copy
//get size of run
sub al,MAX_RLE_COPY
dec ecx
//write run packet
sub ebx,eax
mov dl,[esi]
inc esi
mov dl,[ebp+edx]
RunMemset:
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz RunMemset
jmp EOLCheck
Copy:
//write copy packet
sub ecx,eax
sub ebx,eax
CopyMemcpy:
mov dl,[esi]
inc esi
mov dl,[ebp+edx]
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz CopyMemcpy
EOLCheck:
//if at end of line, move dst and reset linecounter
test ebx,ebx
jnz NextBlock
mov ebx,[sgnWidth]
sub edi,BUFFERX
sub edi,ebx
jmp NextBlock
SkipLoop:
cmp eax,ebx
jle SingleLineSkip
mov edx,ebx
add edi,ebx
sub eax,ebx
jmp SkipMem
SingleLineSkip:
mov edx,eax
add edi,eax
xor eax,eax
SkipMem:
//if at end of line, move dst and reset linecounter
sub ebx,edx
jnz SkipNotEOL
mov ebx,[sgnWidth]
sub edi,BUFFERX
sub edi,ebx
SkipNotEOL:
//have we finished off this block?
test eax,eax
jnz SkipLoop
NextBlock:
test ecx,ecx
jnz Loop1
pop ebp
pop edi
pop esi
pop ebx
}
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
static void RLEDrawUnitClipped(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth) {
_asm {
//**** Assumes _fastcall convention!! ****
push ebx
push esi
push edi
//eax - copy/run/skip block size
//ebx - pixels left to draw this line
//ecx - bytes of RLE data left
//edx - scratch
//esi - source RLE data
//edi - destination buffer
mov esi, edx
mov edi, ecx
xor eax, eax
mov ebx, [nWidth]
mov ecx, [nDataSize]
Loop1:
mov al,[esi]
inc esi
dec ecx
//negative packets are copy/runs, nonnegative are skips
test al,al
jns SkipLoop
neg al
//packets larger than MAX_RLE_COPY are runs, rest are copies
cmp al,MAX_RLE_COPY
jle Copy
//get size of run
sub al,MAX_RLE_COPY
dec ecx
//prepare to write out run packet
mov dl,[esi]
inc esi
//off end of buffer?
cmp edi,[glClipY]
jge SkipLoop
sub ebx,eax
RunMemset:
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz RunMemset
jmp EOLTest
Copy:
//prepare to write out copy packet
sub ecx,eax
//off end of buffer?
cmp edi,[glClipY]
jl PreCopyMemcpy
add esi,eax
jmp SkipLoop
PreCopyMemcpy:
sub ebx,eax
CopyMemcpy:
mov dl,[esi]
inc esi
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz CopyMemcpy
EOLTest:
//if at end of line, move dst and reset linecounter
test ebx,ebx
jnz NextBlock
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
jmp NextBlock
SkipLoop:
//does skip extend past end of this line?
cmp eax,ebx
jle SingleLineSkip
mov edx,ebx
add edi,ebx
sub eax,ebx
jmp SkipMem
SingleLineSkip:
mov edx,eax
add edi,eax
xor eax,eax
SkipMem:
//if at end of line, move dst and reset linecounter
sub ebx,edx
jnz SkipNotEOL
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
SkipNotEOL:
//have we finished off this block? (skips may span multiple lines)
test eax,eax
jnz SkipLoop
NextBlock:
test ecx,ecx
jnz Loop1
pop edi
pop esi
pop ebx
}
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
static void RLEDrawOutlineClipped(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE bOutLineColor) {
_asm {
//**** Assumes _fastcall convention!! ****
push ebx
push esi
push edi
//eax - copy/run/skip block size
//ebx - pixels left to draw this line
//ecx - bytes of RLE data left
//dl - outline color
//dh - scratch
//esi - source RLE data
//edi - destination buffer
mov esi,edx
mov edi,ecx
xor eax,eax
mov ebx,[nWidth]
xor edx,edx
mov ecx,[nDataSize]
mov dl, [bOutLineColor]
Loop1:
mov al,[esi]
inc esi
dec ecx
//negative packets are copy/runs, nonnegative are skips
test al,al
jns SkipLoop
neg al
//packets larger than MAX_RLE_COPY are runs, rest are copies
cmp al,MAX_RLE_COPY
jle Copy
//get size of run
sub al,MAX_RLE_COPY
dec ecx
//no outline for color zero (shadows)
mov dh,[esi]
inc esi
test dh,dh
jz SkipLoop
//off end of buffer?
cmp edi,[glClipY]
jge SkipLoop
//write outline for run packet
mov [edi-1],dl //outline pixel left
sub ebx,eax
mov [edi+eax],dl //and right of run
RunMemset:
mov [edi-BUFFERX],dl //outline above
mov [edi+BUFFERX],dl //and below run
dec eax
lea edi,[edi+1]
jnz RunMemset
jmp EOLCheck
Copy:
sub ecx,eax
//off end of buffer?
cmp edi,[glClipY]
jl PreCopyMemcpy
add esi,eax
jmp SkipLoop
PreCopyMemcpy:
sub ebx,eax
CopyMemcpy:
mov dh,[esi]
inc esi
//don't draw outline for shadow pixels
test dh,dh
jz SkipPixel
mov [edi-1],dl //outline pixel left
mov [edi+1],dl //and right of copy
mov [edi-BUFFERX],dl //outline above
mov [edi+BUFFERX],dl //and below copy
SkipPixel:
dec eax
lea edi,[edi+1]
jnz CopyMemcpy
EOLCheck:
//if at end of line, move dst and reset linecounter
test ebx,ebx
jnz NextBlock
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
jmp NextBlock
SkipLoop:
cmp eax,ebx
jle SingleLineSkip
mov edx,ebx
add edi,ebx
sub eax,ebx
jmp SkipMem
SingleLineSkip:
mov edx,eax
add edi,eax
xor eax,eax
SkipMem:
//if at end of line, move dst and reset linecounter
sub ebx,edx
jnz SkipNotEOL
mov ebx,[nWidth]
sub edi,BUFFERX
sub edi,ebx
SkipNotEOL:
//have we finished off this block?
test eax,eax
jnz SkipLoop
mov dl, [bOutLineColor]
NextBlock:
test ecx,ecx
jnz Loop1
pop edi
pop esi
pop ebx
}
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
static void RLEDrawLitUnitClipped(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE * pLightTable) {
_asm {
//**** Assumes _fastcall convention!! ****
push ebx
push esi
push edi
//eax - copy/run/skip block size
//ebx - pixels left to draw this line
//ecx - bytes of RLE data left
//edx - scratch
//ebp - light table pointer
//esi - source RLE data
//edi - destination buffer
mov esi, edx
mov edi, ecx
mov ebx, [nWidth]
mov ecx, [nDataSize]
mov edx, [pLightTable]
push ebp
mov [sgnWidth],ebx //cheesy way to avoid using ebp
mov ebp,edx
xor eax,eax
xor edx,edx
Loop1:
mov al,[esi]
inc esi
dec ecx
//negative packets are copy/runs, nonnegative are skips
test al,al
jns SkipLoop
neg al
//packets larger than MAX_RLE_COPY are runs, rest are copies
cmp al,MAX_RLE_COPY
jle Copy
//get size of run
sub al,MAX_RLE_COPY
dec ecx
//prepare to write run packet
mov dl,[esi]
inc esi
mov dl,[ebp+edx]
//off end of buffer?
cmp edi,[glClipY]
jge SkipLoop
sub ebx,eax
RunMemset:
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz RunMemset
jmp EOLCheck
Copy:
//write copy packet
sub ecx,eax
//off end of buffer?
cmp edi,[glClipY]
jl PreCopyMemcpy
add esi,eax
jmp SkipLoop
PreCopyMemcpy:
sub ebx,eax
CopyMemcpy:
mov dl,[esi]
inc esi
mov dl,[ebp+edx]
mov [edi],dl
dec eax
lea edi,[edi+1]
jnz CopyMemcpy
EOLCheck:
//if at end of line, move dst and reset linecounter
test ebx,ebx
jnz NextBlock
mov ebx,[sgnWidth]
sub edi,BUFFERX
sub edi,ebx
jmp NextBlock
SkipLoop:
cmp eax,ebx
jle SingleLineSkip
mov edx,ebx
add edi,ebx
sub eax,ebx
jmp SkipMem
SingleLineSkip:
mov edx,eax
add edi,eax
xor eax,eax
SkipMem:
//if at end of line, move dst and reset linecounter
sub ebx,edx
jnz SkipNotEOL
mov ebx,[sgnWidth]
sub edi,BUFFERX
sub edi,ebx
SkipNotEOL:
//have we finished off this block?
test eax,eax
jnz SkipLoop
NextBlock:
test ecx,ecx
jnz Loop1
pop ebp
pop edi
pop esi
pop ebx
}
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
static BYTE LevelUnitPixel(const BYTE *row, int x, int width, BYTE *pLightTable)
{
BYTE pixel, src;
int left, right, curr, nearAvg, darkest;
src = row[x];
if (src == 0)
return 0;
pixel = gbLevelUnitContrastTable[src];
if (pLightTable != NULL)
pixel = pLightTable[pixel];
if (x <= 0 || x + 1 >= width)
return pixel;
left = gbLevelUnitLumaTable[row[x - 1]];
right = gbLevelUnitLumaTable[row[x + 1]];
curr = gbLevelUnitLumaTable[src];
nearAvg = (left + right) >> 1;
darkest = (left < right) ? left : right;
if (nearAvg - curr > 10)
return gbLevelUnitAoTable[pixel];
if (curr - darkest > 16 && curr < 230)
return gbLevelUnitAoTable[pixel];
if (curr - nearAvg > 18)
return gbLevelUnitSharpenLightTable[pixel];
return pixel;
}
static BOOL UseLevelUnitEnhance();
static void RLEDrawEnhancedUnit(BYTE *pDst, BYTE *pRLEData, int nDataSize, int nWidth, BYTE *pLightTable, BOOL clipped)
{
BYTE row[BUFFERX];
BYTE mask[BUFFERX];
BYTE *pSrc, *pRowDst;
int remaining, rowLeft, x, i;
signed char packet;
BYTE pixel;
int count;
if (nWidth <= 0 || nWidth > BUFFERX) {
if (pLightTable != NULL) {
if (clipped)
RLEDrawLitUnitClipped(pDst, pRLEData, nDataSize, nWidth, pLightTable);
else
RLEDrawLitUnit(pDst, pRLEData, nDataSize, nWidth, pLightTable);
}
else {
if (clipped)
RLEDrawUnitClipped(pDst, pRLEData, nDataSize, nWidth);
else
RLEDrawUnit(pDst, pRLEData, nDataSize, nWidth);
}
return;
}
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
pSrc = pRLEData;
pRowDst = pDst;
remaining = nDataSize;
rowLeft = nWidth;
x = 0;
while (remaining > 0) {
packet = (signed char)*pSrc++;
remaining--;
if (packet >= 0) {
count = packet;
while (count > 0) {
i = (count < rowLeft) ? count : rowLeft;
x += i;
rowLeft -= i;
count -= i;
if (rowLeft == 0) {
if (!clipped || pRowDst < (BYTE *)glClipY) {
for (i = 0; i < nWidth; i++) {
if (mask[i])
pRowDst[i] = LevelUnitPixel(row, i, nWidth, pLightTable);
}
}
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
pRowDst -= BUFFERX;
rowLeft = nWidth;
x = 0;
}
}
continue;
}
count = -packet;
if (count > MAX_RLE_COPY) {
count -= MAX_RLE_COPY;
if (remaining <= 0)
break;
pixel = *pSrc++;
remaining--;
while (count-- > 0) {
row[x] = pixel;
mask[x] = TRUE;
x++;
rowLeft--;
if (rowLeft == 0) {
if (!clipped || pRowDst < (BYTE*)glClipY) {
for (i = 0; i < nWidth; i++) {
if (mask[i])
pRowDst[i] = LevelUnitPixel(row, i, nWidth, pLightTable);
}
}
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
pRowDst -= BUFFERX;
rowLeft = nWidth;
x = 0;
}
}
}
else {
while (count-- > 0 && remaining > 0) {
pixel = *pSrc++;
remaining--;
row[x] = pixel;
mask[x] = TRUE;
x++;
rowLeft--;
if (rowLeft == 0) {
if (!clipped || pRowDst < (BYTE*)glClipY) {
for (i = 0; i < nWidth; i++) {
if (mask[i])
pRowDst[i] = LevelUnitPixel(row, i, nWidth, pLightTable);
}
}
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
pRowDst -= BUFFERX;
rowLeft = nWidth;
x = 0;
}
}
}
}
}
static void RLEDrawUnitLerpOverlay(BYTE *pDst, BYTE *pRLEData, int nDataSize, int nWidth, BYTE *pLightTable, BOOL clipped, int density)
{
BYTE row[BUFFERX];
BYTE mask[BUFFERX];
BYTE *pSrc, *pRowDst;
int remaining, rowLeft, x, i, y;
signed char packet;
BYTE pixel;
int count;
BOOL enhanced;
if (density <= 0)
return;
if (density > 3)
density = 3;
if (nWidth <= 0 || nWidth > BUFFERX)
return;
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
enhanced = UseLevelUnitEnhance();
pSrc = pRLEData;
pRowDst = pDst;
remaining = nDataSize;
rowLeft = nWidth;
x = 0;
y = 0;
while (remaining > 0) {
packet = (signed char)*pSrc++;
remaining--;
if (packet >= 0) {
count = packet;
while (count > 0) {
i = (count < rowLeft) ? count : rowLeft;
x += i;
rowLeft -= i;
count -= i;
if (rowLeft == 0) {
if (!clipped || pRowDst < (BYTE*)glClipY) {
for (i = 0; i < nWidth; i++) {
if (mask[i] && (((i + y) & 3) < density))
pRowDst[i] = enhanced ? LevelUnitPixel(row, i, nWidth, pLightTable) : (pLightTable ? pLightTable[row[i]] : row[i]);
}
}
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
pRowDst -= BUFFERX;
rowLeft = nWidth;
x = 0;
y++;
}
}
continue;
}
count = -packet;
if (count > MAX_RLE_COPY) {
count -= MAX_RLE_COPY;
if (remaining <= 0)
break;
pixel = *pSrc++;
remaining--;
while (count-- > 0) {
row[x] = pixel;
mask[x] = TRUE;
x++;
rowLeft--;
if (rowLeft == 0) {
if (!clipped || pRowDst < (BYTE*)glClipY) {
for (i = 0; i < nWidth; i++) {
if (mask[i] && (((i + y) & 3) < density))
pRowDst[i] = enhanced ? LevelUnitPixel(row, i, nWidth, pLightTable) : (pLightTable ? pLightTable[row[i]] : row[i]);
}
}
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
pRowDst -= BUFFERX;
rowLeft = nWidth;
x = 0;
y++;
}
}
}
else {
while (count-- > 0 && remaining > 0) {
pixel = *pSrc++;
remaining--;
row[x] = pixel;
mask[x] = TRUE;
x++;
rowLeft--;
if (rowLeft == 0) {
if (!clipped || pRowDst < (BYTE*)glClipY) {
for (i = 0; i < nWidth; i++) {
if (mask[i] && (((i + y) & 3) < density))
pRowDst[i] = enhanced ? LevelUnitPixel(row, i, nWidth, pLightTable) : (pLightTable ? pLightTable[row[i]] : row[i]);
}
}
memset(row, 0, nWidth);
memset(mask, 0, nWidth);
pRowDst -= BUFFERX;
rowLeft = nWidth;
x = 0;
y++;
}
}
}
}
}
static BOOL UseLevelUnitEnhance()
{
return gbLevelTileEnhanceActive && leveltype != 0;
}
static void DrawEnhancedUnitCommon(
long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, BYTE *pLightTable, BOOL clipped)
{
BYTE *pDst, *pSrc;
DWORD *pFrameTable;
long RLELen, offval, offval2;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int)pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel + 1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart * 16] + xp;
if (UseLevelUnitEnhance()) {
RLEDrawEnhancedUnit(pDst, pSrc, RLELen, nCelW, pLightTable, clipped);
return;
}
if (pLightTable != NULL) {
if (clipped)
RLEDrawLitUnitClipped(pDst, pSrc, RLELen, nCelW, pLightTable);
else
RLEDrawLitUnit(pDst, pSrc, RLELen, nCelW, pLightTable);
}
else {
if (clipped)
RLEDrawUnitClipped(pDst, pSrc, RLELen, nCelW);
else
RLEDrawUnit(pDst, pSrc, RLELen, nCelW);
}
}
static void DrawUnitLerpOverlayCommon(
long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, BYTE *pLightTable, BOOL clipped, int density)
{
BYTE *pDst, *pSrc;
DWORD *pFrameTable;
long RLELen, offval, offval2;
if (density <= 0)
return;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int)pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel + 1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart * 16] + xp;
RLEDrawUnitLerpOverlay(pDst, pSrc, RLELen, nCelW, pLightTable, clipped, density);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawUnit (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend)
{
BYTE *pDst, *pSrc;
DWORD * pFrameTable;
long RLELen, nFrameStart, nFrameEnd;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
nFrameStart = *(WORD*)(pSrc + ostart);
if (!nFrameStart)
return;
nFrameEnd = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (nFrameEnd ? nFrameEnd : pFrameTable[nCel+1] - pFrameTable[nCel]) - nFrameStart;
pSrc += nFrameStart;
pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp;
RLEDrawUnit(pDst, pSrc, RLELen, nCelW);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawUnitOutline(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE * pDst, * pSrc;
DWORD * pFrameTable;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
app_assert(gpBuffer != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp;
RLEDrawOutline(pDst,pSrc,RLELen,nCelW,ocolor);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawInfraUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff)
{
BYTE * pDst, * pSrc;
DWORD * pFrameTable;
long RLELen, offval, offval2, ltaboff;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
RLEDrawLitUnit(pDst,pSrc,RLELen,nCelW,pLightTbl+ltaboff);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawLitUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE * pDst, * pSrc;
DWORD * pFrameTable;
long RLELen, offval, offval2;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp;
if (nLVal)
RLEDrawLitUnit(pDst,pSrc,RLELen,nCelW,pLightTbl + (nLVal << 8));
else
RLEDrawUnit(pDst,pSrc,RLELen,nCelW);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawUnitClipped (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend)
{
BYTE * pDst, * pSrc;
DWORD * pFrameTable;
long RLELen, offval, offval2;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp;
RLEDrawUnitClipped(pDst, pSrc, RLELen, nCelW);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawUnitOutlineClipped(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE * pDst, * pSrc;
DWORD * pFrameTable;
long RLELen, offval, offval2;
app_assert(pCelBuff != NULL);
app_assert(gpBuffer != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp;
glClipY -= BUFFERX;
RLEDrawOutlineClipped(pDst,pSrc,RLELen,nCelW,ocolor);
glClipY += BUFFERX;
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawInfraUnitClipped(
long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff)
{
BYTE * pDst, * pSrc;
DWORD * pFrameTable;
long RLELen, offval, offval2, ltaboff;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
RLEDrawLitUnitClipped(pDst,pSrc,RLELen,nCelW,pLightTbl + ltaboff);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
BYTE * pDst, * pSrc;
DWORD * pFrameTable;
long RLELen, offval, offval2;
app_assert(gpBuffer != NULL);
app_assert(pCelBuff != NULL);
app_assert(nCel > 0);
// jcm.patch1.start.1/14/97
#ifdef GRACEFUL_EXIT
if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0)
return;
#endif
// jcm.patch1.end.1/14/97
pFrameTable = (DWORD*)pCelBuff;
app_assert(nCel <= (int) pFrameTable[0]);
pSrc = pCelBuff + pFrameTable[nCel];
offval = *(WORD*)(pSrc + ostart);
if (!offval)
return;
offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend);
RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval;
pSrc += offval;
pDst = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp;
if (nLVal)
RLEDrawLitUnitClipped(pDst,pSrc,RLELen,nCelW,pLightTbl + (nLVal << 8));
else
RLEDrawUnitClipped(pDst,pSrc,RLELen,nCelW);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawEnhancedUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, FALSE);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density)
{
DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, FALSE, density);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawEnhancedUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, TRUE);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density)
{
DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, TRUE, density);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawEnhancedLitUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
DrawEnhancedUnitCommon(
xp,
yp,
pCelBuff,
nCel,
nCelW,
ostart,
oend,
nLVal ? pLightTbl + (nLVal << 8) : NULL,
FALSE);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawLitUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density)
{
DrawUnitLerpOverlayCommon(
xp,
yp,
pCelBuff,
nCel,
nCelW,
ostart,
oend,
nLVal ? pLightTbl + (nLVal << 8) : NULL,
FALSE,
density);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawEnhancedLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend)
{
DrawEnhancedUnitCommon(
xp,
yp,
pCelBuff,
nCel,
nCelW,
ostart,
oend,
nLVal ? pLightTbl + (nLVal << 8) : NULL,
TRUE);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawLitUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density)
{
DrawUnitLerpOverlayCommon(
xp,
yp,
pCelBuff,
nCel,
nCelW,
ostart,
oend,
nLVal ? pLightTbl + (nLVal << 8) : NULL,
TRUE,
density);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawEnhancedInfraUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff)
{
long ltaboff;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, FALSE);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawInfraUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff, int density)
{
long ltaboff;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, FALSE, density);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawEnhancedInfraUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff)
{
long ltaboff;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, TRUE);
}
#endif
//*************************************************************************
//*************************************************************************
#if RLE_DRAW
void DrawInfraUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff, int density)
{
long ltaboff;
ltaboff = light4flag ? 1024 : 4096;
if (loff == LIGHT_STONE)
ltaboff += 256;
if (loff >= LIGHT_U)
ltaboff += ((loff - LIGHT_U) << 8) + 768;
DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, TRUE, density);
}
#endif
//*************************************************************************
//*************************************************************************
void play_movie(const char * pszMovie,BOOL bAllowCancel);
void PlayInGameMovie(const char * pszMovie) {
PaletteFadeOut(FADE_FAST);
play_movie(pszMovie,FALSE);
ClrDraw();
force_redraw = FULLDRAW;
FullBlit(TRUE);
PaletteFadeIn(FADE_FAST);
force_redraw = FULLDRAW;
}