Initial commit.
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
// asmcoder.cpp
|
||||
// by simon@acid.co.nz
|
||||
|
||||
// testroutine for asmcoder class
|
||||
// see asmcoder.h for readme
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "asmcoder.h"
|
||||
|
||||
void (__fastcall *plot)(void *s,int argb);
|
||||
int (__fastcall *point)(void*s);
|
||||
void (__fastcall *span)(void *s,int *argb,int n);
|
||||
|
||||
void main()
|
||||
{
|
||||
void *pixmap;
|
||||
int n;
|
||||
|
||||
AsmCoder *coder=new AsmCoder();
|
||||
|
||||
pixmap=new int[640*480];
|
||||
|
||||
plot=(void (__fastcall *)(void*,int))new char[96];
|
||||
point=(int (__fastcall *)(void*))new char[96];
|
||||
span=(void (__fastcall *)(void*,int*,int))new char[96];
|
||||
|
||||
// n=coder->CodePlot(plot,16,0,0xf800,0x07e0,0x001f); //0:5:6:5
|
||||
// printf("plotcode size=%d\n",n);
|
||||
// n=coder->CodePoint(point,16,0,0xf800,0x07e0,0x001f); //0:5:6:5
|
||||
// printf("pointcode size=%d\n",n);
|
||||
|
||||
n=coder->CodePlot(plot,24,0,0xff0000,0xff00,0xff); //0:5:6:5
|
||||
printf("plotcode size=%d\n",n);
|
||||
|
||||
n=coder->CodePoint(point,24,0,0xff0000,0xff00,0x00ff); //0:5:6:5
|
||||
printf("pointcode size=%d\n",n);
|
||||
|
||||
n=coder->CodeSpan(span,24,0,0xff0000,0xff00,0x00ff); //0:5:6:5
|
||||
printf("scancode size=%d\n",n);
|
||||
|
||||
printf("&plot=0x%x\n",(int)plot);
|
||||
printf("&pixmap=0x%x\n",(int)pixmap);
|
||||
|
||||
plot(pixmap,0x818283);
|
||||
// short *b=(short *)pixmap;
|
||||
int *b=(int *)pixmap;
|
||||
printf("b[0]=0x%x\n",b[0]);
|
||||
n=point(pixmap);
|
||||
printf("point(0,0)=0x%x\n",n);
|
||||
|
||||
int pdat[]={0x8080,0x707070,0x606060};
|
||||
span(pixmap,pdat,3);
|
||||
|
||||
delete (void *)plot;
|
||||
delete (void *)point;
|
||||
delete pixmap;
|
||||
delete coder;
|
||||
return;
|
||||
}
|
||||
|
||||
// void (__fastcall *plot)(int x,int y,int argb,Surface *s)=(void (__fastcall *)(int,int,int,Surface*))code;
|
||||
|
||||
void ortest()
|
||||
{
|
||||
__asm{
|
||||
or eax,0xff00ff00
|
||||
or eax,-100
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
// asmcoder.h
|
||||
// by simon@acid.co.nz
|
||||
|
||||
// v0.5
|
||||
// point sets nonused bits to 1
|
||||
|
||||
// v0.4
|
||||
// direct pixel address now expected
|
||||
// x,y args removed span removed
|
||||
|
||||
// v0.3
|
||||
// span changed to bytes
|
||||
// pixfield indirect dropped, passed directy to plot
|
||||
// ret(n) added to remove args from fastcall stack
|
||||
// CodePoint() method added
|
||||
|
||||
/*
|
||||
|
||||
asmcoder provides inline assembly generator for high speed runtime tasks
|
||||
|
||||
methods:
|
||||
|
||||
CodePlot(codebase,depth,amask,rmask,gmask,bmask)
|
||||
CodePoint(codebase,depth,amask,rmask,gmask,bmask)
|
||||
CodeSpan(codebase,depth,amask,rmask,gmask,bmask)
|
||||
|
||||
codebase=executable memory (64 bytes)
|
||||
depth=pixel depth (8,16,24,32)
|
||||
amask=32bit alpha pixel mask
|
||||
rmask=32bit red pixel mask
|
||||
gmask=32bit green pixel mask
|
||||
bmask=32bit blue pixel mask
|
||||
|
||||
returns number of bytes of code generated (max 64 bytes)
|
||||
|
||||
call resulting code by typecasting codebase with
|
||||
|
||||
void (__fastcall *plot)(void *pix,int argb)
|
||||
int (__fastcall *point)(void *pix)
|
||||
void (__fastcall *span)(void *pix,int *argb,int count)
|
||||
|
||||
ToDo:
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ASMCODER_H
|
||||
#define ASMCODER_H
|
||||
|
||||
class IA32
|
||||
{
|
||||
public:
|
||||
char *ptr;
|
||||
int off;
|
||||
|
||||
enum Reg32{eax,ecx,edx,ebx,esp,ebp,esi,edi};
|
||||
|
||||
void Reset(void *p) {ptr=(char *)p;off=0;}
|
||||
|
||||
void Code(int c){if (ptr) ptr[off]=c;off++;}
|
||||
void Code16(int c){if (ptr) *(short*)(ptr+off)=c;off+=2;}
|
||||
void Code32(int c){if (ptr) *(int*)(ptr+off)=c;off+=4;}
|
||||
|
||||
void push(Reg32 reg) {Code(0x50+reg);}
|
||||
void pop(Reg32 reg) {Code(0x58+reg);}
|
||||
void ret(int n=0) {if (n==0) Code(0xc3);else {Code(0xc2);Code(n);Code(0);}}
|
||||
void mov(Reg32 dest,Reg32 src) {Code(0x8b);Code((0xc0)|(dest<<3)|(src));}
|
||||
void or(Reg32 dest,Reg32 src) {Code(0x0b);Code((0xc0)|(dest<<3)|(src));}
|
||||
void add(Reg32 dest,Reg32 src) {Code(0x03);Code((0xc0)|(dest<<3)|(src));}
|
||||
void load32(Reg32 dest,Reg32 src,int disp=0)
|
||||
{
|
||||
if (disp==0 && src!=ebp) {Code(0x8b);Code((dest<<3)|(src));}
|
||||
else {Code(0x8b);Code((0x40)|(dest<<3)|(src));Code(disp);}
|
||||
}
|
||||
void load16(Reg32 dest,Reg32 src,int disp=0) {Code(0x66);load32(dest,src,disp);}
|
||||
void load8(Reg32 dest,Reg32 src,int disp=0)
|
||||
{
|
||||
Code(0x8a);if (disp==0 && src!=ebp) {Code((dest<<3)|(src));} else {Code((0x40)|(dest<<3)|(src));Code(disp);}
|
||||
}
|
||||
void store32(Reg32 dest,int disp,Reg32 src)
|
||||
{
|
||||
if (disp==0 && dest!=ebp) {Code(0x89);Code((src<<3)|(dest));Code(0);}
|
||||
else {Code(0x89);Code((0x40)|(src<<3)|(dest));Code(disp);}
|
||||
}
|
||||
void store16(Reg32 dest,int disp,Reg32 src) {Code(0x66);store32(dest,disp,src);}
|
||||
void store8(Reg32 dest,int disp,Reg32 src)
|
||||
{
|
||||
Code(0x88);
|
||||
if (disp==0 && dest!=ebp) {Code((src<<3)|(dest));Code(0);} else {Code((0x40)|(src<<3)|(dest));Code(disp);}
|
||||
}
|
||||
void lea(Reg32 dest,int scale,Reg32 src1,Reg32 src2,int disp=0)
|
||||
{
|
||||
int n,mod,sib;
|
||||
if (disp==0) n=0;else {if (disp>=-128 && disp<128) n=1;else n=2;}
|
||||
mod=(n<<6)|4;
|
||||
sib=(src1<<3)|src2;
|
||||
if (scale==2) sib|=0x40;
|
||||
if (scale==4) sib|=0x80;
|
||||
if (scale==8) sib|=0xc0;
|
||||
Code(0x8d);Code(mod);Code(sib);
|
||||
if (n==1) Code(disp);else if (n==2) Code32(disp);
|
||||
}
|
||||
void lea(Reg32 dest,int scale,Reg32 src,int disp=0)
|
||||
{
|
||||
int mod,sib;
|
||||
sib=(src<<3)|5;
|
||||
mod=(dest<<3)|4;
|
||||
if (scale==2) sib|=0x40;
|
||||
if (scale==4) sib|=0x80;
|
||||
if (scale==8) sib|=0xc0;
|
||||
Code(0x8d);Code(mod);Code(sib);Code32(disp);
|
||||
}
|
||||
void imul(Reg32 dest,int imm,Reg32 src)
|
||||
{
|
||||
Code(0x69);Code((0xc0)|(dest<<3)|(src));Code32(imm);
|
||||
}
|
||||
void shift(Reg32 reg,int imm) //+imm=left -imm=right
|
||||
{
|
||||
int op;
|
||||
if (imm==0) return;
|
||||
if (imm>0) {op=0xe0+reg;} else {op=0xe8+reg;imm=-imm;}
|
||||
if (imm==1) {Code(0xd1);Code(op);} else {Code(0xc1);Code(op);Code(imm);}
|
||||
}
|
||||
void and(Reg32 reg,int imm)
|
||||
{
|
||||
if (imm==0xffffffff) return;
|
||||
if (imm>=-128 && imm<128)
|
||||
{
|
||||
Code(0x83);Code(0xe0+reg);Code(imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reg==eax) {Code(0x25);} else {Code(0x81);Code(0xe0+reg);}Code32(imm);
|
||||
}
|
||||
}
|
||||
void or(Reg32 reg,int imm)
|
||||
{
|
||||
if (imm==0) return;
|
||||
if (imm>=-128 && imm<128)
|
||||
{
|
||||
Code(0x83);Code(0xc0+reg);Code(imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reg==eax) {Code(0x0d);} else {Code(0x81);Code(0xc0+reg);}
|
||||
Code32(imm);
|
||||
}
|
||||
}
|
||||
void jnz(int label) {Code(0x75);Code(label-(off+1));}
|
||||
void add(Reg32 reg,int imm) {Code(0x83);Code(0xc0+reg);Code(imm);}
|
||||
void neg(Reg32 reg) {Code(0xf7);Code(0xd8+reg);}
|
||||
};
|
||||
|
||||
class AsmCoder : IA32
|
||||
{
|
||||
public:
|
||||
int amsb,rmsb,gmsb,bmsb;
|
||||
|
||||
void CalcMSBs(int amask,int rmask,int gmask,int bmask)
|
||||
{
|
||||
unsigned int u;
|
||||
amsb=0;if (u=amask) {while (u!=1) {u>>=1;amsb++;}}
|
||||
rmsb=0;if (u=rmask) {while (u!=1) {u>>=1;rmsb++;}}
|
||||
gmsb=0;if (u=gmask) {while (u!=1) {u>>=1;gmsb++;}}
|
||||
bmsb=0;if (u=bmask) {while (u!=1) {u>>=1;bmsb++;}}
|
||||
}
|
||||
|
||||
// ecx=void *t pixel
|
||||
// edx=int argb
|
||||
|
||||
int CodePlot(void *code,int depth,int amask,int rmask,int gmask,int bmask)
|
||||
{
|
||||
Reset(code);
|
||||
CalcMSBs(amask,rmask,gmask,bmask);
|
||||
|
||||
push (ebx);
|
||||
push (ebp);
|
||||
mov (eax,edx);
|
||||
mov (ebp,ecx);
|
||||
if (rmask==0xff0000 && gmask==0xff00 && bmask==0xff)
|
||||
{
|
||||
if (amask==0 && depth>24) and(eax,0xffffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
|
||||
shift (eax,bmsb-7); //3-0);
|
||||
mov (ecx,ebx);
|
||||
shift (ebx,gmsb-15);
|
||||
if (amask) mov (edx,ecx); //alph
|
||||
if (amask) shift (edx,amsb-31); //alph
|
||||
and (eax,bmask);
|
||||
shift (ecx,rmsb-23);
|
||||
if (amask) and (edx,amask); //alph
|
||||
and (ebx,gmask);
|
||||
if (amask) or (eax,edx); //alph
|
||||
and (ecx,rmask);
|
||||
or (eax,ebx);
|
||||
or (eax,ecx);
|
||||
}
|
||||
switch (depth)
|
||||
{
|
||||
case 16:store16(ebp,0,eax);break;
|
||||
// case 24:store16(ebp,0,eax);shift(eax,-16);store8(ebp,2,eax);break;
|
||||
case 24:store8(ebp,0,eax);shift(eax,-8);store16(ebp,1,eax);break;
|
||||
case 32:store32(ebp,0,eax);break;
|
||||
default:store8(ebp,0,eax);
|
||||
}
|
||||
pop(ebp);
|
||||
pop(ebx);
|
||||
ret();
|
||||
return off;
|
||||
}
|
||||
|
||||
// ecx=void*pix
|
||||
|
||||
int CodePoint(void *code,int depth,int amask,int rmask,int gmask,int bmask)
|
||||
{
|
||||
Reset(code);
|
||||
CalcMSBs(amask,rmask,gmask,bmask);
|
||||
|
||||
push (ebx);
|
||||
switch (depth)
|
||||
{
|
||||
case 16:load16(eax,ecx);break;
|
||||
// case 24:load16(eax,ecx);shift(eax,-16);load8(eax,ecx,2);break;
|
||||
case 24:load16(eax,ecx,1);shift(eax,8);load8(eax,ecx);break;
|
||||
case 32:load32(eax,ecx);break;
|
||||
default:load8(eax,ecx);
|
||||
}
|
||||
if ((amask==0 || amask==0xff000000) && (rmask==0xff0000 && gmask==0xff00 && bmask==0xff))
|
||||
{
|
||||
//
|
||||
}
|
||||
else
|
||||
{
|
||||
mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
|
||||
mov (ecx,eax);
|
||||
if (amask) mov (edx,eax);
|
||||
and (eax,bmask);
|
||||
shift (eax,7-bmsb);
|
||||
and (ebx,gmask);
|
||||
shift (ebx,15-gmsb);
|
||||
and (ecx,rmask);
|
||||
shift (ecx,23-rmsb);
|
||||
if (amask) and (edx,amask);
|
||||
or (eax,ebx);
|
||||
if (amask) shift (edx,31-amsb);
|
||||
or (eax,ecx);
|
||||
if (amask) or (eax,edx);
|
||||
}
|
||||
pop(ebx);
|
||||
int oor=0;
|
||||
if( !amask ) oor|=0xff000000;
|
||||
if( !rmask ) oor|=0x00ff0000;
|
||||
if( !gmask ) oor|=0x0000ff00;
|
||||
if( !bmask ) oor|=0x000000ff;
|
||||
if( oor ) or( eax,oor );
|
||||
ret();
|
||||
return off;
|
||||
}
|
||||
|
||||
// ecx=void *t pixel
|
||||
// edx=int *argb
|
||||
// 8(esp)=count
|
||||
|
||||
int CodeSpan(void *code,int depth,int amask,int rmask,int gmask,int bmask)
|
||||
{
|
||||
int loop;
|
||||
|
||||
Reset(code);
|
||||
CalcMSBs(amask,rmask,gmask,bmask);
|
||||
|
||||
push (ebp);
|
||||
mov (ebp,esp);
|
||||
push (ebx);
|
||||
push (esi);
|
||||
push (edi);
|
||||
|
||||
load32 (edi,ebp,8); //edi=count
|
||||
mov (esi,edx); //esi=[argb]
|
||||
mov (ebp,ecx); //ebp=[pix]
|
||||
neg (edi);
|
||||
|
||||
loop=off;
|
||||
// loop
|
||||
load32 (eax,esi);
|
||||
add (esi,4);
|
||||
|
||||
if (rmask==0xff0000 && gmask==0xff00 && bmask==0xff)
|
||||
{
|
||||
if (amask==0 && depth>24) and(eax,0xffffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
|
||||
shift (eax,bmsb-7); //3-0);
|
||||
mov (ecx,ebx);
|
||||
shift (ebx,gmsb-15);
|
||||
if (amask) mov (edx,ecx); //alph
|
||||
if (amask) shift (edx,amsb-31); //alph
|
||||
and (eax,bmask);
|
||||
shift (ecx,rmsb-23);
|
||||
if (amask) and (edx,amask); //alph
|
||||
and (ebx,gmask);
|
||||
if (amask) or (eax,edx); //alph
|
||||
and (ecx,rmask);
|
||||
or (eax,ebx);
|
||||
or (eax,ecx);
|
||||
}
|
||||
switch (depth)
|
||||
{
|
||||
case 16:store16(ebp,0,eax);add(ebp,2);break;
|
||||
case 24:store8(ebp,0,eax);shift(eax,-8);store16(ebp,1,eax);add(ebp,3);break;
|
||||
case 32:store32(ebp,0,eax);add(ebp,4);break;
|
||||
default:store8(ebp,0,eax);add(ebp,1);
|
||||
}
|
||||
add (edi,1);
|
||||
jnz (loop);
|
||||
|
||||
pop (edi);
|
||||
pop (esi);
|
||||
pop (ebx);
|
||||
pop (ebp);
|
||||
ret (4);
|
||||
return off;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,525 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "ddutil.h"
|
||||
#include "asmcoder.h"
|
||||
#include "gxcanvas.h"
|
||||
#include "gxruntime.h"
|
||||
|
||||
extern gxRuntime *gx_runtime;
|
||||
|
||||
#include "..\..\freeimage241\source\freeimage.h"
|
||||
|
||||
static AsmCoder asm_coder;
|
||||
|
||||
static void calcShifts( unsigned mask,unsigned char *shr,unsigned char *shl ){
|
||||
if( mask ){
|
||||
for( *shl=0;!(mask&1);++*shl,mask>>=1 ){}
|
||||
for( *shr=8;mask&1;--*shr,mask>>=1 ){}
|
||||
}else *shr=*shl=0;
|
||||
}
|
||||
|
||||
PixelFormat::~PixelFormat(){
|
||||
if( plot_code ){
|
||||
VirtualFree( plot_code,0,MEM_RELEASE );
|
||||
}
|
||||
}
|
||||
|
||||
void PixelFormat::setFormat( const DDPIXELFORMAT &pf ){
|
||||
if( plot_code ){
|
||||
VirtualFree( plot_code,0,MEM_RELEASE );
|
||||
}
|
||||
|
||||
if( !(pf.dwFlags & DDPF_RGB) ){
|
||||
memset( this,0,sizeof(*this) );
|
||||
return;
|
||||
}
|
||||
|
||||
plot_code=(char*)VirtualAlloc( 0,128,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE );
|
||||
point_code=plot_code+64;
|
||||
|
||||
depth=pf.dwRGBBitCount;
|
||||
amask=pf.dwRGBAlphaBitMask;
|
||||
rmask=pf.dwRBitMask;
|
||||
gmask=pf.dwGBitMask;
|
||||
bmask=pf.dwBBitMask;
|
||||
pitch=depth/8;argbfill=0;
|
||||
if( !amask ) argbfill|=0xff000000;
|
||||
if( !rmask ) argbfill|=0x00ff0000;
|
||||
if( !gmask ) argbfill|=0x0000ff00;
|
||||
if( !bmask ) argbfill|=0x000000ff;
|
||||
calcShifts( amask,&ashr,&ashl );ashr+=24;
|
||||
calcShifts( rmask,&rshr,&rshl );rshr+=16;
|
||||
calcShifts( gmask,&gshr,&gshl );gshr+=8;
|
||||
calcShifts( bmask,&bshr,&bshl );
|
||||
plot=(Plot)(void*)plot_code;
|
||||
point=(Point)(void*)point_code;
|
||||
asm_coder.CodePlot( plot_code,depth,amask,rmask,gmask,bmask );
|
||||
asm_coder.CodePoint( point_code,depth,amask,rmask,gmask,bmask );
|
||||
}
|
||||
|
||||
static void adjustTexSize( int *width,int *height,IDirect3DDevice7 *dir3dDev ){
|
||||
D3DDEVICEDESC7 ddDesc={0};
|
||||
if( dir3dDev->GetCaps( &ddDesc )<0 ){
|
||||
*width=*height=256;
|
||||
return;
|
||||
}
|
||||
int w=*width,h=*height,min,max;
|
||||
//make power of 2
|
||||
//Try *always* making POW2 size to fix GF6800 non-pow2 tex issue
|
||||
// if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 ){
|
||||
for( w=1;w<*width;w<<=1 ){}
|
||||
for( h=1;h<*height;h<<=1 ){}
|
||||
// }
|
||||
//make square
|
||||
if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY ){
|
||||
if( w>h ) h=w;
|
||||
else w=h;
|
||||
}
|
||||
//check aspect ratio
|
||||
if( max=ddDesc.dwMaxTextureAspectRatio ){
|
||||
int asp=w>h ? w/h : h/w;
|
||||
if( asp>max ){
|
||||
if( w>h ) h=w/max;
|
||||
else w=h/max;
|
||||
}
|
||||
}
|
||||
//clamp size
|
||||
if( (min=ddDesc.dwMinTextureWidth) && w<min ) w=min;
|
||||
if( (min=ddDesc.dwMinTextureHeight) && h<min ) h=min;
|
||||
if( (max=ddDesc.dwMaxTextureWidth) && w>max ) w=max;
|
||||
if( (max=ddDesc.dwMaxTextureHeight) && h>max ) h=max;
|
||||
|
||||
*width=w;*height=h;
|
||||
}
|
||||
|
||||
static ddSurf *createSurface( int width,int height,int pitch,void *bits,IDirectDraw7 *dirDraw ){
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
desc.dwFlags=DDSD_WIDTH|DDSD_HEIGHT|DDSD_LPSURFACE|DDSD_PITCH|DDSD_PIXELFORMAT|DDSD_CAPS;
|
||||
desc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
|
||||
desc.dwWidth=width;desc.dwHeight=height;
|
||||
desc.lPitch=pitch;desc.lpSurface=bits;
|
||||
desc.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
|
||||
desc.ddpfPixelFormat.dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS;
|
||||
desc.ddpfPixelFormat.dwRGBBitCount=32;
|
||||
desc.ddpfPixelFormat.dwRBitMask=0xff0000;
|
||||
desc.ddpfPixelFormat.dwGBitMask=0x00ff00;
|
||||
desc.ddpfPixelFormat.dwBBitMask=0x0000ff;
|
||||
desc.ddpfPixelFormat.dwRGBAlphaBitMask=0xff000000;
|
||||
ddSurf *surf;
|
||||
if( dirDraw->CreateSurface( &desc,&surf,0 )>=0 ) return surf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void buildMask( ddSurf *surf ){
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
surf->Lock( 0,&desc,DDLOCK_WAIT,0 );
|
||||
unsigned char *surf_p=(unsigned char*)desc.lpSurface;
|
||||
PixelFormat fmt( desc.ddpfPixelFormat );
|
||||
|
||||
for( int y=0;y<desc.dwHeight;++y ){
|
||||
unsigned char *p=surf_p;
|
||||
for( int x=0;x<desc.dwWidth;++x ){
|
||||
unsigned argb=fmt.getPixel( p );
|
||||
unsigned rgb=argb&0xffffff;
|
||||
unsigned a=rgb ? 0xff000000 : 0;
|
||||
fmt.setPixel( p,a|rgb );
|
||||
p+=fmt.getPitch();
|
||||
}
|
||||
surf_p+=desc.lPitch;
|
||||
}
|
||||
surf->Unlock( 0 );
|
||||
}
|
||||
|
||||
static void buildAlpha( ddSurf *surf,bool whiten ){
|
||||
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
surf->Lock( 0,&desc,DDLOCK_WAIT,0 );
|
||||
unsigned char *surf_p=(unsigned char*)desc.lpSurface;
|
||||
PixelFormat fmt( desc.ddpfPixelFormat );
|
||||
|
||||
for( int y=0;y<desc.dwHeight;++y ){
|
||||
unsigned char *p=surf_p;
|
||||
for( int x=0;x<desc.dwWidth;++x ){
|
||||
unsigned argb=fmt.getPixel( p );
|
||||
unsigned alpha=(((argb>>16)&0xff)+((argb>>8)&0xff)+(argb&0xff))/3;
|
||||
argb=(alpha<<24) | (argb & 0xffffff);
|
||||
if( whiten ) argb|=0xffffff;
|
||||
fmt.setPixel( p,argb );
|
||||
p+=fmt.getPitch();
|
||||
}
|
||||
surf_p+=desc.lPitch;
|
||||
}
|
||||
surf->Unlock( 0 );
|
||||
}
|
||||
|
||||
void ddUtil::buildMipMaps( ddSurf *surf ){
|
||||
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
surf->GetSurfaceDesc( &desc );
|
||||
if( !(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) ) return;
|
||||
if( !(desc.ddpfPixelFormat.dwFlags & DDPF_RGB) ) return;
|
||||
|
||||
DDSCAPS2 caps={0};
|
||||
caps.dwCaps=DDSCAPS_TEXTURE;
|
||||
caps.dwCaps2=DDSCAPS2_MIPMAPSUBLEVEL;
|
||||
|
||||
IDirectDrawSurface7 *src=surf,*dest;
|
||||
|
||||
while( src->GetAttachedSurface( &caps,&dest )>=0 ){
|
||||
|
||||
DDSURFACEDESC2 src_desc={sizeof(src_desc)};
|
||||
if( src->Lock( 0,&src_desc,DDLOCK_WAIT,0 )<0 ) abort();
|
||||
unsigned char *src_p=(unsigned char*)src_desc.lpSurface;
|
||||
PixelFormat src_fmt( src_desc.ddpfPixelFormat );
|
||||
|
||||
DDSURFACEDESC2 dest_desc={sizeof(dest_desc)};
|
||||
if( dest->Lock( 0,&dest_desc,DDLOCK_WAIT,0 )<0 ) abort();
|
||||
unsigned char *dest_p=(unsigned char *)dest_desc.lpSurface;
|
||||
PixelFormat dest_fmt( dest_desc.ddpfPixelFormat );
|
||||
|
||||
if( src_desc.dwWidth==1 ){
|
||||
for( int y=0;y<dest_desc.dwHeight;++y ){
|
||||
unsigned p1=src_fmt.getPixel( src_p );
|
||||
unsigned p2=src_fmt.getPixel( src_p+src_desc.lPitch );
|
||||
unsigned argb=
|
||||
((p1&0xfefefefe)>>1)+((p2&0xfefefefe)>>1);
|
||||
argb+=( (
|
||||
(p1&0x01010101)+(p2&0x01010101) )>>1 ) & 0x01010101;
|
||||
dest_fmt.setPixel( dest_p,argb );
|
||||
src_p+=src_desc.lPitch*2;
|
||||
dest_p+=dest_desc.lPitch;
|
||||
}
|
||||
}else if( src_desc.dwHeight==1 ){
|
||||
for( int x=0;x<dest_desc.dwWidth;++x ){
|
||||
unsigned p1=src_fmt.getPixel( src_p );
|
||||
unsigned p2=src_fmt.getPixel( src_p+src_fmt.getPitch() );
|
||||
unsigned argb=
|
||||
((p1&0xfefefefe)>>1)+((p2&0xfefefefe)>>1);
|
||||
argb+=( (
|
||||
(p1&0x01010101)+(p2&0x01010101) )>>1 ) & 0x01010101;
|
||||
dest_fmt.setPixel( dest_p,argb );
|
||||
src_p+=src_fmt.getPitch()*2;
|
||||
dest_p+=dest_fmt.getPitch();
|
||||
}
|
||||
}else{
|
||||
for( int y=0;y<dest_desc.dwHeight;++y ){
|
||||
unsigned char *src_t=src_p;
|
||||
unsigned char *dest_t=dest_p;
|
||||
for( int x=0;x<dest_desc.dwWidth;++x ){
|
||||
|
||||
unsigned p1=src_fmt.getPixel( src_t );
|
||||
unsigned p2=src_fmt.getPixel( src_t+src_fmt.getPitch() );
|
||||
unsigned p3=src_fmt.getPixel( src_t+src_desc.lPitch+src_fmt.getPitch() );
|
||||
unsigned p4=src_fmt.getPixel( src_t+src_desc.lPitch );
|
||||
|
||||
unsigned argb=
|
||||
((p1&0xfcfcfcfc)>>2)+((p2&0xfcfcfcfc)>>2)+
|
||||
((p3&0xfcfcfcfc)>>2)+((p4&0xfcfcfcfc)>>2);
|
||||
argb+=( (
|
||||
(p1&0x03030303)+(p2&0x03030303)+
|
||||
(p3&0x03030303)+(p4&0x03030303) )>>2 ) & 0x03030303;
|
||||
|
||||
dest_fmt.setPixel( dest_t,argb );
|
||||
src_t+=src_fmt.getPitch()*2;
|
||||
dest_t+=dest_fmt.getPitch();
|
||||
}
|
||||
src_p+=src_desc.lPitch*2;
|
||||
dest_p+=dest_desc.lPitch;
|
||||
}
|
||||
}
|
||||
src->Unlock( 0 );
|
||||
dest->Unlock( 0 );
|
||||
dest->Release();
|
||||
src=dest;
|
||||
}
|
||||
}
|
||||
|
||||
void ddUtil::copy( ddSurf *dest,int dx,int dy,int dw,int dh,ddSurf *src,int sx,int sy,int sw,int sh ){
|
||||
|
||||
DDSURFACEDESC2 src_desc={sizeof(src_desc)};
|
||||
src->Lock( 0,&src_desc,DDLOCK_WAIT,0 );
|
||||
PixelFormat src_fmt( src_desc.ddpfPixelFormat );
|
||||
unsigned char *src_p=(unsigned char*)src_desc.lpSurface;
|
||||
src_p+=src_desc.lPitch*sy+src_fmt.getPitch()*sx;
|
||||
|
||||
DDSURFACEDESC2 dest_desc={sizeof(dest_desc)};
|
||||
dest->Lock( 0,&dest_desc,DDLOCK_WAIT,0 );
|
||||
PixelFormat dest_fmt( dest_desc.ddpfPixelFormat );
|
||||
unsigned char *dest_p=(unsigned char *)dest_desc.lpSurface;
|
||||
dest_p+=dest_desc.lPitch*dy+dest_fmt.getPitch()*dx;
|
||||
|
||||
for( int y=0;y<dh;++y ){
|
||||
unsigned char *dest=dest_p;
|
||||
unsigned char *src=src_p+src_desc.lPitch*(y*sh/dh);
|
||||
for( int x=0;x<dw;++x ){
|
||||
dest_fmt.setPixel( dest,src_fmt.getPixel( src+src_fmt.getPitch()*(x*sw/dw) ) );
|
||||
dest+=dest_fmt.getPitch();
|
||||
}
|
||||
dest_p+=dest_desc.lPitch;
|
||||
}
|
||||
|
||||
src->Unlock( 0 );
|
||||
dest->Unlock( 0 );
|
||||
}
|
||||
|
||||
ddSurf *ddUtil::createSurface( int w,int h,int flags,gxGraphics *gfx ){
|
||||
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
|
||||
desc.dwFlags=DDSD_CAPS;
|
||||
|
||||
int hi=flags & gxCanvas::CANVAS_TEX_HICOLOR?1:0;
|
||||
|
||||
if( w ){ desc.dwWidth=w;desc.dwFlags|=DDSD_WIDTH; }
|
||||
if( h ){ desc.dwHeight=h;desc.dwFlags|=DDSD_HEIGHT; }
|
||||
|
||||
if( flags & gxCanvas::CANVAS_TEX_MASK ){
|
||||
desc.dwFlags|=DDSD_PIXELFORMAT;
|
||||
desc.ddpfPixelFormat=gfx->texRGBMaskFmt[hi];
|
||||
}else if( flags & gxCanvas::CANVAS_TEX_RGB ){
|
||||
desc.dwFlags|=DDSD_PIXELFORMAT;
|
||||
desc.ddpfPixelFormat=(flags&gxCanvas::CANVAS_TEX_ALPHA)?gfx->texRGBAlphaFmt[hi]:gfx->texRGBFmt[hi];
|
||||
}else if( flags & gxCanvas::CANVAS_TEX_ALPHA ){
|
||||
desc.dwFlags|=DDSD_PIXELFORMAT;
|
||||
desc.ddpfPixelFormat=gfx->texAlphaFmt[hi];
|
||||
}else if( flags & gxCanvas::CANVAS_TEXTURE ){
|
||||
desc.dwFlags|=DDSD_PIXELFORMAT;
|
||||
desc.ddpfPixelFormat=gfx->primFmt;
|
||||
}
|
||||
if( flags & gxCanvas::CANVAS_TEXTURE ){
|
||||
desc.ddsCaps.dwCaps|=DDSCAPS_TEXTURE;
|
||||
if( !(flags & gxCanvas::CANVAS_TEX_VIDMEM) ){
|
||||
desc.ddsCaps.dwCaps2|=DDSCAPS2_TEXTUREMANAGE;
|
||||
if( flags & gxCanvas::CANVAS_TEX_MIPMAP ){
|
||||
desc.ddsCaps.dwCaps|=DDSCAPS_MIPMAP|DDSCAPS_COMPLEX;
|
||||
}
|
||||
}
|
||||
if( flags & (gxCanvas::CANVAS_TEX_CUBE) ){
|
||||
desc.ddsCaps.dwCaps|=DDSCAPS_COMPLEX;
|
||||
desc.ddsCaps.dwCaps2|=DDSCAPS2_CUBEMAP|DDSCAPS2_CUBEMAP_ALLFACES;
|
||||
}
|
||||
adjustTexSize( (int*)&desc.dwWidth,(int*)&desc.dwHeight,gfx->dir3dDev );
|
||||
}else{
|
||||
desc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
|
||||
if( flags & gxCanvas::CANVAS_HIGHCOLOR ){
|
||||
desc.dwFlags|=DDSD_PIXELFORMAT;
|
||||
desc.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
|
||||
desc.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
|
||||
desc.ddpfPixelFormat.dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS;
|
||||
desc.ddpfPixelFormat.dwRGBBitCount=32;
|
||||
desc.ddpfPixelFormat.dwRBitMask=0xff0000;
|
||||
desc.ddpfPixelFormat.dwGBitMask=0x00ff00;
|
||||
desc.ddpfPixelFormat.dwBBitMask=0x0000ff;
|
||||
desc.ddpfPixelFormat.dwRGBAlphaBitMask=0xff000000;
|
||||
}else if( flags & gxCanvas::CANVAS_NONDISPLAY ){
|
||||
desc.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
|
||||
}
|
||||
}
|
||||
ddSurf *surf;
|
||||
if( gfx->dirDraw->CreateSurface( &desc,&surf,0 )>=0 ) return surf;
|
||||
if( desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN ){
|
||||
if( !(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ){
|
||||
//try again in system memory!
|
||||
desc.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
|
||||
if( gfx->dirDraw->CreateSurface( &desc,&surf,0 )>=0 ) return surf;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Tom Speed's DXTC loader
|
||||
//
|
||||
IDirectDrawSurface7 *loadDXTC(const char* filename,gxGraphics *gfx)
|
||||
{
|
||||
HRESULT hr;
|
||||
DDSURFACEDESC2 ddsd;
|
||||
DDSURFACEDESC2 fileddsd;
|
||||
char magicID[4];
|
||||
FILE *fp;
|
||||
|
||||
/* try to open the file */
|
||||
fp = fopen(filename, "rb");
|
||||
if(!fp) return NULL;
|
||||
|
||||
/* valid DDS? */
|
||||
fread(magicID, 1, 4, fp);
|
||||
if (strncmp(magicID, "DDS ", 4) != 0)
|
||||
{
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get the DXTC file surface description */
|
||||
fread(&fileddsd, sizeof(DDSURFACEDESC2), 1, fp);
|
||||
|
||||
if (fileddsd.dwSize != sizeof(DDSURFACEDESC2))
|
||||
{
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy the fileddsd before we manipulate it so you
|
||||
can get neccessary info you want about it later */
|
||||
memcpy(&ddsd, &fileddsd,sizeof(DDSURFACEDESC2));
|
||||
|
||||
/* remove unwanted flags if they exist */
|
||||
//not sure if this is needed, works without it though
|
||||
//ddsd.dwFlags &= ~DDSD_LINEARSIZE;
|
||||
|
||||
int blockSize = 0;
|
||||
int chunkSize = 0;
|
||||
|
||||
if(ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1)
|
||||
blockSize = 8; // DXT1
|
||||
if(ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT3)
|
||||
blockSize = 16; // DXT3
|
||||
if(ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT5)
|
||||
blockSize = 16; // DXT5
|
||||
|
||||
/* if it isn't a format we support, exit */
|
||||
if (blockSize == 0)
|
||||
{
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add texture manage flag */
|
||||
ddsd.ddsCaps.dwCaps2|=DDSCAPS2_TEXTUREMANAGE;
|
||||
|
||||
/* Create the new DXTC surface using the DDSURFACEDESC2
|
||||
we read in from the file */
|
||||
IDirectDrawSurface7 * newSurf = NULL;
|
||||
hr = gfx->dirDraw->CreateSurface(&ddsd, &newSurf, NULL);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Define what type of child surfaces we may wish
|
||||
to access, in this case MipMaps */
|
||||
DDSCAPS2 mipmapddsd;
|
||||
ZeroMemory(&mipmapddsd,sizeof(DDSCAPS2));
|
||||
mipmapddsd.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_MIPMAP|DDSCAPS_COMPLEX;
|
||||
|
||||
/* pointers used when iterating through mipmaps */
|
||||
IDirectDrawSurface7 *topDDS = NULL;
|
||||
IDirectDrawSurface7 *nextDDS = NULL;
|
||||
|
||||
topDDS = newSurf;
|
||||
topDDS->AddRef();
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
/* get a description of this surface */
|
||||
hr = topDDS->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
fclose(fp);
|
||||
topDDS->Release();
|
||||
newSurf->Release();
|
||||
nextDDS->Release();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* how big the raw data is for this surface */
|
||||
chunkSize = ((ddsd.dwWidth+3)/4) * ((ddsd.dwHeight+3)/4) * blockSize;
|
||||
|
||||
/* read in the raw DXTC surface data */
|
||||
if(!fread(ddsd.lpSurface, chunkSize, 1, fp))
|
||||
{
|
||||
fclose(fp);
|
||||
topDDS->Release();
|
||||
newSurf->Release();
|
||||
nextDDS->Release();
|
||||
return NULL;
|
||||
}
|
||||
topDDS->Unlock(NULL);
|
||||
|
||||
|
||||
/* Get next mipmap in chain, or exit the loop if there's no more */
|
||||
hr = topDDS->GetAttachedSurface(&mipmapddsd,&nextDDS);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
fclose(fp);
|
||||
topDDS->Release();
|
||||
break;
|
||||
}
|
||||
|
||||
topDDS->Release();
|
||||
topDDS = nextDDS;
|
||||
nextDDS->Release();
|
||||
}
|
||||
|
||||
return newSurf;
|
||||
}
|
||||
|
||||
ddSurf *ddUtil::loadSurface( const std::string &f,int flags,gxGraphics *gfx ){
|
||||
|
||||
int i=f.find( ".dds" );
|
||||
if( i!=string::npos && i+4==f.size() ){
|
||||
//dds file!
|
||||
ddSurf *surf=loadDXTC( f.c_str(),gfx );
|
||||
return surf;
|
||||
}
|
||||
|
||||
FreeImage_Initialise();
|
||||
FREE_IMAGE_FORMAT fmt=FreeImage_GetFileType( f.c_str(),f.size() );
|
||||
if( fmt==FIF_UNKNOWN ){
|
||||
int n=f.find( "." );if( n==string::npos ) return 0;
|
||||
fmt=FreeImage_GetFileTypeFromExt( f.substr(n+1).c_str() );
|
||||
if( fmt==FIF_UNKNOWN ) return 0;
|
||||
}
|
||||
FIBITMAP *t_dib=FreeImage_Load( fmt,f.c_str(),0 );
|
||||
if( !t_dib ) return 0;
|
||||
|
||||
bool trans=FreeImage_GetBPP( t_dib )==32 || FreeImage_IsTransparent( t_dib );
|
||||
|
||||
FIBITMAP *dib=FreeImage_ConvertTo32Bits( t_dib );
|
||||
|
||||
if( dib ) FreeImage_Unload( t_dib );
|
||||
else dib=t_dib;
|
||||
|
||||
int width=FreeImage_GetWidth(dib);
|
||||
int height=FreeImage_GetHeight(dib);
|
||||
int pitch=FreeImage_GetPitch(dib);
|
||||
void *bits=FreeImage_GetBits(dib);
|
||||
|
||||
ddSurf *src=::createSurface( width,height,pitch,bits,gfx->dirDraw );
|
||||
if( !src ){
|
||||
FreeImage_Unload( dib );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( flags & gxCanvas::CANVAS_TEX_ALPHA ){
|
||||
if( flags & gxCanvas::CANVAS_TEX_MASK ){
|
||||
buildMask( src );
|
||||
}else if( !trans ){
|
||||
buildAlpha( src,(flags & gxCanvas::CANVAS_TEX_RGB)?false:true );
|
||||
}
|
||||
}else{
|
||||
unsigned char *p=(unsigned char *)bits;
|
||||
for( int k=0;k<height;++k ){
|
||||
unsigned char *t=p+3;
|
||||
for( int j=0;j<width;++j ){
|
||||
*t=0xff;t+=4;
|
||||
}
|
||||
p+=pitch;
|
||||
}
|
||||
}
|
||||
|
||||
ddSurf *dest=createSurface( width,height,flags,gfx );
|
||||
if( !dest ){
|
||||
src->Release();
|
||||
FreeImage_Unload( dib );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t_w=width,t_h=height;
|
||||
if( flags & gxCanvas::CANVAS_TEXTURE ) adjustTexSize( &t_w,&t_h,gfx->dir3dDev );
|
||||
copy( dest,0,0,t_w,t_h,src,0,height-1,width,-height );
|
||||
|
||||
src->Release();
|
||||
FreeImage_Unload( dib );
|
||||
return dest;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
#ifndef DDUTIL_H
|
||||
#define DDUTIL_H
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
class gxGraphics;
|
||||
typedef IDirectDrawSurface7 ddSurf;
|
||||
|
||||
struct ddUtil{
|
||||
|
||||
static void buildMipMaps( ddSurf *surf );
|
||||
static void copy( ddSurf *dest,int dx,int dy,int dw,int dh,ddSurf *src,int sx,int sy,int sw,int sh );
|
||||
static ddSurf *loadSurface( const std::string &f,int flags,gxGraphics *gfx );
|
||||
static ddSurf *createSurface( int width,int height,int flags,gxGraphics *gfx );
|
||||
};
|
||||
|
||||
class PixelFormat{
|
||||
int depth,pitch;
|
||||
unsigned amask,rmask,gmask,bmask,argbfill;
|
||||
unsigned char ashr,ashl,rshr,rshl,gshr,gshl,bshr,bshl;
|
||||
typedef void (_fastcall *Plot)(void *pix,unsigned argb);
|
||||
typedef unsigned (_fastcall *Point)(void *pix);
|
||||
Plot plot;
|
||||
Point point;
|
||||
|
||||
char *plot_code,*point_code;
|
||||
|
||||
public:
|
||||
PixelFormat():plot_code(0){
|
||||
}
|
||||
|
||||
PixelFormat( const DDPIXELFORMAT &pf ):plot_code(0){
|
||||
setFormat( pf );
|
||||
}
|
||||
|
||||
~PixelFormat();
|
||||
|
||||
void setFormat( const DDPIXELFORMAT &pf );
|
||||
|
||||
int getDepth()const{
|
||||
return depth;
|
||||
}
|
||||
int getPitch()const{
|
||||
return pitch;
|
||||
}
|
||||
unsigned fromARGB( unsigned n )const{
|
||||
return ( (n>>ashr<<ashl)&amask ) | ( (n>>rshr<<rshl)&rmask ) | ( (n>>gshr<<gshl)&gmask ) | ( (n>>bshr<<bshl)&bmask );
|
||||
}
|
||||
unsigned toARGB( unsigned n )const{
|
||||
return ( (n&amask)>>ashl<<ashr ) | ( (n&rmask)>>rshl<<rshr ) | ( (n&gmask)>>gshl<<gshr ) | ( (n&bmask)>>bshl<<bshr ) | argbfill;
|
||||
}
|
||||
void setPixel( void *p,unsigned n )const{ plot(p,n); }
|
||||
unsigned getPixel( void *p )const{ return point(p); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,285 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxaudio.h"
|
||||
|
||||
struct StaticChannel : public gxChannel{
|
||||
virtual void play()=0;
|
||||
};
|
||||
|
||||
struct SoundChannel : public gxChannel{
|
||||
SoundChannel():channel(-1){
|
||||
}
|
||||
void set( int n ){
|
||||
channel=n;
|
||||
}
|
||||
void stop(){
|
||||
FSOUND_StopSound( channel );
|
||||
}
|
||||
void setPaused( bool paused ){
|
||||
FSOUND_SetPaused( channel,paused );
|
||||
}
|
||||
void setPitch( int pitch ){
|
||||
FSOUND_SetFrequency( channel,pitch );
|
||||
}
|
||||
void setVolume( float volume ){
|
||||
FSOUND_SetVolume( channel,volume * 255.0f );
|
||||
}
|
||||
void setPan( float pan ){
|
||||
FSOUND_SetPan( channel,(pan+1)*127.5f );
|
||||
}
|
||||
void set3d( const float pos[3],const float vel[3] ){
|
||||
FSOUND_3D_SetAttributes( channel,(float*)pos,(float*)vel );
|
||||
}
|
||||
bool isPlaying(){
|
||||
return FSOUND_IsPlaying( channel ) ? true : false;
|
||||
}
|
||||
private:
|
||||
int channel;
|
||||
};
|
||||
|
||||
struct CDChannel : public gxChannel{
|
||||
void play( int track,int mode ){
|
||||
stop();
|
||||
int cd_mode=FSOUND_CD_PLAYONCE;
|
||||
if( mode==gxAudio::CD_MODE_LOOP ) cd_mode=FSOUND_CD_PLAYLOOPED;
|
||||
else if( mode==gxAudio::CD_MODE_ALL ) cd_mode=FSOUND_CD_PLAYCONTINUOUS;
|
||||
FSOUND_CD_SetPlayMode( 0,cd_mode );
|
||||
FSOUND_CD_Play( 0,track );
|
||||
}
|
||||
void stop(){
|
||||
FSOUND_CD_Stop(0 );
|
||||
}
|
||||
void setPaused( bool paused ){
|
||||
FSOUND_CD_SetPaused( 0,paused );
|
||||
}
|
||||
void setPitch( int pitch ){
|
||||
}
|
||||
void setVolume( float volume ){
|
||||
FSOUND_CD_SetVolume( 0,volume*255.0f );
|
||||
}
|
||||
void setPan( float pan ){
|
||||
}
|
||||
void set3d( const float pos[3],const float vel[3] ){
|
||||
}
|
||||
bool isPlaying(){
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct StreamChannel : public StaticChannel{
|
||||
StreamChannel( FSOUND_STREAM *s ):stream(s){
|
||||
channel=FSOUND_Stream_Play( FSOUND_FREE,stream );
|
||||
}
|
||||
~StreamChannel(){
|
||||
FSOUND_Stream_Close( stream );
|
||||
}
|
||||
void play(){
|
||||
stop();
|
||||
channel=FSOUND_Stream_Play( FSOUND_FREE,stream );
|
||||
}
|
||||
void stop(){
|
||||
FSOUND_Stream_Stop( stream );
|
||||
channel=-1;
|
||||
}
|
||||
void setPaused( bool paused ){
|
||||
FSOUND_SetPaused( channel,paused );
|
||||
}
|
||||
void setPitch( int pitch ){
|
||||
FSOUND_SetFrequency( channel,pitch );
|
||||
}
|
||||
void setVolume( float volume ){
|
||||
FSOUND_SetVolume( channel,volume * 255.0f );
|
||||
}
|
||||
void setPan( float pan ){
|
||||
FSOUND_SetPan( channel,(pan+1)*127.5f );
|
||||
}
|
||||
void set3d( const float pos[3],const float vel[3] ){
|
||||
}
|
||||
bool isPlaying(){
|
||||
return FSOUND_IsPlaying( channel ) ? true : false;
|
||||
}
|
||||
private:
|
||||
FSOUND_STREAM *stream;
|
||||
int channel;
|
||||
};
|
||||
|
||||
struct MusicChannel : public StaticChannel{
|
||||
MusicChannel( FMUSIC_MODULE *m ):module(m){
|
||||
play();
|
||||
}
|
||||
~MusicChannel(){
|
||||
FMUSIC_FreeSong( module );
|
||||
}
|
||||
void play(){
|
||||
FMUSIC_PlaySong( module );
|
||||
}
|
||||
void stop(){
|
||||
FMUSIC_StopSong( module );
|
||||
}
|
||||
void setPaused( bool paused ){
|
||||
FMUSIC_SetPaused( module,paused );
|
||||
}
|
||||
void setPitch( int pitch ){
|
||||
}
|
||||
void setVolume( float volume ){
|
||||
FMUSIC_SetMasterVolume( module,volume*255.0f );
|
||||
}
|
||||
void setPan( float pan ){
|
||||
}
|
||||
void set3d( const float pos[3],const float vel[3] ){
|
||||
}
|
||||
bool isPlaying(){
|
||||
return FMUSIC_IsFinished( module ) ? false : true;
|
||||
}
|
||||
private:
|
||||
FMUSIC_MODULE *module;
|
||||
};
|
||||
|
||||
static set<gxSound*> sound_set;
|
||||
static vector<gxChannel*> channels;
|
||||
static map<string,StaticChannel*> songs;
|
||||
static CDChannel *cdChannel;
|
||||
|
||||
static int next_chan;
|
||||
static vector<SoundChannel*> soundChannels;
|
||||
|
||||
static gxChannel *allocSoundChannel( int n ){
|
||||
|
||||
SoundChannel *chan=0;
|
||||
for( int k=0;k<soundChannels.size();++k ){
|
||||
chan=soundChannels[next_chan];
|
||||
if( !chan ){
|
||||
chan=soundChannels[next_chan]=d_new SoundChannel();
|
||||
channels.push_back(chan);
|
||||
}else if( chan->isPlaying() ){
|
||||
chan=0;
|
||||
}
|
||||
if( ++next_chan==soundChannels.size() ) next_chan=0;
|
||||
if( chan ) break;
|
||||
}
|
||||
|
||||
if( !chan ){
|
||||
next_chan=soundChannels.size();
|
||||
soundChannels.resize(soundChannels.size()*2);
|
||||
for( int k=next_chan;k<soundChannels.size();++k ) soundChannels[k]=0;
|
||||
chan=soundChannels[next_chan++]=d_new SoundChannel();
|
||||
channels.push_back( chan );
|
||||
}
|
||||
|
||||
chan->set(n);
|
||||
return chan;
|
||||
}
|
||||
|
||||
gxAudio::gxAudio( gxRuntime *r ):
|
||||
runtime(r){
|
||||
next_chan=0;
|
||||
soundChannels.resize( 4096 );
|
||||
for( int k=0;k<4096;++k ) soundChannels[k]=0;
|
||||
|
||||
cdChannel=d_new CDChannel();
|
||||
channels.push_back( cdChannel );
|
||||
}
|
||||
|
||||
gxAudio::~gxAudio(){
|
||||
//free all channels
|
||||
for( ;channels.size();channels.pop_back() ) delete channels.back();
|
||||
//free all sound_set
|
||||
while( sound_set.size() ) freeSound( *sound_set.begin() );
|
||||
soundChannels.clear();
|
||||
songs.clear();
|
||||
|
||||
FSOUND_Close();
|
||||
}
|
||||
|
||||
gxChannel *gxAudio::play( FSOUND_SAMPLE *sample ){
|
||||
|
||||
int n=FSOUND_PlaySound( FSOUND_FREE,sample );
|
||||
return n>=0 ? allocSoundChannel( n ) : 0;
|
||||
}
|
||||
|
||||
gxChannel *gxAudio::play3d( FSOUND_SAMPLE *sample,const float pos[3],const float vel[3] ){
|
||||
|
||||
int n=FSOUND_PlaySoundEx( FSOUND_FREE,sample,0,true );
|
||||
if( n<0 ) return 0;
|
||||
FSOUND_3D_SetAttributes( n,(float*)pos,(float*)vel );
|
||||
FSOUND_SetPaused( n,false );
|
||||
return allocSoundChannel( n );
|
||||
}
|
||||
|
||||
void gxAudio::pause(){
|
||||
}
|
||||
|
||||
void gxAudio::resume(){
|
||||
}
|
||||
|
||||
gxSound *gxAudio::loadSound( const string &f,bool use3d ){
|
||||
|
||||
int flags=FSOUND_NORMAL | (use3d ? FSOUND_FORCEMONO : FSOUND_2D);
|
||||
|
||||
FSOUND_SAMPLE *sample=FSOUND_Sample_Load( FSOUND_FREE,f.c_str(),flags,0,0 );
|
||||
if( !sample ) return 0;
|
||||
|
||||
gxSound *sound=d_new gxSound( this,sample );
|
||||
sound_set.insert( sound );
|
||||
return sound;
|
||||
}
|
||||
|
||||
gxSound *gxAudio::verifySound( gxSound *s ){
|
||||
return sound_set.count( s ) ? s : 0;
|
||||
}
|
||||
|
||||
void gxAudio::freeSound( gxSound *s ){
|
||||
if( sound_set.erase( s ) ) delete s;
|
||||
}
|
||||
|
||||
void gxAudio::setPaused( bool paused ){
|
||||
FSOUND_SetPaused( FSOUND_ALL,paused );
|
||||
}
|
||||
|
||||
void gxAudio::setVolume( float volume ){
|
||||
}
|
||||
|
||||
void gxAudio::set3dOptions( float roll,float dopp,float dist ){
|
||||
FSOUND_3D_SetRolloffFactor( roll );
|
||||
FSOUND_3D_SetDopplerFactor( dopp );
|
||||
FSOUND_3D_SetDistanceFactor( dist );
|
||||
}
|
||||
|
||||
void gxAudio::set3dListener( const float pos[3],const float vel[3],const float forward[3],const float up[3] ){
|
||||
FSOUND_3D_Listener_SetAttributes( (float*)pos,(float*)vel,forward[0],forward[1],forward[2],up[0],up[1],up[2] );
|
||||
FSOUND_Update();
|
||||
}
|
||||
|
||||
gxChannel *gxAudio::playFile( const string &t,bool use_3d ){
|
||||
string f=tolower( t );
|
||||
StaticChannel *chan=0;
|
||||
map<string,StaticChannel*>::iterator it=songs.find(f);
|
||||
if( it!=songs.end() ){
|
||||
chan=it->second;
|
||||
chan->play();
|
||||
return chan;
|
||||
}else if(
|
||||
f.find( ".raw" )!=string::npos ||
|
||||
f.find( ".wav" )!=string::npos ||
|
||||
f.find( ".mp2" )!=string::npos ||
|
||||
f.find( ".mp3" )!=string::npos ||
|
||||
f.find( ".ogg" )!=string::npos ||
|
||||
f.find( ".wma" )!=string::npos ||
|
||||
f.find( ".asf" )!=string::npos ){
|
||||
FSOUND_STREAM *stream=FSOUND_Stream_Open( f.c_str(),use_3d,0,0 );
|
||||
if( !stream ) return 0;
|
||||
chan=d_new StreamChannel( stream );
|
||||
}else{
|
||||
FMUSIC_MODULE *module=FMUSIC_LoadSong( f.c_str() );
|
||||
if( !module ) return 0;
|
||||
chan=d_new MusicChannel( module );
|
||||
}
|
||||
channels.push_back( chan );
|
||||
songs[f]=chan;
|
||||
return chan;
|
||||
}
|
||||
|
||||
gxChannel *gxAudio::playCDTrack( int track,int mode ){
|
||||
cdChannel->play( track,mode );
|
||||
return cdChannel;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
#ifndef GXAUDIO_H
|
||||
#define GXAUDIO_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gxsound.h"
|
||||
|
||||
class gxRuntime;
|
||||
struct FSOUND_SAMPLE;
|
||||
|
||||
class gxAudio{
|
||||
public:
|
||||
gxRuntime *runtime;
|
||||
|
||||
gxAudio( gxRuntime *runtime );
|
||||
~gxAudio();
|
||||
|
||||
gxChannel *play( FSOUND_SAMPLE *sample );
|
||||
gxChannel *play3d( FSOUND_SAMPLE *sample,const float pos[3],const float vel[3] );
|
||||
|
||||
void pause();
|
||||
void resume();
|
||||
|
||||
private:
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
CD_MODE_ONCE=1,CD_MODE_LOOP,CD_MODE_ALL
|
||||
};
|
||||
|
||||
gxSound *loadSound( const std::string &filename,bool use_3d );
|
||||
gxSound *verifySound( gxSound *sound );
|
||||
void freeSound( gxSound *sound );
|
||||
|
||||
void setPaused( bool paused ); //master pause
|
||||
void setVolume( float volume ); //master volume
|
||||
|
||||
void set3dOptions( float roll,float dopp,float dist );
|
||||
|
||||
void set3dListener( const float pos[3],const float vel[3],const float forward[3],const float up[3] );
|
||||
|
||||
gxChannel *playCDTrack( int track,int mode );
|
||||
gxChannel *playFile( const std::string &filename,bool use_3d );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,724 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxcanvas.h"
|
||||
#include "gxgraphics.h"
|
||||
#include "gxruntime.h"
|
||||
#include "asmcoder.h"
|
||||
|
||||
#define DEBUG_BITMASK
|
||||
|
||||
static int canvas_cnt;
|
||||
static DDBLTFX bltfx={sizeof(DDBLTFX)};
|
||||
|
||||
extern gxRuntime *gx_runtime;
|
||||
|
||||
static unsigned FWMS[]={
|
||||
0xffffffff,0x7fffffff,0x3fffffff,0x1fffffff,
|
||||
0x0fffffff,0x07ffffff,0x03ffffff,0x01ffffff,
|
||||
0x00ffffff,0x007fffff,0x003fffff,0x001fffff,
|
||||
0x000fffff,0x0007ffff,0x0003ffff,0x0001ffff,
|
||||
0x0000ffff,0x00007fff,0x00003fff,0x00001fff,
|
||||
0x00000fff,0x000007ff,0x000003ff,0x000001ff,
|
||||
0x000000ff,0x0000007f,0x0000003f,0x0000001f,
|
||||
0x0000000f,0x00000007,0x00000003,0x00000001};
|
||||
static unsigned LWMS[]={
|
||||
0x80000000,0xc0000000,0xe0000000,0xf0000000,
|
||||
0xf8000000,0xfc000000,0xfe000000,0xff000000,
|
||||
0xff800000,0xffc00000,0xffe00000,0xfff00000,
|
||||
0xfff80000,0xfffc0000,0xfffe0000,0xffff0000,
|
||||
0xffff8000,0xffffc000,0xffffe000,0xfffff000,
|
||||
0xfffff800,0xfffffc00,0xfffffe00,0xffffff00,
|
||||
0xffffff80,0xffffffc0,0xffffffe0,0xfffffff0,
|
||||
0xfffffff8,0xfffffffc,0xfffffffe,0xffffffff};
|
||||
|
||||
static void calcShifts( unsigned mask,unsigned char *shr,unsigned char *shl ){
|
||||
if( mask ){
|
||||
for( *shl=0;!(mask&1);++*shl,mask>>=1 ){}
|
||||
for( *shr=8;mask&1;--*shr,mask>>=1 ){}
|
||||
}else *shr=*shl=0;
|
||||
}
|
||||
|
||||
struct Rect : public RECT{
|
||||
Rect(){
|
||||
}
|
||||
Rect( int x,int y,int w,int h ){
|
||||
left=x;top=y;right=x+w;bottom=y+h;
|
||||
}
|
||||
};
|
||||
|
||||
static bool clip( const RECT &viewport,RECT *d ){
|
||||
if( d->right<=d->left ||
|
||||
d->bottom<=d->top ||
|
||||
d->left>=viewport.right ||
|
||||
d->right<=viewport.left ||
|
||||
d->top>=viewport.bottom ||
|
||||
d->bottom<=viewport.top ) return false;
|
||||
if( d->left<viewport.left ) d->left=viewport.left;
|
||||
if( d->right>viewport.right ) d->right=viewport.right;
|
||||
if( d->top<viewport.top ) d->top=viewport.top;
|
||||
if( d->bottom>viewport.bottom ) d->bottom=viewport.bottom;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool clip( const RECT &viewport,RECT *d,RECT *s ){
|
||||
if( d->right<=d->left ||
|
||||
d->bottom<=d->top ||
|
||||
d->left>=viewport.right ||
|
||||
d->right<=viewport.left ||
|
||||
d->top>=viewport.bottom ||
|
||||
d->bottom<=viewport.top ) return false;
|
||||
int dx,dy;
|
||||
if( (dx=viewport.left-d->left)>0 ){ d->left+=dx;s->left+=dx; }
|
||||
if( (dx=viewport.right-d->right)<0 ){ d->right+=dx;s->right+=dx; }
|
||||
if( (dy=viewport.top-d->top)>0 ){ d->top+=dy;s->top+=dy; }
|
||||
if( (dy=viewport.bottom-d->bottom)<0 ){ d->bottom+=dy;s->bottom+=dy; }
|
||||
return true;
|
||||
}
|
||||
|
||||
gxCanvas::gxCanvas( gxGraphics *g,IDirectDrawSurface7 *s,int f ):
|
||||
graphics(g),main_surf(s),surf(0),z_surf(0),flags(f),cube_mode(CUBEMODE_REFLECTION|CUBESPACE_WORLD),
|
||||
t_surf(0),cm_mask(0),locked_cnt(0),mod_cnt(0),remip_cnt(0){
|
||||
|
||||
if( flags & CANVAS_TEX_CUBE ){
|
||||
cube_surfs[2]=main_surf;
|
||||
for( int k=0;k<6;++k ){
|
||||
if( k==2 ) continue;
|
||||
DWORD n;
|
||||
switch( k ){
|
||||
case 0:n=DDSCAPS2_CUBEMAP_NEGATIVEX;break;
|
||||
case 1:n=DDSCAPS2_CUBEMAP_POSITIVEZ;break;
|
||||
case 2:n=DDSCAPS2_CUBEMAP_POSITIVEX;break;
|
||||
case 3:n=DDSCAPS2_CUBEMAP_NEGATIVEZ;break;
|
||||
case 4:n=DDSCAPS2_CUBEMAP_POSITIVEY;break;
|
||||
case 5:n=DDSCAPS2_CUBEMAP_NEGATIVEY;break;
|
||||
default:return;
|
||||
}
|
||||
DDSCAPS2 caps={0};
|
||||
caps.dwCaps2=DDSCAPS2_CUBEMAP|n;
|
||||
main_surf->GetAttachedSurface( &caps,&cube_surfs[k] );
|
||||
}
|
||||
surf=cube_surfs[1];
|
||||
}else{
|
||||
surf=main_surf;
|
||||
memset( cube_surfs,0,sizeof(cube_surfs) );
|
||||
}
|
||||
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
surf->GetSurfaceDesc( &desc );
|
||||
format.setFormat( desc.ddpfPixelFormat );
|
||||
|
||||
clip_rect.left=clip_rect.top=0;
|
||||
clip_rect.right=desc.dwWidth;
|
||||
clip_rect.bottom=desc.dwHeight;
|
||||
cm_pitch=(clip_rect.right+31)/32+1;
|
||||
setMask( 0 );
|
||||
setColor( ~0 );
|
||||
setClsColor( 0 );
|
||||
setOrigin( 0,0 );
|
||||
setHandle( 0,0 );
|
||||
setFont( graphics->getDefaultFont() );
|
||||
setViewport( 0,0,getWidth(),getHeight() );
|
||||
if( flags & gxCanvas::CANVAS_TEXTURE ) ddUtil::buildMipMaps( surf );
|
||||
}
|
||||
|
||||
gxCanvas::~gxCanvas(){
|
||||
delete[] cm_mask;
|
||||
if( locked_cnt ) surf->Unlock( 0 );
|
||||
if( t_surf ) t_surf->Release();
|
||||
releaseZBuffer();
|
||||
main_surf->Release();
|
||||
}
|
||||
|
||||
void gxCanvas::backup()const{
|
||||
if( flags & CANVAS_TEX_CUBE ) return;
|
||||
|
||||
if( !t_surf ){
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
if( surf->GetSurfaceDesc(&desc)<0 ) return;
|
||||
if( desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) return;
|
||||
|
||||
DDSURFACEDESC2 t_desc={sizeof(t_desc)};
|
||||
t_desc.dwFlags=DDSD_CAPS|DDSD_PIXELFORMAT|DDSD_WIDTH|DDSD_HEIGHT;
|
||||
t_desc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
|
||||
t_desc.dwWidth=desc.dwWidth;t_desc.dwHeight=desc.dwHeight;
|
||||
t_desc.ddpfPixelFormat=desc.ddpfPixelFormat;
|
||||
|
||||
if( graphics->dirDraw->CreateSurface( &t_desc,&t_surf,0 )<0 ){
|
||||
t_surf=0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( t_surf->Blt( 0,surf,0,DDBLT_WAIT,0 )<0 ) return;
|
||||
}
|
||||
|
||||
void gxCanvas::restore()const{
|
||||
if( !t_surf ) return;
|
||||
|
||||
if( surf->Blt( 0,t_surf,0,DDBLT_WAIT,0 )<0 ) return;
|
||||
}
|
||||
|
||||
ddSurf *gxCanvas::getSurface()const{
|
||||
return surf;
|
||||
}
|
||||
|
||||
ddSurf *gxCanvas::getTexSurface()const{
|
||||
if( mod_cnt==remip_cnt ) return main_surf;
|
||||
ddUtil::buildMipMaps( surf );
|
||||
remip_cnt=mod_cnt;
|
||||
return main_surf;
|
||||
}
|
||||
|
||||
bool gxCanvas::clip( RECT *d )const{
|
||||
return ::clip( viewport,d );
|
||||
}
|
||||
|
||||
bool gxCanvas::clip( RECT *d,RECT *s )const{
|
||||
return ::clip( viewport,d,s );
|
||||
}
|
||||
|
||||
void gxCanvas::updateBitMask( const RECT &r )const{
|
||||
|
||||
int w=r.right-r.left;if( w<=0 ) return;
|
||||
int h=r.bottom-r.top;if( h<=0 ) return;
|
||||
|
||||
lock();
|
||||
RECT t=r;
|
||||
t.left&=~31;
|
||||
t.right=(t.right+31)&~31;
|
||||
w=(t.right-t.left)/32;
|
||||
unsigned char *src_row=locked_surf+t.top*locked_pitch+t.left*format.getPitch();
|
||||
unsigned *dest_row=cm_mask+t.top*cm_pitch+t.left/32;
|
||||
unsigned mask_argb=format.toARGB( mask_surf ) & 0xffffff;
|
||||
|
||||
#ifdef DEBUG_BITMASK
|
||||
unsigned *cm_mask_end=cm_mask+cm_pitch*clip_rect.bottom;
|
||||
#endif
|
||||
|
||||
while( h-- ){
|
||||
unsigned *dest=dest_row;
|
||||
unsigned char *src=src_row;
|
||||
for( int c=0;c<w;++c ){
|
||||
unsigned mask=0;
|
||||
for( int x=0;x<32;++x ){
|
||||
unsigned pix=format.getPixel(src) & 0xffffff;
|
||||
mask=(mask<<1)|(pix!=mask_argb);
|
||||
src+=format.getPitch();
|
||||
}
|
||||
#ifdef DEBUG_BITMASK
|
||||
if( dest<cm_mask || dest>=cm_mask_end ){
|
||||
gx_runtime->debugError( "gxCanvas::updateBitMask dest out of range" );
|
||||
}
|
||||
#endif
|
||||
*dest++=mask;
|
||||
}
|
||||
dest_row+=cm_pitch;
|
||||
src_row+=locked_pitch;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void gxCanvas::setModify( int n ){
|
||||
mod_cnt=n;
|
||||
}
|
||||
|
||||
int gxCanvas::getModify()const{
|
||||
return mod_cnt;
|
||||
}
|
||||
|
||||
bool gxCanvas::attachZBuffer(){
|
||||
if( z_surf ) return true;
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
desc.dwFlags=DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT;
|
||||
desc.dwWidth=getWidth();
|
||||
desc.dwHeight=getHeight();
|
||||
desc.ddsCaps.dwCaps=DDSCAPS_ZBUFFER|DDSCAPS_VIDEOMEMORY;
|
||||
desc.ddpfPixelFormat=graphics->zbuffFmt;
|
||||
if( graphics->dirDraw->CreateSurface( &desc,&z_surf,0 )<0 ) return false;
|
||||
surf->AddAttachedSurface( z_surf );
|
||||
return true;
|
||||
}
|
||||
|
||||
void gxCanvas::releaseZBuffer(){
|
||||
if( !z_surf ) return;
|
||||
surf->DeleteAttachedSurface( 0,z_surf );
|
||||
z_surf->Release();
|
||||
z_surf=0;
|
||||
}
|
||||
|
||||
void gxCanvas::damage( const RECT &r )const{
|
||||
++mod_cnt;if( cm_mask ) updateBitMask( r );
|
||||
}
|
||||
|
||||
void gxCanvas::setFont( gxFont *f ){
|
||||
font=f;
|
||||
}
|
||||
|
||||
void gxCanvas::setMask( unsigned argb ){
|
||||
mask_surf=format.fromARGB( argb );
|
||||
}
|
||||
|
||||
void gxCanvas::setColor( unsigned argb ){
|
||||
argb|=0xff000000;
|
||||
color_argb=argb;
|
||||
color_surf=format.fromARGB( argb );
|
||||
}
|
||||
|
||||
void gxCanvas::setClsColor( unsigned argb ){
|
||||
argb|=0xff000000;
|
||||
clsColor_surf=format.fromARGB( argb );
|
||||
}
|
||||
|
||||
void gxCanvas::setOrigin( int x,int y ){
|
||||
origin_x=x;origin_y=y;
|
||||
}
|
||||
|
||||
void gxCanvas::setHandle( int x,int y ){
|
||||
handle_x=x;handle_y=y;
|
||||
}
|
||||
|
||||
void gxCanvas::setViewport( int x,int y,int w,int h ){
|
||||
Rect r( x,y,w,h );
|
||||
if( !::clip( clip_rect,&r ) ) r=Rect(0,0,0,0);
|
||||
viewport=r;
|
||||
}
|
||||
|
||||
//renderering primitives
|
||||
void gxCanvas::cls(){
|
||||
bltfx.dwFillColor=clsColor_surf;
|
||||
surf->Blt( &viewport,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
damage( viewport );
|
||||
}
|
||||
|
||||
void gxCanvas::plot( int x,int y ){
|
||||
x+=origin_x;if( x<viewport.left || x>=viewport.right ) return;
|
||||
y+=origin_y;if( y<viewport.top || y>=viewport.bottom ) return;
|
||||
bltfx.dwFillColor=color_surf;
|
||||
Rect dest( x,y,1,1 );
|
||||
surf->Blt( &dest,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
damage( dest );
|
||||
}
|
||||
|
||||
void gxCanvas::line( int x0,int y0,int x1,int y1 ){
|
||||
int ddf,padj,sadj;
|
||||
int dx,dy,sx,sy,ax,ay;
|
||||
|
||||
x0+=origin_x;y0+=origin_y;
|
||||
x1+=origin_x;y1+=origin_y;
|
||||
|
||||
int cx0,cx1,cy0,cy1,clip0,clip1;
|
||||
|
||||
cx0=viewport.left;
|
||||
cx1=viewport.right-1;
|
||||
cy0=viewport.top;
|
||||
cy1=viewport.bottom-1;
|
||||
|
||||
while( true ){
|
||||
clip0=0;clip1=0;
|
||||
|
||||
if(y0>cy1)clip0|=1;else if(y0<cy0)clip0|=2;
|
||||
if(x0>cx1)clip0|=4;else if(x0<cx0)clip0|=8;
|
||||
if(y1>cy1)clip1|=1;else if(y1<cy0)clip1|=2;
|
||||
if(x1>cx1)clip1|=4;else if(x1<cx0)clip1|=8;
|
||||
|
||||
if((clip0|clip1)==0) break; //draw line
|
||||
if((clip0&clip1)!=0) return; //outside
|
||||
|
||||
if((clip0&1)==1) {x0=x0+((x1-x0)*(cy1-y0))/(y1-y0);y0=cy1;continue;}
|
||||
if((clip0&2)==2) {x0=x0+((x1-x0)*(cy0-y0))/(y1-y0);y0=cy0;continue;}
|
||||
if((clip0&4)==4) {y0=y0+((y1-y0)*(cx1-x0))/(x1-x0);x0=cx1;continue;}
|
||||
if((clip0&8)==8) {y0=y0+((y1-y0)*(cx0-x0))/(x1-x0);x0=cx0;continue;}
|
||||
|
||||
if((clip1&1)==1) {x1=x0+((x1-x0)*(cy1-y0))/(y1-y0);y1=cy1;continue;}
|
||||
if((clip1&2)==2) {x1=x0+((x1-x0)*(cy0-y0))/(y1-y0);y1=cy0;continue;}
|
||||
if((clip1&4)==4) {y1=y0+((y1-y0)*(cx1-x0))/(x1-x0);x1=cx1;continue;}
|
||||
if((clip1&8)==8) {y1=y0+((y1-y0)*(cx0-x0))/(x1-x0);x1=cx0;continue;}
|
||||
}
|
||||
|
||||
dx=x1-x0;dy=y1-y0;
|
||||
if( (dx|dy)==0 ){
|
||||
setPixel( x0,y0,color_argb );
|
||||
return;
|
||||
}
|
||||
|
||||
if (dx>=0) {sx=1;ax=dx;} else {sx=-1;ax=-dx;}
|
||||
if (dy>=0) {sy=1;ay=dy;} else {sy=-1;ay=-dy;}
|
||||
|
||||
lock();
|
||||
if( ax>ay ){
|
||||
ddf=-ax;sadj=ax+ax;padj=ay+ay;
|
||||
while( ax-->=0 ){
|
||||
setPixelFast( x0,y0,color_argb );
|
||||
x0+=sx;ddf+=padj;if( ddf>=0 ){ y0+=sy;ddf-=sadj; }
|
||||
}
|
||||
}else{
|
||||
ddf=-ay;sadj=ay+ay;padj=ax+ax;
|
||||
while( ay-->=0 ){
|
||||
setPixelFast( x0,y0,color_argb );
|
||||
y0+=sy;ddf+=padj;if( ddf>=0 ){ x0+=sx;ddf-=sadj; }
|
||||
}
|
||||
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void gxCanvas::rect( int x,int y,int w,int h,bool solid ){
|
||||
x+=origin_x;y+=origin_y;
|
||||
Rect dest( x,y,w,h );
|
||||
if( !clip( &dest ) ) return;
|
||||
|
||||
bltfx.dwFillColor=color_surf;
|
||||
|
||||
if( solid ){
|
||||
surf->Blt( &dest,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
damage( dest );
|
||||
return;
|
||||
}
|
||||
Rect r1( x,y,w,1 );if( clip( &r1 ) ){
|
||||
surf->Blt( &r1,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
}
|
||||
Rect r2( x,y,1,h );if( clip( &r2 ) ){
|
||||
surf->Blt( &r2,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
}
|
||||
Rect r3( x+w-1,y,1,h );if( clip( &r3 ) ){
|
||||
surf->Blt( &r3,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
}
|
||||
Rect r4( x,y+h-1,w,1 );if( clip( &r4 ) ){
|
||||
surf->Blt( &r4,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
}
|
||||
damage( dest );
|
||||
}
|
||||
|
||||
void gxCanvas::oval( int x1,int y1,int w,int h,bool solid ){
|
||||
x1+=origin_x;y1+=origin_y;
|
||||
Rect dest( x1,y1,w,h );
|
||||
if( !clip( &dest ) ) return;
|
||||
|
||||
bltfx.dwFillColor=color_surf;
|
||||
|
||||
float xr=w*.5f,yr=h*.5f,ar=(float)w/(float)h;
|
||||
float cx=x1+xr+.5f,cy=y1+yr-.5f,rsq=yr*yr,y;
|
||||
|
||||
if( solid ){
|
||||
y=dest.top-cy;
|
||||
for( int t=dest.top;t<dest.bottom;++y,++t ){
|
||||
float x=sqrt( rsq-y*y )*ar;
|
||||
int xa=floor( cx-x ),xb=floor( cx+x );
|
||||
if( xb<=xa || xa>=viewport.right || xb<=viewport.left ) continue;
|
||||
Rect dr;dr.top=t;dr.bottom=t+1;
|
||||
dr.left=xa<viewport.left ? viewport.left : xa;
|
||||
dr.right=xb>viewport.right ? viewport.right : xb;
|
||||
surf->Blt( &dr,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
}
|
||||
damage( dest );
|
||||
return;
|
||||
}
|
||||
|
||||
int p_xa,p_xb,t,hh=floor(cy);
|
||||
|
||||
p_xa=p_xb=cx;
|
||||
t=dest.top;y=t-cy;
|
||||
if( dest.top>y1 ){ --t;--y; }
|
||||
for( ;t<=hh;++y,++t ){
|
||||
float x=sqrt( rsq-y*y )*ar;
|
||||
int xa=floor( cx-x ),xb=floor( cx+x );
|
||||
Rect r1( xa,t,p_xa-xa,1 );if( r1.right<=r1.left ) r1.right=r1.left+1;
|
||||
if( clip( &r1 ) ) surf->Blt( &r1,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
Rect r2( p_xb,t,xb-p_xb,1 );if( r2.left>=r2.right ) r2.left=r2.right-1;
|
||||
if( clip( &r2 ) ) surf->Blt( &r2,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
p_xa=xa;p_xb=xb;
|
||||
}
|
||||
|
||||
p_xa=p_xb=cx;
|
||||
t=dest.bottom-1;y=t-cy;
|
||||
if( dest.bottom<y1+h ){ ++t;++y; }
|
||||
for( ;t>hh;--y,--t ){
|
||||
float x=sqrt( rsq-y*y )*ar;
|
||||
int xa=floor( cx-x ),xb=floor( cx+x );
|
||||
Rect r1( xa,t,p_xa-xa,1 );if( r1.right<=r1.left ) r1.right=r1.left+1;
|
||||
if( clip( &r1 ) ) surf->Blt( &r1,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
Rect r2( p_xb,t,xb-p_xb,1 );if( r2.left>=r2.right ) r2.left=r2.right-1;
|
||||
if( clip( &r2 ) ) surf->Blt( &r2,0,0,DDBLT_WAIT|DDBLT_COLORFILL,&bltfx );
|
||||
p_xa=xa;p_xb=xb;
|
||||
}
|
||||
damage( dest );
|
||||
}
|
||||
|
||||
void gxCanvas::blit( int x,int y,gxCanvas *src,int src_x,int src_y,int src_w,int src_h,bool solid ){
|
||||
x+=origin_x-src->handle_x;
|
||||
y+=origin_y-src->handle_y;
|
||||
Rect dest_r( x,y,src_w,src_h ),src_r( src_x,src_y,src_w,src_h );
|
||||
if( !clip( &dest_r,&src_r ) ) return;
|
||||
if( !::clip( src->clip_rect,&src_r,&dest_r ) ) return;
|
||||
|
||||
if( solid ){
|
||||
surf->Blt( &dest_r,src->surf,&src_r,DDBLT_WAIT,0 );
|
||||
}else{
|
||||
bltfx.ddckSrcColorkey.dwColorSpaceLowValue=
|
||||
bltfx.ddckSrcColorkey.dwColorSpaceHighValue=src->mask_surf;
|
||||
surf->Blt( &dest_r,src->surf,&src_r,DDBLT_WAIT|DDBLT_KEYSRCOVERRIDE,&bltfx );
|
||||
}
|
||||
damage( dest_r );
|
||||
}
|
||||
|
||||
void gxCanvas::text( int x,int y,const string &t ){
|
||||
|
||||
int ty=y+origin_y;
|
||||
if( ty>=viewport.bottom ) return;
|
||||
if( ty+font->getHeight()<=viewport.top ) return;
|
||||
|
||||
int tx=x+origin_x;
|
||||
if( tx>=viewport.right ) return;
|
||||
|
||||
int b=0,w;
|
||||
while( b<t.size() && tx+(w=font->charWidth( t[b] ))<=viewport.left ){
|
||||
tx+=w;x+=w;++b;
|
||||
}
|
||||
int e=b;
|
||||
while( e<t.size() && tx<viewport.right ){
|
||||
tx+=font->charWidth( t[e] );++e;
|
||||
}
|
||||
|
||||
if( e>b ) font->render( this,format.toARGB( color_surf ),x,y,t.substr( b,e-b ) );
|
||||
}
|
||||
|
||||
int gxCanvas::getWidth()const{
|
||||
return clip_rect.right;
|
||||
}
|
||||
|
||||
int gxCanvas::getHeight()const{
|
||||
return clip_rect.bottom;
|
||||
}
|
||||
|
||||
int gxCanvas::getDepth()const{
|
||||
return format.getDepth();
|
||||
}
|
||||
|
||||
void gxCanvas::getOrigin( int *x,int *y )const{
|
||||
*x=origin_x;*y=origin_y;
|
||||
}
|
||||
|
||||
void gxCanvas::getHandle( int *x,int *y )const{
|
||||
*x=handle_x;*y=handle_y;
|
||||
}
|
||||
|
||||
void gxCanvas::getViewport( int *x,int *y,int *w,int *h )const{
|
||||
*x=viewport.left;*y=viewport.top;
|
||||
*w=viewport.right-viewport.left;*h=viewport.bottom-viewport.top;
|
||||
}
|
||||
|
||||
unsigned gxCanvas::getMask()const{
|
||||
return format.toARGB( mask_surf );
|
||||
}
|
||||
|
||||
unsigned gxCanvas::getColor()const{
|
||||
return format.toARGB( color_surf );
|
||||
}
|
||||
|
||||
unsigned gxCanvas::getClsColor()const{
|
||||
return format.toARGB( clsColor_surf );
|
||||
}
|
||||
|
||||
bool gxCanvas::collide( int x1,int y1,const gxCanvas *i2,int x2,int y2,bool solid )const{
|
||||
|
||||
x1-=handle_x;x2-=i2->handle_x;
|
||||
if( x1+clip_rect.right<=x2 || x1>=x2+i2->clip_rect.right ) return false;
|
||||
y1-=handle_y;y2-=i2->handle_y;
|
||||
if( y1+clip_rect.bottom<=y2 || y1>=y2+i2->clip_rect.bottom ) return false;
|
||||
|
||||
if( solid ) return true;
|
||||
|
||||
if( !cm_mask ){
|
||||
cm_mask=d_new unsigned[cm_pitch*clip_rect.bottom];
|
||||
updateBitMask( clip_rect );
|
||||
}
|
||||
if( !i2->cm_mask ){
|
||||
i2->cm_mask=d_new unsigned[i2->cm_pitch*i2->clip_rect.bottom];
|
||||
i2->updateBitMask( i2->clip_rect );
|
||||
}
|
||||
|
||||
const gxCanvas *i1=this;
|
||||
|
||||
//to keep me sane!
|
||||
if( x1>x2 ){
|
||||
std::swap( x1,x2 );
|
||||
std::swap( y1,y2 );
|
||||
std::swap( i1,i2 );
|
||||
}
|
||||
|
||||
Rect r1,r2,ir;
|
||||
r1.left=x1;r1.top=y1;r1.right=x1+i1->clip_rect.right;r1.bottom=y1+i1->clip_rect.bottom;
|
||||
r2.left=x2;r2.top=y2;r2.right=x2+i2->clip_rect.right;r2.bottom=y2+i2->clip_rect.bottom;
|
||||
ir.left=r1.left>r2.left ? r1.left : r2.left;
|
||||
ir.right=r1.right<r2.right ? r1.right : r2.right;
|
||||
ir.top=r1.top>r2.top ? r1.top : r2.top;
|
||||
ir.bottom=r1.bottom<r2.bottom ? r1.bottom : r2.bottom;
|
||||
|
||||
unsigned *s1=i1->cm_mask,*s2=i2->cm_mask;
|
||||
int i1_pitch=i1->cm_pitch,i2_pitch=i2->cm_pitch;
|
||||
s1+=(ir.top-r1.top)*i1_pitch;
|
||||
s2+=(ir.top-r2.top)*i2_pitch;
|
||||
|
||||
int startx=ir.left-r1.left;
|
||||
int stopx=ir.right-r1.left-1;
|
||||
int shr=startx&31;
|
||||
int shl=32-shr;
|
||||
int cnt=stopx/32-startx/32;
|
||||
unsigned lwm=LWMS[stopx&31];
|
||||
|
||||
#ifdef DEBUG_BITMASK
|
||||
unsigned *cm_mask_end1=i1->cm_mask + i1_pitch*i1->clip_rect.bottom;
|
||||
unsigned *cm_mask_end2=i2->cm_mask + i2_pitch*i2->clip_rect.bottom;
|
||||
#endif
|
||||
|
||||
s1+=startx/32;
|
||||
for( int y=ir.top;y<ir.bottom;++y ){
|
||||
unsigned p=0;
|
||||
unsigned *row1=s1,*row2=s2;
|
||||
for( int x=0;x<cnt;++x ){
|
||||
#ifdef DEBUG_BITMASK
|
||||
if( row1<i1->cm_mask || row2<i2->cm_mask ){
|
||||
gx_runtime->debugError( "gxCanvas::collide row underflow" );
|
||||
}
|
||||
if( row1>=cm_mask_end1 || row2>=cm_mask_end2 ){
|
||||
gx_runtime->debugError( "gxCanvas::collide row overflow" );
|
||||
}
|
||||
#endif
|
||||
unsigned n=*row2++;
|
||||
if( ((n>>shr)|p) & *row1++ ) return true;
|
||||
p=shl<32 ? n<<shl : 0;
|
||||
}
|
||||
#ifdef DEBUG_BITMASK
|
||||
if( row1<i1->cm_mask || row2<i2->cm_mask ){
|
||||
gx_runtime->debugError( "gxCanvas::collide row underflow" );
|
||||
}
|
||||
if( row1>=cm_mask_end1 || row2>=cm_mask_end2 ){
|
||||
gx_runtime->debugError( "gxCanvas::collide row overflow" );
|
||||
}
|
||||
#endif
|
||||
if( ((*row2>>shr)|p) & *row1 & lwm ) return true;
|
||||
s1+=i1_pitch;s2+=i2_pitch;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gxCanvas::rect_collide( int x1,int y1,int x2,int y2,int w2,int h2,bool solid )const{
|
||||
|
||||
x1-=handle_x;if( x1+clip_rect.right<=x2 || x1>=x2+w2 ) return false;
|
||||
y1-=handle_y;if( y1+clip_rect.bottom<=y2 || y1>=y2+h2 ) return false;
|
||||
|
||||
if( solid ) return true;
|
||||
|
||||
Rect r1( x1,y1,clip_rect.right,clip_rect.bottom ),r2( x2,y2,w2,h2 ),ir;
|
||||
|
||||
ir.left=r1.left>r2.left ? r1.left : r2.left;
|
||||
ir.right=r1.right<r2.right ? r1.right : r2.right;
|
||||
ir.top=r1.top>r2.top ? r1.top : r2.top;
|
||||
ir.bottom=r1.bottom<r2.bottom ? r1.bottom : r2.bottom;
|
||||
|
||||
if( !cm_mask ){
|
||||
cm_mask=d_new unsigned[cm_pitch*clip_rect.bottom];
|
||||
updateBitMask( clip_rect );
|
||||
}
|
||||
|
||||
unsigned *s1=cm_mask+(ir.top-r1.top)*cm_pitch;
|
||||
|
||||
int startx=ir.left-r1.left;
|
||||
int stopx=ir.right-r1.left-1;
|
||||
int cnt=stopx/32-startx/32;
|
||||
unsigned fwm=FWMS[startx&31];
|
||||
unsigned lwm=LWMS[stopx&31];
|
||||
|
||||
if( !cnt ) {fwm&=lwm;lwm=0;}
|
||||
|
||||
s1+=startx/32;
|
||||
for( int h=ir.top;h<ir.bottom;++h ){
|
||||
unsigned *row=s1;
|
||||
if( *row & fwm ) return true;
|
||||
for( int x=1;x<cnt;++x ){
|
||||
if( *++row ) return true;
|
||||
}
|
||||
if( lwm && (*++row & lwm) ) return true;
|
||||
s1+=cm_pitch;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gxCanvas::lock()const{
|
||||
if( !locked_cnt++ ){
|
||||
DDSURFACEDESC2 desc={sizeof(desc)};
|
||||
if( surf->Lock( 0,&desc,DDLOCK_WAIT|DDLOCK_NOSYSLOCK,0 )<0 ){
|
||||
--locked_cnt;
|
||||
return false;
|
||||
}
|
||||
locked_pitch=desc.lPitch;
|
||||
locked_surf=(unsigned char*)desc.lpSurface;
|
||||
lock_mod_cnt=mod_cnt;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void gxCanvas::unlock()const{
|
||||
if( locked_cnt==1 ){
|
||||
if( lock_mod_cnt!=mod_cnt && cm_mask ) updateBitMask( clip_rect );
|
||||
surf->Unlock( 0 );
|
||||
}
|
||||
--locked_cnt;
|
||||
}
|
||||
|
||||
void gxCanvas::setPixel( int x,int y,unsigned argb ){
|
||||
x+=origin_x;if( x<viewport.left || x>=viewport.right ) return;
|
||||
y+=origin_y;if( y<viewport.top || y>=viewport.bottom ) return;
|
||||
lock();
|
||||
setPixelFast( x,y,argb );
|
||||
unlock();
|
||||
}
|
||||
|
||||
unsigned gxCanvas::getPixel( int x,int y )const{
|
||||
x+=origin_x;if( x<viewport.left || x>=viewport.right ) return format.toARGB( mask_surf );
|
||||
y+=origin_y;if( y<viewport.top || y>=viewport.bottom ) return format.toARGB( mask_surf );
|
||||
lock();
|
||||
unsigned p=getPixelFast( x,y );
|
||||
unlock();
|
||||
return p;
|
||||
}
|
||||
|
||||
void gxCanvas::copyPixelFast( int x,int y,gxCanvas *src,int src_x,int src_y ){
|
||||
switch( format.getDepth() ){
|
||||
case 16:
|
||||
*(short*)(locked_surf+y*locked_pitch+x*2)=
|
||||
*(short*)(src->locked_surf+src_y*src->locked_pitch+src_x*2);
|
||||
break;
|
||||
case 24:{
|
||||
unsigned char *p=locked_surf+y*locked_pitch+x*3;
|
||||
unsigned char *t=src->locked_surf+src_y*src->locked_pitch+src_x*3;
|
||||
*(short*)p=*(short*)t;*(char*)(p+2)=*(char*)(t+2);}
|
||||
break;
|
||||
case 32:
|
||||
*(int*)(locked_surf+y*locked_pitch+x*4)=
|
||||
*(int*)(src->locked_surf+src_y*src->locked_pitch+src_x*4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gxCanvas::copyPixel( int x,int y,gxCanvas *src,int src_x,int src_y ){
|
||||
x+=origin_x;if( x<viewport.left || x>=viewport.right ) return;
|
||||
y+=origin_y;if( y<viewport.top || y>=viewport.bottom ) return;
|
||||
src_x+=src->origin_x;if( src_x<src->viewport.left || src_x>=src->viewport.right ) return;
|
||||
src_y+=src->origin_y;if( src_y<src->viewport.top || src_y>=src->viewport.bottom ) return;
|
||||
lock();
|
||||
src->lock();
|
||||
copyPixelFast( x,y,src,src_x,src_y );
|
||||
src->unlock();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void gxCanvas::setCubeMode( int mode ){
|
||||
cube_mode=mode;
|
||||
}
|
||||
|
||||
void gxCanvas::setCubeFace( int face ){
|
||||
|
||||
getTexSurface();
|
||||
surf=cube_surfs[face];
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
|
||||
#ifndef GXCANVAS_H
|
||||
#define GXCANVAS_H
|
||||
|
||||
#include "ddutil.h"
|
||||
|
||||
class gxFont;
|
||||
class gxGraphics;
|
||||
|
||||
typedef IDirectDrawSurface7 ddSurf;
|
||||
|
||||
class gxCanvas{
|
||||
public:
|
||||
gxCanvas( gxGraphics *graphics,ddSurf *surface,int flags );
|
||||
~gxCanvas();
|
||||
|
||||
void backup()const;
|
||||
void restore()const;
|
||||
ddSurf *getSurface()const;
|
||||
ddSurf *getTexSurface()const;
|
||||
void setModify( int n );
|
||||
int getModify()const;
|
||||
|
||||
bool attachZBuffer();
|
||||
void releaseZBuffer();
|
||||
|
||||
bool clip( RECT *d )const;
|
||||
bool clip( RECT *d,RECT *s )const;
|
||||
void damage( const RECT &r )const;
|
||||
|
||||
private:
|
||||
int flags,cube_mode;
|
||||
gxGraphics *graphics;
|
||||
|
||||
ddSurf *main_surf,*surf,*z_surf,*cube_surfs[6];
|
||||
|
||||
mutable int mod_cnt;
|
||||
mutable ddSurf *t_surf;
|
||||
|
||||
mutable int locked_pitch,locked_cnt,lock_mod_cnt,remip_cnt;
|
||||
mutable unsigned char *locked_surf;
|
||||
|
||||
mutable int cm_pitch;
|
||||
mutable unsigned *cm_mask;
|
||||
|
||||
RECT clip_rect;
|
||||
|
||||
PixelFormat format;
|
||||
|
||||
gxFont *font;
|
||||
RECT viewport;
|
||||
int origin_x,origin_y,handle_x,handle_y;
|
||||
unsigned mask_surf,color_surf,color_argb,clsColor_surf;
|
||||
|
||||
void updateBitMask( const RECT &r )const;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
CANVAS_TEX_RGB= 0x0001,
|
||||
CANVAS_TEX_ALPHA= 0x0002,
|
||||
CANVAS_TEX_MASK= 0x0004,
|
||||
CANVAS_TEX_MIPMAP= 0x0008,
|
||||
CANVAS_TEX_CLAMPU= 0x0010,
|
||||
CANVAS_TEX_CLAMPV= 0x0020,
|
||||
CANVAS_TEX_SPHERE= 0x0040,
|
||||
CANVAS_TEX_CUBE= 0x0080,
|
||||
CANVAS_TEX_VIDMEM= 0x0100,
|
||||
CANVAS_TEX_HICOLOR= 0x0200,
|
||||
|
||||
CANVAS_TEXTURE= 0x10000,
|
||||
CANVAS_NONDISPLAY= 0x20000,
|
||||
CANVAS_HIGHCOLOR= 0x40000
|
||||
};
|
||||
|
||||
enum{
|
||||
CUBEMODE_REFLECTION=1,
|
||||
CUBEMODE_NORMAL=2,
|
||||
CUBEMODE_POSITION=3,
|
||||
|
||||
CUBESPACE_WORLD=0,
|
||||
CUBESPACE_CAMERA=4
|
||||
};
|
||||
|
||||
//MANIPULATORS
|
||||
void setFont( gxFont *font );
|
||||
void setMask( unsigned argb );
|
||||
void setColor( unsigned argb );
|
||||
void setClsColor( unsigned argb );
|
||||
void setOrigin( int x,int y );
|
||||
void setHandle( int x,int y );
|
||||
void setViewport( int x,int y,int w,int h );
|
||||
|
||||
void cls();
|
||||
void plot( int x,int y );
|
||||
void line( int x,int y,int x2,int y2 );
|
||||
void rect( int x,int y,int w,int h,bool solid );
|
||||
void oval( int x,int y,int w,int h,bool solid );
|
||||
void text( int x,int y,const std::string &t );
|
||||
void blit( int x,int y,gxCanvas *src,int src_x,int src_y,int src_w,int src_h,bool solid );
|
||||
|
||||
bool collide( int x,int y,const gxCanvas *src,int src_x,int src_y,bool solid )const;
|
||||
bool rect_collide( int x,int y,int rect_x,int rect_y,int rect_w,int rect_h,bool solid )const;
|
||||
|
||||
bool lock()const;
|
||||
void setPixel( int x,int y,unsigned argb );
|
||||
void setPixelFast( int x,int y,unsigned argb ){
|
||||
format.setPixel( locked_surf+y*locked_pitch+x*format.getPitch(),argb );
|
||||
++mod_cnt;
|
||||
}
|
||||
void copyPixel( int x,int y,gxCanvas *src,int src_x,int src_y );
|
||||
void copyPixelFast( int x,int y,gxCanvas *src,int src_x,int src_y );
|
||||
unsigned getPixel( int x,int y )const;
|
||||
unsigned getPixelFast( int x,int y )const{
|
||||
return format.getPixel( locked_surf+y*locked_pitch+x*format.getPitch() );
|
||||
};
|
||||
void unlock()const;
|
||||
|
||||
void setCubeMode( int mode );
|
||||
void setCubeFace( int face );
|
||||
|
||||
//ACCESSORS
|
||||
int getWidth()const;
|
||||
int getHeight()const;
|
||||
int getDepth()const;
|
||||
int getFlags()const{ return flags; }
|
||||
int cubeMode()const{ return cube_mode; }
|
||||
void getOrigin( int *x,int *y )const;
|
||||
void getHandle( int *x,int *y )const;
|
||||
void getViewport( int *x,int *y,int *w,int *h )const;
|
||||
unsigned getMask()const;
|
||||
unsigned getColor()const;
|
||||
unsigned getClsColor()const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxchannel.h"
|
||||
|
||||
gxChannel::~gxChannel(){
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
#ifndef GXCHANNEL_H
|
||||
#define GXCHANNEL_H
|
||||
|
||||
class gxChannel{
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
virtual ~gxChannel();
|
||||
//modifiers
|
||||
virtual void stop()=0;
|
||||
virtual void setPaused( bool paused )=0;
|
||||
virtual void setPitch( int pitch )=0;
|
||||
virtual void setVolume( float volume )=0;
|
||||
virtual void setPan( float pan )=0;
|
||||
virtual void set3d( const float pos[3],const float vel[3] )=0;
|
||||
|
||||
virtual bool isPlaying()=0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxdevice.h"
|
||||
#include "gxruntime.h"
|
||||
|
||||
gxDevice::gxDevice(){
|
||||
reset();
|
||||
}
|
||||
|
||||
gxDevice::~gxDevice(){
|
||||
}
|
||||
|
||||
void gxDevice::reset(){
|
||||
memset( down_state,0,sizeof(down_state) );
|
||||
memset( axis_states,0,sizeof(axis_states) );
|
||||
memset( hit_count,0,sizeof(hit_count) );
|
||||
put=get=0;
|
||||
}
|
||||
|
||||
void gxDevice::downEvent( int key ){
|
||||
down_state[key]=true;
|
||||
++hit_count[key];
|
||||
if( put-get<QUE_SIZE ) que[put++&QUE_MASK]=key;
|
||||
}
|
||||
|
||||
void gxDevice::upEvent( int key ){
|
||||
down_state[key]=false;
|
||||
}
|
||||
|
||||
void gxDevice::setDownState( int key,bool down ){
|
||||
if( down==down_state[key] ) return;
|
||||
if( down ) downEvent( key );
|
||||
else upEvent( key );
|
||||
}
|
||||
|
||||
void gxDevice::flush(){
|
||||
update();
|
||||
memset( hit_count,0,sizeof(hit_count) );
|
||||
put=get=0;
|
||||
}
|
||||
|
||||
bool gxDevice::keyDown( int key ){
|
||||
update();
|
||||
return down_state[key];
|
||||
}
|
||||
|
||||
int gxDevice::keyHit( int key ){
|
||||
update();
|
||||
int n=hit_count[key];
|
||||
hit_count[key]-=n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int gxDevice::getKey(){
|
||||
update();
|
||||
return get<put ? que[get++ & QUE_MASK] : 0;
|
||||
}
|
||||
|
||||
float gxDevice::getAxisState( int axis ){
|
||||
update();
|
||||
return axis_states[axis];
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
#ifndef GXDEVICE_H
|
||||
#define GXDEVICE_H
|
||||
|
||||
class gxDevice{
|
||||
public:
|
||||
float axis_states[32];
|
||||
|
||||
gxDevice();
|
||||
virtual ~gxDevice();
|
||||
|
||||
virtual void update(){}
|
||||
|
||||
void reset();
|
||||
void downEvent( int key );
|
||||
void upEvent( int key );
|
||||
void setDownState( int key,bool down );
|
||||
|
||||
private:
|
||||
enum{
|
||||
QUE_SIZE=32,QUE_MASK=QUE_SIZE-1
|
||||
};
|
||||
int hit_count[256]; //how many hits of key
|
||||
bool down_state[256]; //time key went down
|
||||
int que[QUE_SIZE],put,get;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
void flush();
|
||||
|
||||
bool keyDown( int key );
|
||||
|
||||
int keyHit( int key );
|
||||
|
||||
int getKey();
|
||||
|
||||
float getAxisState( int axis );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxdir.h"
|
||||
|
||||
gxDir::gxDir( HANDLE h,const WIN32_FIND_DATA &f ):handle(h),findData(f){
|
||||
}
|
||||
|
||||
gxDir::~gxDir(){
|
||||
if( handle!=INVALID_HANDLE_VALUE ) FindClose( handle );
|
||||
}
|
||||
|
||||
string gxDir::getNextFile(){
|
||||
if( handle==INVALID_HANDLE_VALUE ) return "";
|
||||
string t=findData.cFileName;
|
||||
if( !FindNextFile( handle,&findData ) ){
|
||||
FindClose( handle );
|
||||
handle=INVALID_HANDLE_VALUE;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
#ifndef GXDIR_H
|
||||
#define GXDIR_H
|
||||
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
class gxDir{
|
||||
public:
|
||||
gxDir( HANDLE h,const WIN32_FIND_DATA &f );
|
||||
~gxDir();
|
||||
|
||||
private:
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATA findData;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
std::string getNextFile();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxfilesystem.h"
|
||||
|
||||
static set<gxDir*> dir_set;
|
||||
|
||||
gxFileSystem::gxFileSystem(){
|
||||
dir_set.clear();
|
||||
}
|
||||
|
||||
gxFileSystem::~gxFileSystem(){
|
||||
while( dir_set.size() ) closeDir( *dir_set.begin() );
|
||||
}
|
||||
|
||||
bool gxFileSystem::createDir( const std::string &dir ){
|
||||
return CreateDirectory( dir.c_str(),0 ) ? true : false;
|
||||
}
|
||||
|
||||
bool gxFileSystem::deleteDir( const std::string &dir ){
|
||||
return RemoveDirectory( dir.c_str() ) ? true : false;
|
||||
}
|
||||
|
||||
bool gxFileSystem::createFile( const std::string &file ){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gxFileSystem::deleteFile( const std::string &file ){
|
||||
return DeleteFile( file.c_str() ) ? true : false;
|
||||
}
|
||||
|
||||
bool gxFileSystem::copyFile( const std::string &src,const string &dest ){
|
||||
return CopyFile( src.c_str(),dest.c_str(),false ) ? true : false;
|
||||
}
|
||||
|
||||
bool gxFileSystem::renameFile( const std::string &src,const std::string &dest ){
|
||||
return MoveFile( src.c_str(),dest.c_str() ) ? true : false;
|
||||
}
|
||||
|
||||
bool gxFileSystem::setCurrentDir( const std::string &dir ){
|
||||
return SetCurrentDirectory( dir.c_str()) ? true : false;
|
||||
}
|
||||
|
||||
string gxFileSystem::getCurrentDir()const{
|
||||
char buff[MAX_PATH];
|
||||
if( !GetCurrentDirectory( MAX_PATH,buff ) ) return "";
|
||||
string t=buff;if( t.size() && t[t.size()-1]!='\\' ) t+='\\';
|
||||
return t;
|
||||
}
|
||||
|
||||
int gxFileSystem::getFileSize( const std::string &name )const{
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE h=FindFirstFile( name.c_str(),&findData );
|
||||
if( h==INVALID_HANDLE_VALUE ) return 0;
|
||||
int n=findData.dwFileAttributes,sz=findData.nFileSizeLow;
|
||||
FindClose( h );return n & FILE_ATTRIBUTE_DIRECTORY ? 0 : sz;
|
||||
}
|
||||
|
||||
int gxFileSystem::getFileType( const std::string &name )const{
|
||||
DWORD t=GetFileAttributes( name.c_str() );
|
||||
return t==-1 ? FILE_TYPE_NONE :
|
||||
(t & FILE_ATTRIBUTE_DIRECTORY ? FILE_TYPE_DIR : FILE_TYPE_FILE);
|
||||
}
|
||||
|
||||
gxDir *gxFileSystem::openDir( const std::string &name,int flags ){
|
||||
string t=name;
|
||||
if( t[t.size()-1]=='\\' ) t+="*";
|
||||
else t+="\\*";
|
||||
WIN32_FIND_DATA f;
|
||||
HANDLE h=FindFirstFile( t.c_str(),&f );
|
||||
if( h!=INVALID_HANDLE_VALUE ){
|
||||
gxDir *d=d_new gxDir( h,f );
|
||||
dir_set.insert( d );
|
||||
return d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
gxDir *gxFileSystem::verifyDir( gxDir *d ){
|
||||
return dir_set.count(d) ? d : 0;
|
||||
}
|
||||
|
||||
void gxFileSystem::closeDir( gxDir *d ){
|
||||
if( dir_set.erase( d ) ) delete d;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
#ifndef GXFILESYSTEM_H
|
||||
#define GXFILESYSTEM_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gxdir.h"
|
||||
|
||||
class gxFileSystem{
|
||||
public:
|
||||
gxFileSystem();
|
||||
~gxFileSystem();
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
FILE_TYPE_NONE=0,FILE_TYPE_FILE=1,FILE_TYPE_DIR=2
|
||||
};
|
||||
|
||||
bool createDir( const std::string &dir );
|
||||
bool deleteDir( const std::string &dir );
|
||||
bool createFile( const std::string &file );
|
||||
bool deleteFile( const std::string &file );
|
||||
bool copyFile( const std::string &src,const std::string &dest );
|
||||
bool renameFile( const std::string &src,const std::string &dest );
|
||||
bool setCurrentDir( const std::string &dir );
|
||||
|
||||
std::string getCurrentDir()const;
|
||||
int getFileSize( const std::string &name )const;
|
||||
int getFileType( const std::string &name )const;
|
||||
|
||||
gxDir *openDir( const std::string &name,int flags );
|
||||
gxDir *verifyDir( gxDir *d );
|
||||
void closeDir( gxDir *dir );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxfont.h"
|
||||
#include "gxcanvas.h"
|
||||
#include "gxgraphics.h"
|
||||
|
||||
gxFont::gxFont( gxGraphics *g,gxCanvas *c,int w,int h,int b,int e,int d,int *os,int *ws ):
|
||||
graphics(g),canvas(c),
|
||||
width(w),height(h),begin_char(b),end_char(e),def_char(d),
|
||||
offs(os),widths(ws){
|
||||
canvas->setMask( 0xffffff );
|
||||
t_canvas=graphics->createCanvas( graphics->getWidth(),height,0 );
|
||||
}
|
||||
|
||||
gxFont::~gxFont(){
|
||||
delete[] offs;
|
||||
delete[] widths;
|
||||
graphics->freeCanvas( t_canvas );
|
||||
graphics->freeCanvas( canvas );
|
||||
}
|
||||
|
||||
int gxFont::charWidth( int c )const{
|
||||
if( c<begin_char || c>=end_char ) c=def_char;
|
||||
return widths[c-begin_char];
|
||||
}
|
||||
|
||||
void gxFont::render( gxCanvas *dest,unsigned color_argb,int x,int y,const string &t ){
|
||||
int width=getWidth( t );
|
||||
if( width>t_canvas->getWidth() ){
|
||||
graphics->freeCanvas( t_canvas );
|
||||
t_canvas=graphics->createCanvas( width,height,0 );
|
||||
}
|
||||
|
||||
t_canvas->setColor( color_argb );
|
||||
if( !(t_canvas->getColor()&0xffffff) ) t_canvas->setColor( 0x10 );
|
||||
t_canvas->rect( 0,0,width,height,true );
|
||||
|
||||
int t_x=0;
|
||||
for( int k=0;k<t.size();++k ){
|
||||
int c=t[k]&0xff;
|
||||
if( c<begin_char || c>=end_char ) c=def_char;
|
||||
c-=begin_char;
|
||||
int sx=(offs[c]>>16)&0xffff,sy=offs[c]&0xffff;
|
||||
t_canvas->blit( t_x,0,canvas,sx,sy,widths[c],height,false );
|
||||
t_x+=widths[c];
|
||||
}
|
||||
|
||||
dest->blit( x,y,t_canvas,0,0,width,height,false );
|
||||
}
|
||||
|
||||
int gxFont::getWidth()const{
|
||||
return width;
|
||||
}
|
||||
|
||||
int gxFont::getHeight()const{
|
||||
return height;
|
||||
}
|
||||
|
||||
int gxFont::getWidth( const string &t )const{
|
||||
int w=0;
|
||||
for( int k=0;k<t.size();++k ){
|
||||
int c=t[k]&0xff;
|
||||
if( c<begin_char || c>=end_char ) c=def_char;
|
||||
w+=widths[c-begin_char];
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
bool gxFont::isPrintable( int chr )const{
|
||||
return chr>=begin_char && chr<end_char;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
#ifndef GXFONT_H
|
||||
#define GXFONT_H
|
||||
|
||||
class gxCanvas;
|
||||
class gxGraphics;
|
||||
|
||||
typedef IDirectDrawSurface7 ddSurf;
|
||||
|
||||
class gxFont{
|
||||
public:
|
||||
gxFont(
|
||||
gxGraphics *graphics,gxCanvas *canvas,
|
||||
int width,int height,int begin_char,int end_char,int def_char,
|
||||
int *offs,int *widths );
|
||||
~gxFont();
|
||||
|
||||
int charWidth( int c )const;
|
||||
void render( gxCanvas *dest,unsigned color_argb,int x,int y,const std::string &t );
|
||||
|
||||
private:
|
||||
gxGraphics *graphics;
|
||||
gxCanvas *canvas,*t_canvas;
|
||||
int width,height,begin_char,end_char,def_char;
|
||||
int *offs,*widths;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
FONT_BOLD=1,
|
||||
FONT_ITALIC=2,
|
||||
FONT_UNDERLINE=4
|
||||
};
|
||||
|
||||
//ACCESSORS
|
||||
int getWidth()const; //width of widest char
|
||||
int getHeight()const; //height of font
|
||||
int getWidth( const std::string &text )const; //width of string
|
||||
bool isPrintable( int chr )const; //printable char?
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,619 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxgraphics.h"
|
||||
#include "gxruntime.h"
|
||||
|
||||
extern gxRuntime *gx_runtime;
|
||||
|
||||
gxGraphics::gxGraphics( gxRuntime *rt,IDirectDraw7 *dd,IDirectDrawSurface7 *fs,IDirectDrawSurface7 *bs,bool d3d ):
|
||||
runtime(rt),dirDraw(dd),dir3d(0),dir3dDev(0),def_font(0),gfx_lost(false),dummy_mesh(0){
|
||||
|
||||
dirDraw->QueryInterface( IID_IDirectDraw,(void**)&ds_dirDraw );
|
||||
|
||||
front_canvas=d_new gxCanvas( this,fs,0 );
|
||||
back_canvas=d_new gxCanvas( this,bs,0 );
|
||||
|
||||
front_canvas->cls();
|
||||
back_canvas->cls();
|
||||
|
||||
def_font=loadFont( "courier",12,0 );
|
||||
|
||||
front_canvas->setFont( def_font );
|
||||
back_canvas->setFont( def_font );
|
||||
|
||||
memset(&primFmt,0,sizeof(primFmt));
|
||||
primFmt.dwSize=sizeof(primFmt);
|
||||
fs->GetPixelFormat( &primFmt );
|
||||
|
||||
//are we fullscreen?
|
||||
_gamma=0;
|
||||
if( fs!=bs ){
|
||||
if( fs->QueryInterface( IID_IDirectDrawGammaControl,(void**)&_gamma )>=0 ){
|
||||
if( _gamma->GetGammaRamp( 0,&_gammaRamp )<0 ) _gamma=0;
|
||||
}
|
||||
}
|
||||
if( !_gamma ){
|
||||
for( int k=0;k<256;++k ) _gammaRamp.red[k]=_gammaRamp.blue[k]=_gammaRamp.green[k]=k;
|
||||
}
|
||||
}
|
||||
|
||||
gxGraphics::~gxGraphics(){
|
||||
if( _gamma ) _gamma->Release();
|
||||
#ifdef PRO
|
||||
while( scene_set.size() ) freeScene( *scene_set.begin() );
|
||||
#endif
|
||||
while( movie_set.size() ) closeMovie( *movie_set.begin() );
|
||||
while( font_set.size() ) freeFont( *font_set.begin() );
|
||||
while( canvas_set.size() ) freeCanvas( *canvas_set.begin() );
|
||||
|
||||
set<string>::iterator it;
|
||||
for( it=font_res.begin();it!=font_res.end();++it ) RemoveFontResource( (*it).c_str() );
|
||||
font_res.clear();
|
||||
|
||||
delete back_canvas;
|
||||
delete front_canvas;
|
||||
|
||||
ds_dirDraw->Release();
|
||||
|
||||
dirDraw->RestoreDisplayMode();
|
||||
dirDraw->Release();
|
||||
}
|
||||
|
||||
void gxGraphics::setGamma( int r,int g,int b,float dr,float dg,float db ){
|
||||
_gammaRamp.red[r&255]=dr*257.0f;
|
||||
_gammaRamp.green[g&255]=dg*257.0f;
|
||||
_gammaRamp.blue[b&255]=db*257.0f;
|
||||
}
|
||||
|
||||
void gxGraphics::updateGamma( bool calibrate ){
|
||||
if( !_gamma ) return;
|
||||
_gamma->SetGammaRamp( calibrate ? DDSGR_CALIBRATE : 0,&_gammaRamp );
|
||||
}
|
||||
|
||||
void gxGraphics::getGamma( int r,int g,int b,float *dr,float *dg,float *db ){
|
||||
*dr=_gammaRamp.red[r&255]/257.0f;
|
||||
*dg=_gammaRamp.green[g&255]/257.0f;
|
||||
*db=_gammaRamp.blue[b&255]/257.0f;
|
||||
}
|
||||
|
||||
void gxGraphics::backup(){
|
||||
}
|
||||
|
||||
bool gxGraphics::restore(){
|
||||
|
||||
while( dirDraw->TestCooperativeLevel()!=DD_OK ){
|
||||
|
||||
if( dirDraw->TestCooperativeLevel()==DDERR_WRONGMODE ) return false;
|
||||
|
||||
Sleep( 100 );
|
||||
}
|
||||
|
||||
if( back_canvas->getSurface()->IsLost()==DD_OK ) return true;
|
||||
|
||||
dirDraw->RestoreAllSurfaces();
|
||||
|
||||
//restore all canvases
|
||||
set<gxCanvas*>::iterator it;
|
||||
for( it=canvas_set.begin();it!=canvas_set.end();++it ){
|
||||
(*it)->restore();
|
||||
}
|
||||
|
||||
#ifdef PRO
|
||||
//restore all meshes (b3d surfaces)
|
||||
set<gxMesh*>::iterator mesh_it;
|
||||
for( mesh_it=mesh_set.begin();mesh_it!=mesh_set.end();++mesh_it ){
|
||||
(*mesh_it)->restore();
|
||||
}
|
||||
if( dir3d ) dir3d->EvictManagedTextures();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gxCanvas *gxGraphics::getFrontCanvas()const{
|
||||
return front_canvas;
|
||||
}
|
||||
|
||||
gxCanvas *gxGraphics::getBackCanvas()const{
|
||||
return back_canvas;
|
||||
}
|
||||
|
||||
gxFont *gxGraphics::getDefaultFont()const{
|
||||
return def_font;
|
||||
}
|
||||
|
||||
void gxGraphics::vwait(){
|
||||
dirDraw->WaitForVerticalBlank( DDWAITVB_BLOCKBEGIN,0 );
|
||||
}
|
||||
|
||||
void gxGraphics::flip( bool v ){
|
||||
runtime->flip( v );
|
||||
}
|
||||
|
||||
void gxGraphics::copy( gxCanvas *dest,int dx,int dy,int dw,int dh,gxCanvas *src,int sx,int sy,int sw,int sh ){
|
||||
RECT r={ dx,dy,dx+dw,dy+dh };
|
||||
ddUtil::copy( dest->getSurface(),dx,dy,dw,dh,src->getSurface(),sx,sy,sw,sh );
|
||||
dest->damage( r );
|
||||
}
|
||||
|
||||
int gxGraphics::getScanLine()const{
|
||||
DWORD t=0;
|
||||
dirDraw->GetScanLine( &t );
|
||||
return t;
|
||||
}
|
||||
|
||||
int gxGraphics::getTotalVidmem()const{
|
||||
DDCAPS caps={sizeof(caps)};
|
||||
dirDraw->GetCaps( &caps,0 );
|
||||
return caps.dwVidMemTotal;
|
||||
}
|
||||
|
||||
int gxGraphics::getAvailVidmem()const{
|
||||
DDCAPS caps={sizeof(caps)};
|
||||
dirDraw->GetCaps( &caps,0 );
|
||||
return caps.dwVidMemFree;
|
||||
}
|
||||
|
||||
gxMovie *gxGraphics::openMovie( const string &file,int flags ){
|
||||
|
||||
IAMMultiMediaStream *iam_stream;
|
||||
|
||||
if( CoCreateInstance(
|
||||
CLSID_AMMultiMediaStream,NULL,CLSCTX_INPROC_SERVER,
|
||||
IID_IAMMultiMediaStream,(void **)&iam_stream )==S_OK ){
|
||||
|
||||
if( iam_stream->Initialize( STREAMTYPE_READ,AMMSF_NOGRAPHTHREAD,NULL )==S_OK ){
|
||||
|
||||
if( iam_stream->AddMediaStream( ds_dirDraw,&MSPID_PrimaryVideo,0,NULL )==S_OK ){
|
||||
|
||||
iam_stream->AddMediaStream( NULL,&MSPID_PrimaryAudio,AMMSF_ADDDEFAULTRENDERER,NULL );
|
||||
|
||||
WCHAR *path=new WCHAR[ file.size()+1 ];
|
||||
MultiByteToWideChar( CP_ACP,0,file.c_str(),-1,path,sizeof(WCHAR)*(file.size()+1) );
|
||||
int n=iam_stream->OpenFile( path,0 );
|
||||
delete path;
|
||||
|
||||
if( n==S_OK ){
|
||||
gxMovie *movie=d_new gxMovie( this,iam_stream );
|
||||
movie_set.insert( movie );
|
||||
return movie;
|
||||
}
|
||||
}
|
||||
}
|
||||
iam_stream->Release();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
gxMovie *gxGraphics::verifyMovie( gxMovie *m ){
|
||||
return movie_set.count( m ) ? m : 0;
|
||||
}
|
||||
|
||||
void gxGraphics::closeMovie( gxMovie *m ){
|
||||
if( movie_set.erase( m ) ) delete m;
|
||||
}
|
||||
|
||||
gxCanvas *gxGraphics::createCanvas( int w,int h,int flags ){
|
||||
ddSurf *s=ddUtil::createSurface( w,h,flags,this );
|
||||
if( !s ) return 0;
|
||||
gxCanvas *c=d_new gxCanvas( this,s,flags );
|
||||
canvas_set.insert( c );
|
||||
c->cls();
|
||||
return c;
|
||||
}
|
||||
|
||||
gxCanvas *gxGraphics::loadCanvas( const string &f,int flags ){
|
||||
ddSurf *s=ddUtil::loadSurface( f,flags,this );
|
||||
if( !s ) return 0;
|
||||
gxCanvas *c=d_new gxCanvas( this,s,flags );
|
||||
canvas_set.insert( c );
|
||||
return c;
|
||||
}
|
||||
|
||||
gxCanvas *gxGraphics::verifyCanvas( gxCanvas *c ){
|
||||
return canvas_set.count( c ) || c==front_canvas || c==back_canvas ? c : 0;
|
||||
}
|
||||
|
||||
void gxGraphics::freeCanvas( gxCanvas *c ){
|
||||
if( canvas_set.erase( c ) ) delete c;
|
||||
}
|
||||
|
||||
int gxGraphics::getWidth()const{
|
||||
return front_canvas->getWidth();
|
||||
}
|
||||
|
||||
int gxGraphics::getHeight()const{
|
||||
return front_canvas->getHeight();
|
||||
}
|
||||
|
||||
int gxGraphics::getDepth()const{
|
||||
return front_canvas->getDepth();
|
||||
}
|
||||
|
||||
gxFont *gxGraphics::loadFont( const string &f,int height,int flags ){
|
||||
|
||||
int bold=flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR;
|
||||
int italic=flags & gxFont::FONT_ITALIC ? 1 : 0;
|
||||
int underline=flags & gxFont::FONT_UNDERLINE ? 1 : 0;
|
||||
int strikeout=0;
|
||||
|
||||
string t;
|
||||
int n=f.find('.');
|
||||
if( n!=string::npos ){
|
||||
t=fullfilename(f);
|
||||
if( !font_res.count(t) && AddFontResource( t.c_str() ) ) font_res.insert( t );
|
||||
t=filenamefile( f.substr(0,n) );
|
||||
}else{
|
||||
t=f;
|
||||
}
|
||||
|
||||
//save and turn off font smoothing....
|
||||
BOOL smoothing=FALSE;
|
||||
SystemParametersInfo( SPI_GETFONTSMOOTHING,0,&smoothing,0 );
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING,FALSE,0,0 );
|
||||
|
||||
HFONT hfont=CreateFont(
|
||||
height,0,0,0,
|
||||
bold,italic,underline,strikeout,
|
||||
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH|FF_DONTCARE,t.c_str() );
|
||||
|
||||
if( !hfont ){
|
||||
//restore font smoothing
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
HDC hdc=CreateCompatibleDC( 0 );
|
||||
HFONT pfont=(HFONT)SelectObject( hdc,hfont );
|
||||
|
||||
TEXTMETRIC tm={0};
|
||||
if( !GetTextMetrics( hdc,&tm ) ){
|
||||
SelectObject( hdc,pfont );
|
||||
DeleteDC( hdc );
|
||||
DeleteObject( hfont );
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
|
||||
return 0;
|
||||
}
|
||||
height=tm.tmHeight;
|
||||
|
||||
int first=tm.tmFirstChar,last=tm.tmLastChar;
|
||||
int sz=last-first+1;
|
||||
int *offs=d_new int[sz];
|
||||
int *widths=d_new int[sz];
|
||||
int *as=d_new int[sz];
|
||||
|
||||
//calc size of canvas to hold font.
|
||||
int x=0,y=0,max_x=0;
|
||||
for( int k=0;k<sz;++k ){
|
||||
|
||||
char t=k+first;
|
||||
|
||||
SIZE sz;
|
||||
GetTextExtentPoint32( hdc,&t,1,&sz );
|
||||
int w=sz.cx;
|
||||
|
||||
as[k]=0;
|
||||
|
||||
ABC abc;
|
||||
if( GetCharABCWidths( hdc,t,t,&abc ) ){
|
||||
if( abc.abcA<0 ){
|
||||
as[k]=ceil(-abc.abcA);
|
||||
w+=as[k];
|
||||
}
|
||||
if( abc.abcC<0 ) w+=ceil(-abc.abcC);
|
||||
}
|
||||
|
||||
if( x && x+w>getWidth() ){ x=0;y+=height; }
|
||||
offs[k]=(x<<16)|y;
|
||||
widths[k]=w;
|
||||
x+=w;if( x>max_x ) max_x=x;
|
||||
}
|
||||
SelectObject( hdc,pfont );
|
||||
DeleteDC( hdc );
|
||||
|
||||
int cw=max_x,ch=y+height;
|
||||
|
||||
if( gxCanvas *c=createCanvas( cw,ch,0 ) ){
|
||||
ddSurf *surf=c->getSurface();
|
||||
|
||||
HDC surf_hdc;
|
||||
if( surf->GetDC( &surf_hdc )>=0 ){
|
||||
HFONT pfont=(HFONT)SelectObject( surf_hdc,hfont );
|
||||
|
||||
SetBkColor( surf_hdc,0x000000 );
|
||||
SetTextColor( surf_hdc,0xffffff );
|
||||
|
||||
for( int k=0;k<sz;++k ){
|
||||
int x=(offs[k]>>16)&0xffff,y=offs[k]&0xffff;
|
||||
char t=k+first;
|
||||
RECT rect={x,y,x+widths[k],y+height};
|
||||
ExtTextOut( surf_hdc,x+as[k],y,ETO_CLIPPED,&rect,&t,1,0 );
|
||||
}
|
||||
|
||||
SelectObject( surf_hdc,pfont );
|
||||
surf->ReleaseDC( surf_hdc );
|
||||
DeleteObject( hfont );
|
||||
delete[] as;
|
||||
|
||||
c->backup();
|
||||
gxFont *font=d_new gxFont( this,c,tm.tmMaxCharWidth,height,first,last+1,tm.tmDefaultChar,offs,widths );
|
||||
font_set.insert( font );
|
||||
|
||||
//restore font smoothing
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
|
||||
return font;
|
||||
}else{
|
||||
}
|
||||
freeCanvas( c );
|
||||
}else{
|
||||
}
|
||||
DeleteObject( hfont );
|
||||
delete[] as;
|
||||
delete[] widths;
|
||||
delete[] offs;
|
||||
|
||||
//restore font smoothing
|
||||
SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
gxFont *gxGraphics::verifyFont( gxFont *f ){
|
||||
return font_set.count( f ) ? f : 0;
|
||||
}
|
||||
|
||||
void gxGraphics::freeFont( gxFont *f ){
|
||||
if( font_set.erase( f ) ) delete f;
|
||||
}
|
||||
|
||||
//////////////
|
||||
// 3D STUFF //
|
||||
//////////////
|
||||
|
||||
#ifdef PRO
|
||||
|
||||
static int maxDevType;
|
||||
|
||||
static HRESULT CALLBACK enumDevice( char *desc,char *name,D3DDEVICEDESC7 *devDesc,void *context ){
|
||||
gxGraphics *g=(gxGraphics*)context;
|
||||
int t=0;
|
||||
GUID guid=devDesc->deviceGUID;
|
||||
if( guid==IID_IDirect3DRGBDevice ) t=1;
|
||||
else if( guid==IID_IDirect3DHALDevice ) t=2;
|
||||
else if( guid==IID_IDirect3DTnLHalDevice ) t=3;
|
||||
if( t>maxDevType ){
|
||||
g->dir3dDevDesc=*devDesc;
|
||||
maxDevType=t;
|
||||
}
|
||||
return D3DENUMRET_OK;
|
||||
}
|
||||
|
||||
static HRESULT CALLBACK enumZbuffFormat( LPDDPIXELFORMAT format,void *context ){
|
||||
gxGraphics *g=(gxGraphics*)context;
|
||||
if( format->dwZBufferBitDepth==g->primFmt.dwRGBBitCount ){
|
||||
g->zbuffFmt=*format;
|
||||
return D3DENUMRET_CANCEL;
|
||||
}
|
||||
if( format->dwZBufferBitDepth>g->zbuffFmt.dwZBufferBitDepth ){
|
||||
if( format->dwZBufferBitDepth<g->primFmt.dwRGBBitCount ){
|
||||
g->zbuffFmt=*format;
|
||||
}
|
||||
}
|
||||
return D3DENUMRET_OK;
|
||||
}
|
||||
|
||||
struct TexFmt{
|
||||
DDPIXELFORMAT fmt;
|
||||
int bits,a_bits,rgb_bits;
|
||||
};
|
||||
|
||||
static int cntBits( int mask ){
|
||||
int n=0;
|
||||
for( int k=0;k<32;++k ){
|
||||
if( mask & (1<<k) ) ++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static vector<TexFmt> tex_fmts;
|
||||
|
||||
static HRESULT CALLBACK enumTextureFormat( DDPIXELFORMAT *fmt,void *p ){
|
||||
TexFmt t;
|
||||
t.fmt=*fmt;
|
||||
t.bits=fmt->dwRGBBitCount;
|
||||
t.a_bits=(fmt->dwFlags & DDPF_ALPHAPIXELS) ? cntBits(fmt->dwRGBAlphaBitMask) : 0;
|
||||
t.rgb_bits=(fmt->dwFlags & DDPF_RGB) ? cntBits(fmt->dwRBitMask|fmt->dwGBitMask|fmt->dwBBitMask) : 0;
|
||||
|
||||
tex_fmts.push_back( t );
|
||||
|
||||
return D3DENUMRET_OK;
|
||||
}
|
||||
|
||||
static string itobin( int n ){
|
||||
string t;
|
||||
for( int k=0;k<32;n<<=1,++k ){
|
||||
t+=(n&0x80000000) ? '1' : '0';
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static void debugPF( const DDPIXELFORMAT &pf ){
|
||||
string t;
|
||||
t="Bits:"+itoa( pf.dwRGBBitCount );
|
||||
gx_runtime->debugLog( t.c_str() );
|
||||
t="R Mask:"+itobin( pf.dwRBitMask );
|
||||
gx_runtime->debugLog( t.c_str() );
|
||||
t="G Mask:"+itobin( pf.dwGBitMask );
|
||||
gx_runtime->debugLog( t.c_str() );
|
||||
t="B Mask:"+itobin( pf.dwBBitMask );
|
||||
gx_runtime->debugLog( t.c_str() );
|
||||
t="A Mask:"+itobin( pf.dwRGBAlphaBitMask );
|
||||
gx_runtime->debugLog( t.c_str() );
|
||||
}
|
||||
|
||||
static void pickTexFmts( gxGraphics *g,int hi ){
|
||||
//texRGBFmt.
|
||||
{
|
||||
int pick=-1,max=0,bits;
|
||||
for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
|
||||
for( int k=0;k<tex_fmts.size();++k ){
|
||||
const TexFmt &t=tex_fmts[k];
|
||||
if( t.bits>d || !t.rgb_bits || t.rgb_bits<max ) continue;
|
||||
if( t.rgb_bits==max && t.bits>=bits ) continue;
|
||||
pick=k;max=t.rgb_bits;bits=t.bits;
|
||||
}
|
||||
if( !hi && pick>=0 ) break;
|
||||
}
|
||||
if( pick<0 ) g->texRGBFmt[hi]=g->primFmt;
|
||||
else g->texRGBFmt[hi]=tex_fmts[pick].fmt;
|
||||
}
|
||||
//texAlphaFmt
|
||||
{
|
||||
int pick=-1,max=0,bits;
|
||||
for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
|
||||
for( int k=0;k<tex_fmts.size();++k ){
|
||||
const TexFmt &t=tex_fmts[k];
|
||||
if( t.bits>d || !t.a_bits || t.a_bits<max ) continue;
|
||||
if( t.a_bits==max && t.bits>=bits ) continue;
|
||||
pick=k;max=t.a_bits;bits=t.bits;
|
||||
}
|
||||
if( !hi && pick>=0 ) break;
|
||||
}
|
||||
if( pick<0 ) g->texAlphaFmt[hi]=g->primFmt;
|
||||
else g->texAlphaFmt[hi]=tex_fmts[pick].fmt;
|
||||
}
|
||||
//texRGBAlphaFmt
|
||||
{
|
||||
int pick=-1,a8rgb8=-1,max=0,bits;
|
||||
for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
|
||||
for( int k=0;k<tex_fmts.size();++k ){
|
||||
const TexFmt &t=tex_fmts[k];
|
||||
if( t.a_bits==8 && t.bits==16 ){ a8rgb8=k;continue; }
|
||||
if( t.bits>d || !t.a_bits || !t.rgb_bits || t.a_bits<max ) continue;
|
||||
if( t.a_bits==max && t.bits>=bits ) continue;
|
||||
pick=k;max=t.a_bits;bits=t.bits;
|
||||
}
|
||||
if( !hi && pick>=0 ) break;
|
||||
}
|
||||
if( pick<0 ) pick=a8rgb8;
|
||||
if( pick<0 ) g->texRGBAlphaFmt[hi]=g->primFmt;
|
||||
else g->texRGBAlphaFmt[hi]=tex_fmts[pick].fmt;
|
||||
}
|
||||
//texRGBMaskFmt...
|
||||
{
|
||||
int pick=-1,max=0,bits;
|
||||
for( int d=g->primFmt.dwRGBBitCount;d<=32;d+=8 ){
|
||||
for( int k=0;k<tex_fmts.size();++k ){
|
||||
const TexFmt &t=tex_fmts[k];
|
||||
if( !t.a_bits || !t.rgb_bits || t.rgb_bits<max ) continue;
|
||||
if( t.rgb_bits==max && t.bits>=bits ) continue;
|
||||
pick=k;max=t.rgb_bits;bits=t.bits;
|
||||
}
|
||||
if( !hi && pick>=0 ) break;
|
||||
}
|
||||
if( pick<0 ) g->texRGBMaskFmt[hi]=g->primFmt;
|
||||
else g->texRGBMaskFmt[hi]=tex_fmts[pick].fmt;
|
||||
}
|
||||
}
|
||||
|
||||
gxScene *gxGraphics::createScene( int flags ){
|
||||
if( scene_set.size() ) return 0;
|
||||
|
||||
//get d3d
|
||||
if( dirDraw->QueryInterface( IID_IDirect3D7,(void**)&dir3d )>=0 ){
|
||||
//enum devices
|
||||
maxDevType=0;
|
||||
if( dir3d->EnumDevices( enumDevice,this )>=0 && maxDevType>1 ){
|
||||
//enum zbuffer formats
|
||||
zbuffFmt.dwZBufferBitDepth=0;
|
||||
if( dir3d->EnumZBufferFormats( dir3dDevDesc.deviceGUID,enumZbuffFormat,this )>=0 ){
|
||||
//create zbuff for back buffer
|
||||
if( back_canvas->attachZBuffer() ){
|
||||
//create 3d device
|
||||
if( dir3d->CreateDevice( dir3dDevDesc.deviceGUID,back_canvas->getSurface(),&dir3dDev )>=0 ){
|
||||
//enum texture formats
|
||||
tex_fmts.clear();
|
||||
if( dir3dDev->EnumTextureFormats( enumTextureFormat,this )>=0 ){
|
||||
pickTexFmts( this,0 );
|
||||
pickTexFmts( this,1 );
|
||||
tex_fmts.clear();
|
||||
#ifdef BETA
|
||||
gx_runtime->debugLog( "Texture RGB format:" );
|
||||
debugPF( texRGBFmt );
|
||||
gx_runtime->debugLog( "Texture Alpha format:" );
|
||||
debugPF( texAlphaFmt );
|
||||
gx_runtime->debugLog( "Texture RGB Alpha format:" );
|
||||
debugPF( texRGBAlphaFmt );
|
||||
gx_runtime->debugLog( "Texture RGB Mask format:" );
|
||||
debugPF( texRGBMaskFmt );
|
||||
gx_runtime->debugLog( "Texture Primary format:" );
|
||||
debugPF( primFmt );
|
||||
string ts="ZBuffer Bit Depth:"+itoa( zbuffFmt.dwZBufferBitDepth );
|
||||
gx_runtime->debugLog( ts.c_str() );
|
||||
#endif
|
||||
gxScene *scene=d_new gxScene( this,back_canvas );
|
||||
scene_set.insert( scene );
|
||||
|
||||
dummy_mesh=createMesh( 8,12,0 );
|
||||
|
||||
return scene;
|
||||
}
|
||||
dir3dDev->Release();
|
||||
dir3dDev=0;
|
||||
}
|
||||
back_canvas->releaseZBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
dir3d->Release();
|
||||
dir3d=0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
gxScene *gxGraphics::verifyScene( gxScene *s ){
|
||||
return scene_set.count( s ) ? s : 0;
|
||||
}
|
||||
|
||||
void gxGraphics::freeScene( gxScene *scene ){
|
||||
if( !scene_set.erase( scene ) ) return;
|
||||
dummy_mesh=0;
|
||||
while( mesh_set.size() ) freeMesh( *mesh_set.begin() );
|
||||
back_canvas->releaseZBuffer();
|
||||
if( dir3dDev ){ dir3dDev->Release();dir3dDev=0; }
|
||||
if( dir3d ){ dir3d->Release();dir3d=0; }
|
||||
delete scene;
|
||||
}
|
||||
|
||||
gxMesh *gxGraphics::createMesh( int max_verts,int max_tris,int flags ){
|
||||
|
||||
static const int VTXFMT=
|
||||
D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX2|
|
||||
D3DFVF_TEXCOORDSIZE2(0)|D3DFVF_TEXCOORDSIZE2(1);
|
||||
|
||||
int vbflags=0;
|
||||
|
||||
//XP or less?
|
||||
if( runtime->osinfo.dwMajorVersion<6 ){
|
||||
vbflags|=D3DVBCAPS_WRITEONLY;
|
||||
}
|
||||
|
||||
D3DVERTEXBUFFERDESC desc={ sizeof(desc),vbflags,VTXFMT,max_verts };
|
||||
|
||||
IDirect3DVertexBuffer7 *buff;
|
||||
if( dir3d->CreateVertexBuffer( &desc,&buff,0 )<0 ) return 0;
|
||||
WORD *indices=d_new WORD[max_tris*3];
|
||||
gxMesh *mesh=d_new gxMesh( this,buff,indices,max_verts,max_tris );
|
||||
mesh_set.insert( mesh );
|
||||
return mesh;
|
||||
}
|
||||
|
||||
gxMesh *gxGraphics::verifyMesh( gxMesh *m ){
|
||||
return mesh_set.count( m ) ? m : 0;
|
||||
}
|
||||
|
||||
void gxGraphics::freeMesh( gxMesh *mesh ){
|
||||
if( mesh_set.erase( mesh ) ) delete mesh;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,116 @@
|
||||
|
||||
#ifndef GXGRAPHICS_H
|
||||
#define GXGRAPHICS_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <d3d.h>
|
||||
|
||||
#include "ddutil.h"
|
||||
|
||||
#include "gxfont.h"
|
||||
#include "gxcanvas.h"
|
||||
#include "gxscene.h"
|
||||
#include "gxmesh.h"
|
||||
#include "gxmovie.h"
|
||||
|
||||
class gxRuntime;
|
||||
|
||||
class gxGraphics{
|
||||
public:
|
||||
IDirectDraw7 *dirDraw;
|
||||
IDirectDraw *ds_dirDraw;
|
||||
|
||||
IDirect3D7 *dir3d;
|
||||
IDirect3DDevice7 *dir3dDev;
|
||||
D3DDEVICEDESC7 dir3dDevDesc;
|
||||
DDPIXELFORMAT primFmt,zbuffFmt;
|
||||
|
||||
DDPIXELFORMAT texRGBFmt[2],texAlphaFmt[2],texRGBAlphaFmt[2],texRGBMaskFmt[2];
|
||||
|
||||
gxGraphics( gxRuntime *runtime,IDirectDraw7 *dirDraw,IDirectDrawSurface7 *front,IDirectDrawSurface7 *back,bool d3d );
|
||||
~gxGraphics();
|
||||
|
||||
void backup();
|
||||
bool restore();
|
||||
|
||||
gxRuntime *runtime;
|
||||
|
||||
private:
|
||||
|
||||
gxCanvas *front_canvas,*back_canvas;
|
||||
gxFont *def_font;
|
||||
bool gfx_lost;
|
||||
gxMesh *dummy_mesh;
|
||||
|
||||
DDSURFACEDESC2 initDesc( int w,int h,int flags );
|
||||
ddSurf *createSurface( int width,int height,int flags );
|
||||
ddSurf *loadSurface( const std::string &f,int flags );
|
||||
|
||||
std::set<gxFont*> font_set;
|
||||
std::set<gxCanvas*> canvas_set;
|
||||
std::set<gxMesh*> mesh_set;
|
||||
std::set<gxScene*> scene_set;
|
||||
std::set<gxMovie*> movie_set;
|
||||
std::set<std::string> font_res;
|
||||
|
||||
DDGAMMARAMP _gammaRamp;
|
||||
IDirectDrawGammaControl *_gamma;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
GRAPHICS_WINDOWED=1, //windowed mode
|
||||
GRAPHICS_SCALED=2, //scaled window
|
||||
GRAPHICS_3D=4, //3d mode! Hurrah!
|
||||
GRAPHICS_AUTOSUSPEND=8 //suspend graphics when app suspended
|
||||
};
|
||||
|
||||
//MANIPULATORS
|
||||
void vwait();
|
||||
void flip( bool vwait );
|
||||
|
||||
//SPECIAL!
|
||||
void copy( gxCanvas *dest,int dx,int dy,int dw,int dh,gxCanvas *src,int sx,int sy,int sw,int sh );
|
||||
|
||||
//NEW! Gamma control!
|
||||
void setGamma( int r,int g,int b,float dr,float dg,float db );
|
||||
void getGamma( int r,int g,int b,float *dr,float *dg,float *db );
|
||||
void updateGamma( bool calibrate );
|
||||
|
||||
//ACCESSORS
|
||||
int getWidth()const;
|
||||
int getHeight()const;
|
||||
int getDepth()const;
|
||||
int getScanLine()const;
|
||||
int getAvailVidmem()const;
|
||||
int getTotalVidmem()const;
|
||||
|
||||
gxCanvas *getFrontCanvas()const;
|
||||
gxCanvas *getBackCanvas()const;
|
||||
gxFont *getDefaultFont()const;
|
||||
|
||||
//OBJECTS
|
||||
gxCanvas *createCanvas( int width,int height,int flags );
|
||||
gxCanvas *loadCanvas( const std::string &file,int flags );
|
||||
gxCanvas *verifyCanvas( gxCanvas *canvas );
|
||||
void freeCanvas( gxCanvas *canvas );
|
||||
|
||||
gxMovie *openMovie( const std::string &file,int flags );
|
||||
gxMovie *verifyMovie( gxMovie *movie );
|
||||
void closeMovie( gxMovie *movie );
|
||||
|
||||
gxFont *loadFont( const std::string &font,int height,int flags );
|
||||
gxFont *verifyFont( gxFont *font );
|
||||
void freeFont( gxFont *font );
|
||||
|
||||
gxScene *createScene( int flags );
|
||||
gxScene *verifyScene( gxScene *scene );
|
||||
void freeScene( gxScene *scene );
|
||||
|
||||
gxMesh *createMesh( int max_verts,int max_tris,int flags );
|
||||
gxMesh *verifyMesh( gxMesh *mesh );
|
||||
void freeMesh( gxMesh *mesh );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,328 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxinput.h"
|
||||
#include "gxruntime.h"
|
||||
|
||||
#include <dinput.h>
|
||||
|
||||
static const int QUE_SIZE=32;
|
||||
|
||||
class Device : public gxDevice{
|
||||
public:
|
||||
bool acquired;
|
||||
gxInput *input;
|
||||
IDirectInputDevice7 *device;
|
||||
|
||||
Device( gxInput *i,IDirectInputDevice7 *d ):input(i),acquired(false),device(d){
|
||||
}
|
||||
virtual ~Device(){
|
||||
device->Release();
|
||||
}
|
||||
bool acquire(){
|
||||
return acquired=device->Acquire()>=0;
|
||||
}
|
||||
void unacquire(){
|
||||
device->Unacquire();
|
||||
acquired=false;
|
||||
}
|
||||
};
|
||||
|
||||
class Keyboard : public Device{
|
||||
public:
|
||||
Keyboard( gxInput *i,IDirectInputDevice7 *d ):Device(i,d){
|
||||
}
|
||||
void update(){
|
||||
if( !acquired ){
|
||||
input->runtime->idle();
|
||||
return;
|
||||
}
|
||||
int k,cnt=32;
|
||||
DIDEVICEOBJECTDATA data[32],*curr;
|
||||
if( device->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),data,(DWORD*)&cnt,0 )<0 ) return;
|
||||
curr=data;
|
||||
for( k=0;k<cnt;++curr,++k ){
|
||||
int n=curr->dwOfs;if( !n || n>255 ) continue;
|
||||
if( curr->dwData&0x80 ) downEvent( n );
|
||||
else upEvent( n );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Mouse : public Device{
|
||||
public:
|
||||
Mouse( gxInput *i,IDirectInputDevice7 *d ):Device(i,d){
|
||||
}
|
||||
void update(){
|
||||
if( !acquired ){
|
||||
input->runtime->idle();
|
||||
return;
|
||||
}
|
||||
DIMOUSESTATE state;
|
||||
if( device->GetDeviceState(sizeof(state),&state)<0 ) return;
|
||||
if( gxGraphics *g=input->runtime->graphics ){
|
||||
int mx=axis_states[0]+state.lX;
|
||||
int my=axis_states[1]+state.lY;
|
||||
if( mx<0 ) mx=0;
|
||||
else if( mx>=g->getWidth() ) mx=g->getWidth()-1;
|
||||
if( my<0 ) my=0;
|
||||
else if( my>=g->getHeight() ) my=g->getHeight()-1;
|
||||
axis_states[0]=mx;
|
||||
axis_states[1]=my;
|
||||
axis_states[2]+=state.lZ;
|
||||
}
|
||||
for( int k=0;k<3;++k ){
|
||||
setDownState( k+1,state.rgbButtons[k]&0x80 ? true : false );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Joystick : public Device{
|
||||
public:
|
||||
int type,poll_time;
|
||||
int mins[12],maxs[12];
|
||||
Joystick( gxInput *i,IDirectInputDevice7 *d,int t ):Device(i,d),type(t),poll_time(0){
|
||||
for( int k=0;k<12;++k ){
|
||||
//initialize joystick axis ranges (d'oh!)
|
||||
DIPROPRANGE range;
|
||||
range.diph.dwSize=sizeof(DIPROPRANGE);
|
||||
range.diph.dwHeaderSize=sizeof(DIPROPHEADER);
|
||||
range.diph.dwObj=k*4+12;
|
||||
range.diph.dwHow=DIPH_BYOFFSET;
|
||||
if( d->GetProperty( DIPROP_RANGE,&range.diph )<0 ){
|
||||
mins[k]=0;
|
||||
maxs[k]=65535;
|
||||
continue;
|
||||
}
|
||||
mins[k]=range.lMin;
|
||||
maxs[k]=range.lMax-range.lMin;
|
||||
}
|
||||
}
|
||||
void update(){
|
||||
unsigned tm=timeGetTime();
|
||||
if( tm-poll_time<3 ) return;
|
||||
if( device->Poll()<0 ){
|
||||
acquired=false;
|
||||
input->runtime->idle();
|
||||
acquire();if( device->Poll()<0 ) return;
|
||||
}
|
||||
poll_time=tm;
|
||||
DIJOYSTATE state;
|
||||
if( device->GetDeviceState( sizeof( state ),&state )<0 ) return;
|
||||
axis_states[0]=(state.lX-mins[0])/(float)maxs[0]*2-1;
|
||||
axis_states[1]=(state.lY-mins[1])/(float)maxs[1]*2-1;
|
||||
axis_states[2]=(state.lZ-mins[2])/(float)maxs[2]*2-1;
|
||||
axis_states[3]=(state.rglSlider[0]-mins[6])/(float)maxs[6]*2-1;
|
||||
axis_states[4]=(state.rglSlider[1]-mins[7])/(float)maxs[7]*2-1;
|
||||
axis_states[5]=(state.lRx-mins[3])/(float)maxs[3]*2-1;
|
||||
axis_states[6]=(state.lRy-mins[4])/(float)maxs[4]*2-1;
|
||||
axis_states[7]=(state.lRz-mins[5])/(float)maxs[5]*2-1;
|
||||
if( (state.rgdwPOV[0]&0xffff)==0xffff ) axis_states[8]=-1;
|
||||
else axis_states[8]=floor(state.rgdwPOV[0]/100.0f+.5f);
|
||||
|
||||
for( int k=0;k<31;++k ){
|
||||
setDownState( k+1,state.rgbButtons[k]&0x80 ? true : false );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static Keyboard *keyboard;
|
||||
static Mouse *mouse;
|
||||
static vector<Joystick*> joysticks;
|
||||
|
||||
static Keyboard *createKeyboard( gxInput *input ){
|
||||
IDirectInputDevice7 *dev;
|
||||
if( input->dirInput->CreateDeviceEx( GUID_SysKeyboard,IID_IDirectInputDevice7,(void**)&dev,0 )>=0 ){
|
||||
if( dev->SetCooperativeLevel( input->runtime->hwnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE )>=0 ){
|
||||
if( dev->SetDataFormat( &c_dfDIKeyboard )>=0 ){
|
||||
DIPROPDWORD dword;
|
||||
memset( &dword,0,sizeof(dword) );
|
||||
dword.diph.dwSize=sizeof(DIPROPDWORD);
|
||||
dword.diph.dwHeaderSize=sizeof(DIPROPHEADER);
|
||||
dword.diph.dwObj=0;
|
||||
dword.diph.dwHow=DIPH_DEVICE;
|
||||
dword.dwData=32;
|
||||
if( dev->SetProperty( DIPROP_BUFFERSIZE,&dword.diph )>=0 ){
|
||||
return d_new Keyboard( input,dev );
|
||||
}else{
|
||||
input->runtime->debugInfo( "keyboard: SetProperty failed" );
|
||||
}
|
||||
}else{
|
||||
input->runtime->debugInfo( "keyboard: SetDataFormat failed" );
|
||||
}
|
||||
}else{
|
||||
input->runtime->debugInfo( "keyboard: SetCooperativeLevel failed" );
|
||||
}
|
||||
dev->Release();
|
||||
}else{
|
||||
input->runtime->debugInfo( "keyboard: CreateDeviceEx failed" );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Mouse *createMouse( gxInput *input ){
|
||||
IDirectInputDevice7 *dev;
|
||||
if( input->dirInput->CreateDeviceEx( GUID_SysMouse,IID_IDirectInputDevice7,(void**)&dev,0 )>=0 ){
|
||||
if( dev->SetCooperativeLevel( input->runtime->hwnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE )>=0 ){
|
||||
if( dev->SetDataFormat( &c_dfDIMouse )>=0 ){
|
||||
return d_new Mouse( input,dev );
|
||||
}else{
|
||||
input->runtime->debugInfo( "mouse: SetDataFormat failed" );
|
||||
}
|
||||
}else{
|
||||
input->runtime->debugInfo( "mouse: SetCooperativeLevel failed" );
|
||||
}
|
||||
dev->Release();
|
||||
}else{
|
||||
input->runtime->debugInfo( "mouse: CreateDeviceEx failed" );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Joystick *createJoystick( gxInput *input,LPCDIDEVICEINSTANCE devinst ){
|
||||
IDirectInputDevice7 *dev;
|
||||
if( input->dirInput->CreateDeviceEx( devinst->guidInstance,IID_IDirectInputDevice7,(void**)&dev,0 )>=0 ){
|
||||
if( dev->SetCooperativeLevel( input->runtime->hwnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE )>=0 ){
|
||||
if( dev->SetDataFormat( &c_dfDIJoystick )>=0 ){
|
||||
int t=((devinst->dwDevType>>8)&0xff)==DIDEVTYPEJOYSTICK_GAMEPAD ? 1 : 2;
|
||||
return d_new Joystick( input,dev,t );
|
||||
}
|
||||
}
|
||||
dev->Release();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK enumJoystick( LPCDIDEVICEINSTANCE devinst,LPVOID pvRef ){
|
||||
|
||||
if( (devinst->dwDevType&0xff)!=DIDEVTYPE_JOYSTICK ) return DIENUM_CONTINUE;
|
||||
|
||||
if( Joystick *joy=createJoystick( (gxInput*)pvRef,devinst ) ){
|
||||
joysticks.push_back( joy );
|
||||
}
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
gxInput::gxInput( gxRuntime *rt,IDirectInput7 *di ):
|
||||
runtime(rt),dirInput(di){
|
||||
keyboard=createKeyboard( this );
|
||||
mouse=createMouse( this );
|
||||
joysticks.clear();
|
||||
dirInput->EnumDevices( DIDEVTYPE_JOYSTICK,enumJoystick,this,DIEDFL_ATTACHEDONLY );
|
||||
}
|
||||
|
||||
gxInput::~gxInput(){
|
||||
for( int k=0;k<joysticks.size();++k ) delete joysticks[k];
|
||||
joysticks.clear();
|
||||
delete mouse;
|
||||
delete keyboard;
|
||||
|
||||
dirInput->Release();
|
||||
}
|
||||
|
||||
void gxInput::wm_keydown( int key ){
|
||||
if( keyboard ) keyboard->downEvent( key );
|
||||
}
|
||||
|
||||
void gxInput::wm_keyup( int key ){
|
||||
if( keyboard ) keyboard->upEvent( key );
|
||||
}
|
||||
|
||||
void gxInput::wm_mousedown( int key ){
|
||||
if( mouse ) mouse->downEvent( key );
|
||||
}
|
||||
|
||||
void gxInput::wm_mouseup( int key ){
|
||||
if( mouse ) mouse->upEvent( key );
|
||||
}
|
||||
|
||||
void gxInput::wm_mousemove( int x,int y ){
|
||||
if( mouse ){
|
||||
mouse->axis_states[0]=x;
|
||||
mouse->axis_states[1]=y;
|
||||
}
|
||||
}
|
||||
|
||||
void gxInput::wm_mousewheel( int dz ){
|
||||
if( mouse ) mouse->axis_states[2]+=dz;
|
||||
}
|
||||
|
||||
void gxInput::reset(){
|
||||
if( mouse ) mouse->reset();
|
||||
if( keyboard ) keyboard->reset();
|
||||
for( int k=0;k<joysticks.size();++k ) joysticks[k]->reset();
|
||||
}
|
||||
|
||||
bool gxInput::acquire(){
|
||||
bool m_ok=true,k_ok=true;
|
||||
if( mouse ) m_ok=mouse->acquire();
|
||||
if( keyboard ) k_ok=keyboard->acquire();
|
||||
if( m_ok && k_ok ) return true;
|
||||
if( k_ok ) keyboard->unacquire();
|
||||
if( m_ok ) mouse->unacquire();
|
||||
return false;
|
||||
}
|
||||
|
||||
void gxInput::unacquire(){
|
||||
if( keyboard ) keyboard->unacquire();
|
||||
if( mouse ) mouse->unacquire();
|
||||
}
|
||||
|
||||
void gxInput::moveMouse( int x,int y ){
|
||||
if( !mouse ) return;
|
||||
mouse->axis_states[0]=x;
|
||||
mouse->axis_states[1]=y;
|
||||
runtime->moveMouse( x,y );
|
||||
}
|
||||
|
||||
gxDevice *gxInput::getMouse()const{
|
||||
return mouse;
|
||||
}
|
||||
|
||||
gxDevice *gxInput::getKeyboard()const{
|
||||
return keyboard;
|
||||
}
|
||||
|
||||
gxDevice *gxInput::getJoystick( int n )const{
|
||||
return n>=0 && n<joysticks.size() ? joysticks[n] : 0;
|
||||
}
|
||||
|
||||
int gxInput::getJoystickType( int n )const{
|
||||
return n>=0 && n<joysticks.size() ? joysticks[n]->type : 0;
|
||||
}
|
||||
|
||||
int gxInput::numJoysticks()const{
|
||||
return joysticks.size();
|
||||
}
|
||||
|
||||
int gxInput::toAscii( int scan )const{
|
||||
switch( scan ){
|
||||
case DIK_INSERT:return ASC_INSERT;
|
||||
case DIK_DELETE:return ASC_DELETE;
|
||||
case DIK_HOME:return ASC_HOME;
|
||||
case DIK_END:return ASC_END;
|
||||
case DIK_PGUP:return ASC_PAGEUP;
|
||||
case DIK_PGDN:return ASC_PAGEDOWN;
|
||||
case DIK_UP:return ASC_UP;
|
||||
case DIK_DOWN:return ASC_DOWN;
|
||||
case DIK_LEFT:return ASC_LEFT;
|
||||
case DIK_RIGHT:return ASC_RIGHT;
|
||||
}
|
||||
scan&=0x7f;
|
||||
int virt=MapVirtualKey( scan,1 );
|
||||
if( !virt ) return 0;
|
||||
|
||||
static unsigned char mat[256];
|
||||
mat[VK_LSHIFT]=keyboard->keyDown( DIK_LSHIFT ) ? 0x80 : 0;
|
||||
mat[VK_RSHIFT]=keyboard->keyDown( DIK_RSHIFT ) ? 0x80 : 0;
|
||||
mat[VK_SHIFT]=mat[VK_LSHIFT]|mat[VK_RSHIFT];
|
||||
mat[VK_LCONTROL]=keyboard->keyDown( DIK_LCONTROL ) ? 0x80 : 0;
|
||||
mat[VK_RCONTROL]=keyboard->keyDown( DIK_RCONTROL ) ? 0x80 : 0;
|
||||
mat[VK_CONTROL]=mat[VK_LCONTROL]|mat[VK_RCONTROL];
|
||||
mat[VK_LMENU]=keyboard->keyDown( DIK_LMENU ) ? 0x80 : 0;
|
||||
mat[VK_RMENU]=keyboard->keyDown( DIK_RMENU ) ? 0x80 : 0;
|
||||
mat[VK_MENU]=mat[VK_LMENU]|mat[VK_RMENU];
|
||||
|
||||
WORD ch;
|
||||
if( ToAscii( virt,scan,mat,&ch,0 )!=1 ) return 0;
|
||||
return ch & 255;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
#ifndef GXINPUT_H
|
||||
#define GXINPUT_H
|
||||
|
||||
#include <dinput.h>
|
||||
|
||||
#include "gxdevice.h"
|
||||
|
||||
class gxRuntime;
|
||||
|
||||
class gxInput{
|
||||
public:
|
||||
gxRuntime *runtime;
|
||||
IDirectInput7 *dirInput;
|
||||
|
||||
gxInput( gxRuntime *runtime,IDirectInput7 *di );
|
||||
~gxInput();
|
||||
|
||||
void reset();
|
||||
bool acquire();
|
||||
void unacquire();
|
||||
|
||||
void wm_keydown( int key );
|
||||
void wm_keyup( int key );
|
||||
void wm_mousedown( int key );
|
||||
void wm_mouseup( int key );
|
||||
void wm_mousemove( int x,int y );
|
||||
void wm_mousewheel( int dz );
|
||||
|
||||
private:
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
ASC_HOME=1,ASC_END=2,ASC_INSERT=3,ASC_DELETE=4,
|
||||
ASC_PAGEUP=5,ASC_PAGEDOWN=6,
|
||||
ASC_UP=28,ASC_DOWN=29,ASC_RIGHT=30,ASC_LEFT=31
|
||||
};
|
||||
|
||||
void moveMouse( int x,int y );
|
||||
|
||||
gxDevice *getMouse()const;
|
||||
gxDevice *getKeyboard()const;
|
||||
gxDevice *getJoystick( int port )const;
|
||||
int getJoystickType( int port )const;
|
||||
int numJoysticks()const;
|
||||
int toAscii( int key )const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxlight.h"
|
||||
#include "gxscene.h"
|
||||
#include "gxgraphics.h"
|
||||
|
||||
const float PI=3.14159265359f; //180 degrees
|
||||
const float TWOPI=PI*2.0f; //360 degrees
|
||||
const float HALFPI=PI*.5f; //90 degrees
|
||||
const float EPSILON=.000001f;
|
||||
|
||||
gxLight::gxLight( gxScene *s,int type ):
|
||||
scene(s){
|
||||
|
||||
memset(&d3d_light,0,sizeof(d3d_light));
|
||||
|
||||
switch( type ){
|
||||
case LIGHT_POINT:
|
||||
d3d_light.dltType=D3DLIGHT_POINT;
|
||||
break;
|
||||
case LIGHT_SPOT:
|
||||
d3d_light.dltType=D3DLIGHT_SPOT;
|
||||
break;
|
||||
default:
|
||||
d3d_light.dltType=D3DLIGHT_DIRECTIONAL;
|
||||
}
|
||||
|
||||
d3d_light.dcvDiffuse.a=1;
|
||||
d3d_light.dcvDiffuse.r=d3d_light.dcvDiffuse.g=d3d_light.dcvDiffuse.b=1;
|
||||
d3d_light.dcvSpecular.r=d3d_light.dcvSpecular.g=d3d_light.dcvSpecular.b=1;
|
||||
d3d_light.dvRange=D3DLIGHT_RANGE_MAX;
|
||||
d3d_light.dvTheta=0;
|
||||
d3d_light.dvPhi=HALFPI;
|
||||
d3d_light.dvFalloff=1;
|
||||
d3d_light.dvDirection.z=1;
|
||||
setRange( 1000 );
|
||||
}
|
||||
|
||||
gxLight::~gxLight(){
|
||||
}
|
||||
|
||||
void gxLight::setRange( float r ){
|
||||
d3d_light.dvAttenuation1=1.0f/r;
|
||||
}
|
||||
|
||||
void gxLight::setPosition( const float pos[3] ){
|
||||
d3d_light.dvPosition.x=pos[0];
|
||||
d3d_light.dvPosition.y=pos[1];
|
||||
d3d_light.dvPosition.z=pos[2];
|
||||
}
|
||||
|
||||
void gxLight::setDirection( const float dir[3] ){
|
||||
d3d_light.dvDirection.x=dir[0];
|
||||
d3d_light.dvDirection.y=dir[1];
|
||||
d3d_light.dvDirection.z=dir[2];
|
||||
}
|
||||
|
||||
void gxLight::setConeAngles( float inner,float outer ){
|
||||
d3d_light.dvTheta=inner;
|
||||
d3d_light.dvPhi=outer;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef GXLIGHT_H
|
||||
#define GXLIGHT_H
|
||||
|
||||
class gxScene;
|
||||
|
||||
class gxLight{
|
||||
public:
|
||||
gxLight( gxScene *scene,int type );
|
||||
~gxLight();
|
||||
|
||||
D3DLIGHT7 d3d_light;
|
||||
|
||||
private:
|
||||
gxScene *scene;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
LIGHT_DISTANT=1,LIGHT_POINT=2,LIGHT_SPOT=3
|
||||
};
|
||||
void setRange( float range );
|
||||
void setColor( const float rgb[3] ){ memcpy( &d3d_light.dcvDiffuse,rgb,12 ); }
|
||||
void setPosition( const float pos[3] );
|
||||
void setDirection( const float dir[3] );
|
||||
void setConeAngles( float inner,float outer );
|
||||
|
||||
void getColor( float rgb[3] ){ memcpy( rgb,&d3d_light.dcvDiffuse,12 ); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxmesh.h"
|
||||
#include "gxgraphics.h"
|
||||
|
||||
#include "gxruntime.h"
|
||||
|
||||
extern gxRuntime *gx_runtime;
|
||||
|
||||
gxMesh::gxMesh( gxGraphics *g,IDirect3DVertexBuffer7 *vs,WORD *is,int max_vs,int max_ts ):
|
||||
graphics(g),locked_verts(0),vertex_buff(vs),tri_indices(is),max_verts(max_vs),max_tris(max_ts),mesh_dirty(false){
|
||||
}
|
||||
|
||||
gxMesh::~gxMesh(){
|
||||
unlock();
|
||||
|
||||
vertex_buff->Release();
|
||||
|
||||
delete[] tri_indices;
|
||||
}
|
||||
|
||||
bool gxMesh::lock( bool all ){
|
||||
if( locked_verts ) return true;
|
||||
|
||||
//V1.104
|
||||
//int flags=all ? DDLOCK_DISCARDCONTENTS : 0;
|
||||
|
||||
//V1.105
|
||||
//int flags=all ? DDLOCK_DISCARDCONTENTS : DDLOCK_NOOVERWRITE;
|
||||
|
||||
//V1.104/1.105
|
||||
//if( vertex_buff->Lock( DDLOCK_WRITEONLY|DDLOCK_WAIT|flags,(void**)&locked_verts,0 )>=0 ){
|
||||
|
||||
//V1.1.06...
|
||||
int flags=DDLOCK_WAIT|DDLOCK_WRITEONLY;
|
||||
|
||||
//XP or less?
|
||||
if( graphics->runtime->osinfo.dwMajorVersion<6 ){
|
||||
flags|=(all ? DDLOCK_DISCARDCONTENTS : DDLOCK_NOOVERWRITE);
|
||||
}
|
||||
|
||||
if( vertex_buff->Lock( flags,(void**)&locked_verts,0 )>=0 ){
|
||||
mesh_dirty=false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static dxVertex *err_verts=new dxVertex[32768];
|
||||
|
||||
locked_verts=err_verts;
|
||||
return true;
|
||||
}
|
||||
|
||||
void gxMesh::unlock(){
|
||||
if( locked_verts ){
|
||||
vertex_buff->Unlock();
|
||||
locked_verts=0;
|
||||
}
|
||||
}
|
||||
|
||||
void gxMesh::backup(){
|
||||
unlock();
|
||||
}
|
||||
|
||||
void gxMesh::restore(){
|
||||
mesh_dirty=true;
|
||||
}
|
||||
|
||||
/*
|
||||
void gxMesh::backup(){
|
||||
|
||||
unlock();
|
||||
|
||||
if( backup_verts ){
|
||||
delete[] backup_verts;
|
||||
backup_verts=0;
|
||||
}
|
||||
|
||||
dxVertex *verts;
|
||||
if( vertex_buff->Lock( DDLOCK_READONLY|DDLOCK_WAIT,(void**)&verts,0 )>=0 ){
|
||||
backup_verts=d_new dxVertex[ max_verts ];
|
||||
memcpy( backup_verts,verts,sizeof(dxVertex)*max_verts );
|
||||
vertex_buff->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void gxMesh::restore(){
|
||||
|
||||
if( !backup_verts ) return;
|
||||
|
||||
dxVertex *verts;
|
||||
if( vertex_buff->Lock( DDLOCK_WRITEONLY|DDLOCK_WAIT,(void**)&verts,0 )>=0 ){
|
||||
memcpy( verts,backup_verts,sizeof(dxVertex)*max_verts );
|
||||
vertex_buff->Unlock();
|
||||
}
|
||||
|
||||
delete[] backup_verts;
|
||||
backup_verts=0;
|
||||
}
|
||||
*/
|
||||
|
||||
void gxMesh::render( int first_vert,int vert_cnt,int first_tri,int tri_cnt ){
|
||||
unlock();
|
||||
graphics->dir3dDev->DrawIndexedPrimitiveVB(
|
||||
D3DPT_TRIANGLELIST,
|
||||
vertex_buff,first_vert,vert_cnt,
|
||||
tri_indices+first_tri*3,tri_cnt*3,0 );
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
#ifndef GXMESH_H
|
||||
#define GXMESH_H
|
||||
|
||||
#include <d3d.h>
|
||||
|
||||
class gxGraphics;
|
||||
|
||||
class gxMesh{
|
||||
public:
|
||||
|
||||
gxMesh( gxGraphics *graphics,IDirect3DVertexBuffer7 *verts,WORD *indicies,int max_verts,int max_tris );
|
||||
~gxMesh();
|
||||
|
||||
int maxVerts()const{ return max_verts; }
|
||||
int maxTris()const{ return max_tris; }
|
||||
|
||||
bool dirty()const{ return mesh_dirty; }
|
||||
|
||||
void render( int first_vert,int vert_cnt,int first_tri,int tri_cnt );
|
||||
|
||||
void backup();
|
||||
void restore();
|
||||
|
||||
private:
|
||||
struct dxVertex{
|
||||
float coords[3];
|
||||
float normal[3];
|
||||
unsigned argb;
|
||||
float tex_coords[4];
|
||||
};
|
||||
|
||||
gxGraphics *graphics;
|
||||
IDirect3DVertexBuffer7 *vertex_buff;
|
||||
WORD *tri_indices;
|
||||
|
||||
int max_verts,max_tris;
|
||||
bool mesh_dirty;
|
||||
dxVertex *locked_verts;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
bool lock( bool all );
|
||||
void unlock();
|
||||
|
||||
//VERY NAUGHTY!!!!!
|
||||
void setVertex( int n,const void *v ){
|
||||
memcpy( locked_verts+n,v,sizeof(dxVertex) );
|
||||
}
|
||||
void setVertex( int n,const float coords[3],const float normal[3],const float tex_coords[2][2] ){
|
||||
dxVertex *t=locked_verts+n;
|
||||
memcpy( t->coords,coords,12 );
|
||||
memcpy( t->normal,normal,12 );
|
||||
t->argb=0xffffffff;
|
||||
memcpy( t->tex_coords,tex_coords,16 );
|
||||
}
|
||||
void setVertex( int n,const float coords[3],const float normal[3],unsigned argb,const float tex_coords[2][2] ){
|
||||
dxVertex *t=locked_verts+n;
|
||||
memcpy( t->coords,coords,12 );
|
||||
memcpy( t->normal,normal,12 );
|
||||
t->argb=argb;
|
||||
memcpy( t->tex_coords,tex_coords,16 );
|
||||
}
|
||||
void setTriangle( int n,int v0,int v1,int v2 ){
|
||||
tri_indices[n*3]=v0;
|
||||
tri_indices[n*3+1]=v1;
|
||||
tri_indices[n*3+2]=v2;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxmovie.h"
|
||||
#include "gxgraphics.h"
|
||||
|
||||
gxMovie::gxMovie( gxGraphics *g,IMultiMediaStream *mm )
|
||||
:gfx(g),mm_stream( mm ),playing(true){
|
||||
|
||||
mm_stream->GetMediaStream( MSPID_PrimaryVideo,&vid_stream );
|
||||
vid_stream->QueryInterface( IID_IDirectDrawMediaStream,(void**)&dd_stream );
|
||||
|
||||
DDSURFACEDESC desc={sizeof(desc)};
|
||||
dd_stream->GetFormat( &desc,0,0,0 );
|
||||
|
||||
canvas=gfx->createCanvas( desc.dwWidth,desc.dwHeight,0 ); //gxCanvas::CANVAS_NONDISPLAY );
|
||||
canvas->getSurface()->QueryInterface( IID_IDirectDrawSurface,(void**)&dd_surf );
|
||||
|
||||
src_rect.left=src_rect.top=0;
|
||||
src_rect.right=desc.dwWidth;src_rect.bottom=desc.dwHeight;
|
||||
|
||||
dd_stream->CreateSample( dd_surf,&src_rect,0,&dd_sample );
|
||||
|
||||
mm_stream->SetState( STREAMSTATE_RUN );
|
||||
}
|
||||
|
||||
gxMovie::~gxMovie(){
|
||||
mm_stream->SetState( STREAMSTATE_STOP );
|
||||
|
||||
dd_sample->Release();
|
||||
dd_surf->Release();
|
||||
dd_stream->Release();
|
||||
vid_stream->Release();
|
||||
mm_stream->Release();
|
||||
|
||||
gfx->freeCanvas( canvas );
|
||||
}
|
||||
|
||||
bool gxMovie::draw( gxCanvas *dest,int x,int y,int w,int h ){
|
||||
if( !playing ) return false;
|
||||
if( !dd_sample->Update( 0,0,0,0 ) ){
|
||||
RECT dest_rect={x,y,x+w,y+h};
|
||||
dest->getSurface()->Blt( &dest_rect,canvas->getSurface(),&src_rect,DDBLT_WAIT,0 );
|
||||
dest->damage( dest_rect );
|
||||
}else{
|
||||
playing=false;
|
||||
}
|
||||
return playing;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
#ifndef GXMOVIE_H
|
||||
#define GXMOVIE_H
|
||||
|
||||
#include "mmstream.h" // multimedia stream interfaces
|
||||
#include "amstream.h" // DirectShow multimedia stream interfaces
|
||||
#include "ddstream.h" // DirectDraw multimedia stream interfaces
|
||||
|
||||
#include "gxcanvas.h"
|
||||
|
||||
class gxGraphics;
|
||||
|
||||
class gxMovie{
|
||||
|
||||
public:
|
||||
gxMovie( gxGraphics *gfx,IMultiMediaStream *mm_stream );
|
||||
~gxMovie();
|
||||
|
||||
private:
|
||||
bool playing;
|
||||
RECT src_rect;
|
||||
gxGraphics *gfx;
|
||||
gxCanvas *canvas;
|
||||
IDirectDrawSurface *dd_surf;
|
||||
IMediaStream *vid_stream;
|
||||
IDirectDrawMediaStream *dd_stream;
|
||||
IDirectDrawStreamSample *dd_sample;
|
||||
IMultiMediaStream *mm_stream;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
|
||||
bool draw( gxCanvas *dest,int x,int y,int w,int h );
|
||||
|
||||
bool isPlaying()const{ return playing; }
|
||||
int getWidth()const{ return src_rect.right; }
|
||||
int getHeight()const{ return src_rect.bottom; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxmusic.h"
|
||||
|
||||
gxMusic::gxMusic( gxAudio *a,FMUSIC_MODULE *m,FSOUND_STREAM *s ):
|
||||
audio(a),module(m),stream(s),stream_channel(-1){
|
||||
}
|
||||
|
||||
gxMusic::~gxMusic(){
|
||||
if( module ) FMUSIC_FreeSong( module );
|
||||
else FSOUND_Stream_Close( stream );
|
||||
}
|
||||
|
||||
void gxMusic::play(){
|
||||
if( module ){
|
||||
FMUSIC_PlaySong( module );
|
||||
}else{
|
||||
stream_channel=FSOUND_Stream_Play( FSOUND_FREE,stream );
|
||||
}
|
||||
}
|
||||
|
||||
void gxMusic::stop(){
|
||||
if( module ){
|
||||
FMUSIC_StopSong( module );
|
||||
}else{
|
||||
FSOUND_Stream_Stop( stream );
|
||||
stream_channel=-1;
|
||||
}
|
||||
}
|
||||
|
||||
void gxMusic::setVolume( float volume ){
|
||||
if( module ){
|
||||
FMUSIC_SetMasterVolume( module,volume*255.0f );
|
||||
}else{
|
||||
FSOUND_SetVolume( stream_channel,volume*255.0f );
|
||||
}
|
||||
}
|
||||
|
||||
void gxMusic::setPaused( bool paused){
|
||||
if( module ){
|
||||
FMUSIC_SetPaused( module,paused );
|
||||
}else{
|
||||
FSOUND_SetPaused( stream_channel,paused );
|
||||
}
|
||||
}
|
||||
|
||||
bool gxMusic::isPlaying()const{
|
||||
if( module ){
|
||||
return FMUSIC_IsPlaying( module ) ? true : false;
|
||||
}else{
|
||||
return FSOUND_IsPlaying( stream_channel ) ? true : false;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
#ifndef GXMUSIC_H
|
||||
#define GXMUSIC_H
|
||||
|
||||
class gxAudio;
|
||||
|
||||
struct FMUSIC_MODULE;
|
||||
struct FSOUND_STREAM;
|
||||
|
||||
class gxMusic{
|
||||
public:
|
||||
gxAudio *audio;
|
||||
|
||||
gxMusic( gxAudio *audio,FMUSIC_MODULE *module,FSOUND_STREAM *stream );
|
||||
~gxMusic();
|
||||
|
||||
private:
|
||||
FMUSIC_MODULE *module;
|
||||
FSOUND_STREAM *stream;
|
||||
int stream_channel;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
//modifiers
|
||||
void play();
|
||||
void stop();
|
||||
void setPaused( bool paused );
|
||||
void setVolume( float volume );
|
||||
|
||||
//accessors
|
||||
bool isPlaying()const;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,374 @@
|
||||
# Microsoft Developer Studio Project File - Name="gxruntime" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=gxruntime - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "gxruntime.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "gxruntime.mak" CFG="gxruntime - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "gxruntime - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "gxruntime - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "gxruntime - Win32 Blitz3DRelease" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "gxruntime - Win32 Blitz2DRelease" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "gxruntime - Win32 Blitz3DEdu" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "gxruntime - Win32 Blitz3DDemo" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "gxruntime - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /Ox /Ow /Og /Oi /Os /Ob2 /Gf /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"std.h" /FD /c
|
||||
# SUBTRACT CPP /Ot
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /Yu"std.h" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz3DRelease"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "gxruntime___Win32_Blitz3DRelease"
|
||||
# PROP BASE Intermediate_Dir "gxruntime___Win32_Blitz3DRelease"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "gxruntime___Win32_Blitz3DRelease"
|
||||
# PROP Intermediate_Dir "gxruntime___Win32_Blitz3DRelease"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /Ox /Ow /Og /Oi /Os /Ob2 /Gf /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"std.h" /FD /c
|
||||
# SUBTRACT BASE CPP /Ot
|
||||
# ADD CPP /nologo /G6 /Gz /MT /W3 /GX /O2 /Ob2 /D "_LIB" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "PRO" /FD /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz2DRelease"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "gxruntime___Win32_Blitz2DRelease"
|
||||
# PROP BASE Intermediate_Dir "gxruntime___Win32_Blitz2DRelease"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "gxruntime___Win32_Blitz2DRelease"
|
||||
# PROP Intermediate_Dir "gxruntime___Win32_Blitz2DRelease"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /Ox /Ow /Og /Oi /Os /Ob2 /Gf /Gy /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"std.h" /FD /c
|
||||
# SUBTRACT BASE CPP /Ot
|
||||
# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Yu"std.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz3DEdu"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "gxruntime___Win32_Blitz3DEdu"
|
||||
# PROP BASE Intermediate_Dir "gxruntime___Win32_Blitz3DEdu"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "gxruntime___Win32_Blitz3DEdu"
|
||||
# PROP Intermediate_Dir "gxruntime___Win32_Blitz3DEdu"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /Gz /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "PRO" /Yu"std.h" /FD /c
|
||||
# ADD CPP /nologo /G6 /Gz /MT /W3 /GX /O2 /Ob2 /D "_LIB" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "PRO" /D "EDU" /Yu"std.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz3DDemo"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "gxruntime___Win32_Blitz3DDemo"
|
||||
# PROP BASE Intermediate_Dir "gxruntime___Win32_Blitz3DDemo"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "gxruntime___Win32_Blitz3DDemo"
|
||||
# PROP Intermediate_Dir "gxruntime___Win32_Blitz3DDemo"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G6 /Gz /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "PRO" /Yu"std.h" /FD /c
|
||||
# ADD CPP /nologo /G6 /Gz /MT /W3 /GX /O2 /Ob2 /D "_LIB" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "PRO" /D "DEMO" /Yu"std.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "gxruntime - Win32 Release"
|
||||
# Name "gxruntime - Win32 Debug"
|
||||
# Name "gxruntime - Win32 Blitz3DRelease"
|
||||
# Name "gxruntime - Win32 Blitz2DRelease"
|
||||
# Name "gxruntime - Win32 Blitz3DEdu"
|
||||
# Name "gxruntime - Win32 Blitz3DDemo"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ddutil.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxaudio.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxcanvas.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxchannel.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxdevice.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxdir.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxfilesystem.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxfont.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxgraphics.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxinput.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxlight.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxmesh.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxmovie.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxruntime.cpp
|
||||
|
||||
!IF "$(CFG)" == "gxruntime - Win32 Release"
|
||||
|
||||
# ADD CPP /FAs
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz3DRelease"
|
||||
|
||||
# ADD BASE CPP /FAs
|
||||
# ADD CPP /FAs
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz2DRelease"
|
||||
|
||||
# ADD BASE CPP /FAs
|
||||
# ADD CPP /FAs
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz3DEdu"
|
||||
|
||||
# ADD BASE CPP /FAs
|
||||
# ADD CPP /FAs
|
||||
|
||||
!ELSEIF "$(CFG)" == "gxruntime - Win32 Blitz3DDemo"
|
||||
|
||||
# ADD BASE CPP /FAs
|
||||
# ADD CPP /FAs
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxscene.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxsound.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxtimer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\std.cpp
|
||||
# ADD CPP /Yc"std.h"
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asmcoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ddutil.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxaudio.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxcanvas.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxchannel.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxdevice.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxdir.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxfilesystem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxfont.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxgraphics.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxinput.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxlight.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxmesh.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxmovie.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxruntime.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxscene.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxsound.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gxtimer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\std.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,145 @@
|
||||
|
||||
#ifndef GXRUNTIME_H
|
||||
#define GXRUNTIME_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gxaudio.h"
|
||||
#include "gxinput.h"
|
||||
#include "gxgraphics.h"
|
||||
#include "gxfilesystem.h"
|
||||
#include "gxtimer.h"
|
||||
|
||||
#include "../debugger/debugger.h"
|
||||
|
||||
class gxRuntime{
|
||||
/***** INTERNAL INTERFACE *****/
|
||||
public:
|
||||
|
||||
HWND hwnd;
|
||||
HINSTANCE hinst;
|
||||
|
||||
gxAudio *audio;
|
||||
gxInput *input;
|
||||
gxGraphics *graphics;
|
||||
gxFileSystem *fileSystem;
|
||||
|
||||
void flip( bool vwait );
|
||||
void moveMouse( int x,int y );
|
||||
|
||||
LRESULT windowProc( HWND hwnd,UINT msg,WPARAM w,LPARAM l );
|
||||
|
||||
struct GfxMode;
|
||||
struct GfxDriver;
|
||||
|
||||
private:
|
||||
gxRuntime( HINSTANCE hinst,const std::string &cmd_line,HWND hwnd );
|
||||
~gxRuntime();
|
||||
|
||||
void paint();
|
||||
void suspend();
|
||||
void forceSuspend();
|
||||
void resume();
|
||||
void forceResume();
|
||||
void backupWindowState();
|
||||
void restoreWindowState();
|
||||
|
||||
RECT t_rect;
|
||||
int t_style;
|
||||
std::string cmd_line;
|
||||
bool pointer_visible;
|
||||
std::string app_title;
|
||||
std::string app_close;
|
||||
|
||||
bool setDisplayMode( int w,int h,int d,bool d3d,IDirectDraw7 *dd );
|
||||
gxGraphics *openWindowedGraphics( int w,int h,int d,bool d3d );
|
||||
gxGraphics *openExclusiveGraphics( int w,int h,int d,bool d3d );
|
||||
|
||||
bool enum_all;
|
||||
std::vector<GfxDriver*> drivers;
|
||||
GfxDriver *curr_driver;
|
||||
int use_di;
|
||||
|
||||
void enumGfx();
|
||||
void denumGfx();
|
||||
|
||||
void resetInput();
|
||||
void pauseAudio();
|
||||
void resumeAudio();
|
||||
void backupGraphics();
|
||||
void restoreGraphics();
|
||||
void acquireInput();
|
||||
void unacquireInput();
|
||||
|
||||
/***** APP INTERFACE *****/
|
||||
public:
|
||||
static gxRuntime *openRuntime( HINSTANCE hinst,const std::string &cmd_line,Debugger *debugger );
|
||||
static void closeRuntime( gxRuntime *runtime );
|
||||
|
||||
void asyncStop();
|
||||
void asyncRun();
|
||||
void asyncEnd();
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
GFXMODECAPS_3D=1
|
||||
};
|
||||
|
||||
//return true if program should continue, or false for quit.
|
||||
bool idle();
|
||||
bool delay( int ms );
|
||||
|
||||
bool execute( const std::string &cmd );
|
||||
void setTitle( const std::string &title,const std::string &close );
|
||||
int getMilliSecs();
|
||||
void setPointerVisible( bool vis );
|
||||
|
||||
std::string commandLine();
|
||||
|
||||
std::string systemProperty( const std::string &t );
|
||||
|
||||
void debugStop();
|
||||
void debugProfile( int per );
|
||||
void debugStmt( int pos,const char *file );
|
||||
void debugEnter( void *frame,void *env,const char *func );
|
||||
void debugLeave();
|
||||
void debugInfo( const char *t );
|
||||
void debugError( const char *t );
|
||||
void debugLog( const char *t );
|
||||
|
||||
int numGraphicsDrivers();
|
||||
void graphicsDriverInfo( int driver,std::string *name,int *caps );
|
||||
|
||||
int numGraphicsModes( int driver );
|
||||
void graphicsModeInfo( int driver,int mode,int *w,int *h,int *d,int *caps );
|
||||
|
||||
void windowedModeInfo( int *caps );
|
||||
|
||||
gxAudio *openAudio( int flags );
|
||||
void closeAudio( gxAudio *audio );
|
||||
|
||||
gxInput *openInput( int flags );
|
||||
void closeInput( gxInput *input );
|
||||
|
||||
gxGraphics *openGraphics( int w,int h,int d,int driver,int flags );
|
||||
void closeGraphics( gxGraphics *graphics );
|
||||
bool graphicsLost();
|
||||
|
||||
gxFileSystem *openFileSystem( int flags );
|
||||
void closeFileSystem( gxFileSystem *filesys );
|
||||
|
||||
gxTimer *createTimer( int hertz );
|
||||
void freeTimer( gxTimer *timer );
|
||||
|
||||
void enableDirectInput( bool use );
|
||||
int directInputEnabled(){ return use_di; }
|
||||
|
||||
int callDll( const std::string &dll,const std::string &func,const void *in,int in_sz,void *out,int out_sz );
|
||||
|
||||
OSVERSIONINFO osinfo;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,618 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxscene.h"
|
||||
#include "gxgraphics.h"
|
||||
#include "gxruntime.h"
|
||||
|
||||
static bool can_wb;
|
||||
static int hw_tex_stages,tex_stages;
|
||||
static float BLACK[]={0,0,0};
|
||||
static float WHITE[]={1,1,1};
|
||||
static float GRAY[]={.5f,.5f,.5f};
|
||||
static D3DMATRIX sphere_mat,nullmatrix;
|
||||
|
||||
void gxScene::setRS( int n,int t ){
|
||||
if( d3d_rs[n]==t ) return;
|
||||
dir3dDev->SetRenderState( (D3DRENDERSTATETYPE)n,t );
|
||||
d3d_rs[n]=t;
|
||||
}
|
||||
|
||||
void gxScene::setTSS( int n,int s,int t ){
|
||||
if( d3d_tss[n][s]==t ) return;
|
||||
dir3dDev->SetTextureStageState( n,(D3DTEXTURESTAGESTATETYPE)s,t );
|
||||
d3d_tss[n][s]=t;
|
||||
}
|
||||
|
||||
gxScene::gxScene( gxGraphics *g,gxCanvas *t ):
|
||||
graphics(g),target(t),dir3dDev( g->dir3dDev ),
|
||||
n_texs(0),tris_drawn(0){
|
||||
|
||||
memset( d3d_rs,0x55,sizeof(d3d_rs) );
|
||||
memset( d3d_tss,0x55,sizeof(d3d_tss) );
|
||||
|
||||
//nomalize normals
|
||||
setRS( D3DRENDERSTATE_NORMALIZENORMALS,TRUE );
|
||||
|
||||
//vertex coloring
|
||||
setRS( D3DRENDERSTATE_COLORVERTEX,FALSE );
|
||||
setRS( D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,D3DMCS_COLOR1 );
|
||||
setRS( D3DRENDERSTATE_AMBIENTMATERIALSOURCE,D3DMCS_COLOR1 );
|
||||
setRS( D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,D3DMCS_MATERIAL );
|
||||
setRS( D3DRENDERSTATE_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL );
|
||||
|
||||
//Alpha test
|
||||
setRS( D3DRENDERSTATE_ALPHATESTENABLE,false );
|
||||
setRS( D3DRENDERSTATE_ALPHAFUNC,D3DCMP_GREATER );
|
||||
setRS( D3DRENDERSTATE_ALPHAREF,128 );
|
||||
|
||||
//source/dest blending modes
|
||||
setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
|
||||
setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA );
|
||||
|
||||
//suss out caps
|
||||
can_wb=false;
|
||||
hw_tex_stages=1;
|
||||
D3DDEVICEDESC7 devDesc={0};
|
||||
if( dir3dDev->GetCaps( &devDesc )>=0 ){
|
||||
DWORD caps=devDesc.dpcTriCaps.dwRasterCaps;
|
||||
//texture stages
|
||||
hw_tex_stages=devDesc.wMaxSimultaneousTextures;
|
||||
//depth buffer mode
|
||||
if( (caps & D3DPRASTERCAPS_WBUFFER) && graphics->zbuffFmt.dwRGBBitCount==16 ) can_wb=true;
|
||||
//fog mode
|
||||
if( (caps&D3DPRASTERCAPS_FOGTABLE)&&(caps&D3DPRASTERCAPS_WFOG) ){
|
||||
setRS( D3DRENDERSTATE_FOGVERTEXMODE,D3DFOG_NONE );
|
||||
setRS( D3DRENDERSTATE_FOGTABLEMODE,D3DFOG_LINEAR );
|
||||
}else{
|
||||
setRS( D3DRENDERSTATE_FOGTABLEMODE,D3DFOG_NONE );
|
||||
setRS( D3DRENDERSTATE_FOGVERTEXMODE,D3DFOG_LINEAR );
|
||||
}
|
||||
}
|
||||
tex_stages=hw_tex_stages;
|
||||
|
||||
caps_level=100;
|
||||
if( devDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP ){
|
||||
caps_level=110;
|
||||
}
|
||||
|
||||
//default texture states
|
||||
for( int n=0;n<hw_tex_stages;++n ){
|
||||
setTSS( n,D3DTSS_COLORARG1,D3DTA_TEXTURE );
|
||||
setTSS( n,D3DTSS_COLORARG2,D3DTA_CURRENT );
|
||||
setTSS( n,D3DTSS_ALPHAARG1,D3DTA_TEXTURE );
|
||||
setTSS( n,D3DTSS_ALPHAARG2,D3DTA_CURRENT );
|
||||
setTSS( n,D3DTSS_MINFILTER,D3DTFN_LINEAR );
|
||||
setTSS( n,D3DTSS_MAGFILTER,D3DTFG_LINEAR );
|
||||
setTSS( n,D3DTSS_MIPFILTER,D3DTFP_LINEAR );
|
||||
}
|
||||
setHWMultiTex( true );
|
||||
|
||||
//ATI lighting hack
|
||||
dir3dDev->LightEnable( 0,true );
|
||||
dir3dDev->LightEnable( 0,false );
|
||||
|
||||
//globals
|
||||
sphere_mat._11=.5f;sphere_mat._22=-.5f;sphere_mat._33=.5f;
|
||||
sphere_mat._41=.5f;sphere_mat._42=.5f;sphere_mat._43=.5f;
|
||||
nullmatrix._11=nullmatrix._22=nullmatrix._33=nullmatrix._44=1;
|
||||
|
||||
//set null renderstate
|
||||
memset(&material,0,sizeof(material));
|
||||
shininess=0;blend=BLEND_REPLACE;fx=0;
|
||||
for( int k=0;k<MAX_TEXTURES;++k ) memset( &texstate[k],0,sizeof(texstate[k]) );
|
||||
|
||||
wbuffer=can_wb;
|
||||
dither=false;setDither( true );
|
||||
antialias=true;setAntialias( false );
|
||||
wireframe=true;setWireframe( false );
|
||||
flipped=true;setFlippedTris( false );
|
||||
ambient=~0;setAmbient( GRAY );
|
||||
ambient2=~0;setAmbient2( BLACK );
|
||||
fogcolor=~0;setFogColor( BLACK );
|
||||
fogrange_nr=fogrange_fr=0;setFogRange( 1,1000 );
|
||||
fogmode=FOG_LINEAR;setFogMode( FOG_NONE );
|
||||
zmode=-1;setZMode( ZMODE_NORMAL );
|
||||
memset(&projmatrix,0,sizeof(projmatrix));
|
||||
ortho_proj=true;frustum_nr=frustum_fr=frustum_w=frustum_h=0;setPerspProj( 1,1000,1,1 );
|
||||
memset(&viewport,0,sizeof(viewport));viewport.dvMaxZ=1;setViewport( 0,0,target->getWidth(),target->getHeight() );
|
||||
viewmatrix=nullmatrix;setViewMatrix( 0 );
|
||||
worldmatrix=nullmatrix;setWorldMatrix( 0 );
|
||||
|
||||
//set default renderstate
|
||||
blend=fx=~0;shininess=1;
|
||||
RenderState state;memset(&state,0,sizeof(state));
|
||||
state.color[0]=state.color[1]=state.color[2]=state.alpha=1;
|
||||
state.blend=BLEND_REPLACE;
|
||||
setRenderState( state );
|
||||
}
|
||||
|
||||
gxScene::~gxScene(){
|
||||
while( _allLights.size() ) freeLight( *_allLights.begin() );
|
||||
}
|
||||
|
||||
void gxScene::setTexState( int n,const TexState &state,bool tex_blend ){
|
||||
|
||||
int flags=state.canvas->getFlags();
|
||||
int tc_index=state.flags & TEX_COORDS2 ? 1 : 0;
|
||||
|
||||
//set canvas
|
||||
dir3dDev->SetTexture( n,state.canvas->getTexSurface() );
|
||||
|
||||
//set addressing modes
|
||||
setTSS( n,D3DTSS_ADDRESSU,(flags & gxCanvas::CANVAS_TEX_CLAMPU) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP );
|
||||
setTSS( n,D3DTSS_ADDRESSV,(flags & gxCanvas::CANVAS_TEX_CLAMPV) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP );
|
||||
|
||||
//texgen
|
||||
switch( flags&(
|
||||
gxCanvas::CANVAS_TEX_SPHERE|
|
||||
gxCanvas::CANVAS_TEX_CUBE) ){
|
||||
|
||||
case gxCanvas::CANVAS_TEX_SPHERE:
|
||||
setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL );//|tc_index );
|
||||
setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2 );
|
||||
dir3dDev->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0+n),&sphere_mat );
|
||||
break;
|
||||
case gxCanvas::CANVAS_TEX_CUBE:
|
||||
switch( state.canvas->cubeMode() & 3 ){
|
||||
case gxCanvas::CUBEMODE_NORMAL:
|
||||
setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL );//|tc_index );
|
||||
break;
|
||||
case gxCanvas::CUBEMODE_POSITION:
|
||||
setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION );//|tc_index );
|
||||
break;
|
||||
default:
|
||||
setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR );//|tc_index );
|
||||
break;
|
||||
}
|
||||
if( state.canvas->cubeMode() & 4 ){
|
||||
setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_DISABLE );
|
||||
}else{
|
||||
setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT3 );//COUNT4|D3DTTFF_PROJECTED );
|
||||
dir3dDev->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0+n),&inv_viewmatrix );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU|tc_index );
|
||||
if( state.mat_valid){
|
||||
setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2 );
|
||||
dir3dDev->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0+n),(D3DMATRIX*)&state.matrix );
|
||||
}else{
|
||||
setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_DISABLE );
|
||||
}
|
||||
}
|
||||
|
||||
if( !tex_blend ) return;
|
||||
|
||||
//blending
|
||||
switch( state.blend ){
|
||||
case BLEND_ALPHA:
|
||||
setTSS( n,D3DTSS_COLOROP,D3DTOP_BLENDTEXTUREALPHA );
|
||||
break;
|
||||
case BLEND_MULTIPLY:
|
||||
setTSS( n,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
break;
|
||||
case BLEND_ADD:
|
||||
setTSS( n,D3DTSS_COLOROP,D3DTOP_ADD );
|
||||
break;
|
||||
case BLEND_DOT3:
|
||||
setTSS( n,D3DTSS_COLOROP,D3DTOP_DOTPRODUCT3 );
|
||||
break;
|
||||
case BLEND_MULTIPLY2:
|
||||
setTSS( n,D3DTSS_COLOROP,D3DTOP_MODULATE2X );
|
||||
break;
|
||||
}
|
||||
setTSS( n,D3DTSS_ALPHAOP,(flags & gxCanvas::CANVAS_TEX_ALPHA) ? D3DTOP_MODULATE : D3DTOP_SELECTARG2 );
|
||||
}
|
||||
|
||||
int gxScene::hwTexUnits(){
|
||||
return tex_stages;
|
||||
}
|
||||
|
||||
int gxScene::gfxDriverCaps3D(){
|
||||
return caps_level;
|
||||
}
|
||||
|
||||
void gxScene::setZMode(){
|
||||
switch( zmode ){
|
||||
case ZMODE_NORMAL:
|
||||
setRS( D3DRENDERSTATE_ZENABLE,wbuffer ? D3DZB_USEW : D3DZB_TRUE );
|
||||
setRS( D3DRENDERSTATE_ZWRITEENABLE,true );
|
||||
break;
|
||||
case ZMODE_DISABLE:
|
||||
setRS( D3DRENDERSTATE_ZENABLE,D3DZB_FALSE );
|
||||
setRS( D3DRENDERSTATE_ZWRITEENABLE,false );
|
||||
break;
|
||||
case ZMODE_CMPONLY:
|
||||
setRS( D3DRENDERSTATE_ZENABLE,wbuffer ? D3DZB_USEW : D3DZB_TRUE );
|
||||
setRS( D3DRENDERSTATE_ZWRITEENABLE,false );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void gxScene::setLights(){
|
||||
if( fx & FX_FULLBRIGHT ){
|
||||
//no lights on
|
||||
for( int n=0;n<_curLights.size();++n ) dir3dDev->LightEnable( n,false );
|
||||
}else if( fx & FX_CONDLIGHT ){
|
||||
//some lights on
|
||||
for( int n=0;n<_curLights.size();++n ){
|
||||
gxLight *light=_curLights[n];
|
||||
bool enable=light->d3d_light.dltType!=D3DLIGHT_DIRECTIONAL;
|
||||
dir3dDev->LightEnable( n,enable );
|
||||
}
|
||||
}else{
|
||||
//all lights on
|
||||
for( int n=0;n<_curLights.size();++n ) dir3dDev->LightEnable( n,true );
|
||||
}
|
||||
}
|
||||
|
||||
void gxScene::setAmbient(){
|
||||
int n=(fx & FX_FULLBRIGHT) ? 0xffffff : ((fx & FX_CONDLIGHT) ? ambient2 : ambient);
|
||||
setRS( D3DRENDERSTATE_AMBIENT,n );
|
||||
}
|
||||
|
||||
void gxScene::setFogMode(){
|
||||
bool fog= fogmode==FOG_LINEAR && !(fx&FX_NOFOG);
|
||||
setRS( D3DRENDERSTATE_FOGENABLE,fog );
|
||||
}
|
||||
|
||||
void gxScene::setTriCull(){
|
||||
if( fx & FX_DOUBLESIDED ){
|
||||
setRS( D3DRENDERSTATE_CULLMODE,D3DCULL_NONE );
|
||||
}else if( flipped ){
|
||||
setRS( D3DRENDERSTATE_CULLMODE,D3DCULL_CW );
|
||||
}else{
|
||||
setRS( D3DRENDERSTATE_CULLMODE,D3DCULL_CCW );
|
||||
}
|
||||
}
|
||||
|
||||
void gxScene::setHWMultiTex( bool e ){
|
||||
for( int n=0;n<8;++n ){
|
||||
setTSS( n,D3DTSS_COLOROP,D3DTOP_DISABLE );
|
||||
setTSS( n,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
|
||||
dir3dDev->SetTexture( n,0 );
|
||||
}
|
||||
for( int k=0;k<MAX_TEXTURES;++k ){
|
||||
memset( &texstate[k],0,sizeof(texstate[k]) );
|
||||
}
|
||||
tex_stages=e ? hw_tex_stages : 1;
|
||||
n_texs=0;
|
||||
}
|
||||
|
||||
void gxScene::setWBuffer( bool n ){
|
||||
if( n==wbuffer || !can_wb ) return;
|
||||
wbuffer=n;setZMode();
|
||||
}
|
||||
|
||||
void gxScene::setDither( bool n ){
|
||||
if( n==dither ) return;
|
||||
dither=n;setRS( D3DRENDERSTATE_DITHERENABLE,dither ? true : false );
|
||||
}
|
||||
|
||||
void gxScene::setAntialias( bool n ){
|
||||
if( n==antialias ) return;
|
||||
antialias=n;setRS( D3DRENDERSTATE_ANTIALIAS,antialias ? D3DANTIALIAS_SORTINDEPENDENT : D3DANTIALIAS_NONE );
|
||||
}
|
||||
|
||||
void gxScene::setWireframe( bool n ){
|
||||
if( n==wireframe ) return;
|
||||
wireframe=n;setRS( D3DRENDERSTATE_FILLMODE,wireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID );
|
||||
}
|
||||
|
||||
void gxScene::setFlippedTris( bool n ){
|
||||
if( n==flipped ) return;
|
||||
flipped=n;setTriCull();
|
||||
}
|
||||
|
||||
void gxScene::setAmbient( const float rgb[] ){
|
||||
int n=(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
|
||||
ambient=n;setAmbient();
|
||||
}
|
||||
|
||||
void gxScene::setAmbient2( const float rgb[] ){
|
||||
int n=(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
|
||||
ambient2=n;setAmbient();
|
||||
}
|
||||
|
||||
void gxScene::setViewport( int x,int y,int w,int h ){
|
||||
if( x==viewport.dwX && y==viewport.dwY && w==viewport.dwWidth && h==viewport.dwHeight ) return;
|
||||
viewport.dwX=x;viewport.dwY=y;viewport.dwWidth=w;viewport.dwHeight=h;
|
||||
dir3dDev->SetViewport( &viewport );
|
||||
}
|
||||
|
||||
void gxScene::setOrthoProj( float nr,float fr,float w,float h ){
|
||||
if( ortho_proj && nr==frustum_nr && fr==frustum_fr && w==frustum_w && h==frustum_h ) return;
|
||||
frustum_nr=nr;frustum_fr=fr;frustum_w=w;frustum_h=h;ortho_proj=true;
|
||||
float W=2/w;
|
||||
float H=2/h;
|
||||
float Q=1/(fr-nr);
|
||||
projmatrix._11=W;
|
||||
projmatrix._22=H;
|
||||
projmatrix._33=Q;
|
||||
projmatrix._34=0;
|
||||
projmatrix._43=-Q*nr;
|
||||
projmatrix._44=1;
|
||||
dir3dDev->SetTransform( D3DTRANSFORMSTATE_PROJECTION,&projmatrix );
|
||||
}
|
||||
|
||||
void gxScene::setPerspProj( float nr,float fr,float w,float h ){
|
||||
if( !ortho_proj && nr==frustum_nr && fr==frustum_fr && w==frustum_w && h==frustum_h ) return;
|
||||
frustum_nr=nr;frustum_fr=fr;frustum_w=w;frustum_h=h;ortho_proj=false;
|
||||
float W=2*nr/w;
|
||||
float H=2*nr/h;
|
||||
float Q=fr/(fr-nr);
|
||||
projmatrix._11=W;
|
||||
projmatrix._22=H;
|
||||
projmatrix._33=Q;
|
||||
projmatrix._34=1;
|
||||
projmatrix._43=-Q*nr;
|
||||
projmatrix._44=0;
|
||||
dir3dDev->SetTransform( D3DTRANSFORMSTATE_PROJECTION,&projmatrix );
|
||||
}
|
||||
|
||||
void gxScene::setFogColor( const float rgb[3] ){
|
||||
int n=(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
|
||||
if( n==fogcolor ) return;
|
||||
fogcolor=n;setRS( D3DRENDERSTATE_FOGCOLOR,fogcolor );
|
||||
}
|
||||
|
||||
void gxScene::setFogRange( float nr,float fr ){
|
||||
if( nr==fogrange_nr && fr==fogrange_fr ) return;
|
||||
fogrange_nr=nr;fogrange_fr=fr;
|
||||
setRS( D3DRENDERSTATE_FOGSTART,*(DWORD*)&fogrange_nr );
|
||||
setRS( D3DRENDERSTATE_FOGEND,*(DWORD*)&fogrange_fr );
|
||||
}
|
||||
|
||||
void gxScene::setFogMode( int n ){
|
||||
if( n==fogmode ) return;
|
||||
fogmode=n;setFogMode();
|
||||
}
|
||||
|
||||
void gxScene::setZMode( int n ){
|
||||
if( n==zmode ) return;
|
||||
zmode=n;setZMode();
|
||||
}
|
||||
|
||||
void gxScene::setViewMatrix( const Matrix *m ){
|
||||
if( m ){
|
||||
memcpy( &viewmatrix._11,m->elements[0],12 );
|
||||
memcpy( &viewmatrix._21,m->elements[1],12 );
|
||||
memcpy( &viewmatrix._31,m->elements[2],12 );
|
||||
memcpy( &viewmatrix._41,m->elements[3],12 );
|
||||
inv_viewmatrix._11=viewmatrix._11;inv_viewmatrix._21=viewmatrix._12;inv_viewmatrix._31=viewmatrix._13;
|
||||
inv_viewmatrix._12=viewmatrix._21;inv_viewmatrix._22=viewmatrix._22;inv_viewmatrix._32=viewmatrix._23;
|
||||
inv_viewmatrix._13=viewmatrix._31;inv_viewmatrix._23=viewmatrix._32;inv_viewmatrix._33=viewmatrix._33;
|
||||
inv_viewmatrix._44=viewmatrix._44;
|
||||
}else{
|
||||
viewmatrix=inv_viewmatrix=nullmatrix;
|
||||
}
|
||||
|
||||
dir3dDev->SetTransform( D3DTRANSFORMSTATE_VIEW,&viewmatrix );
|
||||
}
|
||||
|
||||
void gxScene::setWorldMatrix( const Matrix *m ){
|
||||
if( m ){
|
||||
memcpy( &worldmatrix._11,m->elements[0],12 );
|
||||
memcpy( &worldmatrix._21,m->elements[1],12 );
|
||||
memcpy( &worldmatrix._31,m->elements[2],12 );
|
||||
memcpy( &worldmatrix._41,m->elements[3],12 );
|
||||
}else worldmatrix=nullmatrix;
|
||||
dir3dDev->SetTransform( D3DTRANSFORMSTATE_WORLD,&worldmatrix );
|
||||
}
|
||||
|
||||
void gxScene::setRenderState( const RenderState &rs ){
|
||||
bool setmat=false;
|
||||
if( memcmp( rs.color,&material.diffuse.r,12 ) ){
|
||||
memcpy( &material.diffuse.r,rs.color,12 );
|
||||
memcpy( &material.ambient.r,rs.color,12 );
|
||||
setmat=true;
|
||||
}
|
||||
if( rs.alpha!=material.diffuse.a ){
|
||||
material.diffuse.a=rs.alpha;
|
||||
if( rs.fx&FX_ALPHATEST ){
|
||||
int alpharef=(rs.fx&FX_VERTEXALPHA)?0:128*rs.alpha;
|
||||
setRS( D3DRENDERSTATE_ALPHAREF,alpharef );
|
||||
}
|
||||
setmat=true;
|
||||
}
|
||||
if( rs.shininess!=shininess ){
|
||||
shininess=rs.shininess;
|
||||
float t=shininess>0 ? (shininess<1 ? shininess : 1) : 0;
|
||||
material.specular.r=material.specular.g=material.specular.b=t;
|
||||
material.power=shininess*128;
|
||||
setRS( D3DRENDERSTATE_SPECULARENABLE,shininess>0 ? true : false );
|
||||
setmat=true;
|
||||
}
|
||||
if( rs.blend!=blend ){
|
||||
blend=rs.blend;
|
||||
switch( blend ){
|
||||
case BLEND_REPLACE:
|
||||
setRS( D3DRENDERSTATE_ALPHABLENDENABLE,false );
|
||||
break;
|
||||
case BLEND_ALPHA:
|
||||
setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
|
||||
setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
|
||||
setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA );
|
||||
break;
|
||||
case BLEND_MULTIPLY:
|
||||
setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
|
||||
setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_DESTCOLOR );
|
||||
setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ZERO );
|
||||
break;
|
||||
case BLEND_ADD:
|
||||
setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
|
||||
setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
|
||||
setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ONE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( rs.fx!=fx ){
|
||||
int t=rs.fx^fx;fx=rs.fx;
|
||||
if( t & (FX_FULLBRIGHT|FX_CONDLIGHT) ){
|
||||
setLights();
|
||||
setAmbient();
|
||||
}
|
||||
if( t&FX_VERTEXCOLOR ){
|
||||
setRS( D3DRENDERSTATE_COLORVERTEX,fx & FX_VERTEXCOLOR ? true : false );
|
||||
}
|
||||
if( t&FX_FLATSHADED ){
|
||||
setRS( D3DRENDERSTATE_SHADEMODE,fx & FX_FLATSHADED ? D3DSHADE_FLAT : D3DSHADE_GOURAUD );
|
||||
}
|
||||
if( t&FX_NOFOG ){
|
||||
setFogMode();
|
||||
}
|
||||
if( t&FX_DOUBLESIDED ){
|
||||
setTriCull();
|
||||
}
|
||||
if( t&FX_EMISSIVE ){
|
||||
//Q3 Hack!
|
||||
int n=fx & FX_EMISSIVE;
|
||||
setRS( D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,n ? D3DMCS_MATERIAL : D3DMCS_COLOR1 );
|
||||
setRS( D3DRENDERSTATE_AMBIENTMATERIALSOURCE,n ? D3DMCS_MATERIAL : D3DMCS_COLOR1 );
|
||||
setRS( D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,n ? D3DMCS_COLOR1 : D3DMCS_MATERIAL );
|
||||
setRS( D3DRENDERSTATE_COLORVERTEX,n ? true : false );
|
||||
}
|
||||
if( t&FX_ALPHATEST ){
|
||||
if( fx&FX_ALPHATEST ){
|
||||
int alpharef=(rs.fx&FX_VERTEXALPHA)?0:128*rs.alpha;
|
||||
setRS( D3DRENDERSTATE_ALPHAREF,alpharef );
|
||||
}
|
||||
setRS( D3DRENDERSTATE_ALPHATESTENABLE,fx & FX_ALPHATEST ? true : false );
|
||||
}
|
||||
}
|
||||
if( setmat ){
|
||||
dir3dDev->SetMaterial( &material );
|
||||
}
|
||||
|
||||
n_texs=0;
|
||||
TexState *hw=texstate;
|
||||
for( int k=0;k<MAX_TEXTURES;++k ){
|
||||
const RenderState::TexState &ts=rs.tex_states[k];
|
||||
if( !ts.canvas || !ts.blend ) continue;
|
||||
bool settex=false;
|
||||
ts.canvas->getTexSurface(); //force mipmap rebuild
|
||||
if( ts.canvas!=hw->canvas ){ hw->canvas=ts.canvas;settex=true; }
|
||||
if( ts.blend!=hw->blend ){ hw->blend=ts.blend;settex=true; }
|
||||
if( ts.flags!=hw->flags ){ hw->flags=ts.flags;settex=true; }
|
||||
if( ts.matrix || hw->mat_valid ){
|
||||
if( ts.matrix ){
|
||||
memcpy( &hw->matrix._11,ts.matrix->elements[0],12 );
|
||||
memcpy( &hw->matrix._21,ts.matrix->elements[1],12 );
|
||||
memcpy( &hw->matrix._31,ts.matrix->elements[2],12 );
|
||||
memcpy( &hw->matrix._41,ts.matrix->elements[3],12 );
|
||||
hw->mat_valid=true;
|
||||
}else{
|
||||
hw->mat_valid=false;
|
||||
}
|
||||
settex=true;
|
||||
}
|
||||
if( settex && n_texs<tex_stages ){
|
||||
setTexState( n_texs,*hw,true );
|
||||
}
|
||||
++hw;++n_texs;
|
||||
}
|
||||
if( n_texs<tex_stages && hw->canvas ){
|
||||
hw->canvas=0;
|
||||
setTSS( n_texs,D3DTSS_COLOROP,D3DTOP_DISABLE );
|
||||
setTSS( n_texs,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
|
||||
dir3dDev->SetTexture( n_texs,0 );
|
||||
}
|
||||
}
|
||||
|
||||
bool gxScene::begin( const vector<gxLight*> &lights ){
|
||||
|
||||
if( dir3dDev->BeginScene()!=D3D_OK ) return false;
|
||||
|
||||
//clear textures!
|
||||
int n;
|
||||
for( n=0;n<tex_stages;++n ){
|
||||
texstate[n].canvas=0;
|
||||
setTSS( n,D3DTSS_COLOROP,D3DTOP_DISABLE );
|
||||
setTSS( n,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
|
||||
dir3dDev->SetTexture( n,0 );
|
||||
}
|
||||
|
||||
//set light states
|
||||
_curLights.clear();
|
||||
for( n=0;n<8;++n ){
|
||||
if( n<lights.size() ){
|
||||
_curLights.push_back( lights[n] );
|
||||
dir3dDev->SetLight( n,&_curLights[n]->d3d_light );
|
||||
}else{
|
||||
dir3dDev->LightEnable( n,false );
|
||||
}
|
||||
}
|
||||
setLights();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void gxScene::clear( const float rgb[3],float alpha,float z,bool clear_argb,bool clear_z ){
|
||||
if( !clear_argb && !clear_z ) return;
|
||||
int flags=(clear_argb ? D3DCLEAR_TARGET : 0) | (clear_z ? D3DCLEAR_ZBUFFER : 0);
|
||||
unsigned argb=(int(alpha*255.0f)<<24)|(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
|
||||
dir3dDev->Clear( 0,0,flags,argb,z,0 );
|
||||
}
|
||||
|
||||
void gxScene::render( gxMesh *m,int first_vert,int vert_cnt,int first_tri,int tri_cnt ){
|
||||
|
||||
m->render( first_vert,vert_cnt,first_tri,tri_cnt );
|
||||
tris_drawn+=tri_cnt;
|
||||
if( n_texs<=tex_stages ) return;
|
||||
|
||||
setTSS( 0,D3DTSS_COLOROP,D3DTOP_SELECTARG1 );
|
||||
setTSS( 0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1 );
|
||||
if( tex_stages>1 ){
|
||||
setTSS( 1,D3DTSS_COLOROP,D3DTOP_DISABLE );
|
||||
setTSS( 1,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
|
||||
}
|
||||
|
||||
setRS( D3DRENDERSTATE_LIGHTING,false );
|
||||
setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
|
||||
|
||||
for( int k=tex_stages;k<n_texs;++k ){
|
||||
const TexState &state=texstate[k];
|
||||
switch( state.blend ){
|
||||
case BLEND_ALPHA:
|
||||
setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
|
||||
setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA );
|
||||
break;
|
||||
case BLEND_MULTIPLY:case BLEND_DOT3:
|
||||
setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_DESTCOLOR );
|
||||
setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ZERO );
|
||||
break;
|
||||
case BLEND_ADD:
|
||||
setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_ONE );
|
||||
setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ONE );
|
||||
break;
|
||||
}
|
||||
setTexState( 0,state,false );
|
||||
m->render( first_vert,vert_cnt,first_tri,tri_cnt );
|
||||
tris_drawn+=tri_cnt;
|
||||
}
|
||||
|
||||
setRS( D3DRENDERSTATE_ALPHABLENDENABLE,false );
|
||||
setRS( D3DRENDERSTATE_LIGHTING,true );
|
||||
if( tex_stages>1 ) setTexState( 1,texstate[1],true );
|
||||
setTexState( 0,texstate[0],true );
|
||||
}
|
||||
|
||||
void gxScene::end(){
|
||||
dir3dDev->EndScene();
|
||||
RECT r={ viewport.dwX,viewport.dwY,viewport.dwX+viewport.dwWidth,viewport.dwY+viewport.dwHeight };
|
||||
target->damage( r );
|
||||
}
|
||||
|
||||
gxLight *gxScene::createLight( int flags ){
|
||||
gxLight *l=d_new gxLight( this,flags );
|
||||
_allLights.insert(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
void gxScene::freeLight( gxLight *l ){
|
||||
_allLights.erase(l);
|
||||
}
|
||||
|
||||
int gxScene::getTrianglesDrawn()const{
|
||||
return tris_drawn;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
|
||||
#ifndef GXSCENE_H
|
||||
#define GXSCENE_H
|
||||
|
||||
#include <map>
|
||||
#include <d3d.h>
|
||||
|
||||
#include "gxlight.h"
|
||||
|
||||
class gxCanvas;
|
||||
|
||||
class gxMesh;
|
||||
class gxLight;
|
||||
class gxGraphics;
|
||||
class gxTexture;
|
||||
|
||||
class gxScene{
|
||||
public:
|
||||
gxGraphics *graphics;
|
||||
IDirect3DDevice7 *dir3dDev;
|
||||
|
||||
gxScene( gxGraphics *graphics,gxCanvas *target );
|
||||
~gxScene();
|
||||
|
||||
void setEnabled( gxLight *light,bool enabled );
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
enum{
|
||||
MAX_TEXTURES= 8
|
||||
};
|
||||
enum{
|
||||
FX_FULLBRIGHT= 0x0001,
|
||||
FX_VERTEXCOLOR= 0x0002,
|
||||
FX_FLATSHADED= 0x0004,
|
||||
FX_NOFOG= 0x0008,
|
||||
FX_DOUBLESIDED= 0x0010,
|
||||
FX_VERTEXALPHA= 0x0020,
|
||||
|
||||
FX_ALPHATEST= 0x2000,
|
||||
FX_CONDLIGHT= 0x4000,
|
||||
FX_EMISSIVE= 0x8000
|
||||
};
|
||||
enum{
|
||||
BLEND_REPLACE= 0,
|
||||
BLEND_ALPHA= 1,
|
||||
BLEND_MULTIPLY= 2,
|
||||
BLEND_ADD= 3,
|
||||
BLEND_DOT3= 4,
|
||||
BLEND_MULTIPLY2=5,
|
||||
};
|
||||
enum{
|
||||
ZMODE_NORMAL= 0,
|
||||
ZMODE_DISABLE= 1,
|
||||
ZMODE_CMPONLY= 2
|
||||
};
|
||||
enum{
|
||||
FOG_NONE= 0,
|
||||
FOG_LINEAR= 1
|
||||
};
|
||||
enum{
|
||||
TEX_COORDS2= 0x0001
|
||||
};
|
||||
struct Matrix{
|
||||
float elements[4][3];
|
||||
};
|
||||
struct RenderState{
|
||||
float color[3];
|
||||
float shininess,alpha;
|
||||
int blend,fx;
|
||||
struct TexState{
|
||||
gxCanvas *canvas;
|
||||
const Matrix *matrix;
|
||||
int blend,flags;
|
||||
}tex_states[MAX_TEXTURES];
|
||||
};
|
||||
|
||||
//state
|
||||
int hwTexUnits();
|
||||
int gfxDriverCaps3D();
|
||||
|
||||
void setWBuffer( bool enable );
|
||||
void setHWMultiTex( bool enable );
|
||||
void setDither( bool enable );
|
||||
void setAntialias( bool enable );
|
||||
void setWireframe( bool enable );
|
||||
void setFlippedTris( bool enable );
|
||||
void setAmbient( const float rgb[3] );
|
||||
void setAmbient2( const float rgb[3] );
|
||||
void setFogColor( const float rgb[3] );
|
||||
void setFogRange( float nr,float fr );
|
||||
void setFogMode( int mode );
|
||||
void setZMode( int mode );
|
||||
void setViewport( int x,int y,int w,int h );
|
||||
void setOrthoProj( float nr,float fr,float nr_w,float nr_h );
|
||||
void setPerspProj( float nr,float fr,float nr_w,float nr_h );
|
||||
void setViewMatrix( const Matrix *matrix );
|
||||
void setWorldMatrix( const Matrix *matrix );
|
||||
void setRenderState( const RenderState &state );
|
||||
|
||||
//rendering
|
||||
bool begin( const std::vector<gxLight*> &lights );
|
||||
void clear( const float rgb[3],float alpha,float z,bool clear_argb,bool clear_z );
|
||||
void render( gxMesh *mesh,int first_vert,int vert_cnt,int first_tri,int tri_cnt );
|
||||
void end();
|
||||
|
||||
//lighting
|
||||
gxLight *createLight( int flags );
|
||||
void freeLight( gxLight *l );
|
||||
|
||||
//info
|
||||
int getTrianglesDrawn()const;
|
||||
|
||||
private:
|
||||
gxCanvas *target;
|
||||
bool wbuffer,dither,antialias,wireframe,flipped;
|
||||
unsigned ambient,ambient2,fogcolor;
|
||||
int caps_level,fogmode,zmode;
|
||||
float fogrange_nr,fogrange_fr;
|
||||
D3DVIEWPORT7 viewport;
|
||||
bool ortho_proj;
|
||||
float frustum_nr,frustum_fr,frustum_w,frustum_h;
|
||||
D3DMATRIX projmatrix,viewmatrix,worldmatrix;
|
||||
D3DMATRIX inv_viewmatrix;
|
||||
D3DMATERIAL7 material;
|
||||
float shininess;
|
||||
int blend,fx;
|
||||
struct TexState{
|
||||
gxCanvas *canvas;
|
||||
int blend,flags;
|
||||
D3DMATRIX matrix;
|
||||
bool mat_valid;
|
||||
};
|
||||
TexState texstate[MAX_TEXTURES];
|
||||
int n_texs,tris_drawn;
|
||||
|
||||
std::set<gxLight*> _allLights;
|
||||
std::vector<gxLight*> _curLights;
|
||||
|
||||
int d3d_rs[160];
|
||||
int d3d_tss[8][32];
|
||||
|
||||
void setRS( int n,int t );
|
||||
void setTSS( int n,int s,int t );
|
||||
|
||||
void setLights();
|
||||
void setZMode();
|
||||
void setAmbient();
|
||||
void setFogMode();
|
||||
void setTriCull();
|
||||
void setTexState( int index,const TexState &state,bool set_blend );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxsound.h"
|
||||
#include "gxaudio.h"
|
||||
|
||||
gxSound::gxSound( gxAudio *a,FSOUND_SAMPLE *s ):
|
||||
audio(a),sample(s),defs_valid(true){
|
||||
FSOUND_Sample_GetDefaults( sample,&def_freq,&def_vol,&def_pan,&def_pri );
|
||||
}
|
||||
|
||||
gxSound::~gxSound(){
|
||||
FSOUND_Sample_Free( sample );
|
||||
}
|
||||
|
||||
void gxSound::setDefaults(){
|
||||
if( !defs_valid ){
|
||||
FSOUND_Sample_SetDefaults( sample,def_freq,def_vol,def_pan,def_pri );
|
||||
defs_valid=true;
|
||||
}
|
||||
}
|
||||
|
||||
gxChannel *gxSound::play(){
|
||||
setDefaults();
|
||||
return audio->play( sample );
|
||||
}
|
||||
|
||||
gxChannel *gxSound::play3d( const float pos[3],const float vel[3] ){
|
||||
setDefaults();
|
||||
return audio->play3d( sample,pos,vel );
|
||||
}
|
||||
|
||||
void gxSound::setLoop( bool loop ){
|
||||
FSOUND_Sample_SetMode( sample,loop ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF );
|
||||
}
|
||||
|
||||
void gxSound::setPitch( int hertz ){
|
||||
def_freq=hertz;
|
||||
defs_valid=false;
|
||||
}
|
||||
|
||||
void gxSound::setVolume( float volume ){
|
||||
def_vol=volume*255.0f;
|
||||
defs_valid=false;
|
||||
}
|
||||
|
||||
void gxSound::setPan( float pan ){
|
||||
def_pan=(pan+1.0f)*127.5f;
|
||||
defs_valid=false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
#ifndef GXSOUND_H
|
||||
#define GXSOUND_H
|
||||
|
||||
#include "gxchannel.h"
|
||||
|
||||
class gxAudio;
|
||||
struct FSOUND_SAMPLE;
|
||||
|
||||
class gxSound{
|
||||
public:
|
||||
gxAudio *audio;
|
||||
|
||||
gxSound( gxAudio *audio,FSOUND_SAMPLE *sample );
|
||||
~gxSound();
|
||||
|
||||
private:
|
||||
bool defs_valid;
|
||||
int def_freq,def_vol,def_pan,def_pri;
|
||||
FSOUND_SAMPLE *sample;
|
||||
float pos[3],vel[3];
|
||||
|
||||
void setDefaults();
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
//actions
|
||||
gxChannel *play();
|
||||
gxChannel *play3d( const float pos[3],const float vel[3] );
|
||||
|
||||
//modifiers
|
||||
void setLoop( bool loop );
|
||||
void setPitch( int hertz );
|
||||
void setVolume( float volume );
|
||||
void setPan( float pan );
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
#include "std.h"
|
||||
#include "gxtimer.h"
|
||||
#include "gxruntime.h"
|
||||
|
||||
gxTimer::gxTimer( gxRuntime *rt,int hertz ):
|
||||
runtime(rt),ticks_get(0),ticks_put(0){
|
||||
event=CreateEvent( 0,false,false,0 );
|
||||
timerID=timeSetEvent( 1000/hertz,0,timerCallback,(DWORD)this,TIME_PERIODIC );
|
||||
}
|
||||
|
||||
gxTimer::~gxTimer(){
|
||||
timeKillEvent( timerID );
|
||||
CloseHandle( event );
|
||||
}
|
||||
|
||||
void CALLBACK gxTimer::timerCallback( UINT id,UINT msg,DWORD user,DWORD dw1,DWORD dw2 ){
|
||||
gxTimer *t=(gxTimer*)user;
|
||||
++t->ticks_put;
|
||||
SetEvent( t->event );
|
||||
}
|
||||
|
||||
int gxTimer::wait(){
|
||||
for(;;){
|
||||
if( WaitForSingleObject( event,1000 )==WAIT_OBJECT_0 ) break;
|
||||
}
|
||||
int n=ticks_put-ticks_get;
|
||||
ticks_get+=n;
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
#ifndef GXTIMER_H
|
||||
#define GXTIMER_H
|
||||
|
||||
class gxRuntime;
|
||||
|
||||
class gxTimer{
|
||||
public:
|
||||
gxTimer( gxRuntime *rt,int hertz );
|
||||
~gxTimer();
|
||||
|
||||
static void CALLBACK timerCallback( UINT id,UINT msg,DWORD user,DWORD dw1,DWORD dw2 );
|
||||
|
||||
private:
|
||||
gxRuntime *runtime;
|
||||
HANDLE event;
|
||||
MMRESULT timerID;
|
||||
int ticks_put,ticks_get;
|
||||
|
||||
/***** GX INTERFACE *****/
|
||||
public:
|
||||
int wait();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#include "std.h"
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef STD_H
|
||||
#define STD_H
|
||||
|
||||
#include "../config/config.h"
|
||||
#include "../stdutil/stdutil.h"
|
||||
|
||||
#pragma warning( disable:4786 )
|
||||
|
||||
#define DIRECTSOUND_VERSION 0x700
|
||||
#define DIRECTINPUT_VERSION 0x700
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <math.h>
|
||||
#include <windows.h>
|
||||
#include <ddraw.h>
|
||||
#include <dinput.h>
|
||||
#include <d3d.h>
|
||||
|
||||
#include "../../fmodsrc375win/src/fmod.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user