From a16218e1d559b8203dcfdcca7811d38b2ae4b3b1 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Fri, 18 Jan 2019 17:03:37 +0100 Subject: [PATCH] runtime: CMake-ify gx --- Runtime/CMakeLists.txt | 5 +- Runtime/gfx/CMakeLists.txt | 113 ++ Runtime/gfx/asmcoder.cpp | 74 + Runtime/gfx/asmcoder.hpp | 528 +++++++ {gxruntime => Runtime/gfx}/ddutil.cpp | 410 ++--- Runtime/gfx/ddutil.hpp | 68 + .../gfx}/graphicsruntime.hpp | 2 +- Runtime/gfx/gxaudio.cpp | 323 ++++ Runtime/gfx/gxaudio.hpp | 45 + Runtime/gfx/gxcanvas.cpp | 995 ++++++++++++ Runtime/gfx/gxcanvas.hpp | 144 ++ {gxruntime => Runtime/gfx}/gxchannel.cpp | 5 +- Runtime/gfx/gxchannel.hpp | 20 + Runtime/gfx/gxdevice.cpp | 75 + Runtime/gfx/gxdevice.hpp | 38 + Runtime/gfx/gxdir.cpp | 23 + {gxruntime => Runtime/gfx}/gxdir.hpp | 12 +- Runtime/gfx/gxfilesystem.cpp | 106 ++ Runtime/gfx/gxfilesystem.hpp | 35 + Runtime/gfx/gxfont.cpp | 81 + Runtime/gfx/gxfont.hpp | 34 + {gxruntime => Runtime/gfx}/gxgraphics.cpp | 429 +++-- Runtime/gfx/gxgraphics.hpp | 126 ++ {gxruntime => Runtime/gfx}/gxinput.cpp | 287 ++-- Runtime/gfx/gxinput.hpp | 52 + Runtime/gfx/gxlight.cpp | 62 + Runtime/gfx/gxlight.hpp | 37 + {gxruntime => Runtime/gfx}/gxmesh.cpp | 54 +- Runtime/gfx/gxmesh.hpp | 85 + {gxruntime => Runtime/gfx}/gxmovie.cpp | 16 +- Runtime/gfx/gxmovie.hpp | 47 + Runtime/gfx/gxmusic.cpp | 61 + Runtime/gfx/gxmusic.hpp | 34 + Runtime/gfx/gxruntime.cpp | 1381 +++++++++++++++++ Runtime/gfx/gxruntime.hpp | 143 ++ Runtime/gfx/gxscene.cpp | 737 +++++++++ Runtime/gfx/gxscene.hpp | 146 ++ Runtime/gfx/gxsound.cpp | 58 + Runtime/gfx/gxsound.hpp | 38 + Runtime/gfx/gxtimer.cpp | 34 + Runtime/gfx/gxtimer.hpp | 27 + {gxruntime => Runtime/gfx}/std.cpp | 0 {gxruntime => Runtime/gfx}/std.hpp | 12 +- gxruntime/asmcoder.cpp | 74 - gxruntime/asmcoder.hpp | 330 ---- gxruntime/ddutil.hpp | 57 - gxruntime/gxaudio.cpp | 286 ---- gxruntime/gxaudio.hpp | 48 - gxruntime/gxcanvas.cpp | 739 --------- gxruntime/gxcanvas.hpp | 138 -- gxruntime/gxchannel.hpp | 21 - gxruntime/gxdevice.cpp | 62 - gxruntime/gxdevice.hpp | 40 - gxruntime/gxdir.cpp | 20 - gxruntime/gxfilesystem.cpp | 83 - gxruntime/gxfilesystem.hpp | 37 - gxruntime/gxfont.cpp | 71 - gxruntime/gxfont.hpp | 42 - gxruntime/gxgraphics.hpp | 126 -- gxruntime/gxinput.hpp | 46 - gxruntime/gxlight.cpp | 60 - gxruntime/gxlight.hpp | 33 - gxruntime/gxmesh.hpp | 73 - gxruntime/gxmovie.hpp | 40 - gxruntime/gxmusic.cpp | 57 - gxruntime/gxmusic.hpp | 34 - gxruntime/gxruntime.cpp | 1194 -------------- gxruntime/gxruntime.hpp | 143 -- gxruntime/gxscene.cpp | 619 -------- gxruntime/gxscene.hpp | 157 -- gxruntime/gxsound.cpp | 51 - gxruntime/gxsound.hpp | 38 - gxruntime/gxtimer.cpp | 31 - gxruntime/gxtimer.hpp | 27 - 74 files changed, 6493 insertions(+), 5286 deletions(-) create mode 100644 Runtime/gfx/CMakeLists.txt create mode 100644 Runtime/gfx/asmcoder.cpp create mode 100644 Runtime/gfx/asmcoder.hpp rename {gxruntime => Runtime/gfx}/ddutil.cpp (52%) create mode 100644 Runtime/gfx/ddutil.hpp rename {gxruntime => Runtime/gfx}/graphicsruntime.hpp (98%) create mode 100644 Runtime/gfx/gxaudio.cpp create mode 100644 Runtime/gfx/gxaudio.hpp create mode 100644 Runtime/gfx/gxcanvas.cpp create mode 100644 Runtime/gfx/gxcanvas.hpp rename {gxruntime => Runtime/gfx}/gxchannel.cpp (63%) create mode 100644 Runtime/gfx/gxchannel.hpp create mode 100644 Runtime/gfx/gxdevice.cpp create mode 100644 Runtime/gfx/gxdevice.hpp create mode 100644 Runtime/gfx/gxdir.cpp rename {gxruntime => Runtime/gfx}/gxdir.hpp (61%) create mode 100644 Runtime/gfx/gxfilesystem.cpp create mode 100644 Runtime/gfx/gxfilesystem.hpp create mode 100644 Runtime/gfx/gxfont.cpp create mode 100644 Runtime/gfx/gxfont.hpp rename {gxruntime => Runtime/gfx}/gxgraphics.cpp (54%) create mode 100644 Runtime/gfx/gxgraphics.hpp rename {gxruntime => Runtime/gfx}/gxinput.cpp (55%) create mode 100644 Runtime/gfx/gxinput.hpp create mode 100644 Runtime/gfx/gxlight.cpp create mode 100644 Runtime/gfx/gxlight.hpp rename {gxruntime => Runtime/gfx}/gxmesh.cpp (58%) create mode 100644 Runtime/gfx/gxmesh.hpp rename {gxruntime => Runtime/gfx}/gxmovie.cpp (84%) create mode 100644 Runtime/gfx/gxmovie.hpp create mode 100644 Runtime/gfx/gxmusic.cpp create mode 100644 Runtime/gfx/gxmusic.hpp create mode 100644 Runtime/gfx/gxruntime.cpp create mode 100644 Runtime/gfx/gxruntime.hpp create mode 100644 Runtime/gfx/gxscene.cpp create mode 100644 Runtime/gfx/gxscene.hpp create mode 100644 Runtime/gfx/gxsound.cpp create mode 100644 Runtime/gfx/gxsound.hpp create mode 100644 Runtime/gfx/gxtimer.cpp create mode 100644 Runtime/gfx/gxtimer.hpp rename {gxruntime => Runtime/gfx}/std.cpp (100%) rename {gxruntime => Runtime/gfx}/std.hpp (90%) delete mode 100644 gxruntime/asmcoder.cpp delete mode 100644 gxruntime/asmcoder.hpp delete mode 100644 gxruntime/ddutil.hpp delete mode 100644 gxruntime/gxaudio.cpp delete mode 100644 gxruntime/gxaudio.hpp delete mode 100644 gxruntime/gxcanvas.cpp delete mode 100644 gxruntime/gxcanvas.hpp delete mode 100644 gxruntime/gxchannel.hpp delete mode 100644 gxruntime/gxdevice.cpp delete mode 100644 gxruntime/gxdevice.hpp delete mode 100644 gxruntime/gxdir.cpp delete mode 100644 gxruntime/gxfilesystem.cpp delete mode 100644 gxruntime/gxfilesystem.hpp delete mode 100644 gxruntime/gxfont.cpp delete mode 100644 gxruntime/gxfont.hpp delete mode 100644 gxruntime/gxgraphics.hpp delete mode 100644 gxruntime/gxinput.hpp delete mode 100644 gxruntime/gxlight.cpp delete mode 100644 gxruntime/gxlight.hpp delete mode 100644 gxruntime/gxmesh.hpp delete mode 100644 gxruntime/gxmovie.hpp delete mode 100644 gxruntime/gxmusic.cpp delete mode 100644 gxruntime/gxmusic.hpp delete mode 100644 gxruntime/gxruntime.cpp delete mode 100644 gxruntime/gxruntime.hpp delete mode 100644 gxruntime/gxscene.cpp delete mode 100644 gxruntime/gxscene.hpp delete mode 100644 gxruntime/gxsound.cpp delete mode 100644 gxruntime/gxsound.hpp delete mode 100644 gxruntime/gxtimer.cpp delete mode 100644 gxruntime/gxtimer.hpp diff --git a/Runtime/CMakeLists.txt b/Runtime/CMakeLists.txt index c8a323c..1bdd4fa 100644 --- a/Runtime/CMakeLists.txt +++ b/Runtime/CMakeLists.txt @@ -1,6 +1,7 @@ project(runtime) add_subdirectory(lib) +add_subdirectory(gfx) add_subdirectory(blitz3d) add_library(${PROJECT_NAME} MODULE @@ -13,8 +14,10 @@ add_library(${PROJECT_NAME} MODULE target_link_libraries(${PROJECT_NAME} PRIVATE runtime_lib - gxruntime + runtime_gfx stdutil + ${fmod_LIBRARIES} + ${FreeImage_LIBRARIES} ) #target_include_directories(${PROJECT_NAME} diff --git a/Runtime/gfx/CMakeLists.txt b/Runtime/gfx/CMakeLists.txt new file mode 100644 index 0000000..67caeb8 --- /dev/null +++ b/Runtime/gfx/CMakeLists.txt @@ -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() diff --git a/Runtime/gfx/asmcoder.cpp b/Runtime/gfx/asmcoder.cpp new file mode 100644 index 0000000..dba8ea9 --- /dev/null +++ b/Runtime/gfx/asmcoder.cpp @@ -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 + +#include +#include + +#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 + } +} diff --git a/Runtime/gfx/asmcoder.hpp b/Runtime/gfx/asmcoder.hpp new file mode 100644 index 0000000..e987b1a --- /dev/null +++ b/Runtime/gfx/asmcoder.hpp @@ -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 diff --git a/gxruntime/ddutil.cpp b/Runtime/gfx/ddutil.cpp similarity index 52% rename from gxruntime/ddutil.cpp rename to Runtime/gfx/ddutil.cpp index f25948a..75ac9cd 100644 --- a/gxruntime/ddutil.cpp +++ b/Runtime/gfx/ddutil.cpp @@ -1,32 +1,37 @@ -#include "GraphicsRuntime.hpp" -#include "std.hpp" #include "ddutil.hpp" +#include "GraphicsRuntime.hpp" #include "asmcoder.hpp" #include "gxcanvas.hpp" #include "gxruntime.hpp" +#include "std.hpp" #define FREEIMAGE_LIB #include -extern gxRuntime *gx_runtime; -static AsmCoder asm_coder; +extern gxRuntime* gx_runtime; +static AsmCoder asm_coder; -static void calcShifts(unsigned mask, unsigned char *shr, unsigned char *shl) { +static void calcShifts(unsigned mask, unsigned char* shr, unsigned char* shl) +{ if (mask) { - for (*shl = 0; !(mask & 1); ++*shl, mask >>= 1) {} - for (*shr = 8; mask & 1; --*shr, mask >>= 1) {} - } - else *shr = *shl = 0; + for (*shl = 0; !(mask & 1); ++*shl, mask >>= 1) { + } + for (*shr = 8; mask & 1; --*shr, mask >>= 1) { + } + } else + *shr = *shl = 0; } -PixelFormat::~PixelFormat() { +PixelFormat::~PixelFormat() +{ if (plot_code) { VirtualFree(plot_code, 0, MEM_RELEASE); } } -void PixelFormat::setFormat(const DDPIXELFORMAT &pf) { +void PixelFormat::setFormat(const DDPIXELFORMAT& pf) +{ if (plot_code) { VirtualFree(plot_code, 0, MEM_RELEASE); } @@ -36,31 +41,40 @@ void PixelFormat::setFormat(const DDPIXELFORMAT &pf) { 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; - depth = pf.dwRGBBitCount; - amask = pf.dwRGBAlphaBitMask; - rmask = pf.dwRBitMask; - gmask = pf.dwGBitMask; - bmask = pf.dwBBitMask; - pitch = depth / 8; argbfill = 0; - if (!amask) argbfill |= 0xff000000; - if (!rmask) argbfill |= 0x00ff0000; - if (!gmask) argbfill |= 0x0000ff00; - if (!bmask) argbfill |= 0x000000ff; - calcShifts(amask, &ashr, &ashl); ashr += 24; - calcShifts(rmask, &rshr, &rshl); rshr += 16; - calcShifts(gmask, &gshr, &gshl); gshr += 8; + depth = pf.dwRGBBitCount; + amask = pf.dwRGBAlphaBitMask; + rmask = pf.dwRBitMask; + gmask = pf.dwGBitMask; + bmask = pf.dwBBitMask; + pitch = depth / 8; + argbfill = 0; + if (!amask) + argbfill |= 0xff000000; + if (!rmask) + argbfill |= 0x00ff0000; + if (!gmask) + argbfill |= 0x0000ff00; + if (!bmask) + argbfill |= 0x000000ff; + calcShifts(amask, &ashr, &ashl); + ashr += 24; + calcShifts(rmask, &rshr, &rshl); + rshr += 16; + calcShifts(gmask, &gshr, &gshl); + gshr += 8; calcShifts(bmask, &bshr, &bshl); - plot = (Plot)(void*)plot_code; + plot = (Plot)(void*)plot_code; point = (Point)(void*)point_code; asm_coder.CodePlot(plot_code, depth, amask, rmask, gmask, bmask); asm_coder.CodePoint(point_code, depth, amask, rmask, gmask, bmask); } -static void adjustTexSize(int *width, int *height, IDirect3DDevice7 *dir3dDev, bool forcePOT = true) { - D3DDEVICEDESC7 ddDesc = { 0 }; +static void adjustTexSize(int* width, int* height, IDirect3DDevice7* dir3dDev, bool forcePOT = true) +{ + D3DDEVICEDESC7 ddDesc = {0}; if (dir3dDev->GetCaps(&ddDesc) < 0) { *width = *height = 256; return; @@ -68,66 +82,82 @@ static void adjustTexSize(int *width, int *height, IDirect3DDevice7 *dir3dDev, b int w = *width, h = *height, min, max; - if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 || ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL || forcePOT) { + if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 + || ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL || forcePOT) { // DirectX Device doesn't support Non Power-Of-Two Textures. - for (w = 1; w < *width; w <<= 1) {} - for (h = 1; h < *height; h <<= 1) {} - } - else if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) { + for (w = 1; w < *width; w <<= 1) { + } + for (h = 1; h < *height; h <<= 1) { + } + } else if (ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) { // DirectX Device only supports Square Textures; - if (w > h) h = w; - else w = h; + if (w > h) + h = w; + else + w = h; } //check aspect ratio if (max = ddDesc.dwMaxTextureAspectRatio) { int asp = w > h ? w / h : h / w; if (asp > max) { - if (w > h) h = w / max; - else w = h / max; + if (w > h) + h = w / max; + else + w = h / max; } } //clamp size - if ((min = ddDesc.dwMinTextureWidth) && w < min) w = min; - if ((min = ddDesc.dwMinTextureHeight) && h < min) h = min; - if ((max = ddDesc.dwMaxTextureWidth) && w > max) w = max; - if ((max = ddDesc.dwMaxTextureHeight) && h > max) h = max; + if ((min = ddDesc.dwMinTextureWidth) && w < min) + w = min; + if ((min = ddDesc.dwMinTextureHeight) && h < min) + h = min; + if ((max = ddDesc.dwMaxTextureWidth) && w > max) + w = max; + if ((max = ddDesc.dwMaxTextureHeight) && h > max) + h = max; - *width = w; *height = h; + *width = w; + *height = h; } -static IDirectDrawSurface7 *createSurface(int width, int height, int pitch, void *bits, IDirectDraw7 *dirDraw) { - DDSURFACEDESC2 desc = { sizeof(desc) }; - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_CAPS; - desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - desc.dwWidth = width; desc.dwHeight = height; - desc.lPitch = pitch; desc.lpSurface = bits; +static IDirectDrawSurface7* createSurface(int width, int height, int pitch, void* bits, IDirectDraw7* dirDraw) +{ + DDSURFACEDESC2 desc = {sizeof(desc)}; + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_CAPS; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + desc.dwWidth = width; + desc.dwHeight = height; + desc.lPitch = pitch; + desc.lpSurface = bits; desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); - desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; - desc.ddpfPixelFormat.dwRGBBitCount = 32; - desc.ddpfPixelFormat.dwRBitMask = 0xff0000; - desc.ddpfPixelFormat.dwGBitMask = 0x00ff00; - desc.ddpfPixelFormat.dwBBitMask = 0x0000ff; + desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + desc.ddpfPixelFormat.dwRGBBitCount = 32; + desc.ddpfPixelFormat.dwRBitMask = 0xff0000; + desc.ddpfPixelFormat.dwGBitMask = 0x00ff00; + desc.ddpfPixelFormat.dwBBitMask = 0x0000ff; desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000; - IDirectDrawSurface7 *surf; - if (dirDraw->CreateSurface(&desc, &surf, 0) >= 0) return surf; + IDirectDrawSurface7* surf; + if (dirDraw->CreateSurface(&desc, &surf, 0) >= 0) + return surf; return 0; } -static void buildMask(IDirectDrawSurface7 *surf) { - DDSURFACEDESC2 desc = { sizeof(desc) }; +static void buildMask(IDirectDrawSurface7* surf) +{ + DDSURFACEDESC2 desc = {sizeof(desc)}; surf->Lock(0, &desc, DDLOCK_WAIT, 0); - unsigned char *surf_p = (unsigned char*)desc.lpSurface; - PixelFormat fmt(desc.ddpfPixelFormat); + unsigned char* surf_p = (unsigned char*)desc.lpSurface; + PixelFormat fmt(desc.ddpfPixelFormat); 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) { unsigned argb = fmt.getPixel(p); - unsigned rgb = argb & 0xffffff; - unsigned a = rgb ? 0xff000000 : 0; + unsigned rgb = argb & 0xffffff; + unsigned a = rgb ? 0xff000000 : 0; fmt.setPixel(p, a | rgb); p += fmt.getPitch(); } @@ -136,20 +166,21 @@ static void buildMask(IDirectDrawSurface7 *surf) { surf->Unlock(0); } -static void buildAlpha(IDirectDrawSurface7 *surf, bool whiten) { - - DDSURFACEDESC2 desc = { sizeof(desc) }; +static void buildAlpha(IDirectDrawSurface7* surf, bool whiten) +{ + DDSURFACEDESC2 desc = {sizeof(desc)}; surf->Lock(0, &desc, DDLOCK_WAIT, 0); - unsigned char *surf_p = (unsigned char*)desc.lpSurface; - PixelFormat fmt(desc.ddpfPixelFormat); + unsigned char* surf_p = (unsigned char*)desc.lpSurface; + PixelFormat fmt(desc.ddpfPixelFormat); 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) { - unsigned argb = fmt.getPixel(p); + unsigned argb = fmt.getPixel(p); unsigned alpha = (((argb >> 16) & 0xff) + ((argb >> 8) & 0xff) + (argb & 0xff)) / 3; - argb = (alpha << 24) | (argb & 0xffffff); - if (whiten) argb |= 0xffffff; + argb = (alpha << 24) | (argb & 0xffffff); + if (whiten) + argb |= 0xffffff; fmt.setPixel(p, argb); p += fmt.getPitch(); } @@ -158,74 +189,68 @@ static void buildAlpha(IDirectDrawSurface7 *surf, bool whiten) { surf->Unlock(0); } -void ddUtil::buildMipMaps(IDirectDrawSurface7 *surf) { - - DDSURFACEDESC2 desc = { sizeof(desc) }; +void ddUtil::buildMipMaps(IDirectDrawSurface7* surf) +{ + DDSURFACEDESC2 desc = {sizeof(desc)}; surf->GetSurfaceDesc(&desc); - if (!(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) return; - if (!(desc.ddpfPixelFormat.dwFlags & DDPF_RGB)) return; + if (!(desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) + return; + if (!(desc.ddpfPixelFormat.dwFlags & DDPF_RGB)) + return; - DDSCAPS2 caps = { 0 }; - caps.dwCaps = DDSCAPS_TEXTURE; - caps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; + DDSCAPS2 caps = {0}; + caps.dwCaps = DDSCAPS_TEXTURE; + caps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; IDirectDrawSurface7 *src = surf, *dest; while (src->GetAttachedSurface(&caps, &dest) >= 0) { + DDSURFACEDESC2 src_desc = {sizeof(src_desc)}; + if (src->Lock(0, &src_desc, DDLOCK_WAIT, 0) < 0) + abort(); + unsigned char* src_p = (unsigned char*)src_desc.lpSurface; + PixelFormat src_fmt(src_desc.ddpfPixelFormat); - DDSURFACEDESC2 src_desc = { sizeof(src_desc) }; - if (src->Lock(0, &src_desc, DDLOCK_WAIT, 0) < 0) abort(); - unsigned char *src_p = (unsigned char*)src_desc.lpSurface; - PixelFormat src_fmt(src_desc.ddpfPixelFormat); - - DDSURFACEDESC2 dest_desc = { sizeof(dest_desc) }; - if (dest->Lock(0, &dest_desc, DDLOCK_WAIT, 0) < 0) abort(); - unsigned char *dest_p = (unsigned char *)dest_desc.lpSurface; - PixelFormat dest_fmt(dest_desc.ddpfPixelFormat); + DDSURFACEDESC2 dest_desc = {sizeof(dest_desc)}; + if (dest->Lock(0, &dest_desc, DDLOCK_WAIT, 0) < 0) + abort(); + unsigned char* dest_p = (unsigned char*)dest_desc.lpSurface; + PixelFormat dest_fmt(dest_desc.ddpfPixelFormat); if (src_desc.dwWidth == 1) { for (DWORD y = 0; y < dest_desc.dwHeight; ++y) { - unsigned p1 = src_fmt.getPixel(src_p); - unsigned p2 = src_fmt.getPixel(src_p + src_desc.lPitch); - unsigned argb = - ((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1); - argb += (( - (p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101; + unsigned p1 = src_fmt.getPixel(src_p); + unsigned p2 = src_fmt.getPixel(src_p + src_desc.lPitch); + unsigned argb = ((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1); + argb += (((p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101; dest_fmt.setPixel(dest_p, argb); src_p += src_desc.lPitch * 2; dest_p += dest_desc.lPitch; } - } - else if (src_desc.dwHeight == 1) { + } else if (src_desc.dwHeight == 1) { for (DWORD x = 0; x < dest_desc.dwWidth; ++x) { - unsigned p1 = src_fmt.getPixel(src_p); - unsigned p2 = src_fmt.getPixel(src_p + src_fmt.getPitch()); - unsigned argb = - ((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1); - argb += (( - (p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101; + unsigned p1 = src_fmt.getPixel(src_p); + unsigned p2 = src_fmt.getPixel(src_p + src_fmt.getPitch()); + unsigned argb = ((p1 & 0xfefefefe) >> 1) + ((p2 & 0xfefefefe) >> 1); + argb += (((p1 & 0x01010101) + (p2 & 0x01010101)) >> 1) & 0x01010101; dest_fmt.setPixel(dest_p, argb); src_p += src_fmt.getPitch() * 2; dest_p += dest_fmt.getPitch(); } - } - else { + } else { for (DWORD y = 0; y < dest_desc.dwHeight; ++y) { - unsigned char *src_t = src_p; - unsigned char *dest_t = dest_p; + unsigned char* src_t = src_p; + unsigned char* dest_t = dest_p; for (DWORD x = 0; x < dest_desc.dwWidth; ++x) { - unsigned p1 = src_fmt.getPixel(src_t); unsigned p2 = src_fmt.getPixel(src_t + src_fmt.getPitch()); unsigned p3 = src_fmt.getPixel(src_t + src_desc.lPitch + src_fmt.getPitch()); unsigned p4 = src_fmt.getPixel(src_t + src_desc.lPitch); - unsigned argb = - ((p1 & 0xfcfcfcfc) >> 2) + ((p2 & 0xfcfcfcfc) >> 2) + - ((p3 & 0xfcfcfcfc) >> 2) + ((p4 & 0xfcfcfcfc) >> 2); - argb += (( - (p1 & 0x03030303) + (p2 & 0x03030303) + - (p3 & 0x03030303) + (p4 & 0x03030303)) >> 2) & 0x03030303; + unsigned argb = ((p1 & 0xfcfcfcfc) >> 2) + ((p2 & 0xfcfcfcfc) >> 2) + ((p3 & 0xfcfcfcfc) >> 2) + + ((p4 & 0xfcfcfcfc) >> 2); + argb += (((p1 & 0x03030303) + (p2 & 0x03030303) + (p3 & 0x03030303) + (p4 & 0x03030303)) >> 2) + & 0x03030303; dest_fmt.setPixel(dest_t, argb); src_t += src_fmt.getPitch() * 2; @@ -242,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) { - - DDSURFACEDESC2 src_desc = { sizeof(src_desc) }; +void ddUtil::copy(IDirectDrawSurface7* dest, int dx, int dy, int dw, int dh, IDirectDrawSurface7* src, int sx, int sy, + int sw, int sh) +{ + DDSURFACEDESC2 src_desc = {sizeof(src_desc)}; src->Lock(0, &src_desc, DDLOCK_WAIT, 0); - PixelFormat src_fmt(src_desc.ddpfPixelFormat); - unsigned char *src_p = (unsigned char*)src_desc.lpSurface; - src_p += src_desc.lPitch*sy + src_fmt.getPitch()*sx; + PixelFormat src_fmt(src_desc.ddpfPixelFormat); + unsigned char* src_p = (unsigned char*)src_desc.lpSurface; + src_p += src_desc.lPitch * sy + src_fmt.getPitch() * sx; - DDSURFACEDESC2 dest_desc = { sizeof(dest_desc) }; + DDSURFACEDESC2 dest_desc = {sizeof(dest_desc)}; dest->Lock(0, &dest_desc, DDLOCK_WAIT, 0); - PixelFormat dest_fmt(dest_desc.ddpfPixelFormat); - unsigned char *dest_p = (unsigned char *)dest_desc.lpSurface; - dest_p += dest_desc.lPitch*dy + dest_fmt.getPitch()*dx; + PixelFormat dest_fmt(dest_desc.ddpfPixelFormat); + unsigned char* dest_p = (unsigned char*)dest_desc.lpSurface; + dest_p += dest_desc.lPitch * dy + dest_fmt.getPitch() * dx; for (int y = 0; y < dh; ++y) { - unsigned char *dest = dest_p; - unsigned char *src = src_p + src_desc.lPitch*(y*sh / dh); + unsigned char* dest = dest_p; + unsigned char* src = src_p + src_desc.lPitch * (y * sh / dh); for (int x = 0; x < dw; ++x) { - dest_fmt.setPixel(dest, src_fmt.getPixel(src + src_fmt.getPitch()*(x*sw / dw))); + dest_fmt.setPixel(dest, src_fmt.getPixel(src + src_fmt.getPitch() * (x * sw / dw))); dest += dest_fmt.getPitch(); } 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); } -IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics *gfx) { - int hi = flags & gxCanvas::CANVAS_TEX_HICOLOR ? 1 : 0; - DDSURFACEDESC2 desc = { sizeof(desc) }; +IDirectDrawSurface7* ddUtil::createSurface(int w, int h, int flags, gxGraphics* gfx) +{ + int hi = flags & gxCanvas::CANVAS_TEX_HICOLOR ? 1 : 0; + DDSURFACEDESC2 desc = {sizeof(desc)}; // Texture Size desc.dwFlags = DDSD_CAPS; - if (w) { desc.dwWidth = w; desc.dwFlags |= DDSD_WIDTH; } - if (h) { desc.dwHeight = h; desc.dwFlags |= DDSD_HEIGHT; } + if (w) { + desc.dwWidth = w; + desc.dwFlags |= DDSD_WIDTH; + } + if (h) { + desc.dwHeight = h; + desc.dwFlags |= DDSD_HEIGHT; + } // Format if (flags & gxCanvas::CANVAS_TEXTURE) { @@ -289,25 +322,20 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics * desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY; if (flags & gxCanvas::CANVAS_TEXTURE) { desc.ddpfPixelFormat = gfx->primFmt; - } - else { + } else { desc.ddpfPixelFormat = gfx->texRGBAlphaFmt[hi]; } - } - else { + } else { if (flags & gxCanvas::CANVAS_TEX_MASK) { desc.dwFlags |= DDSD_PIXELFORMAT; desc.ddpfPixelFormat = gfx->texRGBMaskFmt[hi]; - } - else if (flags & gxCanvas::CANVAS_TEX_RGB) { + } else if (flags & gxCanvas::CANVAS_TEX_RGB) { desc.dwFlags |= DDSD_PIXELFORMAT; - desc.ddpfPixelFormat = (flags&gxCanvas::CANVAS_TEX_ALPHA) ? gfx->texRGBAlphaFmt[hi] : gfx->texRGBFmt[hi]; - } - else if (flags & gxCanvas::CANVAS_TEX_ALPHA) { + desc.ddpfPixelFormat = (flags & gxCanvas::CANVAS_TEX_ALPHA) ? gfx->texRGBAlphaFmt[hi] : gfx->texRGBFmt[hi]; + } else if (flags & gxCanvas::CANVAS_TEX_ALPHA) { desc.dwFlags |= DDSD_PIXELFORMAT; desc.ddpfPixelFormat = gfx->texAlphaFmt[hi]; - } - else if (flags & gxCanvas::CANVAS_TEXTURE) { + } else if (flags & gxCanvas::CANVAS_TEXTURE) { desc.dwFlags |= DDSD_PIXELFORMAT; 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; } adjustTexSize((int*)&desc.dwWidth, (int*)&desc.dwHeight, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT))); - } - else { + } else { desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; if (flags & gxCanvas::CANVAS_HIGHCOLOR) { desc.dwFlags |= DDSD_PIXELFORMAT; desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); - desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; - desc.ddpfPixelFormat.dwRGBBitCount = 32; - desc.ddpfPixelFormat.dwRBitMask = 0xff0000; - desc.ddpfPixelFormat.dwGBitMask = 0x00ff00; - desc.ddpfPixelFormat.dwBBitMask = 0x0000ff; + desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS; + desc.ddpfPixelFormat.dwRGBBitCount = 32; + desc.ddpfPixelFormat.dwRBitMask = 0xff0000; + desc.ddpfPixelFormat.dwGBitMask = 0x00ff00; + desc.ddpfPixelFormat.dwBBitMask = 0x0000ff; desc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000; - } - else if (flags & gxCanvas::CANVAS_NONDISPLAY) { + } else if (flags & gxCanvas::CANVAS_NONDISPLAY) { desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; } } - IDirectDrawSurface7 *surf; + IDirectDrawSurface7* surf; if (gfx->dirDraw->CreateSurface(&desc, &surf, 0) >= 0) { return surf; } @@ -368,7 +394,8 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics * if (!(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) { //try again in system memory! desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - if (gfx->dirDraw->CreateSurface(&desc, &surf, 0) >= 0) return surf; + if (gfx->dirDraw->CreateSurface(&desc, &surf, 0) >= 0) + return surf; } } @@ -377,16 +404,18 @@ IDirectDrawSurface7 *ddUtil::createSurface(int w, int h, int flags, gxGraphics * //Tom Speed's DXTC loader // -IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) { - HRESULT hr; +IDirectDrawSurface7* loadDXTC(const char* filename, gxGraphics* gfx) +{ + HRESULT hr; DDSURFACEDESC2 ddsd; DDSURFACEDESC2 fileddsd; - char magicID[4]; - FILE *fp; + char magicID[4]; + FILE* fp; /* try to open the file */ fp = fopen(filename, "rb"); - if (!fp) return NULL; + if (!fp) + return NULL; /* valid DDS? */ fread(magicID, 1, 4, fp); @@ -432,8 +461,8 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) { /* Create the new DXTC surface using the DDSURFACEDESC2 we read in from the file */ - IDirectDrawSurface7 * newSurf = NULL; - hr = gfx->dirDraw->CreateSurface(&ddsd, &newSurf, NULL); + IDirectDrawSurface7* newSurf = NULL; + hr = gfx->dirDraw->CreateSurface(&ddsd, &newSurf, NULL); if (FAILED(hr)) { fclose(fp); return NULL; @@ -446,8 +475,8 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) { mipmapddsd.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP | DDSCAPS_COMPLEX; /* pointers used when iterating through mipmaps */ - IDirectDrawSurface7 *topDDS = NULL; - IDirectDrawSurface7 *nextDDS = NULL; + IDirectDrawSurface7* topDDS = NULL; + IDirectDrawSurface7* nextDDS = NULL; topDDS = newSurf; topDDS->AddRef(); @@ -476,7 +505,6 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) { } topDDS->Unlock(NULL); - /* Get next mipmap in chain, or exit the loop if there's no more */ hr = topDDS->GetAttachedSurface(&mipmapddsd, &nextDDS); if (FAILED(hr)) { @@ -493,38 +521,44 @@ IDirectDrawSurface7 *loadDXTC(const char* filename, gxGraphics *gfx) { return newSurf; } -IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGraphics *gfx) { - +IDirectDrawSurface7* ddUtil::loadSurface(const std::string& f, int flags, gxGraphics* gfx) +{ int i = f.find(".dds"); if (i != string::npos && i + 4 == f.size()) { //dds file! - IDirectDrawSurface7 *surf = loadDXTC(f.c_str(), gfx); + IDirectDrawSurface7* surf = loadDXTC(f.c_str(), gfx); return surf; } FreeImage_Initialise(); FREE_IMAGE_FORMAT fmt = FreeImage_GetFileType(f.c_str(), f.size()); if (fmt == FIF_UNKNOWN) { - int n = f.find("."); if (n == string::npos) return 0; + int n = f.find("."); + if (n == string::npos) + return 0; fmt = FreeImage_GetFileType(f.c_str()); - if (fmt == FIF_UNKNOWN) return 0; + if (fmt == FIF_UNKNOWN) + return 0; } - FIBITMAP *t_dib = FreeImage_Load(fmt, f.c_str(), 0); - if (!t_dib) return 0; + FIBITMAP* t_dib = FreeImage_Load(fmt, f.c_str(), 0); + if (!t_dib) + return 0; bool trans = FreeImage_GetBPP(t_dib) == 32 || FreeImage_IsTransparent(t_dib); - FIBITMAP *dib = FreeImage_ConvertTo32Bits(t_dib); + FIBITMAP* dib = FreeImage_ConvertTo32Bits(t_dib); - if (dib) FreeImage_Unload(t_dib); - else dib = t_dib; + if (dib) + FreeImage_Unload(t_dib); + else + dib = t_dib; - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - int pitch = FreeImage_GetPitch(dib); - void *bits = FreeImage_GetBits(dib); + int width = FreeImage_GetWidth(dib); + int height = FreeImage_GetHeight(dib); + int pitch = FreeImage_GetPitch(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) { FreeImage_Unload(dib); 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_MASK) { buildMask(src); - } - else if (!trans) { + } else if (!trans) { buildAlpha(src, (flags & gxCanvas::CANVAS_TEX_RGB) ? false : true); } - } - else { - unsigned char *p = (unsigned char *)bits; + } else { + unsigned char* p = (unsigned char*)bits; for (int k = 0; k < height; ++k) { - unsigned char *t = p + 3; + unsigned char* t = p + 3; for (int j = 0; j < width; ++j) { - *t = 0xff; t += 4; + *t = 0xff; + t += 4; } p += pitch; } } - IDirectDrawSurface7 *dest = createSurface(width, height, flags, gfx); + IDirectDrawSurface7* dest = createSurface(width, height, flags, gfx); if (!dest) { src->Release(); FreeImage_Unload(dib); @@ -557,7 +590,8 @@ IDirectDrawSurface7 *ddUtil::loadSurface(const std::string &f, int flags, gxGrap } int t_w = width, t_h = height; - if (flags & gxCanvas::CANVAS_TEXTURE) adjustTexSize(&t_w, &t_h, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT))); + if (flags & gxCanvas::CANVAS_TEXTURE) + adjustTexSize(&t_w, &t_h, gfx->dir3dDev, !(flags & (gxCanvas::CANVAS_TEX_NPOT))); copy(dest, 0, 0, t_w, t_h, src, 0, height - 1, width, -height); src->Release(); diff --git a/Runtime/gfx/ddutil.hpp b/Runtime/gfx/ddutil.hpp new file mode 100644 index 0000000..cd3eabb --- /dev/null +++ b/Runtime/gfx/ddutil.hpp @@ -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 \ No newline at end of file diff --git a/gxruntime/graphicsruntime.hpp b/Runtime/gfx/graphicsruntime.hpp similarity index 98% rename from gxruntime/graphicsruntime.hpp rename to Runtime/gfx/graphicsruntime.hpp index 5d60851..7a9355f 100644 --- a/gxruntime/graphicsruntime.hpp +++ b/Runtime/gfx/graphicsruntime.hpp @@ -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_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(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(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); diff --git a/Runtime/gfx/gxaudio.cpp b/Runtime/gfx/gxaudio.cpp new file mode 100644 index 0000000..1c13b8c --- /dev/null +++ b/Runtime/gfx/gxaudio.cpp @@ -0,0 +1,323 @@ + +#include "gxaudio.hpp" +#include +#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 sound_set; +static vector channels; +static map songs; +static CDChannel* cdChannel; + +static int next_chan; +static vector 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::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; +} diff --git a/Runtime/gfx/gxaudio.hpp b/Runtime/gfx/gxaudio.hpp new file mode 100644 index 0000000..2be9d85 --- /dev/null +++ b/Runtime/gfx/gxaudio.hpp @@ -0,0 +1,45 @@ + +#ifndef GXAUDIO_H +#define GXAUDIO_H + +#include + +#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 \ No newline at end of file diff --git a/Runtime/gfx/gxcanvas.cpp b/Runtime/gfx/gxcanvas.cpp new file mode 100644 index 0000000..4fc663b --- /dev/null +++ b/Runtime/gfx/gxcanvas.cpp @@ -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]; +} \ No newline at end of file diff --git a/Runtime/gfx/gxcanvas.hpp b/Runtime/gfx/gxcanvas.hpp new file mode 100644 index 0000000..aefe78e --- /dev/null +++ b/Runtime/gfx/gxcanvas.hpp @@ -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 \ No newline at end of file diff --git a/gxruntime/gxchannel.cpp b/Runtime/gfx/gxchannel.cpp similarity index 63% rename from gxruntime/gxchannel.cpp rename to Runtime/gfx/gxchannel.cpp index bb680ff..2bfc9dc 100644 --- a/gxruntime/gxchannel.cpp +++ b/Runtime/gfx/gxchannel.cpp @@ -1,6 +1,5 @@ -#include "std.hpp" #include "gxchannel.hpp" +#include "std.hpp" -gxChannel::~gxChannel(){ -} +gxChannel::~gxChannel() {} diff --git a/Runtime/gfx/gxchannel.hpp b/Runtime/gfx/gxchannel.hpp new file mode 100644 index 0000000..894dbf1 --- /dev/null +++ b/Runtime/gfx/gxchannel.hpp @@ -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 \ No newline at end of file diff --git a/Runtime/gfx/gxdevice.cpp b/Runtime/gfx/gxdevice.cpp new file mode 100644 index 0000000..e69625b --- /dev/null +++ b/Runtime/gfx/gxdevice.cpp @@ -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]; +} diff --git a/Runtime/gfx/gxdevice.hpp b/Runtime/gfx/gxdevice.hpp new file mode 100644 index 0000000..0586d56 --- /dev/null +++ b/Runtime/gfx/gxdevice.hpp @@ -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 \ No newline at end of file diff --git a/Runtime/gfx/gxdir.cpp b/Runtime/gfx/gxdir.cpp new file mode 100644 index 0000000..fb70d81 --- /dev/null +++ b/Runtime/gfx/gxdir.cpp @@ -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; +} \ No newline at end of file diff --git a/gxruntime/gxdir.hpp b/Runtime/gfx/gxdir.hpp similarity index 61% rename from gxruntime/gxdir.hpp rename to Runtime/gfx/gxdir.hpp index 7471f78..5c75187 100644 --- a/gxruntime/gxdir.hpp +++ b/Runtime/gfx/gxdir.hpp @@ -5,17 +5,17 @@ #include #include -class gxDir{ -public: - gxDir( HANDLE h,const WIN32_FIND_DATA &f ); +class gxDir { + public: + gxDir(HANDLE h, const WIN32_FIND_DATA& f); ~gxDir(); -private: - HANDLE handle; + private: + HANDLE handle; WIN32_FIND_DATA findData; /***** GX INTERFACE *****/ -public: + public: std::string getNextFile(); }; diff --git a/Runtime/gfx/gxfilesystem.cpp b/Runtime/gfx/gxfilesystem.cpp new file mode 100644 index 0000000..d10c8da --- /dev/null +++ b/Runtime/gfx/gxfilesystem.cpp @@ -0,0 +1,106 @@ + +#include "gxfilesystem.hpp" +#include "std.hpp" + +static set 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; +} diff --git a/Runtime/gfx/gxfilesystem.hpp b/Runtime/gfx/gxfilesystem.hpp new file mode 100644 index 0000000..1fc8edd --- /dev/null +++ b/Runtime/gfx/gxfilesystem.hpp @@ -0,0 +1,35 @@ + +#ifndef GXFILESYSTEM_H +#define GXFILESYSTEM_H + +#include + +#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 \ No newline at end of file diff --git a/Runtime/gfx/gxfont.cpp b/Runtime/gfx/gxfont.cpp new file mode 100644 index 0000000..df63380 --- /dev/null +++ b/Runtime/gfx/gxfont.cpp @@ -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; +} diff --git a/Runtime/gfx/gxfont.hpp b/Runtime/gfx/gxfont.hpp new file mode 100644 index 0000000..f19284a --- /dev/null +++ b/Runtime/gfx/gxfont.hpp @@ -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 \ No newline at end of file diff --git a/gxruntime/gxgraphics.cpp b/Runtime/gfx/gxgraphics.cpp similarity index 54% rename from gxruntime/gxgraphics.cpp rename to Runtime/gfx/gxgraphics.cpp index ba37cf4..a145c7e 100644 --- a/gxruntime/gxgraphics.cpp +++ b/Runtime/gfx/gxgraphics.cpp @@ -1,17 +1,17 @@ -#include "std.hpp" #include "gxgraphics.hpp" #include "gxruntime.hpp" +#include "std.hpp" -extern gxRuntime *gx_runtime; - -gxGraphics::gxGraphics(gxRuntime *rt, IDirectDraw7 *dd, IDirectDrawSurface7 *fs, IDirectDrawSurface7 *bs, bool d3d) : - runtime(rt), dirDraw(dd), dir3d(0), dir3dDev(0), def_font(0), gfx_lost(false), dummy_mesh(0) { +extern gxRuntime* gx_runtime; +gxGraphics::gxGraphics(gxRuntime* rt, IDirectDraw7* dd, IDirectDrawSurface7* fs, IDirectDrawSurface7* bs, bool d3d) + : runtime(rt), dirDraw(dd), dir3d(0), dir3dDev(0), def_font(0), gfx_lost(false), dummy_mesh(0) +{ dirDraw->QueryInterface(IID_IDirectDraw, (void**)&ds_dirDraw); front_canvas = new gxCanvas(this, fs, 0); - back_canvas = new gxCanvas(this, bs, 0); + back_canvas = new gxCanvas(this, bs, 0); front_canvas->cls(); back_canvas->cls(); @@ -29,23 +29,32 @@ gxGraphics::gxGraphics(gxRuntime *rt, IDirectDraw7 *dd, IDirectDrawSurface7 *fs, _gamma = 0; if (fs != bs) { if (fs->QueryInterface(IID_IDirectDrawGammaControl, (void**)&_gamma) >= 0) { - if (_gamma->GetGammaRamp(0, &_gammaRamp) < 0) _gamma = 0; + if (_gamma->GetGammaRamp(0, &_gammaRamp) < 0) + _gamma = 0; } } if (!_gamma) { - for (int k = 0; k < 256; ++k) _gammaRamp.red[k] = _gammaRamp.blue[k] = _gammaRamp.green[k] = k; + for (int k = 0; k < 256; ++k) + _gammaRamp.red[k] = _gammaRamp.blue[k] = _gammaRamp.green[k] = k; } } -gxGraphics::~gxGraphics() { - if (_gamma) _gamma->Release(); - while (scene_set.size()) freeScene(*scene_set.begin()); - while (movie_set.size()) closeMovie(*movie_set.begin()); - while (font_set.size()) freeFont(*font_set.begin()); - while (canvas_set.size()) freeCanvas(*canvas_set.begin()); +gxGraphics::~gxGraphics() +{ + if (_gamma) + _gamma->Release(); + while (scene_set.size()) + freeScene(*scene_set.begin()); + while (movie_set.size()) + closeMovie(*movie_set.begin()); + while (font_set.size()) + freeFont(*font_set.begin()); + while (canvas_set.size()) + freeCanvas(*canvas_set.begin()); set::iterator it; - for (it = font_res.begin(); it != font_res.end(); ++it) RemoveFontResource((*it).c_str()); + for (it = font_res.begin(); it != font_res.end(); ++it) + RemoveFontResource((*it).c_str()); font_res.clear(); delete back_canvas; @@ -57,36 +66,40 @@ gxGraphics::~gxGraphics() { dirDraw->Release(); } -void gxGraphics::setGamma(int r, int g, int b, float dr, float dg, float db) { - _gammaRamp.red[r & 255] = dr*257.0f; - _gammaRamp.green[g & 255] = dg*257.0f; - _gammaRamp.blue[b & 255] = db*257.0f; +void gxGraphics::setGamma(int r, int g, int b, float dr, float dg, float db) +{ + _gammaRamp.red[r & 255] = dr * 257.0f; + _gammaRamp.green[g & 255] = dg * 257.0f; + _gammaRamp.blue[b & 255] = db * 257.0f; } -void gxGraphics::updateGamma(bool calibrate) { - if (!_gamma) return; +void gxGraphics::updateGamma(bool calibrate) +{ + if (!_gamma) + return; _gamma->SetGammaRamp(calibrate ? DDSGR_CALIBRATE : 0, &_gammaRamp); } -void gxGraphics::getGamma(int r, int g, int b, float *dr, float *dg, float *db) { +void gxGraphics::getGamma(int r, int g, int b, float* dr, float* dg, float* db) +{ *dr = _gammaRamp.red[r & 255] / 257.0f; *dg = _gammaRamp.green[g & 255] / 257.0f; *db = _gammaRamp.blue[b & 255] / 257.0f; } -void gxGraphics::backup() { -} - -bool gxGraphics::restore() { +void gxGraphics::backup() {} +bool gxGraphics::restore() +{ while (dirDraw->TestCooperativeLevel() != DD_OK) { - - if (dirDraw->TestCooperativeLevel() == DDERR_WRONGMODE) return false; + if (dirDraw->TestCooperativeLevel() == DDERR_WRONGMODE) + return false; Sleep(100); } - if (back_canvas->getSurface()->IsLost() == DD_OK) return true; + if (back_canvas->getSurface()->IsLost() == DD_OK) + return true; dirDraw->RestoreAllSurfaces(); @@ -101,57 +114,67 @@ bool gxGraphics::restore() { for (mesh_it = mesh_set.begin(); mesh_it != mesh_set.end(); ++mesh_it) { (*mesh_it)->restore(); } - if (dir3d) dir3d->EvictManagedTextures(); + if (dir3d) + dir3d->EvictManagedTextures(); return true; } -gxCanvas *gxGraphics::getFrontCanvas()const { +gxCanvas* gxGraphics::getFrontCanvas() const +{ return front_canvas; } -gxCanvas *gxGraphics::getBackCanvas()const { +gxCanvas* gxGraphics::getBackCanvas() const +{ return back_canvas; } -gxFont *gxGraphics::getDefaultFont()const { +gxFont* gxGraphics::getDefaultFont() const +{ return def_font; } -void gxGraphics::vwait() { +void gxGraphics::vwait() +{ dirDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); } -void gxGraphics::flip(bool v) { +void gxGraphics::flip(bool v) +{ runtime->flip(v); } -void gxGraphics::copy(gxCanvas *dest, int dx, int dy, int dw, int dh, gxCanvas *src, int sx, int sy, int sw, int sh) { - RECT r = { dx,dy,dx + dw,dy + dh }; +void gxGraphics::copy(gxCanvas* dest, int dx, int dy, int dw, int dh, gxCanvas* src, int sx, int sy, int sw, int sh) +{ + RECT r = {dx, dy, dx + dw, dy + dh}; ddUtil::copy(dest->getSurface(), dx, dy, dw, dh, src->getSurface(), sx, sy, sw, sh); dest->damage(r); } -int gxGraphics::getScanLine()const { +int gxGraphics::getScanLine() const +{ DWORD t = 0; dirDraw->GetScanLine(&t); return t; } -int gxGraphics::getTotalVidmem()const { - DDCAPS caps = { sizeof(caps) }; +int gxGraphics::getTotalVidmem() const +{ + DDCAPS caps = {sizeof(caps)}; dirDraw->GetCaps(&caps, 0); return caps.dwVidMemTotal; } -int gxGraphics::getAvailVidmem()const { - DDCAPS caps = { sizeof(caps) }; +int gxGraphics::getAvailVidmem() const +{ + DDCAPS caps = {sizeof(caps)}; dirDraw->GetCaps(&caps, 0); return caps.dwVidMemFree; } -gxMovie *gxGraphics::openMovie(const string &file, int flags) { - +gxMovie* gxGraphics::openMovie(const string& file, int flags) +{ /*IAMMultiMediaStream *iam_stream; if (CoCreateInstance( @@ -181,63 +204,77 @@ gxMovie *gxGraphics::openMovie(const string &file, int flags) { return 0; } -gxMovie *gxGraphics::verifyMovie(gxMovie *m) { +gxMovie* gxGraphics::verifyMovie(gxMovie* m) +{ return movie_set.count(m) ? m : 0; } -void gxGraphics::closeMovie(gxMovie *m) { - if (movie_set.erase(m)) delete m; +void gxGraphics::closeMovie(gxMovie* m) +{ + if (movie_set.erase(m)) + delete m; } -gxCanvas *gxGraphics::createCanvas(int w, int h, int flags) { - IDirectDrawSurface7 *s = ddUtil::createSurface(w, h, flags, this); - if (!s) return 0; - gxCanvas *c = new gxCanvas(this, s, flags); +gxCanvas* gxGraphics::createCanvas(int w, int h, int flags) +{ + IDirectDrawSurface7* s = ddUtil::createSurface(w, h, flags, this); + if (!s) + return 0; + gxCanvas* c = new gxCanvas(this, s, flags); canvas_set.insert(c); c->cls(); return c; } -gxCanvas *gxGraphics::loadCanvas(const string &f, int flags) { - IDirectDrawSurface7 *s = ddUtil::loadSurface(f, flags, this); - if (!s) return 0; - gxCanvas *c = new gxCanvas(this, s, flags); +gxCanvas* gxGraphics::loadCanvas(const string& f, int flags) +{ + IDirectDrawSurface7* s = ddUtil::loadSurface(f, flags, this); + if (!s) + return 0; + gxCanvas* c = new gxCanvas(this, s, flags); canvas_set.insert(c); return c; } -gxCanvas *gxGraphics::verifyCanvas(gxCanvas *c) { +gxCanvas* gxGraphics::verifyCanvas(gxCanvas* c) +{ return canvas_set.count(c) || c == front_canvas || c == back_canvas ? c : 0; } -void gxGraphics::freeCanvas(gxCanvas *c) { - if (canvas_set.erase(c)) delete c; +void gxGraphics::freeCanvas(gxCanvas* c) +{ + if (canvas_set.erase(c)) + delete c; } -int gxGraphics::getWidth()const { +int gxGraphics::getWidth() const +{ return front_canvas->getWidth(); } -int gxGraphics::getHeight()const { +int gxGraphics::getHeight() const +{ return front_canvas->getHeight(); } -int gxGraphics::getDepth()const { +int gxGraphics::getDepth() const +{ return front_canvas->getDepth(); } -gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { - - int bold = flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR; - int italic = flags & gxFont::FONT_ITALIC ? 1 : 0; +gxFont* gxGraphics::loadFont(const string& f, int height, int flags) +{ + int bold = flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR; + int italic = flags & gxFont::FONT_ITALIC ? 1 : 0; int underline = flags & gxFont::FONT_UNDERLINE ? 1 : 0; int strikeout = 0; string t; - int n = f.find('.'); + int n = f.find('.'); if (n != string::npos) { t = fullfilename(f); - if (!font_res.count(t) && AddFontResource(t.c_str())) font_res.insert(t); + if (!font_res.count(t) && AddFontResource(t.c_str())) + font_res.insert(t); t = filenamefile(f.substr(0, n)); } else { t = f; @@ -248,11 +285,8 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &smoothing, 0); SystemParametersInfo(SPI_SETFONTSMOOTHING, FALSE, 0, 0); - HFONT hfont = CreateFont( - height, 0, 0, 0, - bold, italic, underline, strikeout, - ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, - DEFAULT_PITCH | FF_DONTCARE, t.c_str()); + HFONT hfont = CreateFont(height, 0, 0, 0, bold, italic, underline, strikeout, ANSI_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, t.c_str()); if (!hfont) { //restore font smoothing @@ -260,10 +294,10 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { return 0; } - HDC hdc = CreateCompatibleDC(0); + HDC hdc = CreateCompatibleDC(0); HFONT pfont = (HFONT)SelectObject(hdc, hfont); - TEXTMETRIC tm = { 0 }; + TEXTMETRIC tm = {0}; if (!GetTextMetrics(hdc, &tm)) { SelectObject(hdc, pfont); DeleteDC(hdc); @@ -273,16 +307,15 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { } height = tm.tmHeight; - int first = tm.tmFirstChar, last = tm.tmLastChar; - int sz = last - first + 1; - int *offs = new int[sz]; - int *widths = new int[sz]; - int *as = new int[sz]; + int first = tm.tmFirstChar, last = tm.tmLastChar; + int sz = last - first + 1; + int* offs = new int[sz]; + int* widths = new int[sz]; + int* as = new int[sz]; //calc size of canvas to hold font. int x = 0, y = 0, max_x = 0; for (int k = 0; k < sz; ++k) { - char t = k + first; SIZE sz; @@ -297,21 +330,27 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { as[k] = ceil(-abc.abcA); w += as[k]; } - if (abc.abcC < 0) w += (int)ceil(-abc.abcC); + if (abc.abcC < 0) + w += (int)ceil(-abc.abcC); } - if (x && x + w > getWidth()) { x = 0; y += height; } - offs[k] = (x << 16) | y; + if (x && x + w > getWidth()) { + x = 0; + y += height; + } + offs[k] = (x << 16) | y; widths[k] = w; - x += w; if (x > max_x) max_x = x; + x += w; + if (x > max_x) + max_x = x; } SelectObject(hdc, pfont); DeleteDC(hdc); int cw = max_x, ch = y + height; - if (gxCanvas *c = createCanvas(cw, ch, 0)) { - IDirectDrawSurface7 *surf = c->getSurface(); + if (gxCanvas* c = createCanvas(cw, ch, 0)) { + IDirectDrawSurface7* surf = c->getSurface(); HDC surf_hdc; if (surf->GetDC(&surf_hdc) >= 0) { @@ -321,9 +360,9 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { SetTextColor(surf_hdc, 0xffffff); for (int k = 0; k < sz; ++k) { - int x = (offs[k] >> 16) & 0xffff, y = offs[k] & 0xffff; - char t = k + first; - RECT rect = { x,y,x + widths[k],y + height }; + int x = (offs[k] >> 16) & 0xffff, y = offs[k] & 0xffff; + char t = k + first; + RECT rect = {x, y, x + widths[k], y + height}; ExtTextOut(surf_hdc, x + as[k], y, ETO_CLIPPED, &rect, &t, 1, 0); } @@ -333,7 +372,8 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { delete[] as; c->backup(); - gxFont *font = new gxFont(this, c, tm.tmMaxCharWidth, height, first, last + 1, tm.tmDefaultChar, offs, widths); + gxFont* font = + new gxFont(this, c, tm.tmMaxCharWidth, height, first, last + 1, tm.tmDefaultChar, offs, widths); font_set.insert(font); //restore font smoothing @@ -354,12 +394,15 @@ gxFont *gxGraphics::loadFont(const string &f, int height, int flags) { return 0; } -gxFont *gxGraphics::verifyFont(gxFont *f) { +gxFont* gxGraphics::verifyFont(gxFont* f) +{ return font_set.count(f) ? f : 0; } -void gxGraphics::freeFont(gxFont *f) { - if (font_set.erase(f)) delete f; +void gxGraphics::freeFont(gxFont* f) +{ + if (font_set.erase(f)) + delete f; } ////////////// @@ -368,22 +411,27 @@ void gxGraphics::freeFont(gxFont *f) { static int maxDevType; -static HRESULT CALLBACK enumDevice(char *desc, char *name, D3DDEVICEDESC7 *devDesc, void *context) { - gxGraphics *g = (gxGraphics*)context; - int t = 0; - GUID guid = devDesc->deviceGUID; - if (guid == IID_IDirect3DRGBDevice) t = 1; - else if (guid == IID_IDirect3DHALDevice) t = 2; - else if (guid == IID_IDirect3DTnLHalDevice) t = 3; +static HRESULT CALLBACK enumDevice(char* desc, char* name, D3DDEVICEDESC7* devDesc, void* context) +{ + gxGraphics* g = (gxGraphics*)context; + int t = 0; + GUID guid = devDesc->deviceGUID; + if (guid == IID_IDirect3DRGBDevice) + t = 1; + else if (guid == IID_IDirect3DHALDevice) + t = 2; + else if (guid == IID_IDirect3DTnLHalDevice) + t = 3; if (t > maxDevType) { g->dir3dDevDesc = *devDesc; - maxDevType = t; + maxDevType = t; } return D3DENUMRET_OK; } -static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void *context) { - gxGraphics *g = (gxGraphics*)context; +static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void* context) +{ + gxGraphics* g = (gxGraphics*)context; if (format->dwZBufferBitDepth == g->primFmt.dwRGBBitCount) { g->zbuffFmt = *format; return D3DENUMRET_CANCEL; @@ -398,24 +446,27 @@ static HRESULT CALLBACK enumZbuffFormat(LPDDPIXELFORMAT format, void *context) { struct TexFmt { 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; for (int k = 0; k < 32; ++k) { - if (mask & (1 << k)) ++n; + if (mask & (1 << k)) + ++n; } return n; } static vector tex_fmts; -static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT *fmt, void *p) { +static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT* fmt, void* p) +{ TexFmt t; - t.fmt = *fmt; - t.bits = fmt->dwRGBBitCount; - t.a_bits = (fmt->dwFlags & DDPF_ALPHAPIXELS) ? cntBits(fmt->dwRGBAlphaBitMask) : 0; + t.fmt = *fmt; + t.bits = fmt->dwRGBBitCount; + t.a_bits = (fmt->dwFlags & DDPF_ALPHAPIXELS) ? cntBits(fmt->dwRGBAlphaBitMask) : 0; t.rgb_bits = (fmt->dwFlags & DDPF_RGB) ? cntBits(fmt->dwRBitMask | fmt->dwGBitMask | fmt->dwBBitMask) : 0; tex_fmts.push_back(t); @@ -423,7 +474,8 @@ static HRESULT CALLBACK enumTextureFormat(DDPIXELFORMAT *fmt, void *p) { return D3DENUMRET_OK; } -static string itobin(int n) { +static string itobin(int n) +{ string t; for (int k = 0; k < 32; n <<= 1, ++k) { t += (n & 0x80000000) ? '1' : '0'; @@ -431,7 +483,8 @@ static string itobin(int n) { return t; } -static void debugPF(const DDPIXELFORMAT &pf) { +static void debugPF(const DDPIXELFORMAT& pf) +{ string t; t = "Bits:" + itoa(pf.dwRGBBitCount); gx_runtime->debugLog(t.c_str()); @@ -445,73 +498,108 @@ static void debugPF(const DDPIXELFORMAT &pf) { gx_runtime->debugLog(t.c_str()); } -static void pickTexFmts(gxGraphics *g, int hi) { +static void pickTexFmts(gxGraphics* g, int hi) +{ //texRGBFmt. { int pick = -1, max = 0, bits; for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) { for (int k = 0; k < tex_fmts.size(); ++k) { - const TexFmt &t = tex_fmts[k]; - if (t.bits > d || !t.rgb_bits || t.rgb_bits < max) continue; - if (t.rgb_bits == max && t.bits >= bits) continue; - pick = k; max = t.rgb_bits; bits = t.bits; + const TexFmt& t = tex_fmts[k]; + if (t.bits > d || !t.rgb_bits || t.rgb_bits < max) + continue; + if (t.rgb_bits == max && t.bits >= bits) + continue; + pick = k; + max = t.rgb_bits; + bits = t.bits; } - if (!hi && pick >= 0) break; + if (!hi && pick >= 0) + break; } - if (pick < 0) g->texRGBFmt[hi] = g->primFmt; - else g->texRGBFmt[hi] = tex_fmts[pick].fmt; + if (pick < 0) + g->texRGBFmt[hi] = g->primFmt; + else + g->texRGBFmt[hi] = tex_fmts[pick].fmt; } //texAlphaFmt { int pick = -1, max = 0, bits; for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) { for (int k = 0; k < tex_fmts.size(); ++k) { - const TexFmt &t = tex_fmts[k]; - if (t.bits > d || !t.a_bits || t.a_bits < max) continue; - if (t.a_bits == max && t.bits >= bits) continue; - pick = k; max = t.a_bits; bits = t.bits; + const TexFmt& t = tex_fmts[k]; + if (t.bits > d || !t.a_bits || t.a_bits < max) + continue; + if (t.a_bits == max && t.bits >= bits) + continue; + pick = k; + max = t.a_bits; + bits = t.bits; } - if (!hi && pick >= 0) break; + if (!hi && pick >= 0) + break; } - if (pick < 0) g->texAlphaFmt[hi] = g->primFmt; - else g->texAlphaFmt[hi] = tex_fmts[pick].fmt; + if (pick < 0) + g->texAlphaFmt[hi] = g->primFmt; + else + g->texAlphaFmt[hi] = tex_fmts[pick].fmt; } //texRGBAlphaFmt { int pick = -1, a8rgb8 = -1, max = 0, bits; for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) { for (int k = 0; k < tex_fmts.size(); ++k) { - const TexFmt &t = tex_fmts[k]; - if (t.a_bits == 8 && t.bits == 16) { a8rgb8 = k; continue; } - if (t.bits > d || !t.a_bits || !t.rgb_bits || t.a_bits < max) continue; - if (t.a_bits == max && t.bits >= bits) continue; - pick = k; max = t.a_bits; bits = t.bits; + const TexFmt& t = tex_fmts[k]; + if (t.a_bits == 8 && t.bits == 16) { + a8rgb8 = k; + continue; + } + if (t.bits > d || !t.a_bits || !t.rgb_bits || t.a_bits < max) + continue; + if (t.a_bits == max && t.bits >= bits) + continue; + pick = k; + max = t.a_bits; + bits = t.bits; } - if (!hi && pick >= 0) break; + if (!hi && pick >= 0) + break; } - if (pick < 0) pick = a8rgb8; - if (pick < 0) g->texRGBAlphaFmt[hi] = g->primFmt; - else g->texRGBAlphaFmt[hi] = tex_fmts[pick].fmt; + if (pick < 0) + pick = a8rgb8; + if (pick < 0) + g->texRGBAlphaFmt[hi] = g->primFmt; + else + g->texRGBAlphaFmt[hi] = tex_fmts[pick].fmt; } //texRGBMaskFmt... { int pick = -1, max = 0, bits; for (int d = g->primFmt.dwRGBBitCount; d <= 32; d += 8) { for (int k = 0; k < tex_fmts.size(); ++k) { - const TexFmt &t = tex_fmts[k]; - if (!t.a_bits || !t.rgb_bits || t.rgb_bits < max) continue; - if (t.rgb_bits == max && t.bits >= bits) continue; - pick = k; max = t.rgb_bits; bits = t.bits; + const TexFmt& t = tex_fmts[k]; + if (!t.a_bits || !t.rgb_bits || t.rgb_bits < max) + continue; + if (t.rgb_bits == max && t.bits >= bits) + continue; + pick = k; + max = t.rgb_bits; + bits = t.bits; } - if (!hi && pick >= 0) break; + if (!hi && pick >= 0) + break; } - if (pick < 0) g->texRGBMaskFmt[hi] = g->primFmt; - else g->texRGBMaskFmt[hi] = tex_fmts[pick].fmt; + if (pick < 0) + g->texRGBMaskFmt[hi] = g->primFmt; + else + g->texRGBMaskFmt[hi] = tex_fmts[pick].fmt; } } -gxScene *gxGraphics::createScene(int flags) { - if (scene_set.size()) return 0; +gxScene* gxGraphics::createScene(int flags) +{ + if (scene_set.size()) + return 0; //get d3d if (dirDraw->QueryInterface(IID_IDirect3D7, (void**)&dir3d) >= 0) { @@ -545,7 +633,7 @@ gxScene *gxGraphics::createScene(int flags) { string ts = "ZBuffer Bit Depth:" + itoa(zbuffFmt.dwZBufferBitDepth); gx_runtime->debugLog(ts.c_str()); #endif - gxScene *scene = new gxScene(this, back_canvas); + gxScene* scene = new gxScene(this, back_canvas); scene_set.insert(scene); dummy_mesh = createMesh(8, 12, 0); @@ -565,25 +653,34 @@ gxScene *gxGraphics::createScene(int flags) { return 0; } -gxScene *gxGraphics::verifyScene(gxScene *s) { +gxScene* gxGraphics::verifyScene(gxScene* s) +{ return scene_set.count(s) ? s : 0; } -void gxGraphics::freeScene(gxScene *scene) { - if (!scene_set.erase(scene)) return; +void gxGraphics::freeScene(gxScene* scene) +{ + if (!scene_set.erase(scene)) + return; dummy_mesh = 0; - while (mesh_set.size()) freeMesh(*mesh_set.begin()); + while (mesh_set.size()) + freeMesh(*mesh_set.begin()); back_canvas->releaseZBuffer(); - if (dir3dDev) { dir3dDev->Release(); dir3dDev = 0; } - if (dir3d) { dir3d->Release(); dir3d = 0; } + if (dir3dDev) { + dir3dDev->Release(); + dir3dDev = 0; + } + if (dir3d) { + dir3d->Release(); + dir3d = 0; + } delete scene; } -gxMesh *gxGraphics::createMesh(int max_verts, int max_tris, int flags) { - +gxMesh* gxGraphics::createMesh(int max_verts, int max_tris, int flags) +{ static const int VTXFMT = - D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 | - D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1); + D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1); int vbflags = 0; @@ -592,20 +689,24 @@ gxMesh *gxGraphics::createMesh(int max_verts, int max_tris, int flags) { vbflags |= D3DVBCAPS_WRITEONLY; }*/ - D3DVERTEXBUFFERDESC desc = { sizeof(desc),vbflags,VTXFMT,max_verts }; + D3DVERTEXBUFFERDESC desc = {sizeof(desc), vbflags, VTXFMT, max_verts}; - IDirect3DVertexBuffer7 *buff; - if (dir3d->CreateVertexBuffer(&desc, &buff, 0) < 0) return 0; - WORD *indices = new WORD[max_tris * 3]; - gxMesh *mesh = new gxMesh(this, buff, indices, max_verts, max_tris); + IDirect3DVertexBuffer7* buff; + if (dir3d->CreateVertexBuffer(&desc, &buff, 0) < 0) + return 0; + WORD* indices = new WORD[max_tris * 3]; + gxMesh* mesh = new gxMesh(this, buff, indices, max_verts, max_tris); mesh_set.insert(mesh); return mesh; } -gxMesh *gxGraphics::verifyMesh(gxMesh *m) { +gxMesh* gxGraphics::verifyMesh(gxMesh* m) +{ return mesh_set.count(m) ? m : 0; } -void gxGraphics::freeMesh(gxMesh *mesh) { - if (mesh_set.erase(mesh)) delete mesh; +void gxGraphics::freeMesh(gxMesh* mesh) +{ + if (mesh_set.erase(mesh)) + delete mesh; } \ No newline at end of file diff --git a/Runtime/gfx/gxgraphics.hpp b/Runtime/gfx/gxgraphics.hpp new file mode 100644 index 0000000..1dbc4a2 --- /dev/null +++ b/Runtime/gfx/gxgraphics.hpp @@ -0,0 +1,126 @@ + +#ifndef GXGRAPHICS_H +#define GXGRAPHICS_H + +#include +#include + +#include +#include +#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 font_set; + std::set canvas_set; + std::set mesh_set; + std::set scene_set; + std::set movie_set; + std::set 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 \ No newline at end of file diff --git a/gxruntime/gxinput.cpp b/Runtime/gfx/gxinput.cpp similarity index 55% rename from gxruntime/gxinput.cpp rename to Runtime/gfx/gxinput.cpp index 1f0745d..8df7d05 100644 --- a/gxruntime/gxinput.cpp +++ b/Runtime/gfx/gxinput.cpp @@ -1,28 +1,30 @@ #pragma once -#include "std.hpp" #include "gxinput.hpp" #include "gxruntime.hpp" +#include "std.hpp" static const int QUE_SIZE = 32; class Device : public gxDevice { -public: - bool acquired; - gxInput *input; + public: + bool acquired; + gxInput* input; LPDIRECTINPUTDEVICE8 device; - Device(gxInput *i, LPDIRECTINPUTDEVICE8 d) :input(i), acquired(false), device(d) { - } - virtual ~Device() { + Device(gxInput* i, LPDIRECTINPUTDEVICE8 d) : input(i), acquired(false), device(d) {} + virtual ~Device() + { device->Release(); //device->Release(); } - bool acquire() { + bool acquire() + { return device->Acquire() >= 0; //return acquired=device->Acquire()>=0; } - void unacquire() { + void unacquire() + { device->Unacquire(); //device->Unacquire(); acquired = false; @@ -30,44 +32,54 @@ public: }; class Keyboard : public Device { -public: - Keyboard(gxInput *i, LPDIRECTINPUTDEVICE8 d) :Device(i, d) { - } - void update() { + public: + Keyboard(gxInput* i, LPDIRECTINPUTDEVICE8 d) : Device(i, d) {} + void update() + { if (!acquired) { input->runtime->idle(); return; } - int k, cnt = 32; + int k, cnt = 32; DIDEVICEOBJECTDATA data[32], *curr; - if (device->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), data, (DWORD*)&cnt, 0) < 0) return; + if (device->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), data, (DWORD*)&cnt, 0) < 0) + return; curr = data; for (k = 0; k < cnt; ++curr, ++k) { - int n = curr->dwOfs; if (!n || n > 255) continue; - if (curr->dwData & 0x80) downEvent(n); - else upEvent(n); + int n = curr->dwOfs; + if (!n || n > 255) + continue; + if (curr->dwData & 0x80) + downEvent(n); + else + upEvent(n); } } }; class Mouse : public Device { -public: - Mouse(gxInput *i, LPDIRECTINPUTDEVICE8 d) :Device(i, d) { - } - void update() { + public: + Mouse(gxInput* i, LPDIRECTINPUTDEVICE8 d) : Device(i, d) {} + void update() + { if (!acquired) { input->runtime->idle(); return; } DIMOUSESTATE state; - if (device->GetDeviceState(sizeof(state), &state) < 0) return; - if (gxGraphics *g = input->runtime->graphics) { + if (device->GetDeviceState(sizeof(state), &state) < 0) + return; + if (gxGraphics* g = input->runtime->graphics) { int mx = axis_states[0] + state.lX; int my = axis_states[1] + state.lY; - if (mx < 0) mx = 0; - else if (mx >= g->getWidth()) mx = g->getWidth() - 1; - if (my < 0) my = 0; - else if (my >= g->getHeight()) my = g->getHeight() - 1; + if (mx < 0) + mx = 0; + else if (mx >= g->getWidth()) + mx = g->getWidth() - 1; + if (my < 0) + my = 0; + else if (my >= g->getHeight()) + my = g->getHeight() - 1; axis_states[0] = mx; axis_states[1] = my; axis_states[2] += state.lZ; @@ -79,17 +91,18 @@ public: }; class Joystick : public Device { -public: + public: int type, poll_time; int mins[12], maxs[12]; - Joystick(gxInput *i, LPDIRECTINPUTDEVICE8 d, int t) :Device(i, d), type(t), poll_time(0) { + Joystick(gxInput* i, LPDIRECTINPUTDEVICE8 d, int t) : Device(i, d), type(t), poll_time(0) + { for (int k = 0; k < 12; ++k) { //initialize joystick axis ranges (d'oh!) DIPROPRANGE range; - range.diph.dwSize = sizeof(DIPROPRANGE); + range.diph.dwSize = sizeof(DIPROPRANGE); range.diph.dwHeaderSize = sizeof(DIPROPHEADER); - range.diph.dwObj = k * 4 + 12; - range.diph.dwHow = DIPH_BYOFFSET; + range.diph.dwObj = k * 4 + 12; + range.diph.dwHow = DIPH_BYOFFSET; if (d->GetProperty(DIPROP_RANGE, &range.diph) < 0) { mins[k] = 0; maxs[k] = 65535; @@ -99,17 +112,22 @@ public: maxs[k] = range.lMax - range.lMin; } } - void update() { + void update() + { unsigned tm = timeGetTime(); - if (tm - poll_time < 3) return; + if (tm - poll_time < 3) + return; if (device->Poll() < 0) { acquired = false; input->runtime->idle(); - acquire(); if (device->Poll() < 0) return; + acquire(); + if (device->Poll() < 0) + return; } poll_time = tm; DIJOYSTATE state; - if (device->GetDeviceState(sizeof(state), &state) < 0) return; + if (device->GetDeviceState(sizeof(state), &state) < 0) + return; axis_states[0] = (state.lX - mins[0]) / (float)maxs[0] * 2 - 1; axis_states[1] = (state.lY - mins[1]) / (float)maxs[1] * 2 - 1; axis_states[2] = (state.lZ - mins[2]) / (float)maxs[2] * 2 - 1; @@ -118,8 +136,10 @@ public: axis_states[5] = (state.lRx - mins[3]) / (float)maxs[3] * 2 - 1; axis_states[6] = (state.lRy - mins[4]) / (float)maxs[4] * 2 - 1; axis_states[7] = (state.lRz - mins[5]) / (float)maxs[5] * 2 - 1; - if ((state.rgdwPOV[0] & 0xffff) == 0xffff) axis_states[8] = -1; - else axis_states[8] = floor(state.rgdwPOV[0] / 100.0f + .5f); + if ((state.rgdwPOV[0] & 0xffff) == 0xffff) + axis_states[8] = -1; + else + axis_states[8] = floor(state.rgdwPOV[0] / 100.0f + .5f); for (int k = 0; k < 31; ++k) { setDownState(k + 1, state.rgbButtons[k] & 0x80 ? true : false); @@ -127,23 +147,23 @@ public: } }; -static Keyboard *keyboard; -static Mouse *mouse; +static Keyboard* keyboard; +static Mouse* mouse; static vector joysticks; -static Keyboard *createKeyboard(gxInput *input) { +static Keyboard* createKeyboard(gxInput* input) +{ LPDIRECTINPUTDEVICE8 dev; if (input->dirInput->CreateDevice(GUID_SysKeyboard, &dev, NULL) >= 0) { if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) { - if (dev->SetDataFormat(&c_dfDIKeyboard) >= 0) { DIPROPDWORD dword; memset(&dword, 0, sizeof(dword)); - dword.diph.dwSize = sizeof(DIPROPDWORD); + dword.diph.dwSize = sizeof(DIPROPDWORD); dword.diph.dwHeaderSize = sizeof(DIPROPHEADER); - dword.diph.dwObj = 0; - dword.diph.dwHow = DIPH_DEVICE; - dword.dwData = 32; + dword.diph.dwObj = 0; + dword.diph.dwHow = DIPH_DEVICE; + dword.dwData = 32; if (dev->SetProperty(DIPROP_BUFFERSIZE, &dword.diph) >= 0) { return new Keyboard(input, dev); } else { @@ -164,11 +184,11 @@ static Keyboard *createKeyboard(gxInput *input) { return 0; } -static Mouse *createMouse(gxInput *input) { +static Mouse* createMouse(gxInput* input) +{ LPDIRECTINPUTDEVICE8 dev; if (input->dirInput->CreateDevice(GUID_SysMouse, &dev, 0) >= 0) { if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) { - if (dev->SetDataFormat(&c_dfDIMouse) >= 0) { return new Mouse(input, dev); } else { @@ -186,7 +206,8 @@ static Mouse *createMouse(gxInput *input) { return 0; } -static Joystick *createJoystick(gxInput *input, LPCDIDEVICEINSTANCE devinst) { +static Joystick* createJoystick(gxInput* input, LPCDIDEVICEINSTANCE devinst) +{ LPDIRECTINPUTDEVICE8 dev; if (input->dirInput->CreateDevice(devinst->guidInstance, &dev, 0) >= 0) { if (dev->SetCooperativeLevel(input->runtime->hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE) >= 0) { @@ -200,25 +221,29 @@ static Joystick *createJoystick(gxInput *input, LPCDIDEVICEINSTANCE devinst) { 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); } return DIENUM_CONTINUE; } -gxInput::gxInput(gxRuntime *rt, LPDIRECTINPUT8 di) : runtime(rt), dirInput(di) { +gxInput::gxInput(gxRuntime* rt, LPDIRECTINPUT8 di) : runtime(rt), dirInput(di) +{ keyboard = createKeyboard(this); - mouse = createMouse(this); + mouse = createMouse(this); joysticks.clear(); dirInput->EnumDevices(DI8DEVCLASS_GAMECTRL, enumJoystick, this, DIEDFL_ATTACHEDONLY); } -gxInput::~gxInput() { - for (int k = 0; k < joysticks.size(); ++k) delete joysticks[k]; +gxInput::~gxInput() +{ + for (int k = 0; k < joysticks.size(); ++k) + delete joysticks[k]; joysticks.clear(); delete mouse; delete keyboard; @@ -226,110 +251,154 @@ gxInput::~gxInput() { dirInput->Release(); } -void gxInput::wm_keydown(int key) { - if (keyboard) keyboard->downEvent(key); +void gxInput::wm_keydown(int key) +{ + if (keyboard) + keyboard->downEvent(key); } -void gxInput::wm_keyup(int key) { - if (keyboard) keyboard->upEvent(key); +void gxInput::wm_keyup(int key) +{ + if (keyboard) + keyboard->upEvent(key); } -void gxInput::wm_mousedown(int key) { - if (mouse) mouse->downEvent(key); +void gxInput::wm_mousedown(int key) +{ + if (mouse) + mouse->downEvent(key); } -void gxInput::wm_mouseup(int key) { - if (mouse) mouse->upEvent(key); +void gxInput::wm_mouseup(int key) +{ + if (mouse) + mouse->upEvent(key); } -void gxInput::wm_mousemove(int x, int y) { +void gxInput::wm_mousemove(int x, int y) +{ if (mouse) { mouse->axis_states[0] = x; mouse->axis_states[1] = y; } } -void gxInput::wm_mousewheel(int dz) { - if (mouse) mouse->axis_states[2] += dz; +void gxInput::wm_mousewheel(int dz) +{ + if (mouse) + mouse->axis_states[2] += dz; } -void gxInput::reset() { - if (mouse) mouse->reset(); - if (keyboard) keyboard->reset(); - for (int k = 0; k < joysticks.size(); ++k) joysticks[k]->reset(); +void gxInput::reset() +{ + if (mouse) + mouse->reset(); + if (keyboard) + keyboard->reset(); + for (int k = 0; k < joysticks.size(); ++k) + joysticks[k]->reset(); } -bool gxInput::acquire() { +bool gxInput::acquire() +{ bool m_ok = true, k_ok = true; - if (mouse) m_ok = mouse->acquire(); - if (keyboard) k_ok = keyboard->acquire(); - if (m_ok && k_ok) return true; - if (k_ok) keyboard->unacquire(); - if (m_ok) mouse->unacquire(); + if (mouse) + m_ok = mouse->acquire(); + if (keyboard) + k_ok = keyboard->acquire(); + if (m_ok && k_ok) + return true; + if (k_ok) + keyboard->unacquire(); + if (m_ok) + mouse->unacquire(); return false; } -void gxInput::unacquire() { - if (keyboard) keyboard->unacquire(); - if (mouse) mouse->unacquire(); +void gxInput::unacquire() +{ + if (keyboard) + keyboard->unacquire(); + if (mouse) + mouse->unacquire(); } -void gxInput::moveMouse(int x, int y) { - if (!mouse) return; +void gxInput::moveMouse(int x, int y) +{ + if (!mouse) + return; mouse->axis_states[0] = x; mouse->axis_states[1] = y; runtime->moveMouse(x, y); } -gxDevice *gxInput::getMouse()const { +gxDevice* gxInput::getMouse() const +{ return mouse; } -gxDevice *gxInput::getKeyboard()const { +gxDevice* gxInput::getKeyboard() const +{ return keyboard; } -gxDevice *gxInput::getJoystick(int n)const { +gxDevice* gxInput::getJoystick(int n) const +{ return n >= 0 && n < joysticks.size() ? joysticks[n] : 0; } -int gxInput::getJoystickType(int n)const { +int gxInput::getJoystickType(int n) const +{ return n >= 0 && n < joysticks.size() ? joysticks[n]->type : 0; } -int gxInput::numJoysticks()const { +int gxInput::numJoysticks() const +{ return joysticks.size(); } -int gxInput::toAscii(int scan)const { +int gxInput::toAscii(int scan) const +{ switch (scan) { - case DIK_INSERT:return ASC_INSERT; - case DIK_DELETE:return ASC_DELETE; - case DIK_HOME:return ASC_HOME; - case DIK_END:return ASC_END; - case DIK_PGUP:return ASC_PAGEUP; - case DIK_PGDN:return ASC_PAGEDOWN; - case DIK_UP:return ASC_UP; - case DIK_DOWN:return ASC_DOWN; - case DIK_LEFT:return ASC_LEFT; - case DIK_RIGHT:return ASC_RIGHT; + case DIK_INSERT: + return ASC_INSERT; + case DIK_DELETE: + return ASC_DELETE; + case DIK_HOME: + return ASC_HOME; + case DIK_END: + return ASC_END; + case DIK_PGUP: + return ASC_PAGEUP; + case DIK_PGDN: + return ASC_PAGEDOWN; + case DIK_UP: + return ASC_UP; + case DIK_DOWN: + return ASC_DOWN; + case DIK_LEFT: + return ASC_LEFT; + case DIK_RIGHT: + return ASC_RIGHT; } scan &= 0x7f; int virt = MapVirtualKey(scan, 1); - if (!virt) return 0; + if (!virt) + return 0; static unsigned char mat[256]; - mat[VK_LSHIFT] = keyboard->keyDown(DIK_LSHIFT) ? 0x80 : 0; - mat[VK_RSHIFT] = keyboard->keyDown(DIK_RSHIFT) ? 0x80 : 0; - mat[VK_SHIFT] = mat[VK_LSHIFT] | mat[VK_RSHIFT]; + mat[VK_LSHIFT] = keyboard->keyDown(DIK_LSHIFT) ? 0x80 : 0; + mat[VK_RSHIFT] = keyboard->keyDown(DIK_RSHIFT) ? 0x80 : 0; + mat[VK_SHIFT] = mat[VK_LSHIFT] | mat[VK_RSHIFT]; mat[VK_LCONTROL] = keyboard->keyDown(DIK_LCONTROL) ? 0x80 : 0; mat[VK_RCONTROL] = keyboard->keyDown(DIK_RCONTROL) ? 0x80 : 0; - mat[VK_CONTROL] = mat[VK_LCONTROL] | mat[VK_RCONTROL]; - mat[VK_LMENU] = keyboard->keyDown(DIK_LMENU) ? 0x80 : 0; - mat[VK_RMENU] = keyboard->keyDown(DIK_RMENU) ? 0x80 : 0; - mat[VK_MENU] = mat[VK_LMENU] | mat[VK_RMENU]; + mat[VK_CONTROL] = mat[VK_LCONTROL] | mat[VK_RCONTROL]; + mat[VK_LMENU] = keyboard->keyDown(DIK_LMENU) ? 0x80 : 0; + mat[VK_RMENU] = keyboard->keyDown(DIK_RMENU) ? 0x80 : 0; + mat[VK_MENU] = mat[VK_LMENU] | mat[VK_RMENU]; WORD ch; - if (ToAscii(virt, scan, mat, &ch, 0) != 1) return 0; + if (ToAscii(virt, scan, mat, &ch, 0) != 1) + return 0; return ch & 255; } diff --git a/Runtime/gfx/gxinput.hpp b/Runtime/gfx/gxinput.hpp new file mode 100644 index 0000000..0114248 --- /dev/null +++ b/Runtime/gfx/gxinput.hpp @@ -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; +}; \ No newline at end of file diff --git a/Runtime/gfx/gxlight.cpp b/Runtime/gfx/gxlight.cpp new file mode 100644 index 0000000..7ea119c --- /dev/null +++ b/Runtime/gfx/gxlight.cpp @@ -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; +} diff --git a/Runtime/gfx/gxlight.hpp b/Runtime/gfx/gxlight.hpp new file mode 100644 index 0000000..d7b3934 --- /dev/null +++ b/Runtime/gfx/gxlight.hpp @@ -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 \ No newline at end of file diff --git a/gxruntime/gxmesh.cpp b/Runtime/gfx/gxmesh.cpp similarity index 58% rename from gxruntime/gxmesh.cpp rename to Runtime/gfx/gxmesh.cpp index 839bd8d..b1e1b72 100644 --- a/gxruntime/gxmesh.cpp +++ b/Runtime/gfx/gxmesh.cpp @@ -1,17 +1,19 @@ -#include "std.hpp" #include "gxmesh.hpp" #include "gxgraphics.hpp" +#include "std.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 ): -graphics(g),locked_verts(0),vertex_buff(vs),tri_indices(is),max_verts(max_vs),max_tris(max_ts),mesh_dirty(false){ -} +gxMesh::gxMesh(gxGraphics* g, IDirect3DVertexBuffer7* vs, WORD* is, int max_vs, int max_ts) + : graphics(g), locked_verts(0), vertex_buff(vs), tri_indices(is), max_verts(max_vs), max_tris(max_ts), + mesh_dirty(false) +{} -gxMesh::~gxMesh(){ +gxMesh::~gxMesh() +{ unlock(); vertex_buff->Release(); @@ -19,8 +21,10 @@ gxMesh::~gxMesh(){ delete[] tri_indices; } -bool gxMesh::lock( bool all ){ - if( locked_verts ) return true; +bool gxMesh::lock(bool all) +{ + if (locked_verts) + return true; //V1.104 //int flags=all ? DDLOCK_DISCARDCONTENTS : 0; @@ -32,37 +36,40 @@ bool gxMesh::lock( bool all ){ //if( vertex_buff->Lock( DDLOCK_WRITEONLY|DDLOCK_WAIT|flags,(void**)&locked_verts,0 )>=0 ){ //V1.1.06... - int flags=DDLOCK_WAIT|DDLOCK_WRITEONLY; + int flags = DDLOCK_WAIT | DDLOCK_WRITEONLY; //XP or less? /*if( graphics->runtime->osinfo.dwMajorVersion<6 ){ flags|=(all ? DDLOCK_DISCARDCONTENTS : DDLOCK_NOOVERWRITE); }*/ - if( vertex_buff->Lock( flags,(void**)&locked_verts,0 )>=0 ){ - mesh_dirty=false; + if (vertex_buff->Lock(flags, (void**)&locked_verts, 0) >= 0) { + mesh_dirty = false; 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; } -void gxMesh::unlock(){ - if( locked_verts ){ +void gxMesh::unlock() +{ + if (locked_verts) { vertex_buff->Unlock(); - locked_verts=0; + locked_verts = 0; } } -void gxMesh::backup(){ +void gxMesh::backup() +{ unlock(); } -void gxMesh::restore(){ - mesh_dirty=true; +void gxMesh::restore() +{ + mesh_dirty = true; } /* @@ -98,10 +105,9 @@ void gxMesh::restore(){ } */ -void gxMesh::render( int first_vert,int vert_cnt,int first_tri,int tri_cnt ){ +void gxMesh::render(int first_vert, int vert_cnt, int first_tri, int tri_cnt) +{ unlock(); - graphics->dir3dDev->DrawIndexedPrimitiveVB( - D3DPT_TRIANGLELIST, - vertex_buff,first_vert,vert_cnt, - tri_indices+first_tri*3,tri_cnt*3,0 ); + graphics->dir3dDev->DrawIndexedPrimitiveVB(D3DPT_TRIANGLELIST, vertex_buff, first_vert, vert_cnt, + tri_indices + first_tri * 3, tri_cnt * 3, 0); } diff --git a/Runtime/gfx/gxmesh.hpp b/Runtime/gfx/gxmesh.hpp new file mode 100644 index 0000000..386fa42 --- /dev/null +++ b/Runtime/gfx/gxmesh.hpp @@ -0,0 +1,85 @@ + +#ifndef GXMESH_H +#define GXMESH_H + +#include +#include +#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 \ No newline at end of file diff --git a/gxruntime/gxmovie.cpp b/Runtime/gfx/gxmovie.cpp similarity index 84% rename from gxruntime/gxmovie.cpp rename to Runtime/gfx/gxmovie.cpp index a72b0d4..4b1666d 100644 --- a/gxruntime/gxmovie.cpp +++ b/Runtime/gfx/gxmovie.cpp @@ -1,11 +1,10 @@ -#include "std.hpp" #include "gxmovie.hpp" #include "gxgraphics.hpp" +#include "std.hpp" -gxMovie::gxMovie(gxGraphics *g, IMultiMediaStream *mm) - :gfx(g), mm_stream(mm), playing(true) { - +gxMovie::gxMovie(gxGraphics* g, IMultiMediaStream* mm) : gfx(g), mm_stream(mm), playing(true) +{ ////mm_stream->GetMediaStream( MSPID_PrimaryVideo,&vid_stream ); ////vid_stream->QueryInterface(IID_IDirectDrawMediaStream, (void**)&dd_stream); @@ -23,7 +22,8 @@ gxMovie::gxMovie(gxGraphics *g, IMultiMediaStream *mm) //mm_stream->SetState(STREAMSTATE_RUN); } -gxMovie::~gxMovie() { +gxMovie::~gxMovie() +{ /*mm_stream->SetState(STREAMSTATE_STOP); dd_sample->Release(); @@ -35,8 +35,10 @@ gxMovie::~gxMovie() { gfx->freeCanvas(canvas);*/ } -bool gxMovie::draw(gxCanvas *dest, int x, int y, int w, int h) { - if (!playing) return false; +bool gxMovie::draw(gxCanvas* dest, int x, int y, int w, int h) +{ + if (!playing) + return false; /*if (!dd_sample->Update(0, 0, 0, 0)) { RECT dest_rect = { x,y,x + w,y + h }; dest->getSurface()->Blt(&dest_rect, canvas->getSurface(), &src_rect, DDBLT_WAIT, 0); diff --git a/Runtime/gfx/gxmovie.hpp b/Runtime/gfx/gxmovie.hpp new file mode 100644 index 0000000..f2b304d --- /dev/null +++ b/Runtime/gfx/gxmovie.hpp @@ -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 \ No newline at end of file diff --git a/Runtime/gfx/gxmusic.cpp b/Runtime/gfx/gxmusic.cpp new file mode 100644 index 0000000..3bc4878 --- /dev/null +++ b/Runtime/gfx/gxmusic.cpp @@ -0,0 +1,61 @@ + +#include "gxmusic.hpp" +#include +#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; +} diff --git a/Runtime/gfx/gxmusic.hpp b/Runtime/gfx/gxmusic.hpp new file mode 100644 index 0000000..8dc4c6f --- /dev/null +++ b/Runtime/gfx/gxmusic.hpp @@ -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 \ No newline at end of file diff --git a/Runtime/gfx/gxruntime.cpp b/Runtime/gfx/gxruntime.cpp new file mode 100644 index 0000000..922c3aa --- /dev/null +++ b/Runtime/gfx/gxruntime.cpp @@ -0,0 +1,1381 @@ +#pragma once + +#include "gxruntime.hpp" +#include +#include +#include +#include +#include "GraphicsRuntime.hpp" +#include "std.hpp" + +struct gxRuntime::GfxMode { + DDSURFACEDESC2 desc; +}; +struct gxRuntime::GfxDriver { + GUID* guid; + std::string name; + std::vector modes; + D3DDEVICEDESC7 d3d_desc; +}; + +static const int static_ws = WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; +static const int scaled_ws = WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + +static string app_title; +static string app_close; +static gxRuntime* runtime; +static bool busy, suspended; +static volatile bool run_flag; +static DDSURFACEDESC2 desktop_desc; + +typedef int(_stdcall* LibFunc)(const void* in, int in_sz, void* out, int out_sz); + +struct gxDll { + HINSTANCE hinst; + map funcs; +}; + +static map libs; + +static LRESULT CALLBACK windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + +//current gfx mode +// +//0=NONE +//1=SCALED WINDOW +//2=FIXED SIZE WINDOW +//3=EXCLUSIVE +// +static int gfx_mode; +static bool gfx_lost; +static bool auto_suspend; + +//for modes 1 and 2 +static int mod_cnt; +static MMRESULT timerID; +static IDirectDrawClipper* clipper; +static IDirectDrawSurface7* primSurf; +//static Debugger *debugger; + +static set timers; + +enum { WM_STOP = WM_USER + 1, WM_RUN, WM_END }; + +//////////////////// +// STATIC STARTUP // +//////////////////// +gxRuntime* gxRuntime::openRuntime(HINSTANCE hinst, const string& cmd_line, void* d) +{ + if (runtime) + return 0; + + //create debugger + //debugger = d; + + //create WNDCLASS + WNDCLASS wndclass; + memset(&wndclass, 0, sizeof(wndclass)); + wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wndclass.lpfnWndProc = ::windowProc; + wndclass.hInstance = hinst; + wndclass.lpszClassName = TEXT("Blitz Runtime Class"); + wndclass.hCursor = (HCURSOR)LoadCursor(0, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + RegisterClass(&wndclass); + + gfx_mode = 0; + clipper = 0; + primSurf = 0; + busy = suspended = false; + run_flag = true; + + const char* app_t = " "; + int ws = WS_CAPTION, ws_ex = 0; + + HWND hwnd = CreateWindowEx(ws_ex, "Blitz Runtime Class", app_t, ws, 0, 0, 0, 0, 0, 0, 0, 0); + + UpdateWindow(hwnd); + + runtime = new gxRuntime(hinst, cmd_line, hwnd); + return runtime; +} + +void gxRuntime::closeRuntime(gxRuntime* r) +{ + if (!runtime || runtime != r) + return; + + map::const_iterator it; + for (it = libs.begin(); it != libs.end(); ++it) { + FreeLibrary(it->second->hinst); + } + libs.clear(); + + delete runtime; + runtime = 0; +} + +////////////////////////// +// RUNTIME CONSTRUCTION // +////////////////////////// +typedef int(_stdcall* SetAppCompatDataFunc)(int x, int y); + +gxRuntime::gxRuntime(HINSTANCE hi, const string& cl, HWND hw) + : hinst(hi), cmd_line(cl), hwnd(hw), curr_driver(0), enum_all(false), pointer_visible(true), audio(0), input(0), + graphics(0), fileSystem(0), use_di(false) +{ + CoInitialize(0); + + enumGfx(); + TIMECAPS tc; + timeGetDevCaps(&tc, sizeof(tc)); + timeBeginPeriod(tc.wPeriodMin); + + HMODULE ddraw = LoadLibraryA("ddraw.dll"); + if (ddraw) { + SetAppCompatDataFunc SetAppCompatData = (SetAppCompatDataFunc)GetProcAddress(ddraw, "SetAppCompatData"); + if (SetAppCompatData) + SetAppCompatData(12, 0); + FreeLibrary(ddraw); + } +} + +gxRuntime::~gxRuntime() +{ + while (timers.size()) + freeTimer(*timers.begin()); + if (audio) + closeAudio(audio); + if (graphics) + closeGraphics(graphics); + if (input) + closeInput(input); + TIMECAPS tc; + timeGetDevCaps(&tc, sizeof(tc)); + timeEndPeriod(tc.wPeriodMin); + denumGfx(); + DestroyWindow(hwnd); + UnregisterClass("Blitz Runtime Class", hinst); + + CoUninitialize(); +} + +void gxRuntime::pauseAudio() +{ + if (audio) + audio->pause(); +} + +void gxRuntime::resumeAudio() +{ + if (audio) + audio->resume(); +} + +void gxRuntime::backupGraphics() +{ + if (auto_suspend) { + graphics->backup(); + } +} + +void gxRuntime::restoreGraphics() +{ + if (auto_suspend) { + if (!graphics->restore()) + gfx_lost = true; + } +} + +void gxRuntime::resetInput() +{ + if (input) + input->reset(); +} + +void gxRuntime::acquireInput() +{ + if (!input) + return; + if (gfx_mode == 3) { + if (use_di) { + use_di = input->acquire(); + } else { + } + } + input->reset(); +} + +void gxRuntime::unacquireInput() +{ + if (!input) + return; + if (gfx_mode == 3 && use_di) + input->unacquire(); + input->reset(); +} + +///////////// +// SUSPEND // +///////////// +void gxRuntime::suspend() +{ + busy = true; + pauseAudio(); + backupGraphics(); + unacquireInput(); + suspended = true; + busy = false; + + if (gfx_mode == 3) + ShowCursor(1); + + //if (debugger) debugger->debugStop(); +} + +//////////// +// RESUME // +//////////// +void gxRuntime::resume() +{ + if (gfx_mode == 3) + ShowCursor(0); + busy = true; + acquireInput(); + restoreGraphics(); + resumeAudio(); + suspended = false; + busy = false; + + //if (debugger) debugger->debugRun(); +} + +/////////////////// +// FORCE SUSPEND // +/////////////////// +void gxRuntime::forceSuspend() +{ + if (gfx_mode == 3) { + SetForegroundWindow(GetDesktopWindow()); + ShowWindow(GetDesktopWindow(), SW_SHOW); + } else { + suspend(); + } +} + +////////////////// +// FORCE RESUME // +////////////////// +void gxRuntime::forceResume() +{ + if (gfx_mode == 3) { + SetForegroundWindow(hwnd); + ShowWindow(hwnd, SW_SHOWMAXIMIZED); + } else { + resume(); + } +} + +/////////// +// PAINT // +/////////// +void gxRuntime::paint() +{ + switch (gfx_mode) { + case 0: { + } break; + case 1: + case 2: //scaled windowed mode. + { + RECT src, dest; + src.left = src.top = 0; + GetClientRect(hwnd, &dest); + src.right = gfx_mode == 1 ? graphics->getWidth() : dest.right; + src.bottom = gfx_mode == 1 ? graphics->getHeight() : dest.bottom; + POINT p; + p.x = p.y = 0; + ClientToScreen(hwnd, &p); + dest.left += p.x; + dest.right += p.x; + dest.top += p.y; + dest.bottom += p.y; + gxCanvas* f = graphics->getFrontCanvas(); + primSurf->Blt(&dest, f->getSurface(), &src, 0, 0); + } break; + case 3: { + //exclusive mode + } break; + } +} + +////////// +// FLIP // +////////// +void gxRuntime::flip(bool vwait) +{ + gxCanvas* b = graphics->getBackCanvas(); + gxCanvas* f = graphics->getFrontCanvas(); + int n; + switch (gfx_mode) { + case 1: + case 2: + if (vwait) + graphics->vwait(); + f->setModify(b->getModify()); + if (f->getModify() != mod_cnt) { + mod_cnt = f->getModify(); + paint(); + } + break; + case 3: + if (vwait) { + BOOL vb; + while (graphics->dirDraw->GetVerticalBlankStatus(&vb) >= 0 && vb) { + } + n = f->getSurface()->Flip(0, DDFLIP_WAIT); + } else { + n = f->getSurface()->Flip(0, DDFLIP_NOVSYNC | DDFLIP_WAIT); + } + if (n >= 0) + return; + string t = "Flip Failed! Return code:" + itoa(n & 0x7fff); + debugLog(t.c_str()); + break; + } +} + +//////////////// +// MOVE MOUSE // +//////////////// +void gxRuntime::moveMouse(int x, int y) +{ + POINT p; + RECT rect; + switch (gfx_mode) { + case 1: + GetClientRect(hwnd, &rect); + x = x * (rect.right - rect.left) / graphics->getWidth(); + y = y * (rect.bottom - rect.top) / graphics->getHeight(); + case 2: + p.x = x; + p.y = y; + ClientToScreen(hwnd, &p); + x = p.x; + y = p.y; + break; + case 3: + if (use_di) + return; + break; + default: + return; + } + SetCursorPos(x, y); +} + +///////////////// +// WINDOW PROC // +///////////////// +LRESULT gxRuntime::windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + if (busy) { + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + PAINTSTRUCT ps; + + //handle 'special' messages! + switch (msg) { + case WM_PAINT: + if (gfx_mode && !auto_suspend) { + if (!graphics->restore()) + gfx_lost = true; + } + BeginPaint(hwnd, &ps); + paint(); + EndPaint(hwnd, &ps); + return DefWindowProc(hwnd, msg, wparam, lparam); + case WM_ERASEBKGND: + return gfx_mode ? 1 : DefWindowProc(hwnd, msg, wparam, lparam); + case WM_CLOSE: + if (app_close.size()) { + int n = MessageBox(hwnd, app_close.c_str(), app_title.c_str(), + MB_OKCANCEL | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + if (n != IDOK) + return 0; + } + asyncEnd(); + return 0; + case WM_SETCURSOR: + if (!suspended) { + if (gfx_mode == 3) { + SetCursor(0); + return 1; + } else if (!pointer_visible) { + POINT p; + GetCursorPos(&p); + ScreenToClient(hwnd, &p); + RECT r; + GetClientRect(hwnd, &r); + if (p.x >= 0 && p.y >= 0 && p.x < r.right && p.y < r.bottom) { + SetCursor(0); + return 1; + } + } + } + break; + case WM_ACTIVATEAPP: + if (auto_suspend) { + if (wparam) { + if (suspended) + resume(); + } else { + if (!suspended) + suspend(); + } + } + break; + } + + if (!input || suspended) + return DefWindowProc(hwnd, msg, wparam, lparam); + + if (gfx_mode == 3 && use_di) { + use_di = input->acquire(); + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + static const int MK_ALLBUTTONS = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON; + + //handle input messages + switch (msg) { + case WM_LBUTTONDOWN: + input->wm_mousedown(1); + SetCapture(hwnd); + break; + case WM_LBUTTONUP: + input->wm_mouseup(1); + if (!(wparam & MK_ALLBUTTONS)) + ReleaseCapture(); + break; + case WM_RBUTTONDOWN: + input->wm_mousedown(2); + SetCapture(hwnd); + break; + case WM_RBUTTONUP: + input->wm_mouseup(2); + if (!(wparam & MK_ALLBUTTONS)) + ReleaseCapture(); + break; + case WM_MBUTTONDOWN: + input->wm_mousedown(3); + SetCapture(hwnd); + break; + case WM_MBUTTONUP: + input->wm_mouseup(3); + if (!(wparam & MK_ALLBUTTONS)) + ReleaseCapture(); + break; + case WM_MOUSEMOVE: + if (!graphics) + break; + if (gfx_mode == 3 && !use_di) { + POINT p; + GetCursorPos(&p); + input->wm_mousemove(p.x, p.y); + } else { + int x = (short)(lparam & 0xffff), y = lparam >> 16; + if (gfx_mode == 1) { + RECT rect; + GetClientRect(hwnd, &rect); + x = x * graphics->getWidth() / (rect.right - rect.left); + y = y * graphics->getHeight() / (rect.bottom - rect.top); + } + if (x < 0) + x = 0; + else if (x >= graphics->getWidth()) + x = graphics->getWidth() - 1; + if (y < 0) + y = 0; + else if (y >= graphics->getHeight()) + y = graphics->getHeight() - 1; + input->wm_mousemove(x, y); + } + break; + case WM_MOUSEWHEEL: + input->wm_mousewheel((short)HIWORD(wparam)); + break; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (lparam & 0x40000000) + break; + if (int n = ((lparam >> 17) & 0x80) | ((lparam >> 16) & 0x7f)) + input->wm_keydown(n); + break; + case WM_KEYUP: + case WM_SYSKEYUP: + if (int n = ((lparam >> 17) & 0x80) | ((lparam >> 16) & 0x7f)) + input->wm_keyup(n); + break; + default: + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + return 0; +} + +static LRESULT CALLBACK windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + if (runtime) + return runtime->windowProc(hwnd, msg, wparam, lparam); + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +////////////////////////////// +//STOP FROM EXTERNAL SOURCE // +////////////////////////////// +void gxRuntime::asyncStop() +{ + PostMessage(hwnd, WM_STOP, 0, 0); +} + +////////////////////////////// +//RUN FROM EXTERNAL SOURCE // +////////////////////////////// +void gxRuntime::asyncRun() +{ + PostMessage(hwnd, WM_RUN, 0, 0); +} + +////////////////////////////// +// END FROM EXTERNAL SOURCE // +////////////////////////////// +void gxRuntime::asyncEnd() +{ + PostMessage(hwnd, WM_END, 0, 0); +} + +////////// +// IDLE // +////////// +bool gxRuntime::idle() +{ + for (;;) { + MSG msg; + if (suspended && run_flag) { + GetMessage(&msg, 0, 0, 0); + } else { + if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + return run_flag; + } + switch (msg.message) { + case WM_STOP: + if (!suspended) + forceSuspend(); + break; + case WM_RUN: + if (suspended) + forceResume(); + break; + case WM_END: + //debugger = 0; + run_flag = false; + break; + default: + DispatchMessage(&msg); + } + } + return run_flag; +} + +/////////// +// DELAY // +/////////// +bool gxRuntime::delay(int ms) +{ + int t = timeGetTime() + ms; + for (;;) { + if (!idle()) + return false; + int d = t - timeGetTime(); //how long left to wait + if (d <= 0) + return true; + if (d > 100) + d = 100; + Sleep(d); + } +} + +/////////////// +// DEBUGSTMT // +/////////////// +void gxRuntime::debugStmt(int pos, const char* file) +{ + //if (debugger) debugger->debugStmt(pos, file); +} + +/////////////// +// DEBUGSTOP // +/////////////// +void gxRuntime::debugStop() +{ + //if (!suspended) forceSuspend(); +} + +//////////////// +// DEBUGENTER // +//////////////// +void gxRuntime::debugEnter(void* frame, void* env, const char* func) +{ + //if (debugger) debugger->debugEnter(frame, env, func); +} + +//////////////// +// DEBUGLEAVE // +//////////////// +void gxRuntime::debugLeave() +{ + //if (debugger) debugger->debugLeave(); +} + +//////////////// +// DEBUGERROR // +//////////////// +void gxRuntime::debugError(const char* t) +{ + /*if (!debugger) return; + void*d = debugger; + asyncEnd(); + if (!suspended) { + forceSuspend(); + } + d->debugMsg(t, true);*/ +} + +/////////////// +// DEBUGINFO // +/////////////// +void gxRuntime::debugInfo(const char* t) +{ + /*if (!debugger) return; + Debugger *d = debugger; + asyncEnd(); + if (!suspended) { + forceSuspend(); + } + d->debugMsg(t, false);*/ +} + +////////////// +// DEBUGLOG // +////////////// +void gxRuntime::debugLog(const char* t) +{ + //if (debugger) debugger->debugLog(t); +} + +///////////////////////// +// RETURN COMMAND LINE // +///////////////////////// +string gxRuntime::commandLine() +{ + return cmd_line; +} + +///////////// +// EXECUTE // +///////////// +bool gxRuntime::execute(const string& cmd_line) +{ + if (!cmd_line.size()) + return false; + + //convert cmd_line to cmd and params + string cmd = cmd_line, params; + while (cmd.size() && cmd[0] == ' ') + cmd = cmd.substr(1); + if (cmd.find('\"') == 0) { + int n = cmd.find('\"', 1); + if (n != string::npos) { + params = cmd.substr(n + 1); + cmd = cmd.substr(1, n - 1); + } + } else { + int n = cmd.find(' '); + if (n != string::npos) { + params = cmd.substr(n + 1); + cmd = cmd.substr(0, n); + } + } + while (params.size() && params[0] == ' ') + params = params.substr(1); + while (params.size() && params[params.size() - 1] == ' ') + params = params.substr(0, params.size() - 1); + + SetForegroundWindow(GetDesktopWindow()); + + return (int)ShellExecute(GetDesktopWindow(), 0, cmd.c_str(), params.size() ? params.c_str() : 0, 0, SW_SHOW) > 32; +} + +/////////////// +// APP TITLE // +/////////////// +void gxRuntime::setTitle(const string& t, const string& e) +{ + app_title = t; + app_close = e; + SetWindowText(hwnd, app_title.c_str()); +} + +////////////////// +// GETMILLISECS // +////////////////// +int gxRuntime::getMilliSecs() +{ + return timeGetTime(); +} + +///////////////////// +// POINTER VISIBLE // +///////////////////// +void gxRuntime::setPointerVisible(bool vis) +{ + if (pointer_visible == vis) + return; + + pointer_visible = vis; + if (gfx_mode == 3) + return; + + //force a WM_SETCURSOR + POINT pt; + GetCursorPos(&pt); + SetCursorPos(pt.x, pt.y); +} + +///////////////// +// AUDIO SETUP // +///////////////// +gxAudio* gxRuntime::openAudio(int flags) +{ + if (audio) + return 0; + + int f_flags = FSOUND_INIT_GLOBALFOCUS | FSOUND_INIT_USEDEFAULTMIDISYNTH; + + FSOUND_SetHWND(hwnd); + if (!FSOUND_Init(44100, 1024, f_flags)) { + return 0; + } + + audio = new gxAudio(this); + return audio; +} + +void gxRuntime::closeAudio(gxAudio* a) +{ + if (!audio || audio != a) + return; + delete audio; + audio = 0; +} + +///////////////// +// INPUT SETUP // +///////////////// +gxInput* gxRuntime::openInput(int flags) +{ + if (input) + return 0; + LPDIRECTINPUT8 di; + if (DirectInput8Create(hinst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL) >= 0) { + //if (DirectInput8Create(hinst, DIRECTINPUT_VERSION, (void**)&di, NULL) >= 0) { + input = new gxInput(this, di); + acquireInput(); + } else { + debugInfo("Create DirectInput failed"); + } + return input; +} + +void gxRuntime::closeInput(gxInput* i) +{ + if (!input || input != i) + return; + unacquireInput(); + delete input; + input = 0; +} + +///////////////////////////////////////////////////// +// TIMER CALLBACK FOR AUTOREFRESH OF WINDOWED MODE // +///////////////////////////////////////////////////// +static void CALLBACK timerCallback(UINT id, UINT msg, DWORD user, DWORD dw1, DWORD dw2) +{ + if (gfx_mode) { + gxCanvas* f = runtime->graphics->getFrontCanvas(); + if (f->getModify() != mod_cnt) { + mod_cnt = f->getModify(); + InvalidateRect(runtime->hwnd, 0, false); + } + } +} + +//////////////////// +// GRAPHICS SETUP // +//////////////////// +void gxRuntime::backupWindowState() +{ + GetWindowRect(hwnd, &t_rect); + t_style = GetWindowLong(hwnd, GWL_STYLE); +} + +void gxRuntime::restoreWindowState() +{ + SetWindowLong(hwnd, GWL_STYLE, t_style); + SetWindowPos(hwnd, 0, t_rect.left, t_rect.top, t_rect.right - t_rect.left, t_rect.bottom - t_rect.top, + SWP_NOZORDER | SWP_FRAMECHANGED); +} + +bool gxRuntime::setDisplayMode(int w, int h, int d, bool d3d, IDirectDraw7* dirDraw) +{ + if (d) + return dirDraw->SetDisplayMode(w, h, d, 0, 0) >= 0; + + int best_d = 0; + + if (d3d) { + int bd = curr_driver->d3d_desc.dwDeviceRenderBitDepth; + if (bd & DDBD_32) + best_d = 32; + else if (bd & DDBD_24) + best_d = 24; + else if (bd & DDBD_16) + best_d = 16; + } else { + int best_n = 0; + for (d = 16; d <= 32; d += 8) { + if (dirDraw->SetDisplayMode(w, h, d, 0, 0) < 0) + continue; + DDCAPS caps = {sizeof(caps)}; + dirDraw->GetCaps(&caps, 0); + int n = 0; + if (caps.dwCaps & DDCAPS_BLT) + ++n; + if (caps.dwCaps & DDCAPS_BLTCOLORFILL) + ++n; + if (caps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) + ++n; + if (caps.dwCaps2 & DDCAPS2_WIDESURFACES) + ++n; + if (n == 4) + return true; + if (n > best_n) { + best_d = d; + best_n = n; + } + dirDraw->RestoreDisplayMode(); + } + } + return best_d ? dirDraw->SetDisplayMode(w, h, best_d, 0, 0) >= 0 : false; +} + +gxGraphics* gxRuntime::openWindowedGraphics(int w, int h, int d, bool d3d) +{ + IDirectDraw7* dd; + if (DirectDrawCreateEx(curr_driver->guid, (void**)&dd, IID_IDirectDraw7, 0) < 0) + return 0; + + //set coop level + if (dd->SetCooperativeLevel(hwnd, DDSCL_NORMAL) >= 0) { + //create primary surface + IDirectDrawSurface7* ps; + DDSURFACEDESC2 desc = {sizeof(desc)}; + desc.dwFlags = DDSD_CAPS; + desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + if (dd->CreateSurface(&desc, &ps, 0) >= 0) { + //create clipper + IDirectDrawClipper* cp; + if (dd->CreateClipper(0, &cp, 0) >= 0) { + //attach clipper + if (ps->SetClipper(cp) >= 0) { + //set clipper HWND + if (cp->SetHWnd(0, hwnd) >= 0) { + //create front buffer + IDirectDrawSurface7* fs; + DDSURFACEDESC2 desc = {sizeof(desc)}; + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + desc.dwWidth = w; + desc.dwHeight = h; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + + if (d3d) + desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; + + if (dd->CreateSurface(&desc, &fs, 0) >= 0) { + if (timerID = timeSetEvent(100, 10, timerCallback, 0, TIME_PERIODIC)) { + //Success! + clipper = cp; + primSurf = ps; + mod_cnt = 0; + fs->AddRef(); + return new gxGraphics(this, dd, fs, fs, d3d); + } + fs->Release(); + } + } + } + cp->Release(); + } + ps->Release(); + } + } + dd->Release(); + return 0; +} + +gxGraphics* gxRuntime::openExclusiveGraphics(int w, int h, int d, bool d3d) +{ + IDirectDraw7* dd; + if (DirectDrawCreateEx(curr_driver->guid, (void**)&dd, IID_IDirectDraw7, 0) < 0) + return 0; + + //Set coop level + if (dd->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT) >= 0) { + //Set display mode + if (setDisplayMode(w, h, d, d3d, dd)) { + //create primary surface + IDirectDrawSurface7* ps; + DDSURFACEDESC2 desc = {sizeof(desc)}; + desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; + + desc.dwBackBufferCount = 1; + if (d3d) + desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; + + if (dd->CreateSurface(&desc, &ps, 0) >= 0) { + //find back surface + IDirectDrawSurface7* bs; + DDSCAPS2 caps = {sizeof caps}; + caps.dwCaps = DDSCAPS_BACKBUFFER; + if (ps->GetAttachedSurface(&caps, &bs) >= 0) { + return new gxGraphics(this, dd, ps, bs, d3d); + } + ps->Release(); + } + dd->RestoreDisplayMode(); + } + } + dd->Release(); + return 0; +} + +gxGraphics* gxRuntime::openGraphics(int w, int h, int d, int driver, int flags) +{ + if (graphics) + return 0; + + busy = true; + + bool d3d = flags & gxGraphics::GRAPHICS_3D ? true : false; + bool windowed = flags & gxGraphics::GRAPHICS_WINDOWED ? true : false; + + if (windowed) + driver = 0; + + curr_driver = drivers[driver]; + + if (windowed) { + if (graphics = openWindowedGraphics(w, h, d, d3d)) { + gfx_mode = (flags & gxGraphics::GRAPHICS_SCALED) ? 1 : 2; + auto_suspend = (flags & gxGraphics::GRAPHICS_AUTOSUSPEND) ? true : false; + int ws, ww, hh; + if (gfx_mode == 1) { + ws = scaled_ws; + RECT c_r; + GetClientRect(hwnd, &c_r); + ww = c_r.right - c_r.left; + hh = c_r.bottom - c_r.top; + } else { + ws = static_ws; + ww = w; + hh = h; + } + + SetWindowLong(hwnd, GWL_STYLE, ws); + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + + RECT w_r, c_r; + GetWindowRect(hwnd, &w_r); + GetClientRect(hwnd, &c_r); + int tw = (w_r.right - w_r.left) - (c_r.right - c_r.left); + int th = (w_r.bottom - w_r.top) - (c_r.bottom - c_r.top); + int cx = (GetSystemMetrics(SM_CXSCREEN) - ww) / 2; + int cy = (GetSystemMetrics(SM_CYSCREEN) - hh) / 2; + POINT zz = {0, 0}; + ClientToScreen(hwnd, &zz); + int bw = zz.x - w_r.left, bh = zz.y - w_r.top; + int wx = cx - bw, wy = cy - bh; + if (wy < 0) + wy = 0; //not above top! + MoveWindow(hwnd, wx, wy, ww + tw, hh + th, true); + } + } else { + backupWindowState(); + + SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP); + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + + ShowCursor(0); + if (graphics = openExclusiveGraphics(w, h, d, d3d)) { + gfx_mode = 3; + auto_suspend = true; + SetCursorPos(0, 0); + acquireInput(); + } else { + ShowCursor(1); + restoreWindowState(); + } + } + + if (!graphics) + curr_driver = 0; + + gfx_lost = false; + + busy = false; + + return graphics; +} + +void gxRuntime::closeGraphics(gxGraphics* g) +{ + if (!graphics || graphics != g) + return; + + auto_suspend = false; + + busy = true; + + unacquireInput(); + if (timerID) { + timeKillEvent(timerID); + timerID = 0; + } + if (clipper) { + clipper->Release(); + clipper = 0; + } + if (primSurf) { + primSurf->Release(); + primSurf = 0; + } + delete graphics; + graphics = 0; + + if (gfx_mode == 3) { + ShowCursor(1); + restoreWindowState(); + } + gfx_mode = 0; + + gfx_lost = false; + + busy = false; +} + +bool gxRuntime::graphicsLost() +{ + return gfx_lost; +} + +gxFileSystem* gxRuntime::openFileSystem(int flags) +{ + if (fileSystem) + return 0; + + fileSystem = new gxFileSystem(); + return fileSystem; +} + +void gxRuntime::closeFileSystem(gxFileSystem* f) +{ + if (!fileSystem || fileSystem != f) + return; + + delete fileSystem; + fileSystem = 0; +} + +//////////////////// +// GFX ENUM STUFF // +//////////////////// +static HRESULT WINAPI enumMode(DDSURFACEDESC2* desc, void* context) +{ + int dp = desc->ddpfPixelFormat.dwRGBBitCount; + if (dp == 16 || dp == 24 || dp == 32) { + gxRuntime::GfxMode* m = new gxRuntime::GfxMode; + m->desc = *desc; + gxRuntime::GfxDriver* d = (gxRuntime::GfxDriver*)context; + d->modes.push_back(m); + } + return DDENUMRET_OK; +} + +static int maxDevType; +static HRESULT CALLBACK enumDevice(char* desc, char* name, D3DDEVICEDESC7* devDesc, void* context) +{ + int t = 0; + GUID guid = devDesc->deviceGUID; + if (guid == IID_IDirect3DRGBDevice) + t = 1; + else if (guid == IID_IDirect3DHALDevice) + t = 2; + else if (guid == IID_IDirect3DTnLHalDevice) + t = 3; + if (t > 1 && t > maxDevType) { + maxDevType = t; + gxRuntime::GfxDriver* d = (gxRuntime::GfxDriver*)context; + d->d3d_desc = *devDesc; + } + return D3DENUMRET_OK; +} + +static BOOL WINAPI enumDriver(GUID FAR* guid, LPSTR desc, LPSTR name, LPVOID context, HMONITOR hm) +{ + IDirectDraw7* dd; + if (DirectDrawCreateEx(guid, (void**)&dd, IID_IDirectDraw7, 0) < 0) + return 0; + + if (!guid && !desktop_desc.ddpfPixelFormat.dwRGBBitCount) { + desktop_desc.dwSize = sizeof(desktop_desc); + dd->GetDisplayMode(&desktop_desc); + } + + gxRuntime::GfxDriver* d = new gxRuntime::GfxDriver; + + d->guid = guid ? new GUID(*guid) : 0; + d->name = desc; //string( name )+" "+string( desc ); + + memset(&d->d3d_desc, 0, sizeof(d->d3d_desc)); + IDirect3D7* dir3d; + if (dd->QueryInterface(IID_IDirect3D7, (void**)&dir3d) >= 0) { + maxDevType = 0; + dir3d->EnumDevices(enumDevice, d); + dir3d->Release(); + } + vector* drivers = (vector*)context; + drivers->push_back(d); + dd->EnumDisplayModes(0, 0, d, enumMode); + dd->Release(); + return 1; +} + +void gxRuntime::enumGfx() +{ + denumGfx(); + if (enum_all) { + DirectDrawEnumerateEx(enumDriver, &drivers, DDENUM_ATTACHEDSECONDARYDEVICES | DDENUM_NONDISPLAYDEVICES); + } else { + DirectDrawEnumerateEx(enumDriver, &drivers, 0); + } +} + +void gxRuntime::denumGfx() +{ + for (size_t k = 0; k < drivers.size(); ++k) { + gxRuntime::GfxDriver* d = drivers[k]; + for (size_t j = 0; j < d->modes.size(); ++j) + delete d->modes[j]; + delete d->guid; + delete d; + } + drivers.clear(); +} + +int gxRuntime::enumerateGraphicsDrivers() +{ + if (!enum_all) { + enum_all = true; + enumGfx(); + } + return drivers.size(); +} + +void gxRuntime::graphicsDriverInfo(int driver, string* name, int* c) +{ + GfxDriver* g = drivers[driver]; + int caps = 0; + if (g->d3d_desc.dwDeviceRenderBitDepth) + caps |= GFXMODECAPS_3D; + *name = g->name; + *c = caps; +} + +int gxRuntime::countGraphicsModes(int driver) +{ + return drivers[driver]->modes.size(); +} + +void gxRuntime::graphicsModeInfo(int driver, int mode, int* w, int* h, int* d, int* c) +{ + GfxDriver* g = drivers[driver]; + GfxMode* m = g->modes[mode]; + int caps = 0; + int bd = 0; + switch (m->desc.ddpfPixelFormat.dwRGBBitCount) { + case 16: + bd = DDBD_16; + break; + case 24: + bd = DDBD_24; + break; + case 32: + bd = DDBD_32; + break; + } + if (g->d3d_desc.dwDeviceRenderBitDepth & bd) + caps |= GFXMODECAPS_3D; + *w = m->desc.dwWidth; + *h = m->desc.dwHeight; + *d = m->desc.ddpfPixelFormat.dwRGBBitCount; + *c = caps; +} + +void gxRuntime::windowedModeInfo(int* c) +{ + int caps = 0; + int bd = 0; + switch (desktop_desc.ddpfPixelFormat.dwRGBBitCount) { + case 16: + bd = DDBD_16; + break; + case 24: + bd = DDBD_24; + break; + case 32: + bd = DDBD_32; + break; + } + if (drivers[0]->d3d_desc.dwDeviceRenderBitDepth & bd) + caps |= GFXMODECAPS_3D; + *c = caps; +} + +gxTimer* gxRuntime::createTimer(int hertz) +{ + gxTimer* t = new gxTimer(this, hertz); + timers.insert(t); + return t; +} + +void gxRuntime::freeTimer(gxTimer* t) +{ + if (!timers.count(t)) + return; + timers.erase(t); + delete t; +} + +static string toDir(string t) +{ + if (t.size() && t[t.size() - 1] != '\\') + t += '\\'; + return t; +} + +string gxRuntime::systemProperty(const std::string& p) +{ + char buff[MAX_PATH + 1]; + string t = tolower(p); + if (t == "cpu") { + return "Intel"; + } else if (t == "os") { + return "Windows"; + } else if (t == "appdir") { + if (GetModuleFileName(0, buff, MAX_PATH)) { + string t = buff; + int n = t.find_last_of('\\'); + if (n != string::npos) + t = t.substr(0, n); + return toDir(t); + } + } else if (t == "apphwnd") { + return itoa((int)hwnd); + } else if (t == "apphinstance") { + return itoa((int)hinst); + } else if (t == "windowsdir") { + if (GetWindowsDirectory(buff, MAX_PATH)) + return toDir(buff); + } else if (t == "systemdir") { + if (GetSystemDirectory(buff, MAX_PATH)) + return toDir(buff); + } else if (t == "tempdir") { + if (GetTempPath(MAX_PATH, buff)) + return toDir(buff); + } else if (t == "direct3d7") { + if (graphics) + return itoa((int)graphics->dir3d); + } else if (t == "direct3ddevice7") { + if (graphics) + return itoa((int)graphics->dir3dDev); + } else if (t == "directdraw7") { + if (graphics) + return itoa((int)graphics->dirDraw); + } else if (t == "directinput7") { + if (input) + return itoa((int)input->dirInput); + } + return ""; +} + +void gxRuntime::enableDirectInput(bool enable) +{ + if (use_di = enable) { + acquireInput(); + } else { + unacquireInput(); + } +} + +int gxRuntime::callDll(const std::string& dll, const std::string& func, const void* in, int in_sz, void* out, + int out_sz) +{ + map::const_iterator lib_it = libs.find(dll); + + if (lib_it == libs.end()) { + HINSTANCE h = LoadLibrary(dll.c_str()); + if (!h) + return 0; + gxDll* t = new gxDll; + t->hinst = h; + lib_it = libs.insert(make_pair(dll, t)).first; + } + + gxDll* t = lib_it->second; + map::const_iterator fun_it = t->funcs.find(func); + + if (fun_it == t->funcs.end()) { + LibFunc f = (LibFunc)GetProcAddress(t->hinst, func.c_str()); + if (!f) + return 0; + fun_it = t->funcs.insert(make_pair(func, f)).first; + } + + static void* save_esp; + + _asm { + mov[save_esp], esp + } + ; + + int n = fun_it->second(in, in_sz, out, out_sz); + + _asm { + mov esp, [save_esp] + } + ; + + return n; +} diff --git a/Runtime/gfx/gxruntime.hpp b/Runtime/gfx/gxruntime.hpp new file mode 100644 index 0000000..1fc2b85 --- /dev/null +++ b/Runtime/gfx/gxruntime.hpp @@ -0,0 +1,143 @@ + +#ifndef GXRUNTIME_H +#define GXRUNTIME_H + +#include +#include +#include + +#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 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 \ No newline at end of file diff --git a/Runtime/gfx/gxscene.cpp b/Runtime/gfx/gxscene.cpp new file mode 100644 index 0000000..74de63b --- /dev/null +++ b/Runtime/gfx/gxscene.cpp @@ -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& 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; +} diff --git a/Runtime/gfx/gxscene.hpp b/Runtime/gfx/gxscene.hpp new file mode 100644 index 0000000..2f7ff70 --- /dev/null +++ b/Runtime/gfx/gxscene.hpp @@ -0,0 +1,146 @@ + + +#ifndef GXSCENE_H +#define GXSCENE_H + +#include +#include +#include +#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& 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 _allLights; + std::vector _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 \ No newline at end of file diff --git a/Runtime/gfx/gxsound.cpp b/Runtime/gfx/gxsound.cpp new file mode 100644 index 0000000..32955f4 --- /dev/null +++ b/Runtime/gfx/gxsound.cpp @@ -0,0 +1,58 @@ + +#include "gxsound.hpp" +#include +#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; +} diff --git a/Runtime/gfx/gxsound.hpp b/Runtime/gfx/gxsound.hpp new file mode 100644 index 0000000..ac06b90 --- /dev/null +++ b/Runtime/gfx/gxsound.hpp @@ -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 diff --git a/Runtime/gfx/gxtimer.cpp b/Runtime/gfx/gxtimer.cpp new file mode 100644 index 0000000..13f325a --- /dev/null +++ b/Runtime/gfx/gxtimer.cpp @@ -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; +} diff --git a/Runtime/gfx/gxtimer.hpp b/Runtime/gfx/gxtimer.hpp new file mode 100644 index 0000000..be693d6 --- /dev/null +++ b/Runtime/gfx/gxtimer.hpp @@ -0,0 +1,27 @@ + +#ifndef GXTIMER_H +#define GXTIMER_H + +#include + +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 \ No newline at end of file diff --git a/gxruntime/std.cpp b/Runtime/gfx/std.cpp similarity index 100% rename from gxruntime/std.cpp rename to Runtime/gfx/std.cpp diff --git a/gxruntime/std.hpp b/Runtime/gfx/std.hpp similarity index 90% rename from gxruntime/std.hpp rename to Runtime/gfx/std.hpp index 6665837..1fdc1bc 100644 --- a/gxruntime/std.hpp +++ b/Runtime/gfx/std.hpp @@ -4,17 +4,17 @@ #include "stdutil.hpp" -#pragma warning( disable:4786 ) +#pragma warning(disable : 4786) #define DIRECTSOUND_VERSION 0x700 -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include #include #include diff --git a/gxruntime/asmcoder.cpp b/gxruntime/asmcoder.cpp deleted file mode 100644 index ffc75a4..0000000 --- a/gxruntime/asmcoder.cpp +++ /dev/null @@ -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 - -#include -#include - -#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 - } -} diff --git a/gxruntime/asmcoder.hpp b/gxruntime/asmcoder.hpp deleted file mode 100644 index ad259d9..0000000 --- a/gxruntime/asmcoder.hpp +++ /dev/null @@ -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 diff --git a/gxruntime/ddutil.hpp b/gxruntime/ddutil.hpp deleted file mode 100644 index 735eb3e..0000000 --- a/gxruntime/ddutil.hpp +++ /dev/null @@ -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<>rshr<>gshr<>bshr<>ashl<>rshl<>gshl<>bshl< - -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 sound_set; -static vector channels; -static map songs; -static CDChannel *cdChannel; - -static int next_chan; -static vector soundChannels; - -static gxChannel *allocSoundChannel( int n ){ - - SoundChannel *chan=0; - for( int k=0;kisPlaying() ){ - 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;kset(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::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; -} diff --git a/gxruntime/gxaudio.hpp b/gxruntime/gxaudio.hpp deleted file mode 100644 index a58f027..0000000 --- a/gxruntime/gxaudio.hpp +++ /dev/null @@ -1,48 +0,0 @@ - -#ifndef GXAUDIO_H -#define GXAUDIO_H - -#include - -#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 \ No newline at end of file diff --git a/gxruntime/gxcanvas.cpp b/gxruntime/gxcanvas.cpp deleted file mode 100644 index 3549ad8..0000000 --- a/gxruntime/gxcanvas.cpp +++ /dev/null @@ -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]; -} \ No newline at end of file diff --git a/gxruntime/gxcanvas.hpp b/gxruntime/gxcanvas.hpp deleted file mode 100644 index b3dea32..0000000 --- a/gxruntime/gxcanvas.hpp +++ /dev/null @@ -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 \ No newline at end of file diff --git a/gxruntime/gxchannel.hpp b/gxruntime/gxchannel.hpp deleted file mode 100644 index b3c7187..0000000 --- a/gxruntime/gxchannel.hpp +++ /dev/null @@ -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 \ No newline at end of file diff --git a/gxruntime/gxdevice.cpp b/gxruntime/gxdevice.cpp deleted file mode 100644 index 6d5db9a..0000000 --- a/gxruntime/gxdevice.cpp +++ /dev/null @@ -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 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; -} diff --git a/gxruntime/gxfilesystem.hpp b/gxruntime/gxfilesystem.hpp deleted file mode 100644 index 7fed3f0..0000000 --- a/gxruntime/gxfilesystem.hpp +++ /dev/null @@ -1,37 +0,0 @@ - -#ifndef GXFILESYSTEM_H -#define GXFILESYSTEM_H - -#include - -#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 \ No newline at end of file diff --git a/gxruntime/gxfont.cpp b/gxruntime/gxfont.cpp deleted file mode 100644 index 0fd0c34..0000000 --- a/gxruntime/gxfont.cpp +++ /dev/null @@ -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=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=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=end_char ) c=def_char; - w+=widths[c-begin_char]; - } - return w; -} - -bool gxFont::isPrintable( int chr )const{ - return chr>=begin_char && chr -#include - -#include "GraphicsRuntime.hpp" -#include -#include - -#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 font_set; - std::set canvas_set; - std::set mesh_set; - std::set scene_set; - std::set movie_set; - std::set 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 \ No newline at end of file diff --git a/gxruntime/gxinput.hpp b/gxruntime/gxinput.hpp deleted file mode 100644 index 6c1ffde..0000000 --- a/gxruntime/gxinput.hpp +++ /dev/null @@ -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; -}; \ No newline at end of file diff --git a/gxruntime/gxlight.cpp b/gxruntime/gxlight.cpp deleted file mode 100644 index febf27e..0000000 --- a/gxruntime/gxlight.cpp +++ /dev/null @@ -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; -} diff --git a/gxruntime/gxlight.hpp b/gxruntime/gxlight.hpp deleted file mode 100644 index ea298ea..0000000 --- a/gxruntime/gxlight.hpp +++ /dev/null @@ -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 \ No newline at end of file diff --git a/gxruntime/gxmesh.hpp b/gxruntime/gxmesh.hpp deleted file mode 100644 index f0aacf6..0000000 --- a/gxruntime/gxmesh.hpp +++ /dev/null @@ -1,73 +0,0 @@ - -#ifndef GXMESH_H -#define GXMESH_H - -#include -#include "GraphicsRuntime.hpp" -#include - -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 \ No newline at end of file diff --git a/gxruntime/gxmovie.hpp b/gxruntime/gxmovie.hpp deleted file mode 100644 index a6d09f8..0000000 --- a/gxruntime/gxmovie.hpp +++ /dev/null @@ -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 \ No newline at end of file diff --git a/gxruntime/gxmusic.cpp b/gxruntime/gxmusic.cpp deleted file mode 100644 index c921e3b..0000000 --- a/gxruntime/gxmusic.cpp +++ /dev/null @@ -1,57 +0,0 @@ - -#include "std.hpp" -#include "gxmusic.hpp" -#include - -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; -} - diff --git a/gxruntime/gxmusic.hpp b/gxruntime/gxmusic.hpp deleted file mode 100644 index e531884..0000000 --- a/gxruntime/gxmusic.hpp +++ /dev/null @@ -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 \ No newline at end of file diff --git a/gxruntime/gxruntime.cpp b/gxruntime/gxruntime.cpp deleted file mode 100644 index 8442296..0000000 --- a/gxruntime/gxruntime.cpp +++ /dev/null @@ -1,1194 +0,0 @@ -#pragma once - -#include "GraphicsRuntime.hpp" -#include "std.hpp" -#include "gxruntime.hpp" -#include -#include -#include -#include - -struct gxRuntime::GfxMode { - DDSURFACEDESC2 desc; -}; -struct gxRuntime::GfxDriver { - GUID *guid; - std::string name; - std::vector modes; - D3DDEVICEDESC7 d3d_desc; -}; - -static const int static_ws = WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; -static const int scaled_ws = WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; - -static string app_title; -static string app_close; -static gxRuntime *runtime; -static bool busy, suspended; -static volatile bool run_flag; -static DDSURFACEDESC2 desktop_desc; - -typedef int(_stdcall *LibFunc)(const void *in, int in_sz, void *out, int out_sz); - -struct gxDll { - HINSTANCE hinst; - map funcs; -}; - -static map libs; - -static LRESULT CALLBACK windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - -//current gfx mode -// -//0=NONE -//1=SCALED WINDOW -//2=FIXED SIZE WINDOW -//3=EXCLUSIVE -// -static int gfx_mode; -static bool gfx_lost; -static bool auto_suspend; - -//for modes 1 and 2 -static int mod_cnt; -static MMRESULT timerID; -static IDirectDrawClipper *clipper; -static IDirectDrawSurface7 *primSurf; -//static Debugger *debugger; - -static set timers; - -enum { - WM_STOP = WM_USER + 1, WM_RUN, WM_END -}; - -//////////////////// -// STATIC STARTUP // -//////////////////// -gxRuntime *gxRuntime::openRuntime(HINSTANCE hinst, const string &cmd_line, void* d) { - if (runtime) return 0; - - //create debugger - //debugger = d; - - //create WNDCLASS - WNDCLASS wndclass; - memset(&wndclass, 0, sizeof(wndclass)); - wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wndclass.lpfnWndProc = ::windowProc; - wndclass.hInstance = hinst; - wndclass.lpszClassName = TEXT("Blitz Runtime Class"); - wndclass.hCursor = (HCURSOR)LoadCursor(0, IDC_ARROW); - wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - RegisterClass(&wndclass); - - gfx_mode = 0; - clipper = 0; primSurf = 0; - busy = suspended = false; - run_flag = true; - - const char *app_t = " "; - int ws = WS_CAPTION, ws_ex = 0; - - HWND hwnd = CreateWindowEx(ws_ex, "Blitz Runtime Class", app_t, ws, 0, 0, 0, 0, 0, 0, 0, 0); - - UpdateWindow(hwnd); - - runtime = new gxRuntime(hinst, cmd_line, hwnd); - return runtime; -} - -void gxRuntime::closeRuntime(gxRuntime *r) { - if (!runtime || runtime != r) return; - - map::const_iterator it; - for (it = libs.begin(); it != libs.end(); ++it) { - FreeLibrary(it->second->hinst); - } - libs.clear(); - - delete runtime; - runtime = 0; - -} - -////////////////////////// -// RUNTIME CONSTRUCTION // -////////////////////////// -typedef int(_stdcall *SetAppCompatDataFunc)(int x, int y); - -gxRuntime::gxRuntime(HINSTANCE hi, const string &cl, HWND hw) : - hinst(hi), cmd_line(cl), hwnd(hw), curr_driver(0), enum_all(false), - pointer_visible(true), audio(0), input(0), graphics(0), fileSystem(0), use_di(false) { - - CoInitialize(0); - - enumGfx(); - TIMECAPS tc; - timeGetDevCaps(&tc, sizeof(tc)); - timeBeginPeriod(tc.wPeriodMin); - - HMODULE ddraw = LoadLibraryA("ddraw.dll"); - if (ddraw) { - SetAppCompatDataFunc SetAppCompatData = (SetAppCompatDataFunc)GetProcAddress(ddraw, "SetAppCompatData"); - if (SetAppCompatData) SetAppCompatData(12, 0); - FreeLibrary(ddraw); - } -} - -gxRuntime::~gxRuntime() { - while (timers.size()) freeTimer(*timers.begin()); - if (audio) closeAudio(audio); - if (graphics) closeGraphics(graphics); - if (input) closeInput(input); - TIMECAPS tc; - timeGetDevCaps(&tc, sizeof(tc)); - timeEndPeriod(tc.wPeriodMin); - denumGfx(); - DestroyWindow(hwnd); - UnregisterClass("Blitz Runtime Class", hinst); - - CoUninitialize(); -} - -void gxRuntime::pauseAudio() { - if (audio) audio->pause(); -} - -void gxRuntime::resumeAudio() { - if (audio) audio->resume(); -} - -void gxRuntime::backupGraphics() { - if (auto_suspend) { - graphics->backup(); - } -} - -void gxRuntime::restoreGraphics() { - if (auto_suspend) { - if (!graphics->restore()) gfx_lost = true; - } -} - -void gxRuntime::resetInput() { - if (input) input->reset(); -} - -void gxRuntime::acquireInput() { - if (!input) return; - if (gfx_mode == 3) { - if (use_di) { - use_di = input->acquire(); - } else { - } - } - input->reset(); -} - -void gxRuntime::unacquireInput() { - if (!input) return; - if (gfx_mode == 3 && use_di) input->unacquire(); - input->reset(); -} - -///////////// -// SUSPEND // -///////////// -void gxRuntime::suspend() { - busy = true; - pauseAudio(); - backupGraphics(); - unacquireInput(); - suspended = true; - busy = false; - - if (gfx_mode == 3) ShowCursor(1); - - //if (debugger) debugger->debugStop(); -} - -//////////// -// RESUME // -//////////// -void gxRuntime::resume() { - if (gfx_mode == 3) ShowCursor(0); - busy = true; - acquireInput(); - restoreGraphics(); - resumeAudio(); - suspended = false; - busy = false; - - //if (debugger) debugger->debugRun(); -} - -/////////////////// -// FORCE SUSPEND // -/////////////////// -void gxRuntime::forceSuspend() { - if (gfx_mode == 3) { - SetForegroundWindow(GetDesktopWindow()); - ShowWindow(GetDesktopWindow(), SW_SHOW); - } else { - suspend(); - } -} - -////////////////// -// FORCE RESUME // -////////////////// -void gxRuntime::forceResume() { - if (gfx_mode == 3) { - SetForegroundWindow(hwnd); - ShowWindow(hwnd, SW_SHOWMAXIMIZED); - } else { - resume(); - } -} - -/////////// -// PAINT // -/////////// -void gxRuntime::paint() { - switch (gfx_mode) { - case 0: - { - } - break; - case 1:case 2: //scaled windowed mode. - { - RECT src, dest; - src.left = src.top = 0; - GetClientRect(hwnd, &dest); - src.right = gfx_mode == 1 ? graphics->getWidth() : dest.right; - src.bottom = gfx_mode == 1 ? graphics->getHeight() : dest.bottom; - POINT p; p.x = p.y = 0; ClientToScreen(hwnd, &p); - dest.left += p.x; dest.right += p.x; - dest.top += p.y; dest.bottom += p.y; - gxCanvas *f = graphics->getFrontCanvas(); - primSurf->Blt(&dest, f->getSurface(), &src, 0, 0); - } - break; - case 3: - { - //exclusive mode - } - break; - } -} - -////////// -// FLIP // -////////// -void gxRuntime::flip(bool vwait) { - gxCanvas *b = graphics->getBackCanvas(); - gxCanvas *f = graphics->getFrontCanvas(); - int n; - switch (gfx_mode) { - case 1:case 2: - if (vwait) graphics->vwait(); - f->setModify(b->getModify()); - if (f->getModify() != mod_cnt) { - mod_cnt = f->getModify(); - paint(); - } - break; - case 3: - if (vwait) { - BOOL vb; - while (graphics->dirDraw->GetVerticalBlankStatus(&vb) >= 0 && vb) {} - n = f->getSurface()->Flip(0, DDFLIP_WAIT); - } else { - n = f->getSurface()->Flip(0, DDFLIP_NOVSYNC | DDFLIP_WAIT); - } - if (n >= 0) return; - string t = "Flip Failed! Return code:" + itoa(n & 0x7fff); - debugLog(t.c_str()); - break; - } -} - -//////////////// -// MOVE MOUSE // -//////////////// -void gxRuntime::moveMouse(int x, int y) { - POINT p; - RECT rect; - switch (gfx_mode) { - case 1: - GetClientRect(hwnd, &rect); - x = x*(rect.right - rect.left) / graphics->getWidth(); - y = y*(rect.bottom - rect.top) / graphics->getHeight(); - case 2: - p.x = x; p.y = y; ClientToScreen(hwnd, &p); x = p.x; y = p.y; - break; - case 3: - if (use_di) return; - break; - default: - return; - } - SetCursorPos(x, y); -} - -///////////////// -// WINDOW PROC // -///////////////// -LRESULT gxRuntime::windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - - if (busy) { - return DefWindowProc(hwnd, msg, wparam, lparam); - } - - PAINTSTRUCT ps; - - //handle 'special' messages! - switch (msg) { - case WM_PAINT: - if (gfx_mode && !auto_suspend) { - if (!graphics->restore()) gfx_lost = true; - } - BeginPaint(hwnd, &ps); - paint(); - EndPaint(hwnd, &ps); - return DefWindowProc(hwnd, msg, wparam, lparam); - case WM_ERASEBKGND: - return gfx_mode ? 1 : DefWindowProc(hwnd, msg, wparam, lparam); - case WM_CLOSE: - if (app_close.size()) { - int n = MessageBox(hwnd, app_close.c_str(), app_title.c_str(), MB_OKCANCEL | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - if (n != IDOK) return 0; - } - asyncEnd(); - return 0; - case WM_SETCURSOR: - if (!suspended) { - if (gfx_mode == 3) { - SetCursor(0); - return 1; - } else if (!pointer_visible) { - POINT p; - GetCursorPos(&p); - ScreenToClient(hwnd, &p); - RECT r; GetClientRect(hwnd, &r); - if (p.x >= 0 && p.y >= 0 && p.x < r.right && p.y < r.bottom) { - SetCursor(0); - return 1; - } - } - } - break; - case WM_ACTIVATEAPP: - if (auto_suspend) { - if (wparam) { - if (suspended) resume(); - } else { - if (!suspended) suspend(); - } - } - break; - } - - if (!input || suspended) return DefWindowProc(hwnd, msg, wparam, lparam); - - if (gfx_mode == 3 && use_di) { - use_di = input->acquire(); - return DefWindowProc(hwnd, msg, wparam, lparam); - } - - static const int MK_ALLBUTTONS = MK_LBUTTON | MK_RBUTTON | MK_MBUTTON; - - //handle input messages - switch (msg) { - case WM_LBUTTONDOWN: - input->wm_mousedown(1); - SetCapture(hwnd); - break; - case WM_LBUTTONUP: - input->wm_mouseup(1); - if (!(wparam&MK_ALLBUTTONS)) ReleaseCapture(); - break; - case WM_RBUTTONDOWN: - input->wm_mousedown(2); - SetCapture(hwnd); - break; - case WM_RBUTTONUP: - input->wm_mouseup(2); - if (!(wparam&MK_ALLBUTTONS)) ReleaseCapture(); - break; - case WM_MBUTTONDOWN: - input->wm_mousedown(3); - SetCapture(hwnd); - break; - case WM_MBUTTONUP: - input->wm_mouseup(3); - if (!(wparam&MK_ALLBUTTONS)) ReleaseCapture(); - break; - case WM_MOUSEMOVE: - if (!graphics) break; - if (gfx_mode == 3 && !use_di) { - POINT p; GetCursorPos(&p); - input->wm_mousemove(p.x, p.y); - } else { - int x = (short)(lparam & 0xffff), y = lparam >> 16; - if (gfx_mode == 1) { - RECT rect; GetClientRect(hwnd, &rect); - x = x*graphics->getWidth() / (rect.right - rect.left); - y = y*graphics->getHeight() / (rect.bottom - rect.top); - } - if (x < 0) x = 0; - else if (x >= graphics->getWidth()) x = graphics->getWidth() - 1; - if (y < 0) y = 0; - else if (y >= graphics->getHeight()) y = graphics->getHeight() - 1; - input->wm_mousemove(x, y); - } - break; - case WM_MOUSEWHEEL: - input->wm_mousewheel((short)HIWORD(wparam)); - break; - case WM_KEYDOWN:case WM_SYSKEYDOWN: - if (lparam & 0x40000000) break; - if (int n = ((lparam >> 17) & 0x80) | ((lparam >> 16) & 0x7f)) input->wm_keydown(n); - break; - case WM_KEYUP:case WM_SYSKEYUP: - if (int n = ((lparam >> 17) & 0x80) | ((lparam >> 16) & 0x7f)) input->wm_keyup(n); - break; - default: - return DefWindowProc(hwnd, msg, wparam, lparam); - } - - return 0; -} - -static LRESULT CALLBACK windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - if (runtime) return runtime->windowProc(hwnd, msg, wparam, lparam); - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -////////////////////////////// -//STOP FROM EXTERNAL SOURCE // -////////////////////////////// -void gxRuntime::asyncStop() { - PostMessage(hwnd, WM_STOP, 0, 0); -} - -////////////////////////////// -//RUN FROM EXTERNAL SOURCE // -////////////////////////////// -void gxRuntime::asyncRun() { - PostMessage(hwnd, WM_RUN, 0, 0); -} - -////////////////////////////// -// END FROM EXTERNAL SOURCE // -////////////////////////////// -void gxRuntime::asyncEnd() { - PostMessage(hwnd, WM_END, 0, 0); -} - -////////// -// IDLE // -////////// -bool gxRuntime::idle() { - for (;;) { - MSG msg; - if (suspended && run_flag) { - GetMessage(&msg, 0, 0, 0); - } else { - if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) return run_flag; - } - switch (msg.message) { - case WM_STOP: - if (!suspended) forceSuspend(); - break; - case WM_RUN: - if (suspended) forceResume(); - break; - case WM_END: - //debugger = 0; - run_flag = false; - break; - default: - DispatchMessage(&msg); - } - } - return run_flag; -} - -/////////// -// DELAY // -/////////// -bool gxRuntime::delay(int ms) { - int t = timeGetTime() + ms; - for (;;) { - if (!idle()) return false; - int d = t - timeGetTime(); //how long left to wait - if (d <= 0) return true; - if (d > 100) d = 100; - Sleep(d); - } -} - -/////////////// -// DEBUGSTMT // -/////////////// -void gxRuntime::debugStmt(int pos, const char *file) { - //if (debugger) debugger->debugStmt(pos, file); -} - -/////////////// -// DEBUGSTOP // -/////////////// -void gxRuntime::debugStop() { - //if (!suspended) forceSuspend(); -} - -//////////////// -// DEBUGENTER // -//////////////// -void gxRuntime::debugEnter(void *frame, void *env, const char *func) { - //if (debugger) debugger->debugEnter(frame, env, func); -} - -//////////////// -// DEBUGLEAVE // -//////////////// -void gxRuntime::debugLeave() { - //if (debugger) debugger->debugLeave(); -} - -//////////////// -// DEBUGERROR // -//////////////// -void gxRuntime::debugError(const char *t) { - /*if (!debugger) return; - void*d = debugger; - asyncEnd(); - if (!suspended) { - forceSuspend(); - } - d->debugMsg(t, true);*/ -} - -/////////////// -// DEBUGINFO // -/////////////// -void gxRuntime::debugInfo(const char *t) { - /*if (!debugger) return; - Debugger *d = debugger; - asyncEnd(); - if (!suspended) { - forceSuspend(); - } - d->debugMsg(t, false);*/ -} - -////////////// -// DEBUGLOG // -////////////// -void gxRuntime::debugLog(const char *t) { - //if (debugger) debugger->debugLog(t); -} - -///////////////////////// -// RETURN COMMAND LINE // -///////////////////////// -string gxRuntime::commandLine() { - return cmd_line; -} - -///////////// -// EXECUTE // -///////////// -bool gxRuntime::execute(const string &cmd_line) { - - if (!cmd_line.size()) return false; - - //convert cmd_line to cmd and params - string cmd = cmd_line, params; - while (cmd.size() && cmd[0] == ' ') cmd = cmd.substr(1); - if (cmd.find('\"') == 0) { - int n = cmd.find('\"', 1); - if (n != string::npos) { - params = cmd.substr(n + 1); - cmd = cmd.substr(1, n - 1); - } - } else { - int n = cmd.find(' '); - if (n != string::npos) { - params = cmd.substr(n + 1); - cmd = cmd.substr(0, n); - } - } - while (params.size() && params[0] == ' ') params = params.substr(1); - while (params.size() && params[params.size() - 1] == ' ') params = params.substr(0, params.size() - 1); - - SetForegroundWindow(GetDesktopWindow()); - - return (int)ShellExecute(GetDesktopWindow(), 0, cmd.c_str(), params.size() ? params.c_str() : 0, 0, SW_SHOW) > 32; -} - -/////////////// -// APP TITLE // -/////////////// -void gxRuntime::setTitle(const string &t, const string &e) { - app_title = t; - app_close = e; - SetWindowText(hwnd, app_title.c_str()); -} - -////////////////// -// GETMILLISECS // -////////////////// -int gxRuntime::getMilliSecs() { - return timeGetTime(); -} - -///////////////////// -// POINTER VISIBLE // -///////////////////// -void gxRuntime::setPointerVisible(bool vis) { - if (pointer_visible == vis) return; - - pointer_visible = vis; - if (gfx_mode == 3) return; - - //force a WM_SETCURSOR - POINT pt; - GetCursorPos(&pt); - SetCursorPos(pt.x, pt.y); -} - -///////////////// -// AUDIO SETUP // -///////////////// -gxAudio *gxRuntime::openAudio(int flags) { - if (audio) return 0; - - int f_flags = - FSOUND_INIT_GLOBALFOCUS | - FSOUND_INIT_USEDEFAULTMIDISYNTH; - - FSOUND_SetHWND(hwnd); - if (!FSOUND_Init(44100, 1024, f_flags)) { - return 0; - } - - audio = new gxAudio(this); - return audio; -} - -void gxRuntime::closeAudio(gxAudio *a) { - if (!audio || audio != a) return; - delete audio; - audio = 0; -} - -///////////////// -// INPUT SETUP // -///////////////// -gxInput *gxRuntime::openInput(int flags) { - if (input) return 0; - LPDIRECTINPUT8 di; - if (DirectInput8Create(hinst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL) >= 0) { - //if (DirectInput8Create(hinst, DIRECTINPUT_VERSION, (void**)&di, NULL) >= 0) { - input = new gxInput(this, di); - acquireInput(); - } else { - debugInfo("Create DirectInput failed"); - } - return input; -} - -void gxRuntime::closeInput(gxInput *i) { - if (!input || input != i) return; - unacquireInput(); - delete input; - input = 0; -} - -///////////////////////////////////////////////////// -// TIMER CALLBACK FOR AUTOREFRESH OF WINDOWED MODE // -///////////////////////////////////////////////////// -static void CALLBACK timerCallback(UINT id, UINT msg, DWORD user, DWORD dw1, DWORD dw2) { - if (gfx_mode) { - gxCanvas *f = runtime->graphics->getFrontCanvas(); - if (f->getModify() != mod_cnt) { - mod_cnt = f->getModify(); - InvalidateRect(runtime->hwnd, 0, false); - } - } -} - -//////////////////// -// GRAPHICS SETUP // -//////////////////// -void gxRuntime::backupWindowState() { - GetWindowRect(hwnd, &t_rect); - t_style = GetWindowLong(hwnd, GWL_STYLE); -} - -void gxRuntime::restoreWindowState() { - SetWindowLong(hwnd, GWL_STYLE, t_style); - SetWindowPos( - hwnd, 0, t_rect.left, t_rect.top, - t_rect.right - t_rect.left, t_rect.bottom - t_rect.top, - SWP_NOZORDER | SWP_FRAMECHANGED); -} - -bool gxRuntime::setDisplayMode(int w, int h, int d, bool d3d, IDirectDraw7 *dirDraw) { - - if (d) return dirDraw->SetDisplayMode(w, h, d, 0, 0) >= 0; - - int best_d = 0; - - if (d3d) { - int bd = curr_driver->d3d_desc.dwDeviceRenderBitDepth; - if (bd & DDBD_32) best_d = 32; - else if (bd & DDBD_24) best_d = 24; - else if (bd & DDBD_16) best_d = 16; - } else { - int best_n = 0; - for (d = 16; d <= 32; d += 8) { - if (dirDraw->SetDisplayMode(w, h, d, 0, 0) < 0) continue; - DDCAPS caps = { sizeof(caps) }; - dirDraw->GetCaps(&caps, 0); - int n = 0; - if (caps.dwCaps & DDCAPS_BLT) ++n; - if (caps.dwCaps & DDCAPS_BLTCOLORFILL) ++n; - if (caps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) ++n; - if (caps.dwCaps2 & DDCAPS2_WIDESURFACES) ++n; - if (n == 4) return true; - if (n > best_n) { - best_d = d; - best_n = n; - } - dirDraw->RestoreDisplayMode(); - } - } - return best_d ? dirDraw->SetDisplayMode(w, h, best_d, 0, 0) >= 0 : false; -} - -gxGraphics *gxRuntime::openWindowedGraphics(int w, int h, int d, bool d3d) { - - IDirectDraw7 *dd; - if (DirectDrawCreateEx(curr_driver->guid, (void**)&dd, IID_IDirectDraw7, 0) < 0) return 0; - - //set coop level - if (dd->SetCooperativeLevel(hwnd, DDSCL_NORMAL) >= 0) { - //create primary surface - IDirectDrawSurface7 *ps; - DDSURFACEDESC2 desc = { sizeof(desc) }; - desc.dwFlags = DDSD_CAPS; - desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - if (dd->CreateSurface(&desc, &ps, 0) >= 0) { - //create clipper - IDirectDrawClipper *cp; - if (dd->CreateClipper(0, &cp, 0) >= 0) { - //attach clipper - if (ps->SetClipper(cp) >= 0) { - //set clipper HWND - if (cp->SetHWnd(0, hwnd) >= 0) { - //create front buffer - IDirectDrawSurface7 *fs; - DDSURFACEDESC2 desc = { sizeof(desc) }; - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; - desc.dwWidth = w; desc.dwHeight = h; - desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - - if (d3d) desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; - - if (dd->CreateSurface(&desc, &fs, 0) >= 0) { - if (timerID = timeSetEvent(100, 10, timerCallback, 0, TIME_PERIODIC)) { - //Success! - clipper = cp; - primSurf = ps; - mod_cnt = 0; - fs->AddRef(); - return new gxGraphics(this, dd, fs, fs, d3d); - } - fs->Release(); - } - } - } - cp->Release(); - } - ps->Release(); - } - } - dd->Release(); - return 0; -} - -gxGraphics *gxRuntime::openExclusiveGraphics(int w, int h, int d, bool d3d) { - - IDirectDraw7 *dd; - if (DirectDrawCreateEx(curr_driver->guid, (void**)&dd, IID_IDirectDraw7, 0) < 0) return 0; - - //Set coop level - if (dd->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT) >= 0) { - //Set display mode - if (setDisplayMode(w, h, d, d3d, dd)) { - //create primary surface - IDirectDrawSurface7 *ps; - DDSURFACEDESC2 desc = { sizeof(desc) }; - desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; - - desc.dwBackBufferCount = 1; - if (d3d) desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; - - if (dd->CreateSurface(&desc, &ps, 0) >= 0) { - //find back surface - IDirectDrawSurface7 *bs; - DDSCAPS2 caps = { sizeof caps }; - caps.dwCaps = DDSCAPS_BACKBUFFER; - if (ps->GetAttachedSurface(&caps, &bs) >= 0) { - return new gxGraphics(this, dd, ps, bs, d3d); - } - ps->Release(); - } - dd->RestoreDisplayMode(); - } - } - dd->Release(); - return 0; -} - -gxGraphics *gxRuntime::openGraphics(int w, int h, int d, int driver, int flags) { - if (graphics) return 0; - - busy = true; - - bool d3d = flags & gxGraphics::GRAPHICS_3D ? true : false; - bool windowed = flags & gxGraphics::GRAPHICS_WINDOWED ? true : false; - - if (windowed) driver = 0; - - curr_driver = drivers[driver]; - - if (windowed) { - if (graphics = openWindowedGraphics(w, h, d, d3d)) { - gfx_mode = (flags & gxGraphics::GRAPHICS_SCALED) ? 1 : 2; - auto_suspend = (flags & gxGraphics::GRAPHICS_AUTOSUSPEND) ? true : false; - int ws, ww, hh; - if (gfx_mode == 1) { - ws = scaled_ws; - RECT c_r; - GetClientRect(hwnd, &c_r); - ww = c_r.right - c_r.left; - hh = c_r.bottom - c_r.top; - } else { - ws = static_ws; - ww = w; - hh = h; - } - - SetWindowLong(hwnd, GWL_STYLE, ws); - SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - - RECT w_r, c_r; - GetWindowRect(hwnd, &w_r); - GetClientRect(hwnd, &c_r); - int tw = (w_r.right - w_r.left) - (c_r.right - c_r.left); - int th = (w_r.bottom - w_r.top) - (c_r.bottom - c_r.top); - int cx = (GetSystemMetrics(SM_CXSCREEN) - ww) / 2; - int cy = (GetSystemMetrics(SM_CYSCREEN) - hh) / 2; - POINT zz = { 0,0 }; - ClientToScreen(hwnd, &zz); - int bw = zz.x - w_r.left, bh = zz.y - w_r.top; - int wx = cx - bw, wy = cy - bh; if (wy < 0) wy = 0; //not above top! - MoveWindow(hwnd, wx, wy, ww + tw, hh + th, true); - } - } else { - backupWindowState(); - - SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP); - SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - - ShowCursor(0); - if (graphics = openExclusiveGraphics(w, h, d, d3d)) { - gfx_mode = 3; - auto_suspend = true; - SetCursorPos(0, 0); - acquireInput(); - } else { - ShowCursor(1); - restoreWindowState(); - } - } - - if (!graphics) curr_driver = 0; - - gfx_lost = false; - - busy = false; - - return graphics; -} - -void gxRuntime::closeGraphics(gxGraphics *g) { - if (!graphics || graphics != g) return; - - auto_suspend = false; - - busy = true; - - unacquireInput(); - if (timerID) { timeKillEvent(timerID); timerID = 0; } - if (clipper) { clipper->Release(); clipper = 0; } - if (primSurf) { primSurf->Release(); primSurf = 0; } - delete graphics; graphics = 0; - - if (gfx_mode == 3) { - ShowCursor(1); - restoreWindowState(); - } - gfx_mode = 0; - - gfx_lost = false; - - busy = false; -} - -bool gxRuntime::graphicsLost() { - return gfx_lost; -} - -gxFileSystem *gxRuntime::openFileSystem(int flags) { - if (fileSystem) return 0; - - fileSystem = new gxFileSystem(); - return fileSystem; -} - -void gxRuntime::closeFileSystem(gxFileSystem *f) { - if (!fileSystem || fileSystem != f) return; - - delete fileSystem; - fileSystem = 0; -} - -//////////////////// -// GFX ENUM STUFF // -//////////////////// -static HRESULT WINAPI enumMode(DDSURFACEDESC2 *desc, void *context) { - int dp = desc->ddpfPixelFormat.dwRGBBitCount; - if (dp == 16 || dp == 24 || dp == 32) { - gxRuntime::GfxMode *m = new gxRuntime::GfxMode; - m->desc = *desc; - gxRuntime::GfxDriver *d = (gxRuntime::GfxDriver*)context; - d->modes.push_back(m); - } - return DDENUMRET_OK; -} - -static int maxDevType; -static HRESULT CALLBACK enumDevice(char *desc, char *name, D3DDEVICEDESC7 *devDesc, void *context) { - int t = 0; - GUID guid = devDesc->deviceGUID; - if (guid == IID_IDirect3DRGBDevice) t = 1; - else if (guid == IID_IDirect3DHALDevice) t = 2; - else if (guid == IID_IDirect3DTnLHalDevice) t = 3; - if (t > 1 && t > maxDevType) { - maxDevType = t; - gxRuntime::GfxDriver *d = (gxRuntime::GfxDriver*)context; - d->d3d_desc = *devDesc; - } - return D3DENUMRET_OK; -} - -static BOOL WINAPI enumDriver(GUID FAR *guid, LPSTR desc, LPSTR name, LPVOID context, HMONITOR hm) { - IDirectDraw7 *dd; - if (DirectDrawCreateEx(guid, (void**)&dd, IID_IDirectDraw7, 0) < 0) return 0; - - if (!guid && !desktop_desc.ddpfPixelFormat.dwRGBBitCount) { - desktop_desc.dwSize = sizeof(desktop_desc); - dd->GetDisplayMode(&desktop_desc); - } - - gxRuntime::GfxDriver *d = new gxRuntime::GfxDriver; - - d->guid = guid ? new GUID(*guid) : 0; - d->name = desc;//string( name )+" "+string( desc ); - - memset(&d->d3d_desc, 0, sizeof(d->d3d_desc)); - IDirect3D7 *dir3d; - if (dd->QueryInterface(IID_IDirect3D7, (void**)&dir3d) >= 0) { - maxDevType = 0; - dir3d->EnumDevices(enumDevice, d); - dir3d->Release(); - } - vector *drivers = (vector*)context; - drivers->push_back(d); - dd->EnumDisplayModes(0, 0, d, enumMode); - dd->Release(); - return 1; -} - -void gxRuntime::enumGfx() { - denumGfx(); - if (enum_all) { - DirectDrawEnumerateEx(enumDriver, &drivers, DDENUM_ATTACHEDSECONDARYDEVICES | DDENUM_NONDISPLAYDEVICES); - } else { - DirectDrawEnumerateEx(enumDriver, &drivers, 0); - } -} - -void gxRuntime::denumGfx() { - for (size_t k = 0; k < drivers.size(); ++k) { - gxRuntime::GfxDriver *d = drivers[k]; - for (size_t j = 0; j < d->modes.size(); ++j) delete d->modes[j]; - delete d->guid; - delete d; - } - drivers.clear(); -} - -int gxRuntime::enumerateGraphicsDrivers() { - if (!enum_all) { - enum_all = true; - enumGfx(); - } - return drivers.size(); -} - -void gxRuntime::graphicsDriverInfo(int driver, string *name, int *c) { - GfxDriver *g = drivers[driver]; - int caps = 0; - if (g->d3d_desc.dwDeviceRenderBitDepth) caps |= GFXMODECAPS_3D; - *name = g->name; - *c = caps; -} - -int gxRuntime::countGraphicsModes(int driver) { - return drivers[driver]->modes.size(); -} - -void gxRuntime::graphicsModeInfo(int driver, int mode, int *w, int *h, int *d, int *c) { - GfxDriver *g = drivers[driver]; - GfxMode *m = g->modes[mode]; - int caps = 0; - int bd = 0; - switch (m->desc.ddpfPixelFormat.dwRGBBitCount) { - case 16:bd = DDBD_16; break; - case 24:bd = DDBD_24; break; - case 32:bd = DDBD_32; break; - } - if (g->d3d_desc.dwDeviceRenderBitDepth & bd) caps |= GFXMODECAPS_3D; - *w = m->desc.dwWidth; - *h = m->desc.dwHeight; - *d = m->desc.ddpfPixelFormat.dwRGBBitCount; - *c = caps; -} - -void gxRuntime::windowedModeInfo(int *c) { - int caps = 0; - int bd = 0; - switch (desktop_desc.ddpfPixelFormat.dwRGBBitCount) { - case 16:bd = DDBD_16; break; - case 24:bd = DDBD_24; break; - case 32:bd = DDBD_32; break; - } - if (drivers[0]->d3d_desc.dwDeviceRenderBitDepth & bd) caps |= GFXMODECAPS_3D; - *c = caps; -} - -gxTimer *gxRuntime::createTimer(int hertz) { - gxTimer *t = new gxTimer(this, hertz); - timers.insert(t); - return t; -} - -void gxRuntime::freeTimer(gxTimer *t) { - if (!timers.count(t)) return; - timers.erase(t); - delete t; -} - -static string toDir(string t) { - if (t.size() && t[t.size() - 1] != '\\') t += '\\'; - return t; -} - -string gxRuntime::systemProperty(const std::string &p) { - char buff[MAX_PATH + 1]; - string t = tolower(p); - if (t == "cpu") { - return "Intel"; - } else if (t == "os") { - return "Windows"; - } else if (t == "appdir") { - if (GetModuleFileName(0, buff, MAX_PATH)) { - string t = buff; - int n = t.find_last_of('\\'); - if (n != string::npos) t = t.substr(0, n); - return toDir(t); - } - } else if (t == "apphwnd") { - return itoa((int)hwnd); - } else if (t == "apphinstance") { - return itoa((int)hinst); - } else if (t == "windowsdir") { - if (GetWindowsDirectory(buff, MAX_PATH)) return toDir(buff); - } else if (t == "systemdir") { - if (GetSystemDirectory(buff, MAX_PATH)) return toDir(buff); - } else if (t == "tempdir") { - if (GetTempPath(MAX_PATH, buff)) return toDir(buff); - } else if (t == "direct3d7") { - if (graphics) return itoa((int)graphics->dir3d); - } else if (t == "direct3ddevice7") { - if (graphics) return itoa((int)graphics->dir3dDev); - } else if (t == "directdraw7") { - if (graphics) return itoa((int)graphics->dirDraw); - } else if (t == "directinput7") { - if (input) return itoa((int)input->dirInput); - } - return ""; -} - -void gxRuntime::enableDirectInput(bool enable) { - if (use_di = enable) { - acquireInput(); - } else { - unacquireInput(); - } -} - -int gxRuntime::callDll(const std::string &dll, const std::string &func, const void *in, int in_sz, void *out, int out_sz) { - - map::const_iterator lib_it = libs.find(dll); - - if (lib_it == libs.end()) { - HINSTANCE h = LoadLibrary(dll.c_str()); - if (!h) return 0; - gxDll *t = new gxDll; - t->hinst = h; - lib_it = libs.insert(make_pair(dll, t)).first; - } - - gxDll *t = lib_it->second; - map::const_iterator fun_it = t->funcs.find(func); - - if (fun_it == t->funcs.end()) { - LibFunc f = (LibFunc)GetProcAddress(t->hinst, func.c_str()); - if (!f) return 0; - fun_it = t->funcs.insert(make_pair(func, f)).first; - } - - static void *save_esp; - - _asm { - mov[save_esp], esp - }; - - int n = fun_it->second(in, in_sz, out, out_sz); - - _asm { - mov esp, [save_esp] - }; - - return n; -} diff --git a/gxruntime/gxruntime.hpp b/gxruntime/gxruntime.hpp deleted file mode 100644 index eefd617..0000000 --- a/gxruntime/gxruntime.hpp +++ /dev/null @@ -1,143 +0,0 @@ - -#ifndef GXRUNTIME_H -#define GXRUNTIME_H - -#include -#include -#include - -#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 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 \ No newline at end of file diff --git a/gxruntime/gxscene.cpp b/gxruntime/gxscene.cpp deleted file mode 100644 index dbb3758..0000000 --- a/gxruntime/gxscene.cpp +++ /dev/null @@ -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;nLightEnable( 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;kgetWidth(),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;kSetViewport( &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;kgetTexSurface(); //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_texscanvas ){ - 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 &lights ){ - - if( dir3dDev->BeginScene()!=D3D_OK ) return false; - - //clear textures! - int n; - for( n=0;nSetTexture( n,0 ); - } - - //set light states - _curLights.clear(); - for( n=0;n<8;++n ){ - if( nSetLight( 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;krender( 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; -} diff --git a/gxruntime/gxscene.hpp b/gxruntime/gxscene.hpp deleted file mode 100644 index 1a27389..0000000 --- a/gxruntime/gxscene.hpp +++ /dev/null @@ -1,157 +0,0 @@ - - -#ifndef GXSCENE_H -#define GXSCENE_H - -#include -#include "GraphicsRuntime.hpp" -#include -#include - -#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 &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 _allLights; - std::vector _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 \ No newline at end of file diff --git a/gxruntime/gxsound.cpp b/gxruntime/gxsound.cpp deleted file mode 100644 index 5b1b7dc..0000000 --- a/gxruntime/gxsound.cpp +++ /dev/null @@ -1,51 +0,0 @@ - -#include "std.hpp" -#include "gxsound.hpp" -#include "gxaudio.hpp" -#include - -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; -} - diff --git a/gxruntime/gxsound.hpp b/gxruntime/gxsound.hpp deleted file mode 100644 index 964b931..0000000 --- a/gxruntime/gxsound.hpp +++ /dev/null @@ -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 diff --git a/gxruntime/gxtimer.cpp b/gxruntime/gxtimer.cpp deleted file mode 100644 index 5eddc09..0000000 --- a/gxruntime/gxtimer.cpp +++ /dev/null @@ -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; -} - diff --git a/gxruntime/gxtimer.hpp b/gxruntime/gxtimer.hpp deleted file mode 100644 index b08f5e1..0000000 --- a/gxruntime/gxtimer.hpp +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef GXTIMER_H -#define GXTIMER_H - -#include - -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 \ No newline at end of file