runtime: CMake-ify gx
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
project(runtime)
|
project(runtime)
|
||||||
|
|
||||||
add_subdirectory(lib)
|
add_subdirectory(lib)
|
||||||
|
add_subdirectory(gfx)
|
||||||
add_subdirectory(blitz3d)
|
add_subdirectory(blitz3d)
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} MODULE
|
add_library(${PROJECT_NAME} MODULE
|
||||||
@@ -13,8 +14,10 @@ add_library(${PROJECT_NAME} MODULE
|
|||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
runtime_lib
|
runtime_lib
|
||||||
gxruntime
|
runtime_gfx
|
||||||
stdutil
|
stdutil
|
||||||
|
${fmod_LIBRARIES}
|
||||||
|
${FreeImage_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
#target_include_directories(${PROJECT_NAME}
|
#target_include_directories(${PROJECT_NAME}
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -1,32 +1,37 @@
|
|||||||
|
|
||||||
#include "GraphicsRuntime.hpp"
|
|
||||||
#include "std.hpp"
|
|
||||||
#include "ddutil.hpp"
|
#include "ddutil.hpp"
|
||||||
|
#include "GraphicsRuntime.hpp"
|
||||||
#include "asmcoder.hpp"
|
#include "asmcoder.hpp"
|
||||||
#include "gxcanvas.hpp"
|
#include "gxcanvas.hpp"
|
||||||
#include "gxruntime.hpp"
|
#include "gxruntime.hpp"
|
||||||
|
#include "std.hpp"
|
||||||
|
|
||||||
#define FREEIMAGE_LIB
|
#define FREEIMAGE_LIB
|
||||||
#include <freeimage.h>
|
#include <freeimage.h>
|
||||||
|
|
||||||
extern gxRuntime *gx_runtime;
|
extern gxRuntime* gx_runtime;
|
||||||
static AsmCoder asm_coder;
|
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) {
|
if (mask) {
|
||||||
for (*shl = 0; !(mask & 1); ++*shl, mask >>= 1) {}
|
for (*shl = 0; !(mask & 1); ++*shl, mask >>= 1) {
|
||||||
for (*shr = 8; mask & 1; --*shr, mask >>= 1) {}
|
}
|
||||||
}
|
for (*shr = 8; mask & 1; --*shr, mask >>= 1) {
|
||||||
else *shr = *shl = 0;
|
}
|
||||||
|
} else
|
||||||
|
*shr = *shl = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PixelFormat::~PixelFormat() {
|
PixelFormat::~PixelFormat()
|
||||||
|
{
|
||||||
if (plot_code) {
|
if (plot_code) {
|
||||||
VirtualFree(plot_code, 0, MEM_RELEASE);
|
VirtualFree(plot_code, 0, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelFormat::setFormat(const DDPIXELFORMAT &pf) {
|
void PixelFormat::setFormat(const DDPIXELFORMAT& pf)
|
||||||
|
{
|
||||||
if (plot_code) {
|
if (plot_code) {
|
||||||
VirtualFree(plot_code, 0, MEM_RELEASE);
|
VirtualFree(plot_code, 0, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
@@ -36,31 +41,40 @@ void PixelFormat::setFormat(const DDPIXELFORMAT &pf) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
plot_code = (char*)VirtualAlloc(0, 128, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
plot_code = (char*)VirtualAlloc(0, 128, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
point_code = plot_code + 64;
|
point_code = plot_code + 64;
|
||||||
|
|
||||||
depth = pf.dwRGBBitCount;
|
depth = pf.dwRGBBitCount;
|
||||||
amask = pf.dwRGBAlphaBitMask;
|
amask = pf.dwRGBAlphaBitMask;
|
||||||
rmask = pf.dwRBitMask;
|
rmask = pf.dwRBitMask;
|
||||||
gmask = pf.dwGBitMask;
|
gmask = pf.dwGBitMask;
|
||||||
bmask = pf.dwBBitMask;
|
bmask = pf.dwBBitMask;
|
||||||
pitch = depth / 8; argbfill = 0;
|
pitch = depth / 8;
|
||||||
if (!amask) argbfill |= 0xff000000;
|
argbfill = 0;
|
||||||
if (!rmask) argbfill |= 0x00ff0000;
|
if (!amask)
|
||||||
if (!gmask) argbfill |= 0x0000ff00;
|
argbfill |= 0xff000000;
|
||||||
if (!bmask) argbfill |= 0x000000ff;
|
if (!rmask)
|
||||||
calcShifts(amask, &ashr, &ashl); ashr += 24;
|
argbfill |= 0x00ff0000;
|
||||||
calcShifts(rmask, &rshr, &rshl); rshr += 16;
|
if (!gmask)
|
||||||
calcShifts(gmask, &gshr, &gshl); gshr += 8;
|
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);
|
calcShifts(bmask, &bshr, &bshl);
|
||||||
plot = (Plot)(void*)plot_code;
|
plot = (Plot)(void*)plot_code;
|
||||||
point = (Point)(void*)point_code;
|
point = (Point)(void*)point_code;
|
||||||
asm_coder.CodePlot(plot_code, depth, amask, rmask, gmask, bmask);
|
asm_coder.CodePlot(plot_code, depth, amask, rmask, gmask, bmask);
|
||||||
asm_coder.CodePoint(point_code, depth, amask, rmask, gmask, bmask);
|
asm_coder.CodePoint(point_code, depth, amask, rmask, gmask, bmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adjustTexSize(int *width, int *height, IDirect3DDevice7 *dir3dDev, bool forcePOT = true) {
|
static void adjustTexSize(int* width, int* height, IDirect3DDevice7* dir3dDev, bool forcePOT = true)
|
||||||
D3DDEVICEDESC7 ddDesc = { 0 };
|
{
|
||||||
|
D3DDEVICEDESC7 ddDesc = {0};
|
||||||
if (dir3dDev->GetCaps(&ddDesc) < 0) {
|
if (dir3dDev->GetCaps(&ddDesc) < 0) {
|
||||||
*width = *height = 256;
|
*width = *height = 256;
|
||||||
return;
|
return;
|
||||||
@@ -68,66 +82,82 @@ static void adjustTexSize(int *width, int *height, IDirect3DDevice7 *dir3dDev, b
|
|||||||
|
|
||||||
int w = *width, h = *height, min, max;
|
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.
|
// DirectX Device doesn't support Non Power-Of-Two Textures.
|
||||||
|
|
||||||
for (w = 1; w < *width; w <<= 1) {}
|
for (w = 1; w < *width; w <<= 1) {
|
||||||
for (h = 1; h < *height; h <<= 1) {}
|
}
|
||||||
}
|
for (h = 1; h < *height; h <<= 1) {
|
||||||
else if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
|
}
|
||||||
|
} else if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) {
|
||||||
// DirectX Device only supports Square Textures;
|
// DirectX Device only supports Square Textures;
|
||||||
|
|
||||||
if (w > h) h = w;
|
if (w > h)
|
||||||
else w = h;
|
h = w;
|
||||||
|
else
|
||||||
|
w = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check aspect ratio
|
//check aspect ratio
|
||||||
if (max = ddDesc.dwMaxTextureAspectRatio) {
|
if (max = ddDesc.dwMaxTextureAspectRatio) {
|
||||||
int asp = w > h ? w / h : h / w;
|
int asp = w > h ? w / h : h / w;
|
||||||
if (asp > max) {
|
if (asp > max) {
|
||||||
if (w > h) h = w / max;
|
if (w > h)
|
||||||
else w = h / max;
|
h = w / max;
|
||||||
|
else
|
||||||
|
w = h / max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//clamp size
|
//clamp size
|
||||||
if ((min = ddDesc.dwMinTextureWidth) && w < min) w = min;
|
if ((min = ddDesc.dwMinTextureWidth) && w < min)
|
||||||
if ((min = ddDesc.dwMinTextureHeight) && h < min) h = min;
|
w = min;
|
||||||
if ((max = ddDesc.dwMaxTextureWidth) && w > max) w = max;
|
if ((min = ddDesc.dwMinTextureHeight) && h < min)
|
||||||
if ((max = ddDesc.dwMaxTextureHeight) && h > max) h = max;
|
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;
|
DDSURFACEDESC2 desc = {sizeof(desc)};
|
||||||
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_CAPS;
|
||||||
desc.dwWidth = width; desc.dwHeight = height;
|
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||||
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.dwSize = sizeof(DDPIXELFORMAT);
|
||||||
desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
||||||
desc.ddpfPixelFormat.dwRGBBitCount = 32;
|
desc.ddpfPixelFormat.dwRGBBitCount = 32;
|
||||||
desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
|
desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
|
||||||
desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
|
desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
|
||||||
desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
|
desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
|
||||||
desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
|
desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
|
||||||
IDirectDrawSurface7 *surf;
|
IDirectDrawSurface7* surf;
|
||||||
if (dirDraw->CreateSurface(&desc, &surf, 0) >= 0) return surf;
|
if (dirDraw->CreateSurface(&desc, &surf, 0) >= 0)
|
||||||
|
return surf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buildMask(IDirectDrawSurface7 *surf) {
|
static void buildMask(IDirectDrawSurface7* surf)
|
||||||
DDSURFACEDESC2 desc = { sizeof(desc) };
|
{
|
||||||
|
DDSURFACEDESC2 desc = {sizeof(desc)};
|
||||||
surf->Lock(0, &desc, DDLOCK_WAIT, 0);
|
surf->Lock(0, &desc, DDLOCK_WAIT, 0);
|
||||||
unsigned char *surf_p = (unsigned char*)desc.lpSurface;
|
unsigned char* surf_p = (unsigned char*)desc.lpSurface;
|
||||||
PixelFormat fmt(desc.ddpfPixelFormat);
|
PixelFormat fmt(desc.ddpfPixelFormat);
|
||||||
|
|
||||||
for (DWORD y = 0; y < desc.dwHeight; ++y) {
|
for (DWORD y = 0; y < desc.dwHeight; ++y) {
|
||||||
unsigned char *p = surf_p;
|
unsigned char* p = surf_p;
|
||||||
for (DWORD x = 0; x < desc.dwWidth; ++x) {
|
for (DWORD x = 0; x < desc.dwWidth; ++x) {
|
||||||
unsigned argb = fmt.getPixel(p);
|
unsigned argb = fmt.getPixel(p);
|
||||||
unsigned rgb = argb & 0xffffff;
|
unsigned rgb = argb & 0xffffff;
|
||||||
unsigned a = rgb ? 0xff000000 : 0;
|
unsigned a = rgb ? 0xff000000 : 0;
|
||||||
fmt.setPixel(p, a | rgb);
|
fmt.setPixel(p, a | rgb);
|
||||||
p += fmt.getPitch();
|
p += fmt.getPitch();
|
||||||
}
|
}
|
||||||
@@ -136,20 +166,21 @@ static void buildMask(IDirectDrawSurface7 *surf) {
|
|||||||
surf->Unlock(0);
|
surf->Unlock(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void buildAlpha(IDirectDrawSurface7 *surf, bool whiten) {
|
static void buildAlpha(IDirectDrawSurface7* surf, bool whiten)
|
||||||
|
{
|
||||||
DDSURFACEDESC2 desc = { sizeof(desc) };
|
DDSURFACEDESC2 desc = {sizeof(desc)};
|
||||||
surf->Lock(0, &desc, DDLOCK_WAIT, 0);
|
surf->Lock(0, &desc, DDLOCK_WAIT, 0);
|
||||||
unsigned char *surf_p = (unsigned char*)desc.lpSurface;
|
unsigned char* surf_p = (unsigned char*)desc.lpSurface;
|
||||||
PixelFormat fmt(desc.ddpfPixelFormat);
|
PixelFormat fmt(desc.ddpfPixelFormat);
|
||||||
|
|
||||||
for (DWORD y = 0; y < desc.dwHeight; ++y) {
|
for (DWORD y = 0; y < desc.dwHeight; ++y) {
|
||||||
unsigned char *p = surf_p;
|
unsigned char* p = surf_p;
|
||||||
for (DWORD x = 0; x < desc.dwWidth; ++x) {
|
for (DWORD x = 0; x < desc.dwWidth; ++x) {
|
||||||
unsigned argb = fmt.getPixel(p);
|
unsigned argb = fmt.getPixel(p);
|
||||||
unsigned alpha = (((argb >> 16) & 0xff) + ((argb >> 8) & 0xff) + (argb & 0xff)) / 3;
|
unsigned alpha = (((argb >> 16) & 0xff) + ((argb >> 8) & 0xff) + (argb & 0xff)) / 3;
|
||||||
argb = (alpha << 24) | (argb & 0xffffff);
|
argb = (alpha << 24) | (argb & 0xffffff);
|
||||||
if (whiten) argb |= 0xffffff;
|
if (whiten)
|
||||||
|
argb |= 0xffffff;
|
||||||
fmt.setPixel(p, argb);
|
fmt.setPixel(p, argb);
|
||||||
p += fmt.getPitch();
|
p += fmt.getPitch();
|
||||||
}
|
}
|
||||||
@@ -158,74 +189,68 @@ static void buildAlpha(IDirectDrawSurface7 *surf, bool whiten) {
|
|||||||
surf->Unlock(0);
|
surf->Unlock(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ddUtil::buildMipMaps(IDirectDrawSurface7 *surf) {
|
void ddUtil::buildMipMaps(IDirectDrawSurface7* surf)
|
||||||
|
{
|
||||||
DDSURFACEDESC2 desc = { sizeof(desc) };
|
DDSURFACEDESC2 desc = {sizeof(desc)};
|
||||||
surf->GetSurfaceDesc(&desc);
|
surf->GetSurfaceDesc(&desc);
|
||||||
if (!(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) return;
|
if (!(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
|
||||||
if (!(desc.ddpfPixelFormat.dwFlags & DDPF_RGB)) return;
|
return;
|
||||||
|
if (!(desc.ddpfPixelFormat.dwFlags & DDPF_RGB))
|
||||||
|
return;
|
||||||
|
|
||||||
DDSCAPS2 caps = { 0 };
|
DDSCAPS2 caps = {0};
|
||||||
caps.dwCaps = DDSCAPS_TEXTURE;
|
caps.dwCaps = DDSCAPS_TEXTURE;
|
||||||
caps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
|
caps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
|
||||||
|
|
||||||
IDirectDrawSurface7 *src = surf, *dest;
|
IDirectDrawSurface7 *src = surf, *dest;
|
||||||
|
|
||||||
while (src->GetAttachedSurface(&caps, &dest) >= 0) {
|
while (src->GetAttachedSurface(&caps, &dest) >= 0) {
|
||||||
|
DDSURFACEDESC2 src_desc = {sizeof(src_desc)};
|
||||||
|
if (src->Lock(0, &src_desc, DDLOCK_WAIT, 0) < 0)
|
||||||
|
abort();
|
||||||
|
unsigned char* src_p = (unsigned char*)src_desc.lpSurface;
|
||||||
|
PixelFormat src_fmt(src_desc.ddpfPixelFormat);
|
||||||
|
|
||||||
DDSURFACEDESC2 src_desc = { sizeof(src_desc) };
|
DDSURFACEDESC2 dest_desc = {sizeof(dest_desc)};
|
||||||
if (src->Lock(0, &src_desc, DDLOCK_WAIT, 0) < 0) abort();
|
if (dest->Lock(0, &dest_desc, DDLOCK_WAIT, 0) < 0)
|
||||||
unsigned char *src_p = (unsigned char*)src_desc.lpSurface;
|
abort();
|
||||||
PixelFormat src_fmt(src_desc.ddpfPixelFormat);
|
unsigned char* dest_p = (unsigned char*)dest_desc.lpSurface;
|
||||||
|
PixelFormat dest_fmt(dest_desc.ddpfPixelFormat);
|
||||||
DDSURFACEDESC2 dest_desc = { sizeof(dest_desc) };
|
|
||||||
if (dest->Lock(0, &dest_desc, DDLOCK_WAIT, 0) < 0) abort();
|
|
||||||
unsigned char *dest_p = (unsigned char *)dest_desc.lpSurface;
|
|
||||||
PixelFormat dest_fmt(dest_desc.ddpfPixelFormat);
|
|
||||||
|
|
||||||
if (src_desc.dwWidth == 1) {
|
if (src_desc.dwWidth == 1) {
|
||||||
for (DWORD y = 0; y < dest_desc.dwHeight; ++y) {
|
for (DWORD y = 0; y < dest_desc.dwHeight; ++y) {
|
||||||
unsigned p1 = src_fmt.getPixel(src_p);
|
unsigned p1 = src_fmt.getPixel(src_p);
|
||||||
unsigned p2 = src_fmt.getPixel(src_p + src_desc.lPitch);
|
unsigned p2 = src_fmt.getPixel(src_p + src_desc.lPitch);
|
||||||
unsigned argb =
|
unsigned argb = ((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1);
|
||||||
((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1);
|
argb += (((p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101;
|
||||||
argb += ((
|
|
||||||
(p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101;
|
|
||||||
dest_fmt.setPixel(dest_p, argb);
|
dest_fmt.setPixel(dest_p, argb);
|
||||||
src_p += src_desc.lPitch * 2;
|
src_p += src_desc.lPitch * 2;
|
||||||
dest_p += dest_desc.lPitch;
|
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) {
|
for (DWORD x = 0; x < dest_desc.dwWidth; ++x) {
|
||||||
unsigned p1 = src_fmt.getPixel(src_p);
|
unsigned p1 = src_fmt.getPixel(src_p);
|
||||||
unsigned p2 = src_fmt.getPixel(src_p + src_fmt.getPitch());
|
unsigned p2 = src_fmt.getPixel(src_p + src_fmt.getPitch());
|
||||||
unsigned argb =
|
unsigned argb = ((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1);
|
||||||
((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1);
|
argb += (((p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101;
|
||||||
argb += ((
|
|
||||||
(p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101;
|
|
||||||
dest_fmt.setPixel(dest_p, argb);
|
dest_fmt.setPixel(dest_p, argb);
|
||||||
src_p += src_fmt.getPitch() * 2;
|
src_p += src_fmt.getPitch() * 2;
|
||||||
dest_p += dest_fmt.getPitch();
|
dest_p += dest_fmt.getPitch();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for (DWORD y = 0; y < dest_desc.dwHeight; ++y) {
|
for (DWORD y = 0; y < dest_desc.dwHeight; ++y) {
|
||||||
unsigned char *src_t = src_p;
|
unsigned char* src_t = src_p;
|
||||||
unsigned char *dest_t = dest_p;
|
unsigned char* dest_t = dest_p;
|
||||||
for (DWORD x = 0; x < dest_desc.dwWidth; ++x) {
|
for (DWORD x = 0; x < dest_desc.dwWidth; ++x) {
|
||||||
|
|
||||||
unsigned p1 = src_fmt.getPixel(src_t);
|
unsigned p1 = src_fmt.getPixel(src_t);
|
||||||
unsigned p2 = src_fmt.getPixel(src_t + src_fmt.getPitch());
|
unsigned p2 = src_fmt.getPixel(src_t + src_fmt.getPitch());
|
||||||
unsigned p3 = src_fmt.getPixel(src_t + src_desc.lPitch + 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 p4 = src_fmt.getPixel(src_t + src_desc.lPitch);
|
||||||
|
|
||||||
unsigned argb =
|
unsigned argb = ((p1 & 0xfcfcfcfc) >> 2) + ((p2 & 0xfcfcfcfc) >> 2) + ((p3 & 0xfcfcfcfc) >> 2)
|
||||||
((p1 & 0xfcfcfcfc) >> 2) + ((p2 & 0xfcfcfcfc) >> 2) +
|
+ ((p4 & 0xfcfcfcfc) >> 2);
|
||||||
((p3 & 0xfcfcfcfc) >> 2) + ((p4 & 0xfcfcfcfc) >> 2);
|
argb += (((p1 & 0x03030303) + (p2 & 0x03030303) + (p3 & 0x03030303) + (p4 & 0x03030303)) >> 2)
|
||||||
argb += ((
|
& 0x03030303;
|
||||||
(p1 & 0x03030303) + (p2 & 0x03030303) +
|
|
||||||
(p3 & 0x03030303) + (p4 & 0x03030303)) >> 2) & 0x03030303;
|
|
||||||
|
|
||||||
dest_fmt.setPixel(dest_t, argb);
|
dest_fmt.setPixel(dest_t, argb);
|
||||||
src_t += src_fmt.getPitch() * 2;
|
src_t += src_fmt.getPitch() * 2;
|
||||||
@@ -242,25 +267,26 @@ 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) };
|
{
|
||||||
|
DDSURFACEDESC2 src_desc = {sizeof(src_desc)};
|
||||||
src->Lock(0, &src_desc, DDLOCK_WAIT, 0);
|
src->Lock(0, &src_desc, DDLOCK_WAIT, 0);
|
||||||
PixelFormat src_fmt(src_desc.ddpfPixelFormat);
|
PixelFormat src_fmt(src_desc.ddpfPixelFormat);
|
||||||
unsigned char *src_p = (unsigned char*)src_desc.lpSurface;
|
unsigned char* src_p = (unsigned char*)src_desc.lpSurface;
|
||||||
src_p += src_desc.lPitch*sy + src_fmt.getPitch()*sx;
|
src_p += src_desc.lPitch * sy + src_fmt.getPitch() * sx;
|
||||||
|
|
||||||
DDSURFACEDESC2 dest_desc = { sizeof(dest_desc) };
|
DDSURFACEDESC2 dest_desc = {sizeof(dest_desc)};
|
||||||
dest->Lock(0, &dest_desc, DDLOCK_WAIT, 0);
|
dest->Lock(0, &dest_desc, DDLOCK_WAIT, 0);
|
||||||
PixelFormat dest_fmt(dest_desc.ddpfPixelFormat);
|
PixelFormat dest_fmt(dest_desc.ddpfPixelFormat);
|
||||||
unsigned char *dest_p = (unsigned char *)dest_desc.lpSurface;
|
unsigned char* dest_p = (unsigned char*)dest_desc.lpSurface;
|
||||||
dest_p += dest_desc.lPitch*dy + dest_fmt.getPitch()*dx;
|
dest_p += dest_desc.lPitch * dy + dest_fmt.getPitch() * dx;
|
||||||
|
|
||||||
for (int y = 0; y < dh; ++y) {
|
for (int y = 0; y < dh; ++y) {
|
||||||
unsigned char *dest = dest_p;
|
unsigned char* dest = dest_p;
|
||||||
unsigned char *src = src_p + src_desc.lPitch*(y*sh / dh);
|
unsigned char* src = src_p + src_desc.lPitch * (y * sh / dh);
|
||||||
for (int x = 0; x < dw; ++x) {
|
for (int x = 0; x < dw; ++x) {
|
||||||
dest_fmt.setPixel(dest, src_fmt.getPixel(src + src_fmt.getPitch()*(x*sw / dw)));
|
dest_fmt.setPixel(dest, src_fmt.getPixel(src + src_fmt.getPitch() * (x * sw / dw)));
|
||||||
dest += dest_fmt.getPitch();
|
dest += dest_fmt.getPitch();
|
||||||
}
|
}
|
||||||
dest_p += dest_desc.lPitch;
|
dest_p += dest_desc.lPitch;
|
||||||
@@ -270,14 +296,21 @@ void ddUtil::copy(IDirectDrawSurface7 *dest, int dx, int dy, int dw, int dh, IDi
|
|||||||
dest->Unlock(0);
|
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) };
|
int hi = flags & gxCanvas::CANVAS_TEX_HICOLOR ? 1 : 0;
|
||||||
|
DDSURFACEDESC2 desc = {sizeof(desc)};
|
||||||
|
|
||||||
// Texture Size
|
// Texture Size
|
||||||
desc.dwFlags = DDSD_CAPS;
|
desc.dwFlags = DDSD_CAPS;
|
||||||
if (w) { desc.dwWidth = w; desc.dwFlags |= DDSD_WIDTH; }
|
if (w) {
|
||||||
if (h) { desc.dwHeight = h; desc.dwFlags |= DDSD_HEIGHT; }
|
desc.dwWidth = w;
|
||||||
|
desc.dwFlags |= DDSD_WIDTH;
|
||||||
|
}
|
||||||
|
if (h) {
|
||||||
|
desc.dwHeight = h;
|
||||||
|
desc.dwFlags |= DDSD_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
// Format
|
// Format
|
||||||
if (flags & gxCanvas::CANVAS_TEXTURE) {
|
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;
|
desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
|
||||||
if (flags & gxCanvas::CANVAS_TEXTURE) {
|
if (flags & gxCanvas::CANVAS_TEXTURE) {
|
||||||
desc.ddpfPixelFormat = gfx->primFmt;
|
desc.ddpfPixelFormat = gfx->primFmt;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
desc.ddpfPixelFormat = gfx->texRGBAlphaFmt[hi];
|
desc.ddpfPixelFormat = gfx->texRGBAlphaFmt[hi];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (flags & gxCanvas::CANVAS_TEX_MASK) {
|
if (flags & gxCanvas::CANVAS_TEX_MASK) {
|
||||||
desc.dwFlags |= DDSD_PIXELFORMAT;
|
desc.dwFlags |= DDSD_PIXELFORMAT;
|
||||||
desc.ddpfPixelFormat = gfx->texRGBMaskFmt[hi];
|
desc.ddpfPixelFormat = gfx->texRGBMaskFmt[hi];
|
||||||
}
|
} else if (flags & gxCanvas::CANVAS_TEX_RGB) {
|
||||||
else if (flags & gxCanvas::CANVAS_TEX_RGB) {
|
|
||||||
desc.dwFlags |= DDSD_PIXELFORMAT;
|
desc.dwFlags |= DDSD_PIXELFORMAT;
|
||||||
desc.ddpfPixelFormat = (flags&gxCanvas::CANVAS_TEX_ALPHA) ? gfx->texRGBAlphaFmt[hi] : gfx->texRGBFmt[hi];
|
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.dwFlags |= DDSD_PIXELFORMAT;
|
||||||
desc.ddpfPixelFormat = gfx->texAlphaFmt[hi];
|
desc.ddpfPixelFormat = gfx->texAlphaFmt[hi];
|
||||||
}
|
} else if (flags & gxCanvas::CANVAS_TEXTURE) {
|
||||||
else if (flags & gxCanvas::CANVAS_TEXTURE) {
|
|
||||||
desc.dwFlags |= DDSD_PIXELFORMAT;
|
desc.dwFlags |= DDSD_PIXELFORMAT;
|
||||||
desc.ddpfPixelFormat = gfx->primFmt;
|
desc.ddpfPixelFormat = gfx->primFmt;
|
||||||
}
|
}
|
||||||
@@ -341,26 +369,24 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
|
|||||||
desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
|
desc.ddsCaps.dwCaps2 |= DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES;
|
||||||
}
|
}
|
||||||
adjustTexSize((int*)&desc.dwWidth, (int*)&desc.dwHeight, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT)));
|
adjustTexSize((int*)&desc.dwWidth, (int*)&desc.dwHeight, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT)));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
||||||
if (flags & gxCanvas::CANVAS_HIGHCOLOR) {
|
if (flags & gxCanvas::CANVAS_HIGHCOLOR) {
|
||||||
desc.dwFlags |= DDSD_PIXELFORMAT;
|
desc.dwFlags |= DDSD_PIXELFORMAT;
|
||||||
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||||
desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
||||||
desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
|
||||||
desc.ddpfPixelFormat.dwRGBBitCount = 32;
|
desc.ddpfPixelFormat.dwRGBBitCount = 32;
|
||||||
desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
|
desc.ddpfPixelFormat.dwRBitMask = 0xff0000;
|
||||||
desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
|
desc.ddpfPixelFormat.dwGBitMask = 0x00ff00;
|
||||||
desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
|
desc.ddpfPixelFormat.dwBBitMask = 0x0000ff;
|
||||||
desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
|
desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
|
||||||
}
|
} else if (flags & gxCanvas::CANVAS_NONDISPLAY) {
|
||||||
else if (flags & gxCanvas::CANVAS_NONDISPLAY) {
|
|
||||||
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IDirectDrawSurface7 *surf;
|
IDirectDrawSurface7* surf;
|
||||||
if (gfx->dirDraw->CreateSurface(&desc, &surf, 0) >= 0) {
|
if (gfx->dirDraw->CreateSurface(&desc, &surf, 0) >= 0) {
|
||||||
return surf;
|
return surf;
|
||||||
}
|
}
|
||||||
@@ -368,7 +394,8 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
|
|||||||
if (!(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) {
|
if (!(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) {
|
||||||
//try again in system memory!
|
//try again in system memory!
|
||||||
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
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,16 +404,18 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *
|
|||||||
|
|
||||||
//Tom Speed's DXTC loader
|
//Tom Speed's DXTC loader
|
||||||
//
|
//
|
||||||
IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
|
IDirectDrawSurface7* loadDXTC(const char* filename, gxGraphics* gfx)
|
||||||
HRESULT hr;
|
{
|
||||||
|
HRESULT hr;
|
||||||
DDSURFACEDESC2 ddsd;
|
DDSURFACEDESC2 ddsd;
|
||||||
DDSURFACEDESC2 fileddsd;
|
DDSURFACEDESC2 fileddsd;
|
||||||
char magicID[4];
|
char magicID[4];
|
||||||
FILE *fp;
|
FILE* fp;
|
||||||
|
|
||||||
/* try to open the file */
|
/* try to open the file */
|
||||||
fp = fopen(filename, "rb");
|
fp = fopen(filename, "rb");
|
||||||
if (!fp) return NULL;
|
if (!fp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* valid DDS? */
|
/* valid DDS? */
|
||||||
fread(magicID, 1, 4, fp);
|
fread(magicID, 1, 4, fp);
|
||||||
@@ -432,8 +461,8 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
|
|||||||
|
|
||||||
/* Create the new DXTC surface using the DDSURFACEDESC2
|
/* Create the new DXTC surface using the DDSURFACEDESC2
|
||||||
we read in from the file */
|
we read in from the file */
|
||||||
IDirectDrawSurface7 * newSurf = NULL;
|
IDirectDrawSurface7* newSurf = NULL;
|
||||||
hr = gfx->dirDraw->CreateSurface(&ddsd, &newSurf, NULL);
|
hr = gfx->dirDraw->CreateSurface(&ddsd, &newSurf, NULL);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -446,8 +475,8 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
|
|||||||
mipmapddsd.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
|
mipmapddsd.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
|
||||||
|
|
||||||
/* pointers used when iterating through mipmaps */
|
/* pointers used when iterating through mipmaps */
|
||||||
IDirectDrawSurface7 *topDDS = NULL;
|
IDirectDrawSurface7* topDDS = NULL;
|
||||||
IDirectDrawSurface7 *nextDDS = NULL;
|
IDirectDrawSurface7* nextDDS = NULL;
|
||||||
|
|
||||||
topDDS = newSurf;
|
topDDS = newSurf;
|
||||||
topDDS->AddRef();
|
topDDS->AddRef();
|
||||||
@@ -476,7 +505,6 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
|
|||||||
}
|
}
|
||||||
topDDS->Unlock(NULL);
|
topDDS->Unlock(NULL);
|
||||||
|
|
||||||
|
|
||||||
/* Get next mipmap in chain, or exit the loop if there's no more */
|
/* Get next mipmap in chain, or exit the loop if there's no more */
|
||||||
hr = topDDS->GetAttachedSurface(&mipmapddsd, &nextDDS);
|
hr = topDDS->GetAttachedSurface(&mipmapddsd, &nextDDS);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
@@ -493,38 +521,44 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) {
|
|||||||
return newSurf;
|
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");
|
int i = f.find(".dds");
|
||||||
if (i != string::npos && i + 4 == f.size()) {
|
if (i != string::npos && i + 4 == f.size()) {
|
||||||
//dds file!
|
//dds file!
|
||||||
IDirectDrawSurface7 *surf = loadDXTC(f.c_str(), gfx);
|
IDirectDrawSurface7* surf = loadDXTC(f.c_str(), gfx);
|
||||||
return surf;
|
return surf;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeImage_Initialise();
|
FreeImage_Initialise();
|
||||||
FREE_IMAGE_FORMAT fmt = FreeImage_GetFileType(f.c_str(), f.size());
|
FREE_IMAGE_FORMAT fmt = FreeImage_GetFileType(f.c_str(), f.size());
|
||||||
if (fmt == FIF_UNKNOWN) {
|
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());
|
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);
|
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);
|
bool trans = FreeImage_GetBPP(t_dib) == 32 || FreeImage_IsTransparent(t_dib);
|
||||||
|
|
||||||
FIBITMAP *dib = FreeImage_ConvertTo32Bits(t_dib);
|
FIBITMAP* dib = FreeImage_ConvertTo32Bits(t_dib);
|
||||||
|
|
||||||
if (dib) FreeImage_Unload(t_dib);
|
if (dib)
|
||||||
else dib = t_dib;
|
FreeImage_Unload(t_dib);
|
||||||
|
else
|
||||||
|
dib = t_dib;
|
||||||
|
|
||||||
int width = FreeImage_GetWidth(dib);
|
int width = FreeImage_GetWidth(dib);
|
||||||
int height = FreeImage_GetHeight(dib);
|
int height = FreeImage_GetHeight(dib);
|
||||||
int pitch = FreeImage_GetPitch(dib);
|
int pitch = FreeImage_GetPitch(dib);
|
||||||
void *bits = FreeImage_GetBits(dib);
|
void* bits = FreeImage_GetBits(dib);
|
||||||
|
|
||||||
IDirectDrawSurface7 *src = ::createSurface(width, height, pitch, bits, gfx->dirDraw);
|
IDirectDrawSurface7* src = ::createSurface(width, height, pitch, bits, gfx->dirDraw);
|
||||||
if (!src) {
|
if (!src) {
|
||||||
FreeImage_Unload(dib);
|
FreeImage_Unload(dib);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -533,23 +567,22 @@ IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGrap
|
|||||||
if (flags & gxCanvas::CANVAS_TEX_ALPHA) {
|
if (flags & gxCanvas::CANVAS_TEX_ALPHA) {
|
||||||
if (flags & gxCanvas::CANVAS_TEX_MASK) {
|
if (flags & gxCanvas::CANVAS_TEX_MASK) {
|
||||||
buildMask(src);
|
buildMask(src);
|
||||||
}
|
} else if (!trans) {
|
||||||
else if (!trans) {
|
|
||||||
buildAlpha(src, (flags & gxCanvas::CANVAS_TEX_RGB) ? false : true);
|
buildAlpha(src, (flags & gxCanvas::CANVAS_TEX_RGB) ? false : true);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
unsigned char* p = (unsigned char*)bits;
|
||||||
unsigned char *p = (unsigned char *)bits;
|
|
||||||
for (int k = 0; k < height; ++k) {
|
for (int k = 0; k < height; ++k) {
|
||||||
unsigned char *t = p + 3;
|
unsigned char* t = p + 3;
|
||||||
for (int j = 0; j < width; ++j) {
|
for (int j = 0; j < width; ++j) {
|
||||||
*t = 0xff; t += 4;
|
*t = 0xff;
|
||||||
|
t += 4;
|
||||||
}
|
}
|
||||||
p += pitch;
|
p += pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IDirectDrawSurface7 *dest = createSurface(width, height, flags, gfx);
|
IDirectDrawSurface7* dest = createSurface(width, height, flags, gfx);
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
src->Release();
|
src->Release();
|
||||||
FreeImage_Unload(dib);
|
FreeImage_Unload(dib);
|
||||||
@@ -557,7 +590,8 @@ IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
int t_w = width, t_h = height;
|
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);
|
copy(dest, 0, 0, t_w, t_h, src, 0, height - 1, width, -height);
|
||||||
|
|
||||||
src->Release();
|
src->Release();
|
||||||
@@ -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
|
||||||
@@ -35,7 +35,7 @@ DEFINE_GUID(CLSID_AMDirectDrawStream, 0x49c47ce4, 0x9ba4, 0x11d0, 0x82, 0x12, 0x
|
|||||||
DEFINE_GUID(CLSID_AMAudioStream, 0x8496e040, 0xaf4c, 0x11d0, 0x82, 0x12, 0x00, 0xc0, 0x4f, 0xc3, 0x2c, 0x45);
|
DEFINE_GUID(CLSID_AMAudioStream, 0x8496e040, 0xaf4c, 0x11d0, 0x82, 0x12, 0x00, 0xc0, 0x4f, 0xc3, 0x2c, 0x45);
|
||||||
DEFINE_GUID(CLSID_AMAudioData, 0xf2468580, 0xaf8a, 0x11d0, 0x82, 0x12, 0x00, 0xc0, 0x4f, 0xc3, 0x2c, 0x45);
|
DEFINE_GUID(CLSID_AMAudioData, 0xf2468580, 0xaf8a, 0x11d0, 0x82, 0x12, 0x00, 0xc0, 0x4f, 0xc3, 0x2c, 0x45);
|
||||||
DEFINE_GUID(CLSID_AMMediaTypeStream, 0xcf0f2f7c, 0xf7bf, 0x11d0, 0x90, 0xd, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
|
DEFINE_GUID(CLSID_AMMediaTypeStream, 0xcf0f2f7c, 0xf7bf, 0x11d0, 0x90, 0xd, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
|
||||||
DEFINE_GUID(MSPID_PrimaryVideo, 0xa35ff56a, 0x9fda, 0x11d0, 0x8f, 0xdf, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
|
DEFINE_GUID(MSPID_PrimaryVideo, 0xa35ff56a, 0x9fda, 0x11d0, 0x8f, 0xdf, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
|
||||||
DEFINE_GUID(MSPID_PrimaryAudio, 0xa35ff56b, 0x9fda, 0x11d0, 0x8f, 0xdf, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
|
DEFINE_GUID(MSPID_PrimaryAudio, 0xa35ff56b, 0x9fda, 0x11d0, 0x8f, 0xdf, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);
|
||||||
DEFINE_GUID(IID_IDirect3D7, 0xf5049e77, 0x4861, 0x11d2, 0xa4, 0x7, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8);
|
DEFINE_GUID(IID_IDirect3D7, 0xf5049e77, 0x4861, 0x11d2, 0xa4, 0x7, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8);
|
||||||
DEFINE_GUID(IID_IDirect3DRampDevice, 0xF2086B20, 0x259F, 0x11CF, 0xA3, 0x1A, 0x00, 0xAA, 0x00, 0xB9, 0x33, 0x56);
|
DEFINE_GUID(IID_IDirect3DRampDevice, 0xF2086B20, 0x259F, 0x11CF, 0xA3, 0x1A, 0x00, 0xAA, 0x00, 0xB9, 0x33, 0x56);
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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];
|
||||||
|
}
|
||||||
@@ -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 "gxchannel.hpp"
|
||||||
|
#include "std.hpp"
|
||||||
|
|
||||||
gxChannel::~gxChannel(){
|
gxChannel::~gxChannel() {}
|
||||||
}
|
|
||||||
@@ -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
|
||||||
@@ -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];
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -5,17 +5,17 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
class gxDir{
|
class gxDir {
|
||||||
public:
|
public:
|
||||||
gxDir( HANDLE h,const WIN32_FIND_DATA &f );
|
gxDir(HANDLE h, const WIN32_FIND_DATA& f);
|
||||||
~gxDir();
|
~gxDir();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
WIN32_FIND_DATA findData;
|
WIN32_FIND_DATA findData;
|
||||||
|
|
||||||
/***** GX INTERFACE *****/
|
/***** GX INTERFACE *****/
|
||||||
public:
|
public:
|
||||||
std::string getNextFile();
|
std::string getNextFile();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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,17 +1,17 @@
|
|||||||
|
|
||||||
#include "std.hpp"
|
|
||||||
#include "gxgraphics.hpp"
|
#include "gxgraphics.hpp"
|
||||||
#include "gxruntime.hpp"
|
#include "gxruntime.hpp"
|
||||||
|
#include "std.hpp"
|
||||||
|
|
||||||
extern gxRuntime *gx_runtime;
|
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);
|
dirDraw->QueryInterface(IID_IDirectDraw, (void**)&ds_dirDraw);
|
||||||
|
|
||||||
front_canvas = new gxCanvas(this, fs, 0);
|
front_canvas = new gxCanvas(this, fs, 0);
|
||||||
back_canvas = new gxCanvas(this, bs, 0);
|
back_canvas = new gxCanvas(this, bs, 0);
|
||||||
|
|
||||||
front_canvas->cls();
|
front_canvas->cls();
|
||||||
back_canvas->cls();
|
back_canvas->cls();
|
||||||
@@ -29,23 +29,32 @@ gxGraphics::gxGraphics(gxRuntime *rt, IDirectDraw7 *dd, IDirectDrawSurface7 *fs,
|
|||||||
_gamma = 0;
|
_gamma = 0;
|
||||||
if (fs != bs) {
|
if (fs != bs) {
|
||||||
if (fs->QueryInterface(IID_IDirectDrawGammaControl, (void**)&_gamma) >= 0) {
|
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) {
|
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() {
|
gxGraphics::~gxGraphics()
|
||||||
if (_gamma) _gamma->Release();
|
{
|
||||||
while (scene_set.size()) freeScene(*scene_set.begin());
|
if (_gamma)
|
||||||
while (movie_set.size()) closeMovie(*movie_set.begin());
|
_gamma->Release();
|
||||||
while (font_set.size()) freeFont(*font_set.begin());
|
while (scene_set.size())
|
||||||
while (canvas_set.size()) freeCanvas(*canvas_set.begin());
|
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;
|
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();
|
font_res.clear();
|
||||||
|
|
||||||
delete back_canvas;
|
delete back_canvas;
|
||||||
@@ -57,36 +66,40 @@ gxGraphics::~gxGraphics() {
|
|||||||
dirDraw->Release();
|
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.red[r & 255] = dr * 257.0f;
|
||||||
_gammaRamp.blue[b & 255] = db*257.0f;
|
_gammaRamp.green[g & 255] = dg * 257.0f;
|
||||||
|
_gammaRamp.blue[b & 255] = db * 257.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::updateGamma(bool calibrate) {
|
void gxGraphics::updateGamma(bool calibrate)
|
||||||
if (!_gamma) return;
|
{
|
||||||
|
if (!_gamma)
|
||||||
|
return;
|
||||||
_gamma->SetGammaRamp(calibrate ? DDSGR_CALIBRATE : 0, &_gammaRamp);
|
_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;
|
*dr = _gammaRamp.red[r & 255] / 257.0f;
|
||||||
*dg = _gammaRamp.green[g & 255] / 257.0f;
|
*dg = _gammaRamp.green[g & 255] / 257.0f;
|
||||||
*db = _gammaRamp.blue[b & 255] / 257.0f;
|
*db = _gammaRamp.blue[b & 255] / 257.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::backup() {
|
void gxGraphics::backup() {}
|
||||||
}
|
|
||||||
|
|
||||||
bool gxGraphics::restore() {
|
|
||||||
|
|
||||||
|
bool gxGraphics::restore()
|
||||||
|
{
|
||||||
while (dirDraw->TestCooperativeLevel() != DD_OK) {
|
while (dirDraw->TestCooperativeLevel() != DD_OK) {
|
||||||
|
if (dirDraw->TestCooperativeLevel() == DDERR_WRONGMODE)
|
||||||
if (dirDraw->TestCooperativeLevel() == DDERR_WRONGMODE) return false;
|
return false;
|
||||||
|
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (back_canvas->getSurface()->IsLost() == DD_OK) return true;
|
if (back_canvas->getSurface()->IsLost() == DD_OK)
|
||||||
|
return true;
|
||||||
|
|
||||||
dirDraw->RestoreAllSurfaces();
|
dirDraw->RestoreAllSurfaces();
|
||||||
|
|
||||||
@@ -101,57 +114,67 @@ bool gxGraphics::restore() {
|
|||||||
for (mesh_it = mesh_set.begin(); mesh_it != mesh_set.end(); ++mesh_it) {
|
for (mesh_it = mesh_set.begin(); mesh_it != mesh_set.end(); ++mesh_it) {
|
||||||
(*mesh_it)->restore();
|
(*mesh_it)->restore();
|
||||||
}
|
}
|
||||||
if (dir3d) dir3d->EvictManagedTextures();
|
if (dir3d)
|
||||||
|
dir3d->EvictManagedTextures();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxCanvas *gxGraphics::getFrontCanvas()const {
|
gxCanvas* gxGraphics::getFrontCanvas() const
|
||||||
|
{
|
||||||
return front_canvas;
|
return front_canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxCanvas *gxGraphics::getBackCanvas()const {
|
gxCanvas* gxGraphics::getBackCanvas() const
|
||||||
|
{
|
||||||
return back_canvas;
|
return back_canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxFont *gxGraphics::getDefaultFont()const {
|
gxFont* gxGraphics::getDefaultFont() const
|
||||||
|
{
|
||||||
return def_font;
|
return def_font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::vwait() {
|
void gxGraphics::vwait()
|
||||||
|
{
|
||||||
dirDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
|
dirDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::flip(bool v) {
|
void gxGraphics::flip(bool v)
|
||||||
|
{
|
||||||
runtime->flip(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 };
|
{
|
||||||
|
RECT r = {dx, dy, dx + dw, dy + dh};
|
||||||
ddUtil::copy(dest->getSurface(), dx, dy, dw, dh, src->getSurface(), sx, sy, sw, sh);
|
ddUtil::copy(dest->getSurface(), dx, dy, dw, dh, src->getSurface(), sx, sy, sw, sh);
|
||||||
dest->damage(r);
|
dest->damage(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxGraphics::getScanLine()const {
|
int gxGraphics::getScanLine() const
|
||||||
|
{
|
||||||
DWORD t = 0;
|
DWORD t = 0;
|
||||||
dirDraw->GetScanLine(&t);
|
dirDraw->GetScanLine(&t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxGraphics::getTotalVidmem()const {
|
int gxGraphics::getTotalVidmem() const
|
||||||
DDCAPS caps = { sizeof(caps) };
|
{
|
||||||
|
DDCAPS caps = {sizeof(caps)};
|
||||||
dirDraw->GetCaps(&caps, 0);
|
dirDraw->GetCaps(&caps, 0);
|
||||||
return caps.dwVidMemTotal;
|
return caps.dwVidMemTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxGraphics::getAvailVidmem()const {
|
int gxGraphics::getAvailVidmem() const
|
||||||
DDCAPS caps = { sizeof(caps) };
|
{
|
||||||
|
DDCAPS caps = {sizeof(caps)};
|
||||||
dirDraw->GetCaps(&caps, 0);
|
dirDraw->GetCaps(&caps, 0);
|
||||||
return caps.dwVidMemFree;
|
return caps.dwVidMemFree;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxMovie *gxGraphics::openMovie(const string &file, int flags) {
|
gxMovie* gxGraphics::openMovie(const string& file, int flags)
|
||||||
|
{
|
||||||
/*IAMMultiMediaStream *iam_stream;
|
/*IAMMultiMediaStream *iam_stream;
|
||||||
|
|
||||||
if (CoCreateInstance(
|
if (CoCreateInstance(
|
||||||
@@ -181,63 +204,77 @@ gxMovie *gxGraphics::openMovie(const string &file, int flags) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxMovie *gxGraphics::verifyMovie(gxMovie *m) {
|
gxMovie* gxGraphics::verifyMovie(gxMovie* m)
|
||||||
|
{
|
||||||
return movie_set.count(m) ? m : 0;
|
return movie_set.count(m) ? m : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::closeMovie(gxMovie *m) {
|
void gxGraphics::closeMovie(gxMovie* m)
|
||||||
if (movie_set.erase(m)) delete 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;
|
IDirectDrawSurface7* s = ddUtil::createSurface(w, h, flags, this);
|
||||||
gxCanvas *c = new gxCanvas(this, s, flags);
|
if (!s)
|
||||||
|
return 0;
|
||||||
|
gxCanvas* c = new gxCanvas(this, s, flags);
|
||||||
canvas_set.insert(c);
|
canvas_set.insert(c);
|
||||||
c->cls();
|
c->cls();
|
||||||
return c;
|
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;
|
IDirectDrawSurface7* s = ddUtil::loadSurface(f, flags, this);
|
||||||
gxCanvas *c = new gxCanvas(this, s, flags);
|
if (!s)
|
||||||
|
return 0;
|
||||||
|
gxCanvas* c = new gxCanvas(this, s, flags);
|
||||||
canvas_set.insert(c);
|
canvas_set.insert(c);
|
||||||
return 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;
|
return canvas_set.count(c) || c == front_canvas || c == back_canvas ? c : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::freeCanvas(gxCanvas *c) {
|
void gxGraphics::freeCanvas(gxCanvas* c)
|
||||||
if (canvas_set.erase(c)) delete c;
|
{
|
||||||
|
if (canvas_set.erase(c))
|
||||||
|
delete c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxGraphics::getWidth()const {
|
int gxGraphics::getWidth() const
|
||||||
|
{
|
||||||
return front_canvas->getWidth();
|
return front_canvas->getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxGraphics::getHeight()const {
|
int gxGraphics::getHeight() const
|
||||||
|
{
|
||||||
return front_canvas->getHeight();
|
return front_canvas->getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxGraphics::getDepth()const {
|
int gxGraphics::getDepth() const
|
||||||
|
{
|
||||||
return front_canvas->getDepth();
|
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 bold = flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR;
|
||||||
int italic = flags & gxFont::FONT_ITALIC ? 1 : 0;
|
int italic = flags & gxFont::FONT_ITALIC ? 1 : 0;
|
||||||
int underline = flags & gxFont::FONT_UNDERLINE ? 1 : 0;
|
int underline = flags & gxFont::FONT_UNDERLINE ? 1 : 0;
|
||||||
int strikeout = 0;
|
int strikeout = 0;
|
||||||
|
|
||||||
string t;
|
string t;
|
||||||
int n = f.find('.');
|
int n = f.find('.');
|
||||||
if (n != string::npos) {
|
if (n != string::npos) {
|
||||||
t = fullfilename(f);
|
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));
|
t = filenamefile(f.substr(0, n));
|
||||||
} else {
|
} else {
|
||||||
t = f;
|
t = f;
|
||||||
@@ -248,11 +285,8 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|||||||
SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &smoothing, 0);
|
SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &smoothing, 0);
|
||||||
SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, 0, 0);
|
SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, 0, 0);
|
||||||
|
|
||||||
HFONT hfont = CreateFont(
|
HFONT hfont = CreateFont(height, 0, 0, 0, bold, italic, underline, strikeout, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
|
||||||
height, 0, 0, 0,
|
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, t.c_str());
|
||||||
bold, italic, underline, strikeout,
|
|
||||||
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
|
||||||
DEFAULT_PITCH | FF_DONTCARE, t.c_str());
|
|
||||||
|
|
||||||
if (!hfont) {
|
if (!hfont) {
|
||||||
//restore font smoothing
|
//restore font smoothing
|
||||||
@@ -260,10 +294,10 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC hdc = CreateCompatibleDC(0);
|
HDC hdc = CreateCompatibleDC(0);
|
||||||
HFONT pfont = (HFONT)SelectObject(hdc, hfont);
|
HFONT pfont = (HFONT)SelectObject(hdc, hfont);
|
||||||
|
|
||||||
TEXTMETRIC tm = { 0 };
|
TEXTMETRIC tm = {0};
|
||||||
if (!GetTextMetrics(hdc, &tm)) {
|
if (!GetTextMetrics(hdc, &tm)) {
|
||||||
SelectObject(hdc, pfont);
|
SelectObject(hdc, pfont);
|
||||||
DeleteDC(hdc);
|
DeleteDC(hdc);
|
||||||
@@ -273,16 +307,15 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|||||||
}
|
}
|
||||||
height = tm.tmHeight;
|
height = tm.tmHeight;
|
||||||
|
|
||||||
int first = tm.tmFirstChar, last = tm.tmLastChar;
|
int first = tm.tmFirstChar, last = tm.tmLastChar;
|
||||||
int sz = last - first + 1;
|
int sz = last - first + 1;
|
||||||
int *offs = new int[sz];
|
int* offs = new int[sz];
|
||||||
int *widths = new int[sz];
|
int* widths = new int[sz];
|
||||||
int *as = new int[sz];
|
int* as = new int[sz];
|
||||||
|
|
||||||
//calc size of canvas to hold font.
|
//calc size of canvas to hold font.
|
||||||
int x = 0, y = 0, max_x = 0;
|
int x = 0, y = 0, max_x = 0;
|
||||||
for (int k = 0; k < sz; ++k) {
|
for (int k = 0; k < sz; ++k) {
|
||||||
|
|
||||||
char t = k + first;
|
char t = k + first;
|
||||||
|
|
||||||
SIZE sz;
|
SIZE sz;
|
||||||
@@ -297,21 +330,27 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|||||||
as[k] = ceil(-abc.abcA);
|
as[k] = ceil(-abc.abcA);
|
||||||
w += as[k];
|
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()) {
|
||||||
offs[k] = (x << 16) | y;
|
x = 0;
|
||||||
|
y += height;
|
||||||
|
}
|
||||||
|
offs[k] = (x << 16) | y;
|
||||||
widths[k] = w;
|
widths[k] = w;
|
||||||
x += w; if (x > max_x) max_x = x;
|
x += w;
|
||||||
|
if (x > max_x)
|
||||||
|
max_x = x;
|
||||||
}
|
}
|
||||||
SelectObject(hdc, pfont);
|
SelectObject(hdc, pfont);
|
||||||
DeleteDC(hdc);
|
DeleteDC(hdc);
|
||||||
|
|
||||||
int cw = max_x, ch = y + height;
|
int cw = max_x, ch = y + height;
|
||||||
|
|
||||||
if (gxCanvas *c = createCanvas(cw, ch, 0)) {
|
if (gxCanvas* c = createCanvas(cw, ch, 0)) {
|
||||||
IDirectDrawSurface7 *surf = c->getSurface();
|
IDirectDrawSurface7* surf = c->getSurface();
|
||||||
|
|
||||||
HDC surf_hdc;
|
HDC surf_hdc;
|
||||||
if (surf->GetDC(&surf_hdc) >= 0) {
|
if (surf->GetDC(&surf_hdc) >= 0) {
|
||||||
@@ -321,9 +360,9 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|||||||
SetTextColor(surf_hdc, 0xffffff);
|
SetTextColor(surf_hdc, 0xffffff);
|
||||||
|
|
||||||
for (int k = 0; k < sz; ++k) {
|
for (int k = 0; k < sz; ++k) {
|
||||||
int x = (offs[k] >> 16) & 0xffff, y = offs[k] & 0xffff;
|
int x = (offs[k] >> 16) & 0xffff, y = offs[k] & 0xffff;
|
||||||
char t = k + first;
|
char t = k + first;
|
||||||
RECT rect = { x,y,x + widths[k],y + height };
|
RECT rect = {x, y, x + widths[k], y + height};
|
||||||
ExtTextOut(surf_hdc, x + as[k], y, ETO_CLIPPED, &rect, &t, 1, 0);
|
ExtTextOut(surf_hdc, x + as[k], y, ETO_CLIPPED, &rect, &t, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +372,8 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|||||||
delete[] as;
|
delete[] as;
|
||||||
|
|
||||||
c->backup();
|
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);
|
font_set.insert(font);
|
||||||
|
|
||||||
//restore font smoothing
|
//restore font smoothing
|
||||||
@@ -354,12 +394,15 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxFont *gxGraphics::verifyFont(gxFont *f) {
|
gxFont* gxGraphics::verifyFont(gxFont* f)
|
||||||
|
{
|
||||||
return font_set.count(f) ? f : 0;
|
return font_set.count(f) ? f : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::freeFont(gxFont *f) {
|
void gxGraphics::freeFont(gxFont* f)
|
||||||
if (font_set.erase(f)) delete f;
|
{
|
||||||
|
if (font_set.erase(f))
|
||||||
|
delete f;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
@@ -368,22 +411,27 @@ void gxGraphics::freeFont(gxFont *f) {
|
|||||||
|
|
||||||
static int maxDevType;
|
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;
|
gxGraphics* g = (gxGraphics*)context;
|
||||||
GUID guid = devDesc->deviceGUID;
|
int t = 0;
|
||||||
if (guid == IID_IDirect3DRGBDevice) t = 1;
|
GUID guid = devDesc->deviceGUID;
|
||||||
else if (guid == IID_IDirect3DHALDevice) t = 2;
|
if (guid == IID_IDirect3DRGBDevice)
|
||||||
else if (guid == IID_IDirect3DTnLHalDevice) t = 3;
|
t = 1;
|
||||||
|
else if (guid == IID_IDirect3DHALDevice)
|
||||||
|
t = 2;
|
||||||
|
else if (guid == IID_IDirect3DTnLHalDevice)
|
||||||
|
t = 3;
|
||||||
if (t > maxDevType) {
|
if (t > maxDevType) {
|
||||||
g->dir3dDevDesc = *devDesc;
|
g->dir3dDevDesc = *devDesc;
|
||||||
maxDevType = t;
|
maxDevType = t;
|
||||||
}
|
}
|
||||||
return D3DENUMRET_OK;
|
return D3DENUMRET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void *context) {
|
static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void* context)
|
||||||
gxGraphics *g = (gxGraphics*)context;
|
{
|
||||||
|
gxGraphics* g = (gxGraphics*)context;
|
||||||
if (format->dwZBufferBitDepth == g->primFmt.dwRGBBitCount) {
|
if (format->dwZBufferBitDepth == g->primFmt.dwRGBBitCount) {
|
||||||
g->zbuffFmt = *format;
|
g->zbuffFmt = *format;
|
||||||
return D3DENUMRET_CANCEL;
|
return D3DENUMRET_CANCEL;
|
||||||
@@ -398,24 +446,27 @@ static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void *context) {
|
|||||||
|
|
||||||
struct TexFmt {
|
struct TexFmt {
|
||||||
DDPIXELFORMAT fmt;
|
DDPIXELFORMAT fmt;
|
||||||
int bits, a_bits, rgb_bits;
|
int bits, a_bits, rgb_bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cntBits(int mask) {
|
static int cntBits(int mask)
|
||||||
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (int k = 0; k < 32; ++k) {
|
for (int k = 0; k < 32; ++k) {
|
||||||
if (mask & (1 << k)) ++n;
|
if (mask & (1 << k))
|
||||||
|
++n;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static vector<TexFmt> tex_fmts;
|
static vector<TexFmt> tex_fmts;
|
||||||
|
|
||||||
static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT *fmt, void *p) {
|
static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT* fmt, void* p)
|
||||||
|
{
|
||||||
TexFmt t;
|
TexFmt t;
|
||||||
t.fmt = *fmt;
|
t.fmt = *fmt;
|
||||||
t.bits = fmt->dwRGBBitCount;
|
t.bits = fmt->dwRGBBitCount;
|
||||||
t.a_bits = (fmt->dwFlags & DDPF_ALPHAPIXELS) ? cntBits(fmt->dwRGBAlphaBitMask) : 0;
|
t.a_bits = (fmt->dwFlags & DDPF_ALPHAPIXELS) ? cntBits(fmt->dwRGBAlphaBitMask) : 0;
|
||||||
t.rgb_bits = (fmt->dwFlags & DDPF_RGB) ? cntBits(fmt->dwRBitMask | fmt->dwGBitMask | fmt->dwBBitMask) : 0;
|
t.rgb_bits = (fmt->dwFlags & DDPF_RGB) ? cntBits(fmt->dwRBitMask | fmt->dwGBitMask | fmt->dwBBitMask) : 0;
|
||||||
|
|
||||||
tex_fmts.push_back(t);
|
tex_fmts.push_back(t);
|
||||||
@@ -423,7 +474,8 @@ static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT *fmt, void *p) {
|
|||||||
return D3DENUMRET_OK;
|
return D3DENUMRET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string itobin(int n) {
|
static string itobin(int n)
|
||||||
|
{
|
||||||
string t;
|
string t;
|
||||||
for (int k = 0; k < 32; n <<= 1, ++k) {
|
for (int k = 0; k < 32; n <<= 1, ++k) {
|
||||||
t += (n & 0x80000000) ? '1' : '0';
|
t += (n & 0x80000000) ? '1' : '0';
|
||||||
@@ -431,7 +483,8 @@ static string itobin(int n) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugPF(const DDPIXELFORMAT &pf) {
|
static void debugPF(const DDPIXELFORMAT& pf)
|
||||||
|
{
|
||||||
string t;
|
string t;
|
||||||
t = "Bits:" + itoa(pf.dwRGBBitCount);
|
t = "Bits:" + itoa(pf.dwRGBBitCount);
|
||||||
gx_runtime->debugLog(t.c_str());
|
gx_runtime->debugLog(t.c_str());
|
||||||
@@ -445,73 +498,108 @@ static void debugPF(const DDPIXELFORMAT &pf) {
|
|||||||
gx_runtime->debugLog(t.c_str());
|
gx_runtime->debugLog(t.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pickTexFmts(gxGraphics *g, int hi) {
|
static void pickTexFmts(gxGraphics* g, int hi)
|
||||||
|
{
|
||||||
//texRGBFmt.
|
//texRGBFmt.
|
||||||
{
|
{
|
||||||
int pick = -1, max = 0, bits;
|
int pick = -1, max = 0, bits;
|
||||||
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
||||||
for (int k = 0; k < tex_fmts.size(); ++k) {
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
||||||
const TexFmt &t = tex_fmts[k];
|
const TexFmt& t = tex_fmts[k];
|
||||||
if (t.bits > d || !t.rgb_bits || t.rgb_bits < max) continue;
|
if (t.bits > d || !t.rgb_bits || t.rgb_bits < max)
|
||||||
if (t.rgb_bits == max && t.bits >= bits) continue;
|
continue;
|
||||||
pick = k; max = t.rgb_bits; bits = t.bits;
|
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;
|
if (pick < 0)
|
||||||
else g->texRGBFmt[hi] = tex_fmts[pick].fmt;
|
g->texRGBFmt[hi] = g->primFmt;
|
||||||
|
else
|
||||||
|
g->texRGBFmt[hi] = tex_fmts[pick].fmt;
|
||||||
}
|
}
|
||||||
//texAlphaFmt
|
//texAlphaFmt
|
||||||
{
|
{
|
||||||
int pick = -1, max = 0, bits;
|
int pick = -1, max = 0, bits;
|
||||||
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
||||||
for (int k = 0; k < tex_fmts.size(); ++k) {
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
||||||
const TexFmt &t = tex_fmts[k];
|
const TexFmt& t = tex_fmts[k];
|
||||||
if (t.bits > d || !t.a_bits || t.a_bits < max) continue;
|
if (t.bits > d || !t.a_bits || t.a_bits < max)
|
||||||
if (t.a_bits == max && t.bits >= bits) continue;
|
continue;
|
||||||
pick = k; max = t.a_bits; bits = t.bits;
|
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;
|
if (pick < 0)
|
||||||
else g->texAlphaFmt[hi] = tex_fmts[pick].fmt;
|
g->texAlphaFmt[hi] = g->primFmt;
|
||||||
|
else
|
||||||
|
g->texAlphaFmt[hi] = tex_fmts[pick].fmt;
|
||||||
}
|
}
|
||||||
//texRGBAlphaFmt
|
//texRGBAlphaFmt
|
||||||
{
|
{
|
||||||
int pick = -1, a8rgb8 = -1, max = 0, bits;
|
int pick = -1, a8rgb8 = -1, max = 0, bits;
|
||||||
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
||||||
for (int k = 0; k < tex_fmts.size(); ++k) {
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
||||||
const TexFmt &t = tex_fmts[k];
|
const TexFmt& t = tex_fmts[k];
|
||||||
if (t.a_bits == 8 && t.bits == 16) { a8rgb8 = k; continue; }
|
if (t.a_bits == 8 && t.bits == 16) {
|
||||||
if (t.bits > d || !t.a_bits || !t.rgb_bits || t.a_bits < max) continue;
|
a8rgb8 = k;
|
||||||
if (t.a_bits == max && t.bits >= bits) continue;
|
continue;
|
||||||
pick = k; max = t.a_bits; bits = t.bits;
|
}
|
||||||
|
if (t.bits > d || !t.a_bits || !t.rgb_bits || t.a_bits < max)
|
||||||
|
continue;
|
||||||
|
if (t.a_bits == max && t.bits >= bits)
|
||||||
|
continue;
|
||||||
|
pick = k;
|
||||||
|
max = t.a_bits;
|
||||||
|
bits = t.bits;
|
||||||
}
|
}
|
||||||
if (!hi && pick >= 0) break;
|
if (!hi && pick >= 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (pick < 0) pick = a8rgb8;
|
if (pick < 0)
|
||||||
if (pick < 0) g->texRGBAlphaFmt[hi] = g->primFmt;
|
pick = a8rgb8;
|
||||||
else g->texRGBAlphaFmt[hi] = tex_fmts[pick].fmt;
|
if (pick < 0)
|
||||||
|
g->texRGBAlphaFmt[hi] = g->primFmt;
|
||||||
|
else
|
||||||
|
g->texRGBAlphaFmt[hi] = tex_fmts[pick].fmt;
|
||||||
}
|
}
|
||||||
//texRGBMaskFmt...
|
//texRGBMaskFmt...
|
||||||
{
|
{
|
||||||
int pick = -1, max = 0, bits;
|
int pick = -1, max = 0, bits;
|
||||||
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) {
|
||||||
for (int k = 0; k < tex_fmts.size(); ++k) {
|
for (int k = 0; k < tex_fmts.size(); ++k) {
|
||||||
const TexFmt &t = tex_fmts[k];
|
const TexFmt& t = tex_fmts[k];
|
||||||
if (!t.a_bits || !t.rgb_bits || t.rgb_bits < max) continue;
|
if (!t.a_bits || !t.rgb_bits || t.rgb_bits < max)
|
||||||
if (t.rgb_bits == max && t.bits >= bits) continue;
|
continue;
|
||||||
pick = k; max = t.rgb_bits; bits = t.bits;
|
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;
|
if (pick < 0)
|
||||||
else g->texRGBMaskFmt[hi] = tex_fmts[pick].fmt;
|
g->texRGBMaskFmt[hi] = g->primFmt;
|
||||||
|
else
|
||||||
|
g->texRGBMaskFmt[hi] = tex_fmts[pick].fmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gxScene *gxGraphics::createScene(int flags) {
|
gxScene* gxGraphics::createScene(int flags)
|
||||||
if (scene_set.size()) return 0;
|
{
|
||||||
|
if (scene_set.size())
|
||||||
|
return 0;
|
||||||
|
|
||||||
//get d3d
|
//get d3d
|
||||||
if (dirDraw->QueryInterface(IID_IDirect3D7, (void**)&dir3d) >= 0) {
|
if (dirDraw->QueryInterface(IID_IDirect3D7, (void**)&dir3d) >= 0) {
|
||||||
@@ -545,7 +633,7 @@ gxScene *gxGraphics::createScene(int flags) {
|
|||||||
string ts = "ZBuffer Bit Depth:" + itoa(zbuffFmt.dwZBufferBitDepth);
|
string ts = "ZBuffer Bit Depth:" + itoa(zbuffFmt.dwZBufferBitDepth);
|
||||||
gx_runtime->debugLog(ts.c_str());
|
gx_runtime->debugLog(ts.c_str());
|
||||||
#endif
|
#endif
|
||||||
gxScene *scene = new gxScene(this, back_canvas);
|
gxScene* scene = new gxScene(this, back_canvas);
|
||||||
scene_set.insert(scene);
|
scene_set.insert(scene);
|
||||||
|
|
||||||
dummy_mesh = createMesh(8, 12, 0);
|
dummy_mesh = createMesh(8, 12, 0);
|
||||||
@@ -565,25 +653,34 @@ gxScene *gxGraphics::createScene(int flags) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxScene *gxGraphics::verifyScene(gxScene *s) {
|
gxScene* gxGraphics::verifyScene(gxScene* s)
|
||||||
|
{
|
||||||
return scene_set.count(s) ? s : 0;
|
return scene_set.count(s) ? s : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::freeScene(gxScene *scene) {
|
void gxGraphics::freeScene(gxScene* scene)
|
||||||
if (!scene_set.erase(scene)) return;
|
{
|
||||||
|
if (!scene_set.erase(scene))
|
||||||
|
return;
|
||||||
dummy_mesh = 0;
|
dummy_mesh = 0;
|
||||||
while (mesh_set.size()) freeMesh(*mesh_set.begin());
|
while (mesh_set.size())
|
||||||
|
freeMesh(*mesh_set.begin());
|
||||||
back_canvas->releaseZBuffer();
|
back_canvas->releaseZBuffer();
|
||||||
if (dir3dDev) { dir3dDev->Release(); dir3dDev = 0; }
|
if (dir3dDev) {
|
||||||
if (dir3d) { dir3d->Release(); dir3d = 0; }
|
dir3dDev->Release();
|
||||||
|
dir3dDev = 0;
|
||||||
|
}
|
||||||
|
if (dir3d) {
|
||||||
|
dir3d->Release();
|
||||||
|
dir3d = 0;
|
||||||
|
}
|
||||||
delete scene;
|
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 =
|
static const int VTXFMT =
|
||||||
D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 |
|
D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1);
|
||||||
D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1);
|
|
||||||
|
|
||||||
int vbflags = 0;
|
int vbflags = 0;
|
||||||
|
|
||||||
@@ -592,20 +689,24 @@ gxMesh *gxGraphics::createMesh(int max_verts, int max_tris, int flags) {
|
|||||||
vbflags |= D3DVBCAPS_WRITEONLY;
|
vbflags |= D3DVBCAPS_WRITEONLY;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
D3DVERTEXBUFFERDESC desc = { sizeof(desc),vbflags,VTXFMT,max_verts };
|
D3DVERTEXBUFFERDESC desc = {sizeof(desc), vbflags, VTXFMT, max_verts};
|
||||||
|
|
||||||
IDirect3DVertexBuffer7 *buff;
|
IDirect3DVertexBuffer7* buff;
|
||||||
if (dir3d->CreateVertexBuffer(&desc, &buff, 0) < 0) return 0;
|
if (dir3d->CreateVertexBuffer(&desc, &buff, 0) < 0)
|
||||||
WORD *indices = new WORD[max_tris * 3];
|
return 0;
|
||||||
gxMesh *mesh = new gxMesh(this, buff, indices, max_verts, max_tris);
|
WORD* indices = new WORD[max_tris * 3];
|
||||||
|
gxMesh* mesh = new gxMesh(this, buff, indices, max_verts, max_tris);
|
||||||
mesh_set.insert(mesh);
|
mesh_set.insert(mesh);
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxMesh *gxGraphics::verifyMesh(gxMesh *m) {
|
gxMesh* gxGraphics::verifyMesh(gxMesh* m)
|
||||||
|
{
|
||||||
return mesh_set.count(m) ? m : 0;
|
return mesh_set.count(m) ? m : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxGraphics::freeMesh(gxMesh *mesh) {
|
void gxGraphics::freeMesh(gxMesh* mesh)
|
||||||
if (mesh_set.erase(mesh)) delete mesh;
|
{
|
||||||
|
if (mesh_set.erase(mesh))
|
||||||
|
delete mesh;
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -1,28 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "std.hpp"
|
|
||||||
#include "gxinput.hpp"
|
#include "gxinput.hpp"
|
||||||
#include "gxruntime.hpp"
|
#include "gxruntime.hpp"
|
||||||
|
#include "std.hpp"
|
||||||
|
|
||||||
static const int QUE_SIZE = 32;
|
static const int QUE_SIZE = 32;
|
||||||
|
|
||||||
class Device : public gxDevice {
|
class Device : public gxDevice {
|
||||||
public:
|
public:
|
||||||
bool acquired;
|
bool acquired;
|
||||||
gxInput *input;
|
gxInput* input;
|
||||||
LPDIRECTINPUTDEVICE8 device;
|
LPDIRECTINPUTDEVICE8 device;
|
||||||
|
|
||||||
Device(gxInput *i, LPDIRECTINPUTDEVICE8 d) :input(i), acquired(false), device(d) {
|
Device(gxInput* i, LPDIRECTINPUTDEVICE8 d) : input(i), acquired(false), device(d) {}
|
||||||
}
|
virtual ~Device()
|
||||||
virtual ~Device() {
|
{
|
||||||
device->Release();
|
device->Release();
|
||||||
//device->Release();
|
//device->Release();
|
||||||
}
|
}
|
||||||
bool acquire() {
|
bool acquire()
|
||||||
|
{
|
||||||
return device->Acquire() >= 0;
|
return device->Acquire() >= 0;
|
||||||
//return acquired=device->Acquire()>=0;
|
//return acquired=device->Acquire()>=0;
|
||||||
}
|
}
|
||||||
void unacquire() {
|
void unacquire()
|
||||||
|
{
|
||||||
device->Unacquire();
|
device->Unacquire();
|
||||||
//device->Unacquire();
|
//device->Unacquire();
|
||||||
acquired = false;
|
acquired = false;
|
||||||
@@ -30,44 +32,54 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Keyboard : public Device {
|
class Keyboard : public Device {
|
||||||
public:
|
public:
|
||||||
Keyboard(gxInput *i, LPDIRECTINPUTDEVICE8 d) :Device(i, d) {
|
Keyboard(gxInput* i, LPDIRECTINPUTDEVICE8 d) : Device(i, d) {}
|
||||||
}
|
void update()
|
||||||
void update() {
|
{
|
||||||
if (!acquired) {
|
if (!acquired) {
|
||||||
input->runtime->idle();
|
input->runtime->idle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int k, cnt = 32;
|
int k, cnt = 32;
|
||||||
DIDEVICEOBJECTDATA data[32], *curr;
|
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;
|
curr = data;
|
||||||
for (k = 0; k < cnt; ++curr, ++k) {
|
for (k = 0; k < cnt; ++curr, ++k) {
|
||||||
int n = curr->dwOfs; if (!n || n > 255) continue;
|
int n = curr->dwOfs;
|
||||||
if (curr->dwData & 0x80) downEvent(n);
|
if (!n || n > 255)
|
||||||
else upEvent(n);
|
continue;
|
||||||
|
if (curr->dwData & 0x80)
|
||||||
|
downEvent(n);
|
||||||
|
else
|
||||||
|
upEvent(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mouse : public Device {
|
class Mouse : public Device {
|
||||||
public:
|
public:
|
||||||
Mouse(gxInput *i, LPDIRECTINPUTDEVICE8 d) :Device(i, d) {
|
Mouse(gxInput* i, LPDIRECTINPUTDEVICE8 d) : Device(i, d) {}
|
||||||
}
|
void update()
|
||||||
void update() {
|
{
|
||||||
if (!acquired) {
|
if (!acquired) {
|
||||||
input->runtime->idle();
|
input->runtime->idle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DIMOUSESTATE state;
|
DIMOUSESTATE state;
|
||||||
if (device->GetDeviceState(sizeof(state), &state) < 0) return;
|
if (device->GetDeviceState(sizeof(state), &state) < 0)
|
||||||
if (gxGraphics *g = input->runtime->graphics) {
|
return;
|
||||||
|
if (gxGraphics* g = input->runtime->graphics) {
|
||||||
int mx = axis_states[0] + state.lX;
|
int mx = axis_states[0] + state.lX;
|
||||||
int my = axis_states[1] + state.lY;
|
int my = axis_states[1] + state.lY;
|
||||||
if (mx < 0) mx = 0;
|
if (mx < 0)
|
||||||
else if (mx >= g->getWidth()) mx = g->getWidth() - 1;
|
mx = 0;
|
||||||
if (my < 0) my = 0;
|
else if (mx >= g->getWidth())
|
||||||
else if (my >= g->getHeight()) my = g->getHeight() - 1;
|
mx = g->getWidth() - 1;
|
||||||
|
if (my < 0)
|
||||||
|
my = 0;
|
||||||
|
else if (my >= g->getHeight())
|
||||||
|
my = g->getHeight() - 1;
|
||||||
axis_states[0] = mx;
|
axis_states[0] = mx;
|
||||||
axis_states[1] = my;
|
axis_states[1] = my;
|
||||||
axis_states[2] += state.lZ;
|
axis_states[2] += state.lZ;
|
||||||
@@ -79,17 +91,18 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Joystick : public Device {
|
class Joystick : public Device {
|
||||||
public:
|
public:
|
||||||
int type, poll_time;
|
int type, poll_time;
|
||||||
int mins[12], maxs[12];
|
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) {
|
for (int k = 0; k < 12; ++k) {
|
||||||
//initialize joystick axis ranges (d'oh!)
|
//initialize joystick axis ranges (d'oh!)
|
||||||
DIPROPRANGE range;
|
DIPROPRANGE range;
|
||||||
range.diph.dwSize = sizeof(DIPROPRANGE);
|
range.diph.dwSize = sizeof(DIPROPRANGE);
|
||||||
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||||
range.diph.dwObj = k * 4 + 12;
|
range.diph.dwObj = k * 4 + 12;
|
||||||
range.diph.dwHow = DIPH_BYOFFSET;
|
range.diph.dwHow = DIPH_BYOFFSET;
|
||||||
if (d->GetProperty(DIPROP_RANGE, &range.diph) < 0) {
|
if (d->GetProperty(DIPROP_RANGE, &range.diph) < 0) {
|
||||||
mins[k] = 0;
|
mins[k] = 0;
|
||||||
maxs[k] = 65535;
|
maxs[k] = 65535;
|
||||||
@@ -99,17 +112,22 @@ public:
|
|||||||
maxs[k] = range.lMax - range.lMin;
|
maxs[k] = range.lMax - range.lMin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void update() {
|
void update()
|
||||||
|
{
|
||||||
unsigned tm = timeGetTime();
|
unsigned tm = timeGetTime();
|
||||||
if (tm - poll_time < 3) return;
|
if (tm - poll_time < 3)
|
||||||
|
return;
|
||||||
if (device->Poll() < 0) {
|
if (device->Poll() < 0) {
|
||||||
acquired = false;
|
acquired = false;
|
||||||
input->runtime->idle();
|
input->runtime->idle();
|
||||||
acquire(); if (device->Poll() < 0) return;
|
acquire();
|
||||||
|
if (device->Poll() < 0)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
poll_time = tm;
|
poll_time = tm;
|
||||||
DIJOYSTATE state;
|
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[0] = (state.lX - mins[0]) / (float)maxs[0] * 2 - 1;
|
||||||
axis_states[1] = (state.lY - mins[1]) / (float)maxs[1] * 2 - 1;
|
axis_states[1] = (state.lY - mins[1]) / (float)maxs[1] * 2 - 1;
|
||||||
axis_states[2] = (state.lZ - mins[2]) / (float)maxs[2] * 2 - 1;
|
axis_states[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[5] = (state.lRx - mins[3]) / (float)maxs[3] * 2 - 1;
|
||||||
axis_states[6] = (state.lRy - mins[4]) / (float)maxs[4] * 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;
|
axis_states[7] = (state.lRz - mins[5]) / (float)maxs[5] * 2 - 1;
|
||||||
if ((state.rgdwPOV[0] & 0xffff) == 0xffff) axis_states[8] = -1;
|
if ((state.rgdwPOV[0] & 0xffff) == 0xffff)
|
||||||
else axis_states[8] = floor(state.rgdwPOV[0] / 100.0f + .5f);
|
axis_states[8] = -1;
|
||||||
|
else
|
||||||
|
axis_states[8] = floor(state.rgdwPOV[0] / 100.0f + .5f);
|
||||||
|
|
||||||
for (int k = 0; k < 31; ++k) {
|
for (int k = 0; k < 31; ++k) {
|
||||||
setDownState(k + 1, state.rgbButtons[k] & 0x80 ? true : false);
|
setDownState(k + 1, state.rgbButtons[k] & 0x80 ? true : false);
|
||||||
@@ -127,23 +147,23 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Keyboard *keyboard;
|
static Keyboard* keyboard;
|
||||||
static Mouse *mouse;
|
static Mouse* mouse;
|
||||||
static vector<Joystick*> joysticks;
|
static vector<Joystick*> joysticks;
|
||||||
|
|
||||||
static Keyboard *createKeyboard(gxInput *input) {
|
static Keyboard* createKeyboard(gxInput* input)
|
||||||
|
{
|
||||||
LPDIRECTINPUTDEVICE8 dev;
|
LPDIRECTINPUTDEVICE8 dev;
|
||||||
if (input->dirInput->CreateDevice(GUID_SysKeyboard, &dev, NULL) >= 0) {
|
if (input->dirInput->CreateDevice(GUID_SysKeyboard, &dev, NULL) >= 0) {
|
||||||
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
|
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
|
||||||
|
|
||||||
if (dev->SetDataFormat(&c_dfDIKeyboard) >= 0) {
|
if (dev->SetDataFormat(&c_dfDIKeyboard) >= 0) {
|
||||||
DIPROPDWORD dword;
|
DIPROPDWORD dword;
|
||||||
memset(&dword, 0, sizeof(dword));
|
memset(&dword, 0, sizeof(dword));
|
||||||
dword.diph.dwSize = sizeof(DIPROPDWORD);
|
dword.diph.dwSize = sizeof(DIPROPDWORD);
|
||||||
dword.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
dword.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||||
dword.diph.dwObj = 0;
|
dword.diph.dwObj = 0;
|
||||||
dword.diph.dwHow = DIPH_DEVICE;
|
dword.diph.dwHow = DIPH_DEVICE;
|
||||||
dword.dwData = 32;
|
dword.dwData = 32;
|
||||||
if (dev->SetProperty(DIPROP_BUFFERSIZE, &dword.diph) >= 0) {
|
if (dev->SetProperty(DIPROP_BUFFERSIZE, &dword.diph) >= 0) {
|
||||||
return new Keyboard(input, dev);
|
return new Keyboard(input, dev);
|
||||||
} else {
|
} else {
|
||||||
@@ -164,11 +184,11 @@ static Keyboard *createKeyboard(gxInput *input) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Mouse *createMouse(gxInput *input) {
|
static Mouse* createMouse(gxInput* input)
|
||||||
|
{
|
||||||
LPDIRECTINPUTDEVICE8 dev;
|
LPDIRECTINPUTDEVICE8 dev;
|
||||||
if (input->dirInput->CreateDevice(GUID_SysMouse, &dev, 0) >= 0) {
|
if (input->dirInput->CreateDevice(GUID_SysMouse, &dev, 0) >= 0) {
|
||||||
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
|
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
|
||||||
|
|
||||||
if (dev->SetDataFormat(&c_dfDIMouse) >= 0) {
|
if (dev->SetDataFormat(&c_dfDIMouse) >= 0) {
|
||||||
return new Mouse(input, dev);
|
return new Mouse(input, dev);
|
||||||
} else {
|
} else {
|
||||||
@@ -186,7 +206,8 @@ static Mouse *createMouse(gxInput *input) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Joystick *createJoystick(gxInput *input, LPCDIDEVICEINSTANCE devinst) {
|
static Joystick* createJoystick(gxInput* input, LPCDIDEVICEINSTANCE devinst)
|
||||||
|
{
|
||||||
LPDIRECTINPUTDEVICE8 dev;
|
LPDIRECTINPUTDEVICE8 dev;
|
||||||
if (input->dirInput->CreateDevice(devinst->guidInstance, &dev, 0) >= 0) {
|
if (input->dirInput->CreateDevice(devinst->guidInstance, &dev, 0) >= 0) {
|
||||||
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
|
if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) {
|
||||||
@@ -200,25 +221,29 @@ static Joystick *createJoystick(gxInput *input, LPCDIDEVICEINSTANCE devinst) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL CALLBACK enumJoystick(LPCDIDEVICEINSTANCE devinst, LPVOID pvRef) {
|
static BOOL CALLBACK enumJoystick(LPCDIDEVICEINSTANCE devinst, LPVOID pvRef)
|
||||||
|
{
|
||||||
|
if ((devinst->dwDevType & 0xff) != DI8DEVCLASS_GAMECTRL)
|
||||||
|
return DIENUM_CONTINUE;
|
||||||
|
|
||||||
if ((devinst->dwDevType & 0xff) != DI8DEVCLASS_GAMECTRL) return DIENUM_CONTINUE;
|
if (Joystick* joy = createJoystick((gxInput*)pvRef, devinst)) {
|
||||||
|
|
||||||
if (Joystick *joy = createJoystick((gxInput*)pvRef, devinst)) {
|
|
||||||
joysticks.push_back(joy);
|
joysticks.push_back(joy);
|
||||||
}
|
}
|
||||||
return DIENUM_CONTINUE;
|
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);
|
keyboard = createKeyboard(this);
|
||||||
mouse = createMouse(this);
|
mouse = createMouse(this);
|
||||||
joysticks.clear();
|
joysticks.clear();
|
||||||
dirInput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumJoystick, this, DIEDFL_ATTACHEDONLY);
|
dirInput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumJoystick, this, DIEDFL_ATTACHEDONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
gxInput::~gxInput() {
|
gxInput::~gxInput()
|
||||||
for (int k = 0; k < joysticks.size(); ++k) delete joysticks[k];
|
{
|
||||||
|
for (int k = 0; k < joysticks.size(); ++k)
|
||||||
|
delete joysticks[k];
|
||||||
joysticks.clear();
|
joysticks.clear();
|
||||||
delete mouse;
|
delete mouse;
|
||||||
delete keyboard;
|
delete keyboard;
|
||||||
@@ -226,110 +251,154 @@ gxInput::~gxInput() {
|
|||||||
dirInput->Release();
|
dirInput->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::wm_keydown(int key) {
|
void gxInput::wm_keydown(int key)
|
||||||
if (keyboard) keyboard->downEvent(key);
|
{
|
||||||
|
if (keyboard)
|
||||||
|
keyboard->downEvent(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::wm_keyup(int key) {
|
void gxInput::wm_keyup(int key)
|
||||||
if (keyboard) keyboard->upEvent(key);
|
{
|
||||||
|
if (keyboard)
|
||||||
|
keyboard->upEvent(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::wm_mousedown(int key) {
|
void gxInput::wm_mousedown(int key)
|
||||||
if (mouse) mouse->downEvent(key);
|
{
|
||||||
|
if (mouse)
|
||||||
|
mouse->downEvent(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::wm_mouseup(int key) {
|
void gxInput::wm_mouseup(int key)
|
||||||
if (mouse) mouse->upEvent(key);
|
{
|
||||||
|
if (mouse)
|
||||||
|
mouse->upEvent(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::wm_mousemove(int x, int y) {
|
void gxInput::wm_mousemove(int x, int y)
|
||||||
|
{
|
||||||
if (mouse) {
|
if (mouse) {
|
||||||
mouse->axis_states[0] = x;
|
mouse->axis_states[0] = x;
|
||||||
mouse->axis_states[1] = y;
|
mouse->axis_states[1] = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::wm_mousewheel(int dz) {
|
void gxInput::wm_mousewheel(int dz)
|
||||||
if (mouse) mouse->axis_states[2] += dz;
|
{
|
||||||
|
if (mouse)
|
||||||
|
mouse->axis_states[2] += dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::reset() {
|
void gxInput::reset()
|
||||||
if (mouse) mouse->reset();
|
{
|
||||||
if (keyboard) keyboard->reset();
|
if (mouse)
|
||||||
for (int k = 0; k < joysticks.size(); ++k) joysticks[k]->reset();
|
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;
|
bool m_ok = true, k_ok = true;
|
||||||
if (mouse) m_ok = mouse->acquire();
|
if (mouse)
|
||||||
if (keyboard) k_ok = keyboard->acquire();
|
m_ok = mouse->acquire();
|
||||||
if (m_ok && k_ok) return true;
|
if (keyboard)
|
||||||
if (k_ok) keyboard->unacquire();
|
k_ok = keyboard->acquire();
|
||||||
if (m_ok) mouse->unacquire();
|
if (m_ok && k_ok)
|
||||||
|
return true;
|
||||||
|
if (k_ok)
|
||||||
|
keyboard->unacquire();
|
||||||
|
if (m_ok)
|
||||||
|
mouse->unacquire();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::unacquire() {
|
void gxInput::unacquire()
|
||||||
if (keyboard) keyboard->unacquire();
|
{
|
||||||
if (mouse) mouse->unacquire();
|
if (keyboard)
|
||||||
|
keyboard->unacquire();
|
||||||
|
if (mouse)
|
||||||
|
mouse->unacquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxInput::moveMouse(int x, int y) {
|
void gxInput::moveMouse(int x, int y)
|
||||||
if (!mouse) return;
|
{
|
||||||
|
if (!mouse)
|
||||||
|
return;
|
||||||
mouse->axis_states[0] = x;
|
mouse->axis_states[0] = x;
|
||||||
mouse->axis_states[1] = y;
|
mouse->axis_states[1] = y;
|
||||||
runtime->moveMouse(x, y);
|
runtime->moveMouse(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
gxDevice *gxInput::getMouse()const {
|
gxDevice* gxInput::getMouse() const
|
||||||
|
{
|
||||||
return mouse;
|
return mouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxDevice *gxInput::getKeyboard()const {
|
gxDevice* gxInput::getKeyboard() const
|
||||||
|
{
|
||||||
return keyboard;
|
return keyboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
gxDevice *gxInput::getJoystick(int n)const {
|
gxDevice* gxInput::getJoystick(int n) const
|
||||||
|
{
|
||||||
return n >= 0 && n < joysticks.size() ? joysticks[n] : 0;
|
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;
|
return n >= 0 && n < joysticks.size() ? joysticks[n]->type : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxInput::numJoysticks()const {
|
int gxInput::numJoysticks() const
|
||||||
|
{
|
||||||
return joysticks.size();
|
return joysticks.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int gxInput::toAscii(int scan)const {
|
int gxInput::toAscii(int scan) const
|
||||||
|
{
|
||||||
switch (scan) {
|
switch (scan) {
|
||||||
case DIK_INSERT:return ASC_INSERT;
|
case DIK_INSERT:
|
||||||
case DIK_DELETE:return ASC_DELETE;
|
return ASC_INSERT;
|
||||||
case DIK_HOME:return ASC_HOME;
|
case DIK_DELETE:
|
||||||
case DIK_END:return ASC_END;
|
return ASC_DELETE;
|
||||||
case DIK_PGUP:return ASC_PAGEUP;
|
case DIK_HOME:
|
||||||
case DIK_PGDN:return ASC_PAGEDOWN;
|
return ASC_HOME;
|
||||||
case DIK_UP:return ASC_UP;
|
case DIK_END:
|
||||||
case DIK_DOWN:return ASC_DOWN;
|
return ASC_END;
|
||||||
case DIK_LEFT:return ASC_LEFT;
|
case DIK_PGUP:
|
||||||
case DIK_RIGHT:return ASC_RIGHT;
|
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;
|
scan &= 0x7f;
|
||||||
int virt = MapVirtualKey(scan, 1);
|
int virt = MapVirtualKey(scan, 1);
|
||||||
if (!virt) return 0;
|
if (!virt)
|
||||||
|
return 0;
|
||||||
|
|
||||||
static unsigned char mat[256];
|
static unsigned char mat[256];
|
||||||
mat[VK_LSHIFT] = keyboard->keyDown(DIK_LSHIFT) ? 0x80 : 0;
|
mat[VK_LSHIFT] = keyboard->keyDown(DIK_LSHIFT) ? 0x80 : 0;
|
||||||
mat[VK_RSHIFT] = keyboard->keyDown(DIK_RSHIFT) ? 0x80 : 0;
|
mat[VK_RSHIFT] = keyboard->keyDown(DIK_RSHIFT) ? 0x80 : 0;
|
||||||
mat[VK_SHIFT] = mat[VK_LSHIFT] | mat[VK_RSHIFT];
|
mat[VK_SHIFT] = mat[VK_LSHIFT] | mat[VK_RSHIFT];
|
||||||
mat[VK_LCONTROL] = keyboard->keyDown(DIK_LCONTROL) ? 0x80 : 0;
|
mat[VK_LCONTROL] = keyboard->keyDown(DIK_LCONTROL) ? 0x80 : 0;
|
||||||
mat[VK_RCONTROL] = keyboard->keyDown(DIK_RCONTROL) ? 0x80 : 0;
|
mat[VK_RCONTROL] = keyboard->keyDown(DIK_RCONTROL) ? 0x80 : 0;
|
||||||
mat[VK_CONTROL] = mat[VK_LCONTROL] | mat[VK_RCONTROL];
|
mat[VK_CONTROL] = mat[VK_LCONTROL] | mat[VK_RCONTROL];
|
||||||
mat[VK_LMENU] = keyboard->keyDown(DIK_LMENU) ? 0x80 : 0;
|
mat[VK_LMENU] = keyboard->keyDown(DIK_LMENU) ? 0x80 : 0;
|
||||||
mat[VK_RMENU] = keyboard->keyDown(DIK_RMENU) ? 0x80 : 0;
|
mat[VK_RMENU] = keyboard->keyDown(DIK_RMENU) ? 0x80 : 0;
|
||||||
mat[VK_MENU] = mat[VK_LMENU] | mat[VK_RMENU];
|
mat[VK_MENU] = mat[VK_LMENU] | mat[VK_RMENU];
|
||||||
|
|
||||||
WORD ch;
|
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;
|
return ch & 255;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -1,17 +1,19 @@
|
|||||||
|
|
||||||
#include "std.hpp"
|
|
||||||
#include "gxmesh.hpp"
|
#include "gxmesh.hpp"
|
||||||
#include "gxgraphics.hpp"
|
#include "gxgraphics.hpp"
|
||||||
|
#include "std.hpp"
|
||||||
|
|
||||||
#include "gxruntime.hpp"
|
#include "gxruntime.hpp"
|
||||||
|
|
||||||
extern gxRuntime *gx_runtime;
|
extern gxRuntime* gx_runtime;
|
||||||
|
|
||||||
gxMesh::gxMesh( gxGraphics *g,IDirect3DVertexBuffer7 *vs,WORD *is,int max_vs,int max_ts ):
|
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){
|
: 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();
|
unlock();
|
||||||
|
|
||||||
vertex_buff->Release();
|
vertex_buff->Release();
|
||||||
@@ -19,8 +21,10 @@ gxMesh::~gxMesh(){
|
|||||||
delete[] tri_indices;
|
delete[] tri_indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gxMesh::lock( bool all ){
|
bool gxMesh::lock(bool all)
|
||||||
if( locked_verts ) return true;
|
{
|
||||||
|
if (locked_verts)
|
||||||
|
return true;
|
||||||
|
|
||||||
//V1.104
|
//V1.104
|
||||||
//int flags=all ? DDLOCK_DISCARDCONTENTS : 0;
|
//int flags=all ? DDLOCK_DISCARDCONTENTS : 0;
|
||||||
@@ -32,37 +36,40 @@ bool gxMesh::lock( bool all ){
|
|||||||
//if( vertex_buff->Lock( DDLOCK_WRITEONLY|DDLOCK_WAIT|flags,(void**)&locked_verts,0 )>=0 ){
|
//if( vertex_buff->Lock( DDLOCK_WRITEONLY|DDLOCK_WAIT|flags,(void**)&locked_verts,0 )>=0 ){
|
||||||
|
|
||||||
//V1.1.06...
|
//V1.1.06...
|
||||||
int flags=DDLOCK_WAIT|DDLOCK_WRITEONLY;
|
int flags = DDLOCK_WAIT | DDLOCK_WRITEONLY;
|
||||||
|
|
||||||
//XP or less?
|
//XP or less?
|
||||||
/*if( graphics->runtime->osinfo.dwMajorVersion<6 ){
|
/*if( graphics->runtime->osinfo.dwMajorVersion<6 ){
|
||||||
flags|=(all ? DDLOCK_DISCARDCONTENTS : DDLOCK_NOOVERWRITE);
|
flags|=(all ? DDLOCK_DISCARDCONTENTS : DDLOCK_NOOVERWRITE);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if( vertex_buff->Lock( flags,(void**)&locked_verts,0 )>=0 ){
|
if (vertex_buff->Lock(flags, (void**)&locked_verts, 0) >= 0) {
|
||||||
mesh_dirty=false;
|
mesh_dirty = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dxVertex *err_verts=new dxVertex[32768];
|
static dxVertex* err_verts = new dxVertex[32768];
|
||||||
|
|
||||||
locked_verts=err_verts;
|
locked_verts = err_verts;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxMesh::unlock(){
|
void gxMesh::unlock()
|
||||||
if( locked_verts ){
|
{
|
||||||
|
if (locked_verts) {
|
||||||
vertex_buff->Unlock();
|
vertex_buff->Unlock();
|
||||||
locked_verts=0;
|
locked_verts = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxMesh::backup(){
|
void gxMesh::backup()
|
||||||
|
{
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void gxMesh::restore(){
|
void gxMesh::restore()
|
||||||
mesh_dirty=true;
|
{
|
||||||
|
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();
|
unlock();
|
||||||
graphics->dir3dDev->DrawIndexedPrimitiveVB(
|
graphics->dir3dDev->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST, vertex_buff, first_vert, vert_cnt,
|
||||||
D3DPT_TRIANGLELIST,
|
tri_indices + first_tri * 3, tri_cnt * 3, 0);
|
||||||
vertex_buff,first_vert,vert_cnt,
|
|
||||||
tri_indices+first_tri*3,tri_cnt*3,0 );
|
|
||||||
}
|
}
|
||||||
@@ -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 "gxmovie.hpp"
|
||||||
#include "gxgraphics.hpp"
|
#include "gxgraphics.hpp"
|
||||||
|
#include "std.hpp"
|
||||||
|
|
||||||
gxMovie::gxMovie(gxGraphics *g, IMultiMediaStream *mm)
|
gxMovie::gxMovie(gxGraphics* g, IMultiMediaStream* mm) : gfx(g), mm_stream(mm), playing(true)
|
||||||
:gfx(g), mm_stream(mm), playing(true) {
|
{
|
||||||
|
|
||||||
////mm_stream->GetMediaStream( MSPID_PrimaryVideo,&vid_stream );
|
////mm_stream->GetMediaStream( MSPID_PrimaryVideo,&vid_stream );
|
||||||
////vid_stream->QueryInterface(IID_IDirectDrawMediaStream, (void**)&dd_stream);
|
////vid_stream->QueryInterface(IID_IDirectDrawMediaStream, (void**)&dd_stream);
|
||||||
|
|
||||||
@@ -23,7 +22,8 @@ gxMovie::gxMovie(gxGraphics *g, IMultiMediaStream *mm)
|
|||||||
//mm_stream->SetState(STREAMSTATE_RUN);
|
//mm_stream->SetState(STREAMSTATE_RUN);
|
||||||
}
|
}
|
||||||
|
|
||||||
gxMovie::~gxMovie() {
|
gxMovie::~gxMovie()
|
||||||
|
{
|
||||||
/*mm_stream->SetState(STREAMSTATE_STOP);
|
/*mm_stream->SetState(STREAMSTATE_STOP);
|
||||||
|
|
||||||
dd_sample->Release();
|
dd_sample->Release();
|
||||||
@@ -35,8 +35,10 @@ gxMovie::~gxMovie() {
|
|||||||
gfx->freeCanvas(canvas);*/
|
gfx->freeCanvas(canvas);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gxMovie::draw(gxCanvas *dest, int x, int y, int w, int h) {
|
bool gxMovie::draw(gxCanvas* dest, int x, int y, int w, int h)
|
||||||
if (!playing) return false;
|
{
|
||||||
|
if (!playing)
|
||||||
|
return false;
|
||||||
/*if (!dd_sample->Update(0, 0, 0, 0)) {
|
/*if (!dd_sample->Update(0, 0, 0, 0)) {
|
||||||
RECT dest_rect = { x,y,x + w,y + h };
|
RECT dest_rect = { x,y,x + w,y + h };
|
||||||
dest->getSurface()->Blt(&dest_rect, canvas->getSurface(), &src_rect, DDBLT_WAIT, 0);
|
dest->getSurface()->Blt(&dest_rect, canvas->getSurface(), &src_rect, DDBLT_WAIT, 0);
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
#ifndef GXMUSIC_H
|
||||||
|
#define GXMUSIC_H
|
||||||
|
|
||||||
|
class gxAudio;
|
||||||
|
|
||||||
|
struct FMUSIC_MODULE;
|
||||||
|
struct FSOUND_STREAM;
|
||||||
|
|
||||||
|
class gxMusic {
|
||||||
|
public:
|
||||||
|
gxAudio* audio;
|
||||||
|
|
||||||
|
gxMusic(gxAudio* audio, FMUSIC_MODULE* module, FSOUND_STREAM* stream);
|
||||||
|
~gxMusic();
|
||||||
|
|
||||||
|
private:
|
||||||
|
FMUSIC_MODULE* module;
|
||||||
|
FSOUND_STREAM* stream;
|
||||||
|
int stream_channel;
|
||||||
|
|
||||||
|
/***** GX INTERFACE *****/
|
||||||
|
public:
|
||||||
|
//modifiers
|
||||||
|
void play();
|
||||||
|
void stop();
|
||||||
|
void setPaused(bool paused);
|
||||||
|
void setVolume(float volume);
|
||||||
|
|
||||||
|
//accessors
|
||||||
|
bool isPlaying() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -4,17 +4,17 @@
|
|||||||
|
|
||||||
#include "stdutil.hpp"
|
#include "stdutil.hpp"
|
||||||
|
|
||||||
#pragma warning( disable:4786 )
|
#pragma warning(disable : 4786)
|
||||||
|
|
||||||
#define DIRECTSOUND_VERSION 0x700
|
#define DIRECTSOUND_VERSION 0x700
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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];
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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];
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user