runtime: CMake-ify gx

This commit is contained in:
Michael Fabian 'Xaymar' Dirks
2019-01-18 17:03:37 +01:00
parent 28598fae6b
commit a16218e1d5
74 changed files with 6493 additions and 5286 deletions
+4 -1
View File
@@ -1,6 +1,7 @@
project(runtime)
add_subdirectory(lib)
add_subdirectory(gfx)
add_subdirectory(blitz3d)
add_library(${PROJECT_NAME} MODULE
@@ -13,8 +14,10 @@ add_library(${PROJECT_NAME} MODULE
target_link_libraries(${PROJECT_NAME}
PRIVATE
runtime_lib
gxruntime
runtime_gfx
stdutil
${fmod_LIBRARIES}
${FreeImage_LIBRARIES}
)
#target_include_directories(${PROJECT_NAME}
+113
View File
@@ -0,0 +1,113 @@
project(runtime_gfx)
add_library(${PROJECT_NAME} STATIC
"asmcoder.hpp"
"asmcoder.cpp"
"ddutil.hpp"
"ddutil.cpp"
"graphicsruntime.hpp"
"gxaudio.hpp"
"gxaudio.cpp"
"gxcanvas.hpp"
"gxcanvas.cpp"
"gxchannel.hpp"
"gxchannel.cpp"
"gxdevice.hpp"
"gxdevice.cpp"
"gxdir.hpp"
"gxdir.cpp"
"gxfilesystem.hpp"
"gxfilesystem.cpp"
"gxfont.hpp"
"gxfont.cpp"
"gxgraphics.hpp"
"gxgraphics.cpp"
"gxinput.hpp"
"gxinput.cpp"
"gxlight.hpp"
"gxlight.cpp"
"gxmesh.hpp"
"gxmesh.cpp"
"gxmovie.hpp"
"gxmovie.cpp"
"gxmusic.hpp"
"gxmusic.cpp"
"gxruntime.hpp"
"gxruntime.cpp"
"gxscene.hpp"
"gxscene.cpp"
"gxsound.hpp"
"gxsound.cpp"
"gxtimer.hpp"
"gxtimer.cpp"
"std.hpp"
"std.cpp"
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
stdutil
PUBLIC
shell32
winmm
${fmod_LIBRARIES}
${FreeImage_LIBRARIES}
)
target_include_directories(${PROJECT_NAME}
PRIVATE
"${fmod_INCLUDE_DIRS}"
"${FreeImage_INCLUDE_DIRS}"
PUBLIC
${PROJECT_SOURCE_DIR}
)
if (WIN32)
target_compile_definitions(${PROJECT_NAME}
PRIVATE
_CRT_SECURE_NO_WARNINGS
# windows.hpp
WIN32_LEAN_AND_MEAN
NOGPICAPMASKS
#NOVIRTUALKEYCODES
#NOWINMESSAGES
#NOWINSTYLES
#NOSYSMETRICS
NOMENUS
NOICONS
#NOKEYSTATES
NOSYSCOMMANDS
NORASTEROPS
#NOSHOWWINDOW
NOATOM
NOCLIPBOARD
NOCOLOR
NOCTLMGR
NODRAWTEXT
#NOGDI
NOKERNEL
#NOUSER
NONLS
#NOMB
NOMEMMGR
NOMETAFILE
#NOMSG
NOOPENFILE
NOSCROLL
NOSERVICE
NOSOUND
#NOTEXTMETRIC
NOWH
#NOWINOFFSETS
NOCOMM
NOKANJI
NOHELP
NOPROFILER
NODEFERWINDOWPOS
NOMCX
NOIME
NOMDI
NOMINMAX
NOINOUT
)
endif()
+74
View File
@@ -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.hpp"
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
}
}
+528
View File
@@ -0,0 +1,528 @@
// 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
+134 -100
View File
@@ -1,10 +1,10 @@
#include "GraphicsRuntime.hpp"
#include "std.hpp"
#include "ddutil.hpp"
#include "GraphicsRuntime.hpp"
#include "asmcoder.hpp"
#include "gxcanvas.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
#define FREEIMAGE_LIB
#include <freeimage.h>
@@ -12,21 +12,26 @@
extern gxRuntime* gx_runtime;
static AsmCoder asm_coder;
static void calcShifts(unsigned mask, unsigned char *shr, unsigned char *shl) {
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) {}
for (*shl = 0; !(mask & 1); ++*shl, mask >>= 1) {
}
else *shr = *shl = 0;
for (*shr = 8; mask & 1; --*shr, mask >>= 1) {
}
} else
*shr = *shl = 0;
}
PixelFormat::~PixelFormat() {
PixelFormat::~PixelFormat()
{
if (plot_code) {
VirtualFree(plot_code, 0, MEM_RELEASE);
}
}
void PixelFormat::setFormat(const DDPIXELFORMAT &pf) {
void PixelFormat::setFormat(const DDPIXELFORMAT& pf)
{
if (plot_code) {
VirtualFree(plot_code, 0, MEM_RELEASE);
}
@@ -44,14 +49,22 @@ void PixelFormat::setFormat(const DDPIXELFORMAT &pf) {
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;
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;
@@ -59,7 +72,8 @@ void PixelFormat::setFormat(const DDPIXELFORMAT &pf) {
asm_coder.CodePoint(point_code, depth, amask, rmask, gmask, bmask);
}
static void adjustTexSize(int *width, int *height, IDirect3DDevice7 *dir3dDev, bool forcePOT = true) {
static void adjustTexSize(int* width, int* height, IDirect3DDevice7* dir3dDev, bool forcePOT = true)
{
D3DDEVICEDESC7 ddDesc = {0};
if (dir3dDev->GetCaps(&ddDesc) < 0) {
*width = *height = 256;
@@ -68,42 +82,56 @@ static void adjustTexSize(int *width, int *height, IDirect3DDevice7 *dir3dDev, b
int w = *width, h = *height, min, max;
if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 || ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL || forcePOT) {
if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2
|| ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL || forcePOT) {
// DirectX Device doesn't support Non Power-Of-Two Textures.
for (w = 1; w < *width; w <<= 1) {}
for (h = 1; h < *height; h <<= 1) {}
for (w = 1; w < *width; w <<= 1) {
}
else if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
for (h = 1; h < *height; h <<= 1) {
}
} else if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
// DirectX Device only supports Square Textures;
if (w > h) h = w;
else w = h;
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;
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;
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;
*width = w;
*height = h;
}
static IDirectDrawSurface7 *createSurface(int width, int height, int pitch, void *bits, IDirectDraw7 *dirDraw) {
static IDirectDrawSurface7* 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.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;
@@ -112,11 +140,13 @@ static IDirectDrawSurface7 *createSurface(int width, int height, int pitch, void
desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
IDirectDrawSurface7* surf;
if (dirDraw->CreateSurface(&desc, &surf, 0) >= 0) return surf;
if (dirDraw->CreateSurface(&desc, &surf, 0) >= 0)
return surf;
return 0;
}
static void buildMask(IDirectDrawSurface7 *surf) {
static void buildMask(IDirectDrawSurface7* surf)
{
DDSURFACEDESC2 desc = {sizeof(desc)};
surf->Lock(0, &desc, DDLOCK_WAIT, 0);
unsigned char* surf_p = (unsigned char*)desc.lpSurface;
@@ -136,8 +166,8 @@ static void buildMask(IDirectDrawSurface7 *surf) {
surf->Unlock(0);
}
static void buildAlpha(IDirectDrawSurface7 *surf, bool whiten) {
static void buildAlpha(IDirectDrawSurface7* surf, bool whiten)
{
DDSURFACEDESC2 desc = {sizeof(desc)};
surf->Lock(0, &desc, DDLOCK_WAIT, 0);
unsigned char* surf_p = (unsigned char*)desc.lpSurface;
@@ -149,7 +179,8 @@ static void buildAlpha(IDirectDrawSurface7 *surf, bool whiten) {
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;
if (whiten)
argb |= 0xffffff;
fmt.setPixel(p, argb);
p += fmt.getPitch();
}
@@ -158,12 +189,14 @@ static void buildAlpha(IDirectDrawSurface7 *surf, bool whiten) {
surf->Unlock(0);
}
void ddUtil::buildMipMaps(IDirectDrawSurface7 *surf) {
void ddUtil::buildMipMaps(IDirectDrawSurface7* surf)
{
DDSURFACEDESC2 desc = {sizeof(desc)};
surf->GetSurfaceDesc(&desc);
if (!(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) return;
if (!(desc.ddpfPixelFormat.dwFlags & DDPF_RGB)) return;
if (!(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
return;
if (!(desc.ddpfPixelFormat.dwFlags & DDPF_RGB))
return;
DDSCAPS2 caps = {0};
caps.dwCaps = DDSCAPS_TEXTURE;
@@ -172,14 +205,15 @@ void ddUtil::buildMipMaps(IDirectDrawSurface7 *surf) {
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();
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();
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);
@@ -187,45 +221,36 @@ void ddUtil::buildMipMaps(IDirectDrawSurface7 *surf) {
for (DWORD 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;
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) {
} else if (src_desc.dwHeight == 1) {
for (DWORD 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;
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 {
} else {
for (DWORD y = 0; y < dest_desc.dwHeight; ++y) {
unsigned char* src_t = src_p;
unsigned char* dest_t = dest_p;
for (DWORD 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;
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;
@@ -242,8 +267,9 @@ void ddUtil::buildMipMaps(IDirectDrawSurface7 *surf) {
}
}
void ddUtil::copy(IDirectDrawSurface7 *dest, int dx, int dy, int dw, int dh, IDirectDrawSurface7 *src, int sx, int sy, int sw, int sh) {
void ddUtil::copy(IDirectDrawSurface7* dest, int dx, int dy, int dw, int dh, IDirectDrawSurface7* 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);
@@ -270,14 +296,21 @@ void ddUtil::copy(IDirectDrawSurface7 *dest, int dx, int dy, int dw, int dh, IDi
dest->Unlock(0);
}
IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *gfx) {
IDirectDrawSurface7* ddUtil::createSurface(int w, int h, int flags, gxGraphics* gfx)
{
int hi = flags & gxCanvas::CANVAS_TEX_HICOLOR ? 1 : 0;
DDSURFACEDESC2 desc = {sizeof(desc)};
// Texture Size
desc.dwFlags = DDSD_CAPS;
if (w) { desc.dwWidth = w; desc.dwFlags |= DDSD_WIDTH; }
if (h) { desc.dwHeight = h; desc.dwFlags |= DDSD_HEIGHT; }
if (w) {
desc.dwWidth = w;
desc.dwFlags |= DDSD_WIDTH;
}
if (h) {
desc.dwHeight = h;
desc.dwFlags |= DDSD_HEIGHT;
}
// Format
if (flags & gxCanvas::CANVAS_TEXTURE) {
@@ -289,25 +322,20 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
if (flags & gxCanvas::CANVAS_TEXTURE) {
desc.ddpfPixelFormat = gfx->primFmt;
}
else {
} else {
desc.ddpfPixelFormat = gfx->texRGBAlphaFmt[hi];
}
}
else {
} else {
if (flags & gxCanvas::CANVAS_TEX_MASK) {
desc.dwFlags |= DDSD_PIXELFORMAT;
desc.ddpfPixelFormat = gfx->texRGBMaskFmt[hi];
}
else if (flags & gxCanvas::CANVAS_TEX_RGB) {
} 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) {
} else if (flags & gxCanvas::CANVAS_TEX_ALPHA) {
desc.dwFlags |= DDSD_PIXELFORMAT;
desc.ddpfPixelFormat = gfx->texAlphaFmt[hi];
}
else if (flags & gxCanvas::CANVAS_TEXTURE) {
} else if (flags & gxCanvas::CANVAS_TEXTURE) {
desc.dwFlags |= DDSD_PIXELFORMAT;
desc.ddpfPixelFormat = gfx->primFmt;
}
@@ -341,8 +369,7 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
}
adjustTexSize((int*)&desc.dwWidth, (int*)&desc.dwHeight, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT)));
}
else {
} else {
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if (flags & gxCanvas::CANVAS_HIGHCOLOR) {
desc.dwFlags |= DDSD_PIXELFORMAT;
@@ -354,8 +381,7 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
}
else if (flags & gxCanvas::CANVAS_NONDISPLAY) {
} else if (flags & gxCanvas::CANVAS_NONDISPLAY) {
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
}
@@ -368,7 +394,8 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
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;
if (gfx->dirDraw->CreateSurface(&desc, &surf, 0) >= 0)
return surf;
}
}
@@ -377,7 +404,8 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
//Tom Speed's DXTC loader
//
IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
IDirectDrawSurface7* loadDXTC(const char* filename, gxGraphics* gfx)
{
HRESULT hr;
DDSURFACEDESC2 ddsd;
DDSURFACEDESC2 fileddsd;
@@ -386,7 +414,8 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
/* try to open the file */
fp = fopen(filename, "rb");
if (!fp) return NULL;
if (!fp)
return NULL;
/* valid DDS? */
fread(magicID, 1, 4, fp);
@@ -476,7 +505,6 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
}
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)) {
@@ -493,8 +521,8 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
return newSurf;
}
IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGraphics *gfx) {
IDirectDrawSurface7* 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!
@@ -505,19 +533,25 @@ IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGrap
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;
int n = f.find(".");
if (n == string::npos)
return 0;
fmt = FreeImage_GetFileType(f.c_str());
if (fmt == FIF_UNKNOWN) return 0;
if (fmt == FIF_UNKNOWN)
return 0;
}
FIBITMAP* t_dib = FreeImage_Load(fmt, f.c_str(), 0);
if (!t_dib) return 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;
if (dib)
FreeImage_Unload(t_dib);
else
dib = t_dib;
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
@@ -533,17 +567,16 @@ IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGrap
if (flags & gxCanvas::CANVAS_TEX_ALPHA) {
if (flags & gxCanvas::CANVAS_TEX_MASK) {
buildMask(src);
}
else if (!trans) {
} else if (!trans) {
buildAlpha(src, (flags & gxCanvas::CANVAS_TEX_RGB) ? false : true);
}
}
else {
} 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;
*t = 0xff;
t += 4;
}
p += pitch;
}
@@ -557,7 +590,8 @@ IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGrap
}
int t_w = width, t_h = height;
if (flags & gxCanvas::CANVAS_TEXTURE) adjustTexSize(&t_w, &t_h, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT)));
if (flags & gxCanvas::CANVAS_TEXTURE)
adjustTexSize(&t_w, &t_h, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT)));
copy(dest, 0, 0, t_w, t_h, src, 0, height - 1, width, -height);
src->Release();
+68
View File
@@ -0,0 +1,68 @@
#ifndef DDUTIL_H
#define DDUTIL_H
#include "GraphicsRuntime.hpp"
class gxGraphics;
struct ddUtil {
static void buildMipMaps(IDirectDrawSurface7* surf);
static void copy(IDirectDrawSurface7* dest, int dx, int dy, int dw, int dh, IDirectDrawSurface7* src, int sx,
int sy, int sw, int sh);
static IDirectDrawSurface7* loadSurface(const std::string& f, int flags, gxGraphics* gfx);
static IDirectDrawSurface7* 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
+323
View File
@@ -0,0 +1,323 @@
#include "gxaudio.hpp"
#include <fmod.h>
#include "std.hpp"
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] = 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++] = 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 = 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 = 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 = new StreamChannel(stream);
} else {
FMUSIC_MODULE* module = FMUSIC_LoadSong(f.c_str());
if (!module)
return 0;
chan = 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;
}
+45
View File
@@ -0,0 +1,45 @@
#ifndef GXAUDIO_H
#define GXAUDIO_H
#include <string>
#include "gxsound.hpp"
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
+995
View File
@@ -0,0 +1,995 @@
#include "gxcanvas.hpp"
#include "asmcoder.hpp"
#include "gxgraphics.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
#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);
// Create Z-Buffer
if (flags & CANVAS_3DRENDER) {
DDSURFACEDESC2 zdesc = {sizeof(zdesc)};
zdesc.dwWidth = desc.dwWidth;
zdesc.dwHeight = desc.dwHeight;
zdesc.ddpfPixelFormat = g->zbuffFmt;
zdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
zdesc.ddsCaps.dwCaps =
DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSCAPS_ZBUFFER;
if (g->dirDraw->CreateSurface(&zdesc, &z_surf, 0) >= 0) {
surf->AddAttachedSurface(z_surf);
}
}
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;
}
IDirectDrawSurface7* gxCanvas::getSurface() const
{
return surf;
}
IDirectDrawSurface7* 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 = new unsigned[cm_pitch * clip_rect.bottom];
updateBitMask(clip_rect);
}
if (!i2->cm_mask) {
i2->cm_mask = 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 = 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];
}
+144
View File
@@ -0,0 +1,144 @@
#ifndef GXCANVAS_H
#define GXCANVAS_H
#include "ddutil.hpp"
class gxFont;
class gxGraphics;
class gxCanvas {
public:
gxCanvas(gxGraphics* graphics, IDirectDrawSurface7* surface, int flags);
~gxCanvas();
void backup() const;
void restore() const;
IDirectDrawSurface7* getSurface() const;
IDirectDrawSurface7* 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;
IDirectDrawSurface7 *main_surf, *surf, *z_surf, *cube_surfs[6];
mutable int mod_cnt;
mutable IDirectDrawSurface7* 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_TEX_NPOT = 0x0400, // 1024
CANVAS_3DRENDER = 0x0800, // 2048
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
@@ -1,6 +1,5 @@
#include "std.hpp"
#include "gxchannel.hpp"
#include "std.hpp"
gxChannel::~gxChannel(){
}
gxChannel::~gxChannel() {}
+20
View File
@@ -0,0 +1,20 @@
#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
+75
View File
@@ -0,0 +1,75 @@
#include "gxdevice.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
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];
}
+38
View File
@@ -0,0 +1,38 @@
#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
+23
View File
@@ -0,0 +1,23 @@
#include "gxdir.hpp"
#include "std.hpp"
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;
}
+106
View File
@@ -0,0 +1,106 @@
#include "gxfilesystem.hpp"
#include "std.hpp"
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 = 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;
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef GXFILESYSTEM_H
#define GXFILESYSTEM_H
#include <string>
#include "gxdir.hpp"
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
+81
View File
@@ -0,0 +1,81 @@
#include "gxfont.hpp"
#include "gxcanvas.hpp"
#include "gxgraphics.hpp"
#include "std.hpp"
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;
}
+34
View File
@@ -0,0 +1,34 @@
#ifndef GXFONT_H
#define GXFONT_H
class gxCanvas;
class gxGraphics;
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
@@ -1,13 +1,13 @@
#include "std.hpp"
#include "gxgraphics.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
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) {
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 = new gxCanvas(this, fs, 0);
@@ -29,23 +29,32 @@ gxGraphics::gxGraphics(gxRuntime *rt, IDirectDraw7 *dd, IDirectDrawSurface7 *fs,
_gamma = 0;
if (fs != bs) {
if (fs->QueryInterface(IID_IDirectDrawGammaControl, (void**)&_gamma) >= 0) {
if (_gamma->GetGammaRamp(0, &_gammaRamp) < 0) _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;
for (int k = 0; k < 256; ++k)
_gammaRamp.red[k] = _gammaRamp.blue[k] = _gammaRamp.green[k] = k;
}
}
gxGraphics::~gxGraphics() {
if (_gamma) _gamma->Release();
while (scene_set.size()) freeScene(*scene_set.begin());
while (movie_set.size()) closeMovie(*movie_set.begin());
while (font_set.size()) freeFont(*font_set.begin());
while (canvas_set.size()) freeCanvas(*canvas_set.begin());
gxGraphics::~gxGraphics()
{
if (_gamma)
_gamma->Release();
while (scene_set.size())
freeScene(*scene_set.begin());
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());
for (it = font_res.begin(); it != font_res.end(); ++it)
RemoveFontResource((*it).c_str());
font_res.clear();
delete back_canvas;
@@ -57,36 +66,40 @@ gxGraphics::~gxGraphics() {
dirDraw->Release();
}
void gxGraphics::setGamma(int r, int g, int b, float dr, float dg, float db) {
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;
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) {
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() {
void gxGraphics::backup() {}
bool gxGraphics::restore()
{
while (dirDraw->TestCooperativeLevel() != DD_OK) {
if (dirDraw->TestCooperativeLevel() == DDERR_WRONGMODE) return false;
if (dirDraw->TestCooperativeLevel() == DDERR_WRONGMODE)
return false;
Sleep(100);
}
if (back_canvas->getSurface()->IsLost() == DD_OK) return true;
if (back_canvas->getSurface()->IsLost() == DD_OK)
return true;
dirDraw->RestoreAllSurfaces();
@@ -101,57 +114,67 @@ bool gxGraphics::restore() {
for (mesh_it = mesh_set.begin(); mesh_it != mesh_set.end(); ++mesh_it) {
(*mesh_it)->restore();
}
if (dir3d) dir3d->EvictManagedTextures();
if (dir3d)
dir3d->EvictManagedTextures();
return true;
}
gxCanvas *gxGraphics::getFrontCanvas()const {
gxCanvas* gxGraphics::getFrontCanvas() const
{
return front_canvas;
}
gxCanvas *gxGraphics::getBackCanvas()const {
gxCanvas* gxGraphics::getBackCanvas() const
{
return back_canvas;
}
gxFont *gxGraphics::getDefaultFont()const {
gxFont* gxGraphics::getDefaultFont() const
{
return def_font;
}
void gxGraphics::vwait() {
void gxGraphics::vwait()
{
dirDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
}
void gxGraphics::flip(bool v) {
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) {
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 {
int gxGraphics::getScanLine() const
{
DWORD t = 0;
dirDraw->GetScanLine(&t);
return t;
}
int gxGraphics::getTotalVidmem()const {
int gxGraphics::getTotalVidmem() const
{
DDCAPS caps = {sizeof(caps)};
dirDraw->GetCaps(&caps, 0);
return caps.dwVidMemTotal;
}
int gxGraphics::getAvailVidmem()const {
int gxGraphics::getAvailVidmem() const
{
DDCAPS caps = {sizeof(caps)};
dirDraw->GetCaps(&caps, 0);
return caps.dwVidMemFree;
}
gxMovie *gxGraphics::openMovie(const string &file, int flags) {
gxMovie* gxGraphics::openMovie(const string& file, int flags)
{
/*IAMMultiMediaStream *iam_stream;
if (CoCreateInstance(
@@ -181,53 +204,66 @@ gxMovie *gxGraphics::openMovie(const string &file, int flags) {
return 0;
}
gxMovie *gxGraphics::verifyMovie(gxMovie *m) {
gxMovie* gxGraphics::verifyMovie(gxMovie* m)
{
return movie_set.count(m) ? m : 0;
}
void gxGraphics::closeMovie(gxMovie *m) {
if (movie_set.erase(m)) delete m;
void gxGraphics::closeMovie(gxMovie* m)
{
if (movie_set.erase(m))
delete m;
}
gxCanvas *gxGraphics::createCanvas(int w, int h, int flags) {
gxCanvas* gxGraphics::createCanvas(int w, int h, int flags)
{
IDirectDrawSurface7* s = ddUtil::createSurface(w, h, flags, this);
if (!s) return 0;
if (!s)
return 0;
gxCanvas* c = new gxCanvas(this, s, flags);
canvas_set.insert(c);
c->cls();
return c;
}
gxCanvas *gxGraphics::loadCanvas(const string &f, int flags) {
gxCanvas* gxGraphics::loadCanvas(const string& f, int flags)
{
IDirectDrawSurface7* s = ddUtil::loadSurface(f, flags, this);
if (!s) return 0;
if (!s)
return 0;
gxCanvas* c = new gxCanvas(this, s, flags);
canvas_set.insert(c);
return c;
}
gxCanvas *gxGraphics::verifyCanvas(gxCanvas *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;
void gxGraphics::freeCanvas(gxCanvas* c)
{
if (canvas_set.erase(c))
delete c;
}
int gxGraphics::getWidth()const {
int gxGraphics::getWidth() const
{
return front_canvas->getWidth();
}
int gxGraphics::getHeight()const {
int gxGraphics::getHeight() const
{
return front_canvas->getHeight();
}
int gxGraphics::getDepth()const {
int gxGraphics::getDepth() const
{
return front_canvas->getDepth();
}
gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
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;
@@ -237,7 +273,8 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
int n = f.find('.');
if (n != string::npos) {
t = fullfilename(f);
if (!font_res.count(t) && AddFontResource(t.c_str())) font_res.insert(t);
if (!font_res.count(t) && AddFontResource(t.c_str()))
font_res.insert(t);
t = filenamefile(f.substr(0, n));
} else {
t = f;
@@ -248,11 +285,8 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
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());
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
@@ -282,7 +316,6 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
//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;
@@ -297,13 +330,19 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
as[k] = ceil(-abc.abcA);
w += as[k];
}
if (abc.abcC < 0) w += (int)ceil(-abc.abcC);
if (abc.abcC < 0)
w += (int)ceil(-abc.abcC);
}
if (x && x + w > getWidth()) { x = 0; y += height; }
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;
x += w;
if (x > max_x)
max_x = x;
}
SelectObject(hdc, pfont);
DeleteDC(hdc);
@@ -333,7 +372,8 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
delete[] as;
c->backup();
gxFont *font = new gxFont(this, c, tm.tmMaxCharWidth, height, first, last + 1, tm.tmDefaultChar, offs, widths);
gxFont* font =
new gxFont(this, c, tm.tmMaxCharWidth, height, first, last + 1, tm.tmDefaultChar, offs, widths);
font_set.insert(font);
//restore font smoothing
@@ -354,12 +394,15 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
return 0;
}
gxFont *gxGraphics::verifyFont(gxFont *f) {
gxFont* gxGraphics::verifyFont(gxFont* f)
{
return font_set.count(f) ? f : 0;
}
void gxGraphics::freeFont(gxFont *f) {
if (font_set.erase(f)) delete f;
void gxGraphics::freeFont(gxFont* f)
{
if (font_set.erase(f))
delete f;
}
//////////////
@@ -368,13 +411,17 @@ void gxGraphics::freeFont(gxFont *f) {
static int maxDevType;
static HRESULT CALLBACK enumDevice(char *desc, char *name, D3DDEVICEDESC7 *devDesc, void *context) {
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 (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;
@@ -382,7 +429,8 @@ static HRESULT CALLBACK enumDevice(char *desc, char *name, D3DDEVICEDESC7 *devDe
return D3DENUMRET_OK;
}
static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void *context) {
static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void* context)
{
gxGraphics* g = (gxGraphics*)context;
if (format->dwZBufferBitDepth == g->primFmt.dwRGBBitCount) {
g->zbuffFmt = *format;
@@ -401,17 +449,20 @@ struct TexFmt {
int bits, a_bits, rgb_bits;
};
static int cntBits(int mask) {
static int cntBits(int mask)
{
int n = 0;
for (int k = 0; k < 32; ++k) {
if (mask & (1 << k)) ++n;
if (mask & (1 << k))
++n;
}
return n;
}
static vector<TexFmt> tex_fmts;
static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT *fmt, void *p) {
static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT* fmt, void* p)
{
TexFmt t;
t.fmt = *fmt;
t.bits = fmt->dwRGBBitCount;
@@ -423,7 +474,8 @@ static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT *fmt, void *p) {
return D3DENUMRET_OK;
}
static string itobin(int n) {
static string itobin(int n)
{
string t;
for (int k = 0; k < 32; n <<= 1, ++k) {
t += (n & 0x80000000) ? '1' : '0';
@@ -431,7 +483,8 @@ static string itobin(int n) {
return t;
}
static void debugPF(const DDPIXELFORMAT &pf) {
static void debugPF(const DDPIXELFORMAT& pf)
{
string t;
t = "Bits:" + itoa(pf.dwRGBBitCount);
gx_runtime->debugLog(t.c_str());
@@ -445,21 +498,29 @@ static void debugPF(const DDPIXELFORMAT &pf) {
gx_runtime->debugLog(t.c_str());
}
static void pickTexFmts(gxGraphics *g, int hi) {
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 (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 (!hi && pick >= 0)
break;
}
if (pick < 0) g->texRGBFmt[hi] = g->primFmt;
else g->texRGBFmt[hi] = tex_fmts[pick].fmt;
if (pick < 0)
g->texRGBFmt[hi] = g->primFmt;
else
g->texRGBFmt[hi] = tex_fmts[pick].fmt;
}
//texAlphaFmt
{
@@ -467,14 +528,21 @@ static void pickTexFmts(gxGraphics *g, int hi) {
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 (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 (!hi && pick >= 0)
break;
}
if (pick < 0) g->texAlphaFmt[hi] = g->primFmt;
else g->texAlphaFmt[hi] = tex_fmts[pick].fmt;
if (pick < 0)
g->texAlphaFmt[hi] = g->primFmt;
else
g->texAlphaFmt[hi] = tex_fmts[pick].fmt;
}
//texRGBAlphaFmt
{
@@ -482,16 +550,27 @@ static void pickTexFmts(gxGraphics *g, int hi) {
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 (t.a_bits == 8 && t.bits == 16) {
a8rgb8 = k;
continue;
}
if (!hi && pick >= 0) break;
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 (pick < 0) pick = a8rgb8;
if (pick < 0) g->texRGBAlphaFmt[hi] = g->primFmt;
else g->texRGBAlphaFmt[hi] = tex_fmts[pick].fmt;
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...
{
@@ -499,19 +578,28 @@ static void pickTexFmts(gxGraphics *g, int hi) {
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 (!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 (!hi && pick >= 0)
break;
}
if (pick < 0) g->texRGBMaskFmt[hi] = g->primFmt;
else g->texRGBMaskFmt[hi] = tex_fmts[pick].fmt;
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;
gxScene* gxGraphics::createScene(int flags)
{
if (scene_set.size())
return 0;
//get d3d
if (dirDraw->QueryInterface(IID_IDirect3D7, (void**)&dir3d) >= 0) {
@@ -565,25 +653,34 @@ gxScene *gxGraphics::createScene(int flags) {
return 0;
}
gxScene *gxGraphics::verifyScene(gxScene *s) {
gxScene* gxGraphics::verifyScene(gxScene* s)
{
return scene_set.count(s) ? s : 0;
}
void gxGraphics::freeScene(gxScene *scene) {
if (!scene_set.erase(scene)) return;
void gxGraphics::freeScene(gxScene* scene)
{
if (!scene_set.erase(scene))
return;
dummy_mesh = 0;
while (mesh_set.size()) freeMesh(*mesh_set.begin());
while (mesh_set.size())
freeMesh(*mesh_set.begin());
back_canvas->releaseZBuffer();
if (dir3dDev) { dir3dDev->Release(); dir3dDev = 0; }
if (dir3d) { dir3d->Release(); dir3d = 0; }
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) {
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);
D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1);
int vbflags = 0;
@@ -595,17 +692,21 @@ gxMesh *gxGraphics::createMesh(int max_verts, int max_tris, int flags) {
D3DVERTEXBUFFERDESC desc = {sizeof(desc), vbflags, VTXFMT, max_verts};
IDirect3DVertexBuffer7* buff;
if (dir3d->CreateVertexBuffer(&desc, &buff, 0) < 0) return 0;
if (dir3d->CreateVertexBuffer(&desc, &buff, 0) < 0)
return 0;
WORD* indices = new WORD[max_tris * 3];
gxMesh* mesh = new gxMesh(this, buff, indices, max_verts, max_tris);
mesh_set.insert(mesh);
return mesh;
}
gxMesh *gxGraphics::verifyMesh(gxMesh *m) {
gxMesh* gxGraphics::verifyMesh(gxMesh* m)
{
return mesh_set.count(m) ? m : 0;
}
void gxGraphics::freeMesh(gxMesh *mesh) {
if (mesh_set.erase(mesh)) delete mesh;
void gxGraphics::freeMesh(gxMesh* mesh)
{
if (mesh_set.erase(mesh))
delete mesh;
}
+126
View File
@@ -0,0 +1,126 @@
#ifndef GXGRAPHICS_H
#define GXGRAPHICS_H
#include <set>
#include <string>
#include <d3d.h>
#include <windows.h>
#include "GraphicsRuntime.hpp"
#include "ddutil.hpp"
#include "gxcanvas.hpp"
#include "gxfont.hpp"
#include "gxmesh.hpp"
#include "gxmovie.hpp"
#include "gxscene.hpp"
class gxRuntime;
class gxGraphics {
private:
// Direct3D9
//LPDIRECT3D9 d3d9;
//LPDIRECT3DDEVICE9 d3d9dev;
//IDirect3DDevice9* d3d9Device;
public:
gxGraphics(gxRuntime* runtime);
gxGraphics(gxRuntime* runtime, IDirectDraw7* dirDraw, IDirectDrawSurface7* front, IDirectDrawSurface7* back,
bool d3d);
~gxGraphics();
IDirectDraw7* dirDraw;
IDirectDraw* ds_dirDraw;
IDirect3D7* dir3d;
IDirect3DDevice7* dir3dDev;
D3DDEVICEDESC7 dir3dDevDesc;
DDPIXELFORMAT primFmt, zbuffFmt;
DDPIXELFORMAT texRGBFmt[2], texAlphaFmt[2], texRGBAlphaFmt[2], texRGBMaskFmt[2];
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);
IDirectDrawSurface7* createSurface(int width, int height, int flags);
IDirectDrawSurface7* 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
+152 -83
View File
@@ -1,8 +1,8 @@
#pragma once
#include "std.hpp"
#include "gxinput.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
static const int QUE_SIZE = 32;
@@ -12,17 +12,19 @@ public:
gxInput* input;
LPDIRECTINPUTDEVICE8 device;
Device(gxInput *i, LPDIRECTINPUTDEVICE8 d) :input(i), acquired(false), device(d) {
}
virtual ~Device() {
Device(gxInput* i, LPDIRECTINPUTDEVICE8 d) : input(i), acquired(false), device(d) {}
virtual ~Device()
{
device->Release();
//device->Release();
}
bool acquire() {
bool acquire()
{
return device->Acquire() >= 0;
//return acquired=device->Acquire()>=0;
}
void unacquire() {
void unacquire()
{
device->Unacquire();
//device->Unacquire();
acquired = false;
@@ -31,43 +33,53 @@ public:
class Keyboard : public Device {
public:
Keyboard(gxInput *i, LPDIRECTINPUTDEVICE8 d) :Device(i, d) {
}
void update() {
Keyboard(gxInput* i, LPDIRECTINPUTDEVICE8 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;
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);
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, LPDIRECTINPUTDEVICE8 d) :Device(i, d) {
}
void update() {
Mouse(gxInput* i, LPDIRECTINPUTDEVICE8 d) : Device(i, d) {}
void update()
{
if (!acquired) {
input->runtime->idle();
return;
}
DIMOUSESTATE state;
if (device->GetDeviceState(sizeof(state), &state) < 0) return;
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;
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;
@@ -82,7 +94,8 @@ class Joystick : public Device {
public:
int type, poll_time;
int mins[12], maxs[12];
Joystick(gxInput *i, LPDIRECTINPUTDEVICE8 d, int t) :Device(i, d), type(t), poll_time(0) {
Joystick(gxInput* i, LPDIRECTINPUTDEVICE8 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;
@@ -99,17 +112,22 @@ public:
maxs[k] = range.lMax - range.lMin;
}
}
void update() {
void update()
{
unsigned tm = timeGetTime();
if (tm - poll_time < 3) return;
if (tm - poll_time < 3)
return;
if (device->Poll() < 0) {
acquired = false;
input->runtime->idle();
acquire(); if (device->Poll() < 0) return;
acquire();
if (device->Poll() < 0)
return;
}
poll_time = tm;
DIJOYSTATE state;
if (device->GetDeviceState(sizeof(state), &state) < 0) return;
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;
@@ -118,8 +136,10 @@ public:
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);
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);
@@ -131,11 +151,11 @@ static Keyboard *keyboard;
static Mouse* mouse;
static vector<Joystick*> joysticks;
static Keyboard *createKeyboard(gxInput *input) {
static Keyboard* createKeyboard(gxInput* input)
{
LPDIRECTINPUTDEVICE8 dev;
if (input->dirInput->CreateDevice(GUID_SysKeyboard, &dev, NULL) >= 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));
@@ -164,11 +184,11 @@ static Keyboard *createKeyboard(gxInput *input) {
return 0;
}
static Mouse *createMouse(gxInput *input) {
static Mouse* createMouse(gxInput* input)
{
LPDIRECTINPUTDEVICE8 dev;
if (input->dirInput->CreateDevice(GUID_SysMouse, &dev, 0) >= 0) {
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
if (dev->SetDataFormat(&c_dfDIMouse) >= 0) {
return new Mouse(input, dev);
} else {
@@ -186,7 +206,8 @@ static Mouse *createMouse(gxInput *input) {
return 0;
}
static Joystick *createJoystick(gxInput *input, LPCDIDEVICEINSTANCE devinst) {
static Joystick* createJoystick(gxInput* input, LPCDIDEVICEINSTANCE devinst)
{
LPDIRECTINPUTDEVICE8 dev;
if (input->dirInput->CreateDevice(devinst->guidInstance, &dev, 0) >= 0) {
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
@@ -200,9 +221,10 @@ static Joystick *createJoystick(gxInput *input, LPCDIDEVICEINSTANCE devinst) {
return 0;
}
static BOOL CALLBACK enumJoystick(LPCDIDEVICEINSTANCE devinst, LPVOID pvRef) {
if ((devinst->dwDevType & 0xff) != DI8DEVCLASS_GAMECTRL) return DIENUM_CONTINUE;
static BOOL CALLBACK enumJoystick(LPCDIDEVICEINSTANCE devinst, LPVOID pvRef)
{
if ((devinst->dwDevType & 0xff) != DI8DEVCLASS_GAMECTRL)
return DIENUM_CONTINUE;
if (Joystick* joy = createJoystick((gxInput*)pvRef, devinst)) {
joysticks.push_back(joy);
@@ -210,15 +232,18 @@ static BOOL CALLBACK enumJoystick(LPCDIDEVICEINSTANCE devinst, LPVOID pvRef) {
return DIENUM_CONTINUE;
}
gxInput::gxInput(gxRuntime *rt, LPDIRECTINPUT8 di) : runtime(rt), dirInput(di) {
gxInput::gxInput(gxRuntime* rt, LPDIRECTINPUT8 di) : runtime(rt), dirInput(di)
{
keyboard = createKeyboard(this);
mouse = createMouse(this);
joysticks.clear();
dirInput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumJoystick, this, DIEDFL_ATTACHEDONLY);
}
gxInput::~gxInput() {
for (int k = 0; k < joysticks.size(); ++k) delete joysticks[k];
gxInput::~gxInput()
{
for (int k = 0; k < joysticks.size(); ++k)
delete joysticks[k];
joysticks.clear();
delete mouse;
delete keyboard;
@@ -226,97 +251,140 @@ gxInput::~gxInput() {
dirInput->Release();
}
void gxInput::wm_keydown(int key) {
if (keyboard) keyboard->downEvent(key);
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_keyup(int key)
{
if (keyboard)
keyboard->upEvent(key);
}
void gxInput::wm_mousedown(int key) {
if (mouse) mouse->downEvent(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_mouseup(int key)
{
if (mouse)
mouse->upEvent(key);
}
void gxInput::wm_mousemove(int x, int y) {
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::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();
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 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();
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::unacquire()
{
if (keyboard)
keyboard->unacquire();
if (mouse)
mouse->unacquire();
}
void gxInput::moveMouse(int x, int y) {
if (!mouse) return;
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 {
gxDevice* gxInput::getMouse() const
{
return mouse;
}
gxDevice *gxInput::getKeyboard()const {
gxDevice* gxInput::getKeyboard() const
{
return keyboard;
}
gxDevice *gxInput::getJoystick(int n)const {
gxDevice* gxInput::getJoystick(int n) const
{
return n >= 0 && n < joysticks.size() ? joysticks[n] : 0;
}
int gxInput::getJoystickType(int n)const {
int gxInput::getJoystickType(int n) const
{
return n >= 0 && n < joysticks.size() ? joysticks[n]->type : 0;
}
int gxInput::numJoysticks()const {
int gxInput::numJoysticks() const
{
return joysticks.size();
}
int gxInput::toAscii(int scan)const {
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;
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;
if (!virt)
return 0;
static unsigned char mat[256];
mat[VK_LSHIFT] = keyboard->keyDown(DIK_LSHIFT) ? 0x80 : 0;
@@ -330,6 +398,7 @@ int gxInput::toAscii(int scan)const {
mat[VK_MENU] = mat[VK_LMENU] | mat[VK_RMENU];
WORD ch;
if (ToAscii(virt, scan, mat, &ch, 0) != 1) return 0;
if (ToAscii(virt, scan, mat, &ch, 0) != 1)
return 0;
return ch & 255;
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include "GraphicsRuntime.hpp"
#include "gxdevice.hpp"
#include "std.hpp"
class gxRuntime;
class gxInput {
public:
gxRuntime* runtime;
LPDIRECTINPUT8 dirInput;
gxInput(gxRuntime* runtime, LPDIRECTINPUT8 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;
};
+62
View File
@@ -0,0 +1,62 @@
#include "gxlight.hpp"
#include "gxgraphics.hpp"
#include "gxscene.hpp"
#include "std.hpp"
const float PI = 3.14159265359f; //180 degrees
const float TWOPI = PI * 2.0f; //360 degrees
const float HALFPI = PI * .5f; //90 degrees
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;
}
+37
View File
@@ -0,0 +1,37 @@
#include "GraphicsRuntime.hpp"
#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
+20 -14
View File
@@ -1,17 +1,19 @@
#include "std.hpp"
#include "gxmesh.hpp"
#include "gxgraphics.hpp"
#include "std.hpp"
#include "gxruntime.hpp"
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(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(){
gxMesh::~gxMesh()
{
unlock();
vertex_buff->Release();
@@ -19,8 +21,10 @@ gxMesh::~gxMesh(){
delete[] tri_indices;
}
bool gxMesh::lock( bool all ){
if( locked_verts ) return true;
bool gxMesh::lock(bool all)
{
if (locked_verts)
return true;
//V1.104
//int flags=all ? DDLOCK_DISCARDCONTENTS : 0;
@@ -50,18 +54,21 @@ bool gxMesh::lock( bool all ){
return true;
}
void gxMesh::unlock(){
void gxMesh::unlock()
{
if (locked_verts) {
vertex_buff->Unlock();
locked_verts = 0;
}
}
void gxMesh::backup(){
void gxMesh::backup()
{
unlock();
}
void gxMesh::restore(){
void gxMesh::restore()
{
mesh_dirty = true;
}
@@ -98,10 +105,9 @@ void gxMesh::restore(){
}
*/
void gxMesh::render( int first_vert,int vert_cnt,int first_tri,int tri_cnt ){
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,
graphics->dir3dDev->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST, vertex_buff, first_vert, vert_cnt,
tri_indices + first_tri * 3, tri_cnt * 3, 0);
}
+85
View File
@@ -0,0 +1,85 @@
#ifndef GXMESH_H
#define GXMESH_H
#include <d3d.h>
#include <windows.h>
#include "GraphicsRuntime.hpp"
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
@@ -1,11 +1,10 @@
#include "std.hpp"
#include "gxmovie.hpp"
#include "gxgraphics.hpp"
#include "std.hpp"
gxMovie::gxMovie(gxGraphics *g, IMultiMediaStream *mm)
:gfx(g), mm_stream(mm), playing(true) {
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);
@@ -23,7 +22,8 @@ gxMovie::gxMovie(gxGraphics *g, IMultiMediaStream *mm)
//mm_stream->SetState(STREAMSTATE_RUN);
}
gxMovie::~gxMovie() {
gxMovie::~gxMovie()
{
/*mm_stream->SetState(STREAMSTATE_STOP);
dd_sample->Release();
@@ -35,8 +35,10 @@ gxMovie::~gxMovie() {
gfx->freeCanvas(canvas);*/
}
bool gxMovie::draw(gxCanvas *dest, int x, int y, int w, int h) {
if (!playing) return false;
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);
+47
View File
@@ -0,0 +1,47 @@
#ifndef GXMOVIE_H
#define GXMOVIE_H
#include "amstream.h" // DirectShow multimedia stream interfaces
#include "ddstream.h" // DirectDraw multimedia stream interfaces
#include "mmstream.h" // multimedia stream interfaces
#include "gxcanvas.hpp"
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
+61
View File
@@ -0,0 +1,61 @@
#include "gxmusic.hpp"
#include <fmod.h>
#include "std.hpp"
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;
}
+34
View File
@@ -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
+143
View File
@@ -0,0 +1,143 @@
#ifndef GXRUNTIME_H
#define GXRUNTIME_H
#include <string>
#include <vector>
#include <windows.h>
#include "gxaudio.hpp"
#include "gxfilesystem.hpp"
#include "gxgraphics.hpp"
#include "gxinput.hpp"
#include "gxtimer.hpp"
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, void* d);
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 enumerateGraphicsDrivers();
void graphicsDriverInfo(int driver, std::string* name, int* caps);
int countGraphicsModes(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
+737
View File
@@ -0,0 +1,737 @@
#include "gxscene.hpp"
#include "gxgraphics.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
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 = new gxLight(this, flags);
_allLights.insert(l);
return l;
}
void gxScene::freeLight(gxLight* l)
{
_allLights.erase(l);
}
int gxScene::getTrianglesDrawn() const
{
return tris_drawn;
}
+146
View File
@@ -0,0 +1,146 @@
#ifndef GXSCENE_H
#define GXSCENE_H
#include <d3d.h>
#include <map>
#include <windows.h>
#include "GraphicsRuntime.hpp"
#include "gxlight.hpp"
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
+58
View File
@@ -0,0 +1,58 @@
#include "gxsound.hpp"
#include <fmod.h>
#include "gxaudio.hpp"
#include "std.hpp"
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;
}
+38
View File
@@ -0,0 +1,38 @@
#ifndef GXSOUND_H
#define GXSOUND_H
#include "gxchannel.hpp"
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
+34
View File
@@ -0,0 +1,34 @@
#include "gxtimer.hpp"
#include "gxruntime.hpp"
#include "std.hpp"
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;
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef GXTIMER_H
#define GXTIMER_H
#include <mmsyscom.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
+5 -5
View File
@@ -8,13 +8,13 @@
#define DIRECTSOUND_VERSION 0x700
#include <set>
#include <map>
#include <list>
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <math.h>
#include <windows.h>
-74
View File
@@ -1,74 +0,0 @@
// 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.hpp"
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
}
}
-330
View File
@@ -1,330 +0,0 @@
// 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
-57
View File
@@ -1,57 +0,0 @@
#ifndef DDUTIL_H
#define DDUTIL_H
#include "GraphicsRuntime.hpp"
class gxGraphics;
struct ddUtil{
static void buildMipMaps( IDirectDrawSurface7 *surf );
static void copy( IDirectDrawSurface7 *dest,int dx,int dy,int dw,int dh,IDirectDrawSurface7 *src,int sx,int sy,int sw,int sh );
static IDirectDrawSurface7 *loadSurface( const std::string &f,int flags,gxGraphics *gfx );
static IDirectDrawSurface7 *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
-286
View File
@@ -1,286 +0,0 @@
#include "std.hpp"
#include "gxaudio.hpp"
#include <fmod.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]=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++]=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=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=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=new StreamChannel( stream );
}else{
FMUSIC_MODULE *module=FMUSIC_LoadSong( f.c_str() );
if( !module ) return 0;
chan=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;
}
-48
View File
@@ -1,48 +0,0 @@
#ifndef GXAUDIO_H
#define GXAUDIO_H
#include <string>
#include "gxsound.hpp"
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
-739
View File
@@ -1,739 +0,0 @@
#include "std.hpp"
#include "gxcanvas.hpp"
#include "gxgraphics.hpp"
#include "gxruntime.hpp"
#include "asmcoder.hpp"
#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);
// Create Z-Buffer
if (flags & CANVAS_3DRENDER) {
DDSURFACEDESC2 zdesc = { sizeof(zdesc) };
zdesc.dwWidth = desc.dwWidth;
zdesc.dwHeight = desc.dwHeight;
zdesc.ddpfPixelFormat = g->zbuffFmt;
zdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
zdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSCAPS_ZBUFFER;
if (g->dirDraw->CreateSurface(&zdesc, &z_surf, 0) >= 0) {
surf->AddAttachedSurface(z_surf);
}
}
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;
}
IDirectDrawSurface7 *gxCanvas::getSurface()const {
return surf;
}
IDirectDrawSurface7 *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 = new unsigned[cm_pitch*clip_rect.bottom];
updateBitMask(clip_rect);
}
if (!i2->cm_mask) {
i2->cm_mask = 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 = 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];
}
-138
View File
@@ -1,138 +0,0 @@
#ifndef GXCANVAS_H
#define GXCANVAS_H
#include "ddutil.hpp"
class gxFont;
class gxGraphics;
class gxCanvas {
public:
gxCanvas(gxGraphics *graphics, IDirectDrawSurface7 *surface, int flags);
~gxCanvas();
void backup()const;
void restore()const;
IDirectDrawSurface7 *getSurface()const;
IDirectDrawSurface7 *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;
IDirectDrawSurface7 *main_surf, *surf, *z_surf, *cube_surfs[6];
mutable int mod_cnt;
mutable IDirectDrawSurface7 *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_TEX_NPOT = 0x0400, // 1024
CANVAS_3DRENDER = 0x0800, // 2048
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
-21
View File
@@ -1,21 +0,0 @@
#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
-62
View File
@@ -1,62 +0,0 @@
#include "std.hpp"
#include "gxdevice.hpp"
#include "gxruntime.hpp"
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];
}
-40
View File
@@ -1,40 +0,0 @@
#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
-20
View File
@@ -1,20 +0,0 @@
#include "std.hpp"
#include "gxdir.hpp"
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;
}
-83
View File
@@ -1,83 +0,0 @@
#include "std.hpp"
#include "gxfilesystem.hpp"
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=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;
}
-37
View File
@@ -1,37 +0,0 @@
#ifndef GXFILESYSTEM_H
#define GXFILESYSTEM_H
#include <string>
#include "gxdir.hpp"
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
-71
View File
@@ -1,71 +0,0 @@
#include "std.hpp"
#include "gxfont.hpp"
#include "gxcanvas.hpp"
#include "gxgraphics.hpp"
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;
}
-42
View File
@@ -1,42 +0,0 @@
#ifndef GXFONT_H
#define GXFONT_H
class gxCanvas;
class gxGraphics;
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
-126
View File
@@ -1,126 +0,0 @@
#ifndef GXGRAPHICS_H
#define GXGRAPHICS_H
#include <set>
#include <string>
#include "GraphicsRuntime.hpp"
#include <windows.h>
#include <d3d.h>
#include "ddutil.hpp"
#include "gxfont.hpp"
#include "gxcanvas.hpp"
#include "gxscene.hpp"
#include "gxmesh.hpp"
#include "gxmovie.hpp"
class gxRuntime;
class gxGraphics {
private:
// Direct3D9
//LPDIRECT3D9 d3d9;
//LPDIRECT3DDEVICE9 d3d9dev;
//IDirect3DDevice9* d3d9Device;
public:
gxGraphics(gxRuntime* runtime);
gxGraphics(gxRuntime* runtime, IDirectDraw7 *dirDraw, IDirectDrawSurface7 *front, IDirectDrawSurface7 *back, bool d3d);
~gxGraphics();
IDirectDraw7 *dirDraw;
IDirectDraw *ds_dirDraw;
IDirect3D7 *dir3d;
IDirect3DDevice7 *dir3dDev;
D3DDEVICEDESC7 dir3dDevDesc;
DDPIXELFORMAT primFmt,zbuffFmt;
DDPIXELFORMAT texRGBFmt[2], texAlphaFmt[2], texRGBAlphaFmt[2], texRGBMaskFmt[2];
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);
IDirectDrawSurface7 *createSurface(int width, int height, int flags);
IDirectDrawSurface7 *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
-46
View File
@@ -1,46 +0,0 @@
#pragma once
#include "std.hpp"
#include "gxdevice.hpp"
#include "GraphicsRuntime.hpp"
class gxRuntime;
class gxInput{
public:
gxRuntime *runtime;
LPDIRECTINPUT8 dirInput;
gxInput( gxRuntime *runtime, LPDIRECTINPUT8 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;
};
-60
View File
@@ -1,60 +0,0 @@
#include "std.hpp"
#include "gxlight.hpp"
#include "gxscene.hpp"
#include "gxgraphics.hpp"
const float PI=3.14159265359f; //180 degrees
const float TWOPI=PI*2.0f; //360 degrees
const float HALFPI=PI*.5f; //90 degrees
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;
}
-33
View File
@@ -1,33 +0,0 @@
#include "GraphicsRuntime.hpp"
#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
-73
View File
@@ -1,73 +0,0 @@
#ifndef GXMESH_H
#define GXMESH_H
#include <windows.h>
#include "GraphicsRuntime.hpp"
#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
-40
View File
@@ -1,40 +0,0 @@
#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.hpp"
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
-57
View File
@@ -1,57 +0,0 @@
#include "std.hpp"
#include "gxmusic.hpp"
#include <fmod.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;
}
-34
View File
@@ -1,34 +0,0 @@
#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
-143
View File
@@ -1,143 +0,0 @@
#ifndef GXRUNTIME_H
#define GXRUNTIME_H
#include <windows.h>
#include <string>
#include <vector>
#include "gxaudio.hpp"
#include "gxinput.hpp"
#include "gxgraphics.hpp"
#include "gxfilesystem.hpp"
#include "gxtimer.hpp"
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, void* d );
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 enumerateGraphicsDrivers();
void graphicsDriverInfo( int driver,std::string *name,int *caps );
int countGraphicsModes( 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
-619
View File
@@ -1,619 +0,0 @@
#include "std.hpp"
#include "gxscene.hpp"
#include "gxgraphics.hpp"
#include "gxruntime.hpp"
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=new gxLight( this,flags );
_allLights.insert(l);
return l;
}
void gxScene::freeLight( gxLight *l ){
_allLights.erase(l);
}
int gxScene::getTrianglesDrawn()const{
return tris_drawn;
}
-157
View File
@@ -1,157 +0,0 @@
#ifndef GXSCENE_H
#define GXSCENE_H
#include <map>
#include "GraphicsRuntime.hpp"
#include <windows.h>
#include <d3d.h>
#include "gxlight.hpp"
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
-51
View File
@@ -1,51 +0,0 @@
#include "std.hpp"
#include "gxsound.hpp"
#include "gxaudio.hpp"
#include <fmod.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;
}
-38
View File
@@ -1,38 +0,0 @@
#ifndef GXSOUND_H
#define GXSOUND_H
#include "gxchannel.hpp"
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
-31
View File
@@ -1,31 +0,0 @@
#include "std.hpp"
#include "gxtimer.hpp"
#include "gxruntime.hpp"
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;
}
-27
View File
@@ -1,27 +0,0 @@
#ifndef GXTIMER_H
#define GXTIMER_H
#include <mmsyscom.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